blob: c77418066ddbc11014fc44828a2310f1b3116b4c [file] [log] [blame]
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001/*
Patrik Stridvall151170c1998-12-26 12:00:43 +00002 * X11 event driver
Patrik Stridvalle35d6361998-12-07 09:13:40 +00003 *
4 * Copyright 1993 Alexandre Julliard
Noel Borthwickd05b7be1999-09-20 15:42:47 +00005 * 1999 Noel Borthwick
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00006 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Patrik Stridvalle35d6361998-12-07 09:13:40 +000020 */
21
22#include "config.h"
23
Patrik Stridvalle35d6361998-12-07 09:13:40 +000024#include <X11/Xatom.h>
25#include <X11/keysym.h>
Patrik Stridvall3d511612000-04-25 19:55:35 +000026
Patrik Stridvalle35d6361998-12-07 09:13:40 +000027#include "ts_xlib.h"
28#include "ts_xresource.h"
29#include "ts_xutil.h"
Lionel Ulmer3ba4be41999-12-12 19:42:47 +000030#ifdef HAVE_LIBXXF86DGA2
31#include "ts_xf86dga2.h"
32#endif
33
Patrik Stridvalle35d6361998-12-07 09:13:40 +000034#include <assert.h>
Patrik Stridvalle35d6361998-12-07 09:13:40 +000035#include <string.h>
Alexandre Julliardf37e3a42000-09-16 20:58:06 +000036#include "wine/winuser16.h"
Alexandre Julliard60e17522000-09-25 23:56:41 +000037#include "shlobj.h" /* DROPFILES */
Alexandre Julliardf37e3a42000-09-16 20:58:06 +000038
Patrik Stridvallab121e71999-02-04 11:11:01 +000039#include "clipboard.h"
40#include "dce.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000041#include "wine/debug.h"
Lionel Ulmer62e4d551999-12-12 21:28:44 +000042#include "input.h"
Patrik Stridvall6cc47d42000-03-08 18:26:56 +000043#include "win.h"
Patrik Stridvallab121e71999-02-04 11:11:01 +000044#include "winpos.h"
Jim Aston2e1cafa1999-03-14 16:35:05 +000045#include "windef.h"
Dmitry Timoshkovb91d2df2001-06-26 19:36:23 +000046#include "winreg.h"
Patrik Stridvalle35d6361998-12-07 09:13:40 +000047#include "x11drv.h"
François Gougetdea3d782001-01-02 21:00:46 +000048#include "shellapi.h"
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000049
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000050WINE_DEFAULT_DEBUG_CHANNEL(event);
51WINE_DECLARE_DEBUG_CHANNEL(win);
Vincent Béron9a624912002-05-31 23:06:46 +000052
Patrik Stridvalle35d6361998-12-07 09:13:40 +000053/* X context to associate a hwnd to an X window */
54extern XContext winContext;
55
56extern Atom wmProtocols;
57extern Atom wmDeleteWindow;
58extern Atom dndProtocol;
59extern Atom dndSelection;
60
Patrik Stridvalle35d6361998-12-07 09:13:40 +000061#define DndNotDnd -1 /* OffiX drag&drop */
62#define DndUnknown 0
63#define DndRawData 1
64#define DndFile 2
65#define DndFiles 3
66#define DndText 4
67#define DndDir 5
68#define DndLink 6
69#define DndExe 7
70
71#define DndEND 8
72
73#define DndURL 128 /* KDE drag&drop */
74
Noel Borthwick36d7ca31999-07-24 12:16:00 +000075/* The last X window which had the focus */
76static Window glastXFocusWin = 0;
Patrik Stridvalle35d6361998-12-07 09:13:40 +000077
78static const char * const event_names[] =
79{
80 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
81 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
82 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
83 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
84 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
85 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
86 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
87 "ClientMessage", "MappingNotify"
88};
89
Noel Borthwickd05b7be1999-09-20 15:42:47 +000090
Patrik Stridvalle35d6361998-12-07 09:13:40 +000091static void EVENT_ProcessEvent( XEvent *event );
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +000092static BOOL X11DRV_CheckFocus(void);
Patrik Stridvalle35d6361998-12-07 09:13:40 +000093
94 /* Event handlers */
Francois Boisverte5811f01999-04-15 15:22:23 +000095static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
96static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
Noel Borthwickd05b7be1999-09-20 15:42:47 +000097static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
Francois Boisverte5811f01999-04-15 15:22:23 +000098static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
Noel Borthwickd05b7be1999-09-20 15:42:47 +000099static void EVENT_PropertyNotify( XPropertyEvent *event );
Francois Boisverte5811f01999-04-15 15:22:23 +0000100static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000101
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000102extern void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event );
103extern void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event );
104extern void X11DRV_MotionNotify( HWND hwnd, XMotionEvent *event );
Alexandre Julliard9428f062002-06-14 00:08:40 +0000105extern void X11DRV_EnterNotify( HWND hwnd, XCrossingEvent *event );
Alexandre Julliard4b626182001-10-17 17:50:02 +0000106extern void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event );
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000107extern void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event );
Alexandre Julliardf4b14102001-06-22 03:42:27 +0000108extern void X11DRV_Expose( HWND hwnd, XExposeEvent *event );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000109extern void X11DRV_MapNotify( HWND hwnd, XMapEvent *event );
110extern void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event );
111extern void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
Alexandre Julliard4b626182001-10-17 17:50:02 +0000112extern void X11DRV_MappingNotify( XMappingEvent *event );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000113
Lionel Ulmer3ba4be41999-12-12 19:42:47 +0000114#ifdef HAVE_LIBXXF86DGA2
115static int DGAMotionEventType;
116static int DGAButtonPressEventType;
117static int DGAButtonReleaseEventType;
118static int DGAKeyPressEventType;
119static int DGAKeyReleaseEventType;
120
121static BOOL DGAUsed = FALSE;
122static HWND DGAhwnd = 0;
123
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000124extern void X11DRV_DGAMotionEvent( HWND hwnd, XDGAMotionEvent *event );
125extern void X11DRV_DGAButtonPressEvent( HWND hwnd, XDGAButtonEvent *event );
126extern void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XDGAButtonEvent *event );
Lionel Ulmer3ba4be41999-12-12 19:42:47 +0000127#endif
128
Lionel Ulmeracc74671999-11-07 21:25:57 +0000129/* Static used for the current input method */
130static INPUT_TYPE current_input_type = X11DRV_INPUT_ABSOLUTE;
131static BOOL in_transition = FALSE; /* This is not used as for today */
Ulrich Weigand7581f851999-05-22 18:57:17 +0000132
Alexandre Julliard26320d12001-03-23 23:45:45 +0000133
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000134/***********************************************************************
Alexandre Julliard43230042001-05-16 19:52:29 +0000135 * process_events
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000136 */
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000137static int process_events( struct x11drv_thread_data *data )
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000138{
Ulrich Weigand7581f851999-05-22 18:57:17 +0000139 XEvent event;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000140 int count = 0;
Ulrich Weigand7581f851999-05-22 18:57:17 +0000141
Alexandre Julliardee21c442001-01-15 22:31:24 +0000142 wine_tsx11_lock();
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000143 while ( XPending( data->display ) )
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000144 {
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000145 XNextEvent( data->display, &event );
Alexandre Julliardee21c442001-01-15 22:31:24 +0000146 wine_tsx11_unlock();
Ulrich Weigand7581f851999-05-22 18:57:17 +0000147 EVENT_ProcessEvent( &event );
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000148 count++;
Alexandre Julliardee21c442001-01-15 22:31:24 +0000149 wine_tsx11_lock();
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000150 }
Alexandre Julliardee21c442001-01-15 22:31:24 +0000151 wine_tsx11_unlock();
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000152 return count;
Ulrich Weigand7581f851999-05-22 18:57:17 +0000153}
154
Alexandre Julliard43230042001-05-16 19:52:29 +0000155
Ulrich Weigand7581f851999-05-22 18:57:17 +0000156/***********************************************************************
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000157 * MsgWaitForMultipleObjectsEx (X11DRV.@)
Ulrich Weigand7581f851999-05-22 18:57:17 +0000158 */
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000159DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
160 DWORD timeout, DWORD mask, DWORD flags )
Ulrich Weigand7581f851999-05-22 18:57:17 +0000161{
Alexandre Julliard43230042001-05-16 19:52:29 +0000162 HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1]; /* FIXME! */
163 DWORD i, ret;
164 struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
165
166 if (!data || data->process_event_count)
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000167 return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
168 timeout, flags & MWMO_ALERTABLE );
Alexandre Julliard43230042001-05-16 19:52:29 +0000169
170 for (i = 0; i < count; i++) new_handles[i] = handles[i];
171 new_handles[count] = data->display_fd;
172
Alexandre Julliard43230042001-05-16 19:52:29 +0000173 wine_tsx11_lock();
174 XFlush( gdi_display );
175 XFlush( data->display );
176 wine_tsx11_unlock();
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000177
178 data->process_event_count++;
179 if (process_events( data )) ret = count;
180 else
181 {
182 ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
183 timeout, flags & MWMO_ALERTABLE );
184 if (ret == count) process_events( data );
185 }
Alexandre Julliard43230042001-05-16 19:52:29 +0000186 data->process_event_count--;
187 return ret;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000188}
189
Alexandre Julliard43230042001-05-16 19:52:29 +0000190
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000191/***********************************************************************
192 * EVENT_ProcessEvent
193 *
194 * Process an X event.
195 */
196static void EVENT_ProcessEvent( XEvent *event )
197{
Francois Boisverte5811f01999-04-15 15:22:23 +0000198 HWND hWnd;
Alexandre Julliard43230042001-05-16 19:52:29 +0000199 Display *display = event->xany.display;
Ulrich Weigand6d45e7a1999-03-16 10:37:30 +0000200
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000201 TRACE( "called.\n" );
Ulrich Weigand7581f851999-05-22 18:57:17 +0000202
Ulrich Weigand6d45e7a1999-03-16 10:37:30 +0000203 switch (event->type)
Alex Korobka44a1b591999-04-01 12:03:52 +0000204 {
205 case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000206 FIXME("Got SelectionNotify - must not happen!\n");
Alex Korobka44a1b591999-04-01 12:03:52 +0000207 /* fall through */
208
Ulrich Weigand6d45e7a1999-03-16 10:37:30 +0000209 /* We get all these because of StructureNotifyMask.
210 This check is placed here to avoid getting error messages below,
211 as X might send some of these even for windows that have already
212 been deleted ... */
Ulrich Weigand6d45e7a1999-03-16 10:37:30 +0000213 case CirculateNotify:
214 case CreateNotify:
215 case DestroyNotify:
216 case GravityNotify:
217 case ReparentNotify:
218 return;
Alex Korobka44a1b591999-04-01 12:03:52 +0000219 }
Ove Kaaven7da242d1999-11-07 22:44:06 +0000220
Lionel Ulmer3ba4be41999-12-12 19:42:47 +0000221#ifdef HAVE_LIBXXF86DGA2
222 if (DGAUsed) {
223 if (event->type == DGAMotionEventType) {
224 TRACE("DGAMotionEvent received.\n");
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000225 X11DRV_DGAMotionEvent( DGAhwnd, (XDGAMotionEvent *)event );
Lionel Ulmer3ba4be41999-12-12 19:42:47 +0000226 return;
227 }
228 if (event->type == DGAButtonPressEventType) {
229 TRACE("DGAButtonPressEvent received.\n");
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000230 X11DRV_DGAButtonPressEvent( DGAhwnd, (XDGAButtonEvent *)event );
Lionel Ulmer3ba4be41999-12-12 19:42:47 +0000231 return;
232 }
233 if (event->type == DGAButtonReleaseEventType) {
234 TRACE("DGAButtonReleaseEvent received.\n");
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000235 X11DRV_DGAButtonReleaseEvent( DGAhwnd, (XDGAButtonEvent *)event );
Lionel Ulmer3ba4be41999-12-12 19:42:47 +0000236 return;
237 }
238 if ((event->type == DGAKeyPressEventType) ||
239 (event->type == DGAKeyReleaseEventType)) {
Lionel Ulmer62e4d551999-12-12 21:28:44 +0000240 /* Fill a XKeyEvent to send to EVENT_Key */
Lionel Ulmer3ba4be41999-12-12 19:42:47 +0000241 XKeyEvent ke;
Lionel Ulmer62e4d551999-12-12 21:28:44 +0000242 XDGAKeyEvent *evt = (XDGAKeyEvent *) event;
Lionel Ulmer3ba4be41999-12-12 19:42:47 +0000243
244 TRACE("DGAKeyPress/ReleaseEvent received.\n");
Vincent Béron9a624912002-05-31 23:06:46 +0000245
Lionel Ulmer62e4d551999-12-12 21:28:44 +0000246 if (evt->type == DGAKeyReleaseEventType)
247 ke.type = KeyRelease;
248 else
249 ke.type = KeyPress;
250 ke.serial = evt->serial;
251 ke.send_event = FALSE;
252 ke.display = evt->display;
253 ke.window = 0;
254 ke.root = 0;
255 ke.subwindow = 0;
256 ke.time = evt->time;
Alexandre Julliard4b626182001-10-17 17:50:02 +0000257 ke.x = -1;
258 ke.y = -1;
Lionel Ulmer62e4d551999-12-12 21:28:44 +0000259 ke.x_root = -1;
260 ke.y_root = -1;
261 ke.state = evt->state;
262 ke.keycode = evt->keycode;
263 ke.same_screen = TRUE;
Alexandre Julliard4b626182001-10-17 17:50:02 +0000264 X11DRV_KeyEvent( 0, &ke );
Lionel Ulmer3ba4be41999-12-12 19:42:47 +0000265 return;
266 }
267 }
268#endif
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000269
270 if (TSXFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
Ulrich Weigand7581f851999-05-22 18:57:17 +0000271 hWnd = 0; /* Not for a registered window */
Francois Boisverte5811f01999-04-15 15:22:23 +0000272
Alexandre Julliard43230042001-05-16 19:52:29 +0000273 if ( !hWnd && event->xany.window != root_window
Vincent Béron9a624912002-05-31 23:06:46 +0000274 && event->type != PropertyNotify
Stephane Lussierfa8b7282000-04-16 17:07:27 +0000275 && event->type != MappingNotify)
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000276 WARN( "Got event %s for unknown Window %08lx\n",
277 event_names[event->type], event->xany.window );
Ulrich Weigand9cfeb5b1999-03-10 13:26:09 +0000278 else
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000279 TRACE("Got event %s for hwnd %04x\n",
280 event_names[event->type], hWnd );
Francois Boisverte5811f01999-04-15 15:22:23 +0000281
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000282 switch(event->type)
283 {
284 case KeyPress:
285 case KeyRelease:
Alexandre Julliard4b626182001-10-17 17:50:02 +0000286 /* FIXME: should generate a motion event if event point is different from current pos */
287 X11DRV_KeyEvent( hWnd, (XKeyEvent*)event );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000288 break;
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000289
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000290 case ButtonPress:
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000291 X11DRV_ButtonPress( hWnd, (XButtonEvent*)event );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000292 break;
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000293
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000294 case ButtonRelease:
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000295 X11DRV_ButtonRelease( hWnd, (XButtonEvent*)event );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000296 break;
Alexandre Julliardf9037de2001-06-25 20:01:03 +0000297
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000298 case MotionNotify:
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000299 X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000300 break;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000301
Alexandre Julliard9428f062002-06-14 00:08:40 +0000302 case EnterNotify:
303 X11DRV_EnterNotify( hWnd, (XCrossingEvent*)event );
304 break;
305
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000306 case FocusIn:
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000307 EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
Noel Borthwick36d7ca31999-07-24 12:16:00 +0000308 break;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000309
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000310 case FocusOut:
Francois Boisverte5811f01999-04-15 15:22:23 +0000311 EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000312 break;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000313
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000314 case Expose:
Alexandre Julliardf4b14102001-06-22 03:42:27 +0000315 X11DRV_Expose( hWnd, &event->xexpose );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000316 break;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000317
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000318 case ConfigureNotify:
Alexandre Julliard43230042001-05-16 19:52:29 +0000319 if (!hWnd) return;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000320 X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000321 break;
322
323 case SelectionRequest:
Alexandre Julliard43230042001-05-16 19:52:29 +0000324 if (!hWnd) return;
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000325 EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000326 break;
327
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000328 case SelectionClear:
Alexandre Julliard43230042001-05-16 19:52:29 +0000329 if (!hWnd) return;
Francois Boisverte5811f01999-04-15 15:22:23 +0000330 EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000331 break;
Vincent Béron9a624912002-05-31 23:06:46 +0000332
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000333 case PropertyNotify:
334 EVENT_PropertyNotify( (XPropertyEvent *)event );
335 break;
336
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000337 case ClientMessage:
Alexandre Julliard43230042001-05-16 19:52:29 +0000338 if (!hWnd) return;
Francois Boisverte5811f01999-04-15 15:22:23 +0000339 EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000340 break;
341
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000342 case NoExpose:
343 break;
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000344
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000345 case MapNotify:
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000346 X11DRV_MapNotify( hWnd, (XMapEvent *)event );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000347 break;
Alex Korobka44a1b591999-04-01 12:03:52 +0000348
349 case UnmapNotify:
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000350 X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
Alex Korobka44a1b591999-04-01 12:03:52 +0000351 break;
352
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000353 case KeymapNotify:
354 X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
355 break;
356
Stephane Lussierfa8b7282000-04-16 17:07:27 +0000357 case MappingNotify:
Alexandre Julliard4b626182001-10-17 17:50:02 +0000358 X11DRV_MappingNotify( (XMappingEvent *) event );
Stephane Lussierfa8b7282000-04-16 17:07:27 +0000359 break;
360
Vincent Béron9a624912002-05-31 23:06:46 +0000361 default:
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000362 WARN("Unprocessed event %s for hwnd %04x\n",
Francois Boisverte5811f01999-04-15 15:22:23 +0000363 event_names[event->type], hWnd );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000364 break;
365 }
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000366 TRACE( "returns.\n" );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000367}
368
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000369
370/**********************************************************************
371 * EVENT_FocusIn
372 */
Francois Boisverte5811f01999-04-15 15:22:23 +0000373static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event )
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000374{
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000375 WND *pWndLastFocus;
376 XWindowAttributes win_attr;
377 BOOL bIsDisabled;
378
379 if (!hWnd) return;
380
381 bIsDisabled = GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED;
382
Dimitrie O. Paune361cea2002-05-23 02:43:09 +0000383 /* If the window has been disabled, revert the X focus back to the last
Vincent Béron9a624912002-05-31 23:06:46 +0000384 * focus window. This is to disallow the window manager from switching
Dimitrie O. Paune361cea2002-05-23 02:43:09 +0000385 * focus away while the app is in a modal state.
386 */
387 if (bIsDisabled && glastXFocusWin)
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000388 {
389 /* Change focus only if saved focus window is registered and viewable */
390 wine_tsx11_lock();
391 if (XFindContext( event->display, glastXFocusWin, winContext,
392 (char **)&pWndLastFocus ) == 0 )
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000393 {
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000394 if (XGetWindowAttributes( event->display, glastXFocusWin, &win_attr ) &&
395 (win_attr.map_state == IsViewable) )
396 {
397 XSetInputFocus( event->display, glastXFocusWin, RevertToParent, CurrentTime );
398 wine_tsx11_unlock();
399 return;
400 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000401 }
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000402 wine_tsx11_unlock();
403 }
404
Alexandre Julliardfb23e102002-03-22 01:03:36 +0000405 if (event->detail != NotifyPointer && hWnd != GetForegroundWindow())
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000406 SetForegroundWindow( hWnd );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000407}
408
409
410/**********************************************************************
411 * EVENT_FocusOut
412 *
413 * Note: only top-level override-redirect windows get FocusOut events.
414 */
Francois Boisverte5811f01999-04-15 15:22:23 +0000415static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event )
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000416{
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000417 /* Save the last window which had the focus */
418 glastXFocusWin = event->window;
419 if (!hWnd) return;
420 if (GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED) glastXFocusWin = 0;
Abey Georgefbecbc21999-10-13 13:49:01 +0000421
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000422 if (event->detail != NotifyPointer && hWnd == GetForegroundWindow())
423 {
424 /* don't reset the foreground window, if the window which is
Stephane Lussierd7418502000-09-27 00:22:00 +0000425 getting the focus is a Wine window */
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000426 if (!X11DRV_CheckFocus())
427 {
428 SendMessageA( hWnd, WM_CANCELMODE, 0, 0 );
429 /* Abey : 6-Oct-99. Check again if the focus out window is the
430 Foreground window, because in most cases the messages sent
431 above must have already changed the foreground window, in which
432 case we don't have to change the foreground window to 0 */
Stephane Lussierd7418502000-09-27 00:22:00 +0000433
Alexandre Julliarddc4fe772001-06-04 21:55:17 +0000434 if (hWnd == GetForegroundWindow())
435 SetForegroundWindow( 0 );
436 }
437 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000438}
439
440/**********************************************************************
Josh DuBois2c6e3ff2001-02-12 03:39:34 +0000441 * CheckFocus (X11DRV.@)
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000442 */
Alexandre Julliard9ae0fe52001-04-24 23:28:52 +0000443static BOOL X11DRV_CheckFocus(void)
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000444{
Alexandre Julliard43230042001-05-16 19:52:29 +0000445 Display *display = thread_display();
Ulrich Weigandb38e1de1999-06-12 06:42:20 +0000446 HWND hWnd;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000447 Window xW;
448 int state;
Vincent Béron9a624912002-05-31 23:06:46 +0000449
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000450 TSXGetInputFocus(display, &xW, &state);
451 if( xW == None ||
Vincent Béron9a624912002-05-31 23:06:46 +0000452 TSXFindContext(display, xW, winContext, (char **)&hWnd) )
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000453 return FALSE;
454 return TRUE;
455}
456
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000457
458/***********************************************************************
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000459 * EVENT_SelectionRequest_TARGETS
460 * Service a TARGETS selection request event
461 */
Alexandre Julliard43230042001-05-16 19:52:29 +0000462static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
463 Atom target, Atom rprop )
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000464{
465 Atom xaTargets = TSXInternAtom(display, "TARGETS", False);
466 Atom* targets;
467 Atom prop;
468 UINT wFormat;
469 unsigned long cTargets;
470 BOOL bHavePixmap;
471 int xRc;
472
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000473 TRACE("Request for %s\n", TSXGetAtomName(display, target));
Vincent Béron9a624912002-05-31 23:06:46 +0000474
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000475 /*
476 * Count the number of items we wish to expose as selection targets.
477 * We include the TARGETS item, and a PIXMAP if we have CF_DIB or CF_BITMAP
478 */
479 cTargets = CountClipboardFormats() + 1;
480 if ( CLIPBOARD_IsPresent(CF_DIB) || CLIPBOARD_IsPresent(CF_BITMAP) )
481 cTargets++;
Vincent Béron9a624912002-05-31 23:06:46 +0000482
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000483 /* Allocate temp buffer */
Dimitrie O. Paunabdbced2000-04-29 14:20:28 +0000484 targets = (Atom*)HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
485 if(targets == NULL) return None;
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000486
487 /* Create TARGETS property list (First item in list is TARGETS itself) */
488
489 for ( targets[0] = xaTargets, cTargets = 1, wFormat = 0, bHavePixmap = FALSE;
490 (wFormat = EnumClipboardFormats( wFormat )); )
491 {
492 if ( (prop = X11DRV_CLIPBOARD_MapFormatToProperty(wFormat)) != None )
493 {
494 /* Scan through what we have so far to avoid duplicates */
495 int i;
496 BOOL bExists;
497 for (i = 0, bExists = FALSE; i < cTargets; i++)
498 {
499 if (targets[i] == prop)
500 {
501 bExists = TRUE;
502 break;
503 }
504 }
505 if (!bExists)
506 {
507 targets[cTargets++] = prop;
Vincent Béron9a624912002-05-31 23:06:46 +0000508
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000509 /* Add PIXMAP prop for bitmaps additionally */
510 if ( (wFormat == CF_DIB || wFormat == CF_BITMAP )
511 && !bHavePixmap )
512 {
513 targets[cTargets++] = XA_PIXMAP;
514 bHavePixmap = TRUE;
515 }
516 }
517 }
518 }
519
Alexandre Julliard383da682000-02-10 22:15:21 +0000520 if (TRACE_ON(event))
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000521 {
Alexandre Julliard383da682000-02-10 22:15:21 +0000522 int i;
523 for ( i = 0; i < cTargets; i++)
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000524 {
Alexandre Julliard383da682000-02-10 22:15:21 +0000525 if (targets[i])
526 {
527 char *itemFmtName = TSXGetAtomName(display, targets[i]);
528 TRACE("\tAtom# %d: Type %s\n", i, itemFmtName);
529 TSXFree(itemFmtName);
530 }
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000531 }
532 }
Vincent Béron9a624912002-05-31 23:06:46 +0000533
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000534 /* Update the X property */
Francois Gougete76218d2001-05-09 17:31:31 +0000535 TRACE("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000536
537 /* We may want to consider setting the type to xaTargets instead,
538 * in case some apps expect this instead of XA_ATOM */
539 xRc = TSXChangeProperty(display, requestor, rprop,
540 XA_ATOM, 32, PropModeReplace,
541 (unsigned char *)targets, cTargets);
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000542 TRACE("(Rc=%d)\n", xRc);
Vincent Béron9a624912002-05-31 23:06:46 +0000543
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000544 HeapFree( GetProcessHeap(), 0, targets );
545
546 return rprop;
547}
548
549
550/***********************************************************************
551 * EVENT_SelectionRequest_STRING
552 * Service a STRING selection request event
553 */
Alexandre Julliard43230042001-05-16 19:52:29 +0000554static Atom EVENT_SelectionRequest_STRING( Display *display, Window requestor,
555 Atom target, Atom rprop )
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000556{
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000557 static UINT text_cp = (UINT)-1;
558 HANDLE hUnicodeText;
559 LPWSTR uni_text;
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000560 LPSTR text;
561 int size,i,j;
562 char* lpstr = 0;
563 char *itemFmtName;
564 int xRc;
565
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000566 if(text_cp == (UINT)-1)
Dmitry Timoshkovb91d2df2001-06-26 19:36:23 +0000567 {
568 HKEY hkey;
569 /* default value */
570 text_cp = CP_ACP;
571 if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\x11drv", &hkey))
572 {
573 char buf[20];
574 DWORD type, count = sizeof(buf);
575 if(!RegQueryValueExA(hkey, "TextCP", 0, &type, buf, &count))
576 text_cp = atoi(buf);
577 RegCloseKey(hkey);
578 }
579 }
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000580
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000581 /*
582 * Map the requested X selection property type atom name to a
583 * windows clipboard format ID.
584 */
585 itemFmtName = TSXGetAtomName(display, target);
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000586 TRACE("Request for %s (wFormat=%x %s)\n",
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000587 itemFmtName, CF_UNICODETEXT, CLIPBOARD_GetFormatName(CF_UNICODETEXT));
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000588 TSXFree(itemFmtName);
589
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000590 hUnicodeText = GetClipboardData(CF_UNICODETEXT);
591 if(!hUnicodeText)
Marcus Meissner9b84bb62000-03-04 19:18:47 +0000592 return None;
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000593 uni_text = GlobalLock(hUnicodeText);
594 if(!uni_text)
595 return None;
596
597 size = WideCharToMultiByte(text_cp, 0, uni_text, -1, NULL, 0, NULL, NULL);
598 text = HeapAlloc(GetProcessHeap(), 0, size);
Marcus Meissner9b84bb62000-03-04 19:18:47 +0000599 if (!text)
600 return None;
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000601 WideCharToMultiByte(text_cp, 0, uni_text, -1, text, size, NULL, NULL);
602
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000603 /* remove carriage returns */
Vincent Béron9a624912002-05-31 23:06:46 +0000604
Dimitrie O. Paunabdbced2000-04-29 14:20:28 +0000605 lpstr = (char*)HeapAlloc( GetProcessHeap(), 0, size-- );
606 if(lpstr == NULL) return None;
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000607 for(i=0,j=0; i < size && text[i]; i++ )
608 {
Vincent Béron9a624912002-05-31 23:06:46 +0000609 if( text[i] == '\r' &&
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000610 (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
611 lpstr[j++] = text[i];
612 }
613 lpstr[j]='\0';
Vincent Béron9a624912002-05-31 23:06:46 +0000614
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000615 /* Update the X property */
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000616 TRACE("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000617 xRc = TSXChangeProperty(display, requestor, rprop,
618 XA_STRING, 8, PropModeReplace,
619 lpstr, j);
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000620 TRACE("(Rc=%d)\n", xRc);
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000621
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000622 GlobalUnlock(hUnicodeText);
623 HeapFree(GetProcessHeap(), 0, text);
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000624 HeapFree( GetProcessHeap(), 0, lpstr );
625
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000626 return rprop;
627}
628
629/***********************************************************************
630 * EVENT_SelectionRequest_PIXMAP
631 * Service a PIXMAP selection request event
632 */
Alexandre Julliard43230042001-05-16 19:52:29 +0000633static Atom EVENT_SelectionRequest_PIXMAP( Display *display, Window requestor,
634 Atom target, Atom rprop )
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000635{
636 HANDLE hClipData = 0;
Niels Kristian Bech Jensenc69a80c1999-11-28 20:31:04 +0000637 Pixmap pixmap = 0;
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000638 UINT wFormat;
639 char * itemFmtName;
640 int xRc;
641#if(0)
642 XSetWindowAttributes win_attr;
643 XWindowAttributes win_attr_src;
644#endif
Vincent Béron9a624912002-05-31 23:06:46 +0000645
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000646 /*
647 * Map the requested X selection property type atom name to a
648 * windows clipboard format ID.
649 */
650 itemFmtName = TSXGetAtomName(display, target);
651 wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000652 TRACE("Request for %s (wFormat=%x %s)\n",
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000653 itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat));
654 TSXFree(itemFmtName);
Vincent Béron9a624912002-05-31 23:06:46 +0000655
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000656 hClipData = GetClipboardData(wFormat);
657 if ( !hClipData )
658 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000659 TRACE("Could not retrieve a Pixmap compatible format from clipboard!\n");
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000660 rprop = None; /* Fail the request */
661 goto END;
662 }
663
664 if (wFormat == CF_DIB)
665 {
666 HWND hwnd = GetOpenClipboardWindow();
667 HDC hdc = GetDC(hwnd);
Vincent Béron9a624912002-05-31 23:06:46 +0000668
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000669 /* For convert from packed DIB to Pixmap */
670 pixmap = X11DRV_DIB_CreatePixmapFromDIB(hClipData, hdc);
Vincent Béron9a624912002-05-31 23:06:46 +0000671
Alexandre Julliard629aab12001-09-19 20:34:17 +0000672 ReleaseDC(hwnd, hdc);
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000673 }
674 else if (wFormat == CF_BITMAP)
675 {
676 HWND hwnd = GetOpenClipboardWindow();
677 HDC hdc = GetDC(hwnd);
Vincent Béron9a624912002-05-31 23:06:46 +0000678
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000679 pixmap = X11DRV_BITMAP_CreatePixmapFromBitmap(hClipData, hdc);
680
Alexandre Julliard629aab12001-09-19 20:34:17 +0000681 ReleaseDC(hwnd, hdc);
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000682 }
683 else
684 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000685 FIXME("%s to PIXMAP conversion not yet implemented!\n",
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000686 CLIPBOARD_GetFormatName(wFormat));
687 rprop = None;
688 goto END;
689 }
690
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000691 TRACE("\tUpdating property %s on Window %ld with %s %ld...\n",
692 TSXGetAtomName(display, rprop), (long)requestor,
693 TSXGetAtomName(display, target), pixmap);
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000694
695 /* Store the Pixmap handle in the property */
Vincent Béron9a624912002-05-31 23:06:46 +0000696 xRc = TSXChangeProperty(display, requestor, rprop, target,
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000697 32, PropModeReplace,
698 (unsigned char *)&pixmap, 1);
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000699 TRACE("(Rc=%d)\n", xRc);
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000700
701 /* Enable the code below if you want to handle destroying Pixmap resources
702 * in response to property notify events. Clients like XPaint don't
703 * appear to be duplicating Pixmaps so they don't like us deleting,
704 * the resource in response to the property being deleted.
705 */
706#if(0)
707 /* Express interest in property notify events so that we can delete the
708 * pixmap when the client deletes the property atom.
709 */
710 xRc = TSXGetWindowAttributes(display, requestor, &win_attr_src);
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000711 TRACE("Turning on PropertyChangeEvent notifications from window %ld\n",
712 (long)requestor);
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000713 win_attr.event_mask = win_attr_src.your_event_mask | PropertyChangeMask;
714 TSXChangeWindowAttributes(display, requestor, CWEventMask, &win_attr);
715
716 /* Register the Pixmap we created with the request property Atom.
717 * When this property is destroyed we also destroy the Pixmap in
718 * response to the PropertyNotify event.
719 */
720 X11DRV_CLIPBOARD_RegisterPixmapResource( rprop, pixmap );
721#endif
Vincent Béron9a624912002-05-31 23:06:46 +0000722
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000723END:
724 return rprop;
725}
726
727
728/***********************************************************************
729 * EVENT_SelectionRequest_WCF
730 * Service a Wine Clipboard Format selection request event.
731 * For <WCF>* data types we simply copy the data to X without conversion.
732 */
Alexandre Julliard43230042001-05-16 19:52:29 +0000733static Atom EVENT_SelectionRequest_WCF( Display *display, Window requestor,
734 Atom target, Atom rprop )
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000735{
736 HANDLE hClipData = 0;
737 void* lpClipData;
738 UINT wFormat;
739 char * itemFmtName;
740 int cBytes;
741 int xRc;
Vincent Béron9a624912002-05-31 23:06:46 +0000742
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000743 /*
744 * Map the requested X selection property type atom name to a
745 * windows clipboard format ID.
746 */
747 itemFmtName = TSXGetAtomName(display, target);
748 wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000749 TRACE("Request for %s (wFormat=%x %s)\n",
750 itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat));
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000751 TSXFree(itemFmtName);
Vincent Béron9a624912002-05-31 23:06:46 +0000752
Dmitry Timoshkov698ef152001-06-25 20:08:44 +0000753 hClipData = GetClipboardData(wFormat);
Vincent Béron9a624912002-05-31 23:06:46 +0000754
Dmitry Timoshkov698ef152001-06-25 20:08:44 +0000755 if( hClipData && (lpClipData = GlobalLock(hClipData)) )
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000756 {
Dmitry Timoshkov698ef152001-06-25 20:08:44 +0000757 cBytes = GlobalSize(hClipData);
Vincent Béron9a624912002-05-31 23:06:46 +0000758
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000759 TRACE("\tUpdating property %s, %d bytes...\n",
760 TSXGetAtomName(display, rprop), cBytes);
Vincent Béron9a624912002-05-31 23:06:46 +0000761
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000762 xRc = TSXChangeProperty(display, requestor, rprop,
763 target, 8, PropModeReplace,
764 (unsigned char *)lpClipData, cBytes);
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000765 TRACE("(Rc=%d)\n", xRc);
Vincent Béron9a624912002-05-31 23:06:46 +0000766
Dmitry Timoshkov698ef152001-06-25 20:08:44 +0000767 GlobalUnlock(hClipData);
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000768 }
769 else
770 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000771 TRACE("\tCould not retrieve native format!\n");
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000772 rprop = None; /* Fail the request */
773 }
Vincent Béron9a624912002-05-31 23:06:46 +0000774
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000775 return rprop;
776}
777
778
779/***********************************************************************
780 * EVENT_SelectionRequest_MULTIPLE
781 * Service a MULTIPLE selection request event
782 * rprop contains a list of (target,property) atom pairs.
783 * The first atom names a target and the second names a property.
784 * The effect is as if we have received a sequence of SelectionRequest events
785 * (one for each atom pair) except that:
786 * 1. We reply with a SelectionNotify only when all the requested conversions
787 * have been performed.
788 * 2. If we fail to convert the target named by an atom in the MULTIPLE property,
789 * we replace the atom in the property by None.
790 */
791static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
792{
Alexandre Julliard43230042001-05-16 19:52:29 +0000793 Display *display = pevent->display;
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000794 Atom rprop;
795 Atom atype=AnyPropertyType;
796 int aformat;
797 unsigned long remain;
798 Atom* targetPropList=NULL;
799 unsigned long cTargetPropList = 0;
800/* Atom xAtomPair = TSXInternAtom(display, "ATOM_PAIR", False); */
Vincent Béron9a624912002-05-31 23:06:46 +0000801
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000802 /* If the specified property is None the requestor is an obsolete client.
803 * We support these by using the specified target atom as the reply property.
804 */
805 rprop = pevent->property;
Vincent Béron9a624912002-05-31 23:06:46 +0000806 if( rprop == None )
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000807 rprop = pevent->target;
808 if (!rprop)
809 goto END;
810
811 /* Read the MULTIPLE property contents. This should contain a list of
812 * (target,property) atom pairs.
813 */
814 if(TSXGetWindowProperty(display, pevent->requestor, rprop,
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000815 0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
816 &cTargetPropList, &remain,
817 (unsigned char**)&targetPropList) != Success)
818 TRACE("\tCouldn't read MULTIPLE property\n");
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000819 else
820 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000821 TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
822 TSXGetAtomName(display, atype), aformat, cTargetPropList, remain);
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000823
824 /*
825 * Make sure we got what we expect.
826 * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
827 * in a MULTIPLE selection request should be of type ATOM_PAIR.
828 * However some X apps(such as XPaint) are not compliant with this and return
829 * a user defined atom in atype when XGetWindowProperty is called.
830 * The data *is* an atom pair but is not denoted as such.
831 */
832 if(aformat == 32 /* atype == xAtomPair */ )
833 {
834 int i;
Vincent Béron9a624912002-05-31 23:06:46 +0000835
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000836 /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
837 * for each (target,property) pair */
838
839 for (i = 0; i < cTargetPropList; i+=2)
840 {
841 char *targetName = TSXGetAtomName(display, targetPropList[i]);
842 char *propName = TSXGetAtomName(display, targetPropList[i+1]);
843 XSelectionRequestEvent event;
844
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000845 TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
846 i/2, targetName, propName);
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000847 TSXFree(targetName);
848 TSXFree(propName);
Vincent Béron9a624912002-05-31 23:06:46 +0000849
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000850 /* We must have a non "None" property to service a MULTIPLE target atom */
851 if ( !targetPropList[i+1] )
852 {
Francois Gougete76218d2001-05-09 17:31:31 +0000853 TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000854 continue;
855 }
Vincent Béron9a624912002-05-31 23:06:46 +0000856
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000857 /* Set up an XSelectionRequestEvent for this (target,property) pair */
858 memcpy( &event, pevent, sizeof(XSelectionRequestEvent) );
859 event.target = targetPropList[i];
860 event.property = targetPropList[i+1];
Vincent Béron9a624912002-05-31 23:06:46 +0000861
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000862 /* Fire a SelectionRequest, informing the handler that we are processing
863 * a MULTIPLE selection request event.
864 */
865 EVENT_SelectionRequest( hWnd, &event, TRUE );
866 }
867 }
868
869 /* Free the list of targets/properties */
870 TSXFree(targetPropList);
871 }
872
873END:
874 return rprop;
875}
876
877
878/***********************************************************************
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000879 * EVENT_SelectionRequest
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000880 * Process an event selection request event.
881 * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
882 * recursively while servicing a "MULTIPLE" selection target.
883 *
Noel Borthwick29700671999-09-03 15:17:57 +0000884 * Note: We only receive this event when WINE owns the X selection
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000885 */
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000886static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000887{
Alexandre Julliard43230042001-05-16 19:52:29 +0000888 Display *display = event->display;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000889 XSelectionEvent result;
Noel Borthwick29700671999-09-03 15:17:57 +0000890 Atom rprop = None;
891 Window request = event->requestor;
Noel Borthwick29700671999-09-03 15:17:57 +0000892 BOOL couldOpen = FALSE;
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000893 Atom xaClipboard = TSXInternAtom(display, "CLIPBOARD", False);
894 Atom xaTargets = TSXInternAtom(display, "TARGETS", False);
895 Atom xaMultiple = TSXInternAtom(display, "MULTIPLE", False);
Noel Borthwick29700671999-09-03 15:17:57 +0000896
897 /*
898 * We can only handle the selection request if :
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000899 * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
900 * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
901 * since this has been already done.
Noel Borthwick29700671999-09-03 15:17:57 +0000902 */
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000903 if ( !bIsMultiple )
904 {
905 if ( ( (event->selection != XA_PRIMARY) && (event->selection != xaClipboard) )
906 || !(couldOpen = OpenClipboard(hWnd)) )
907 goto END;
908 }
Noel Borthwick29700671999-09-03 15:17:57 +0000909
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000910 /* If the specified property is None the requestor is an obsolete client.
911 * We support these by using the specified target atom as the reply property.
912 */
Noel Borthwick29700671999-09-03 15:17:57 +0000913 rprop = event->property;
Vincent Béron9a624912002-05-31 23:06:46 +0000914 if( rprop == None )
Noel Borthwick29700671999-09-03 15:17:57 +0000915 rprop = event->target;
Vincent Béron9a624912002-05-31 23:06:46 +0000916
Noel Borthwick29700671999-09-03 15:17:57 +0000917 if(event->target == xaTargets) /* Return a list of all supported targets */
918 {
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000919 /* TARGETS selection request */
Alexandre Julliard43230042001-05-16 19:52:29 +0000920 rprop = EVENT_SelectionRequest_TARGETS( display, request, event->target, rprop );
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000921 }
922 else if(event->target == xaMultiple) /* rprop contains a list of (target, property) atom pairs */
923 {
924 /* MULTIPLE selection request */
Alexandre Julliard43230042001-05-16 19:52:29 +0000925 rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
Noel Borthwick29700671999-09-03 15:17:57 +0000926 }
927 else if(event->target == XA_STRING) /* treat CF_TEXT as Unix text */
Alex Korobka44a1b591999-04-01 12:03:52 +0000928 {
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000929 /* XA_STRING selection request */
Alexandre Julliard43230042001-05-16 19:52:29 +0000930 rprop = EVENT_SelectionRequest_STRING( display, request, event->target, rprop );
Alex Korobka44a1b591999-04-01 12:03:52 +0000931 }
Noel Borthwick29700671999-09-03 15:17:57 +0000932 else if(event->target == XA_PIXMAP) /* Convert DIB's to Pixmaps */
933 {
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000934 /* XA_PIXMAP selection request */
Alexandre Julliard43230042001-05-16 19:52:29 +0000935 rprop = EVENT_SelectionRequest_PIXMAP( display, request, event->target, rprop );
Noel Borthwick29700671999-09-03 15:17:57 +0000936 }
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000937 else if(event->target == XA_BITMAP) /* Convert DIB's to 1-bit Pixmaps */
Noel Borthwick29700671999-09-03 15:17:57 +0000938 {
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000939 /* XA_BITMAP selection request - TODO: create a monochrome Pixmap */
Alexandre Julliard43230042001-05-16 19:52:29 +0000940 rprop = EVENT_SelectionRequest_PIXMAP( display, request, XA_PIXMAP, rprop );
Noel Borthwick29700671999-09-03 15:17:57 +0000941 }
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000942 else if(X11DRV_CLIPBOARD_IsNativeProperty(event->target)) /* <WCF>* */
943 {
944 /* All <WCF> selection requests */
Alexandre Julliard43230042001-05-16 19:52:29 +0000945 rprop = EVENT_SelectionRequest_WCF( display, request, event->target, rprop );
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000946 }
947 else
948 rprop = None; /* Don't support this format */
Noel Borthwick29700671999-09-03 15:17:57 +0000949
950END:
951 /* close clipboard only if we opened before */
952 if(couldOpen) CloseClipboard();
Vincent Béron9a624912002-05-31 23:06:46 +0000953
954 if( rprop == None)
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000955 TRACE("\tRequest ignored\n");
Alex Korobka44a1b591999-04-01 12:03:52 +0000956
Vincent Béron9a624912002-05-31 23:06:46 +0000957 /* reply to sender
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000958 * SelectionNotify should be sent only at the end of a MULTIPLE request
959 */
960 if ( !bIsMultiple )
961 {
962 result.type = SelectionNotify;
963 result.display = display;
964 result.requestor = request;
965 result.selection = event->selection;
966 result.property = rprop;
967 result.target = event->target;
968 result.time = event->time;
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000969 TRACE("Sending SelectionNotify event...\n");
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000970 TSXSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
971 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000972}
973
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000974/***********************************************************************
975 * EVENT_SelectionClear
976 */
Francois Boisverte5811f01999-04-15 15:22:23 +0000977static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000978{
Alexandre Julliard43230042001-05-16 19:52:29 +0000979 Atom xaClipboard = TSXInternAtom(event->display, "CLIPBOARD", False);
Vincent Béron9a624912002-05-31 23:06:46 +0000980
Noel Borthwick29700671999-09-03 15:17:57 +0000981 if (event->selection == XA_PRIMARY || event->selection == xaClipboard)
982 X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000983}
984
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000985/***********************************************************************
986 * EVENT_PropertyNotify
987 * We use this to release resources like Pixmaps when a selection
988 * client no longer needs them.
989 */
990static void EVENT_PropertyNotify( XPropertyEvent *event )
991{
992 /* Check if we have any resources to free */
Francois Gougete76218d2001-05-09 17:31:31 +0000993 TRACE("Received PropertyNotify event: \n");
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000994
995 switch(event->state)
996 {
997 case PropertyDelete:
998 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000999 TRACE("\tPropertyDelete for atom %s on window %ld\n",
1000 TSXGetAtomName(event->display, event->atom), (long)event->window);
Vincent Béron9a624912002-05-31 23:06:46 +00001001
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001002 if (X11DRV_IsSelectionOwner())
Noel Borthwickd05b7be1999-09-20 15:42:47 +00001003 X11DRV_CLIPBOARD_FreeResources( event->atom );
1004 break;
1005 }
1006
1007 case PropertyNewValue:
1008 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001009 TRACE("\tPropertyNewValue for atom %s on window %ld\n\n",
1010 TSXGetAtomName(event->display, event->atom), (long)event->window);
Noel Borthwickd05b7be1999-09-20 15:42:47 +00001011 break;
1012 }
Vincent Béron9a624912002-05-31 23:06:46 +00001013
Noel Borthwickd05b7be1999-09-20 15:42:47 +00001014 default:
1015 break;
1016 }
1017}
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001018
1019/**********************************************************************
1020 * EVENT_DropFromOffix
1021 *
1022 * don't know if it still works (last Changlog is from 96/11/04)
1023 */
Francois Boisverte5811f01999-04-15 15:22:23 +00001024static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001025{
1026 unsigned long data_length;
1027 unsigned long aux_long;
1028 unsigned char* p_data = NULL;
1029 union {
1030 Atom atom_aux;
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +00001031 struct {
1032 int x;
1033 int y;
1034 } pt_aux;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001035 int i;
1036 } u;
1037 int x, y;
1038 BOOL16 bAccept;
Alexandre Julliard83f52d12000-09-26 22:20:14 +00001039 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO16));
1040 LPDRAGINFO16 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
Alexandre Julliard58017232000-12-22 01:09:26 +00001041 SEGPTR spDragInfo = K32WOWGlobalLock16(hDragInfo);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001042 Window w_aux_root, w_aux_child;
Francois Boisverte5811f01999-04-15 15:22:23 +00001043 WND* pWnd;
Vincent Béron9a624912002-05-31 23:06:46 +00001044
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001045 if( !lpDragInfo || !spDragInfo ) return;
Vincent Béron9a624912002-05-31 23:06:46 +00001046
Francois Boisverte5811f01999-04-15 15:22:23 +00001047 pWnd = WIN_FindWndPtr(hWnd);
Vincent Béron9a624912002-05-31 23:06:46 +00001048
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001049 TSXQueryPointer( event->display, get_whole_window(pWnd), &w_aux_root, &w_aux_child,
Stephane Lussierb50272b1999-02-21 18:15:26 +00001050 &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
1051 (unsigned int*)&aux_long);
Vincent Béron9a624912002-05-31 23:06:46 +00001052
Francois Boisverte5811f01999-04-15 15:22:23 +00001053 lpDragInfo->hScope = hWnd;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001054 lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y;
Vincent Béron9a624912002-05-31 23:06:46 +00001055
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001056 /* find out drop point and drop window */
1057 if( x < 0 || y < 0 ||
1058 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1059 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1060 { bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
1061 else
1062 {
Francois Boisverte5811f01999-04-15 15:22:23 +00001063 bAccept = DRAG_QueryUpdate( hWnd, spDragInfo, TRUE );
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001064 x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
1065 }
Francois Boisverte5811f01999-04-15 15:22:23 +00001066 WIN_ReleaseWndPtr(pWnd);
Vincent Béron9a624912002-05-31 23:06:46 +00001067
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001068 GlobalFree16( hDragInfo );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001069
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001070 if (!bAccept) return;
1071
1072 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1073 dndSelection, 0, 65535, FALSE,
1074 AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1075 &data_length, &aux_long, &p_data);
1076
1077 if( !aux_long && p_data) /* don't bother if > 64K */
1078 {
1079 signed char *p = (signed char*) p_data;
1080 char *p_drop;
1081
1082 aux_long = 0;
1083 while( *p ) /* calculate buffer size */
1084 {
1085 p_drop = p;
1086 if((u.i = *p) != -1 )
1087 {
1088 INT len = GetShortPathNameA( p, NULL, 0 );
1089 if (len) aux_long += len + 1;
1090 else *p = -1;
1091 }
1092 p += strlen(p) + 1;
1093 }
1094 if( aux_long && aux_long < 65535 )
1095 {
1096 HDROP hDrop;
1097 DROPFILES *lpDrop;
1098
1099 aux_long += sizeof(DROPFILES) + 1;
1100 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
1101 lpDrop = (DROPFILES*)GlobalLock( hDrop );
1102
1103 if( lpDrop )
1104 {
1105 WND *pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
1106 lpDrop->pFiles = sizeof(DROPFILES);
1107 lpDrop->pt.x = x;
1108 lpDrop->pt.y = y;
1109 lpDrop->fNC =
1110 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1111 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1112 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1113 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1114 lpDrop->fWide = FALSE;
1115 WIN_ReleaseWndPtr(pDropWnd);
1116 p_drop = (char *)(lpDrop + 1);
1117 p = p_data;
1118 while(*p)
1119 {
1120 if( *p != -1 ) /* use only "good" entries */
1121 {
1122 GetShortPathNameA( p, p_drop, 65535 );
1123 p_drop += strlen( p_drop ) + 1;
1124 }
1125 p += strlen(p) + 1;
1126 }
1127 *p_drop = '\0';
1128 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1129 }
1130 }
1131 }
1132 if( p_data ) TSXFree(p_data);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001133}
1134
1135/**********************************************************************
1136 * EVENT_DropURLs
1137 *
Vincent Béron9a624912002-05-31 23:06:46 +00001138 * drop items are separated by \n
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001139 * each item is prefixed by its mime type
1140 *
1141 * event->data.l[3], event->data.l[4] contains drop x,y position
1142 */
Francois Boisverte5811f01999-04-15 15:22:23 +00001143static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001144{
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001145 unsigned long data_length;
1146 unsigned long aux_long, drop_len = 0;
1147 unsigned char *p_data = NULL; /* property data */
1148 char *p_drop = NULL;
1149 char *p, *next;
Alexandre Julliard60e17522000-09-25 23:56:41 +00001150 int x, y;
1151 DROPFILES *lpDrop;
1152 HDROP hDrop;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001153 union {
1154 Atom atom_aux;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001155 int i;
1156 Window w_aux;
1157 } u; /* unused */
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001158
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001159 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001160
Alexandre Julliard43230042001-05-16 19:52:29 +00001161 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001162 dndSelection, 0, 65535, FALSE,
1163 AnyPropertyType, &u.atom_aux, &u.i,
1164 &data_length, &aux_long, &p_data);
1165 if (aux_long)
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001166 WARN("property too large, truncated!\n");
1167 TRACE("urls=%s\n", p_data);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001168
1169 if( !aux_long && p_data) { /* don't bother if > 64K */
1170 /* calculate length */
1171 p = p_data;
1172 next = strchr(p, '\n');
1173 while (p) {
1174 if (next) *next=0;
1175 if (strncmp(p,"file:",5) == 0 ) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001176 INT len = GetShortPathNameA( p+5, NULL, 0 );
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001177 if (len) drop_len += len + 1;
1178 }
Vincent Béron9a624912002-05-31 23:06:46 +00001179 if (next) {
1180 *next = '\n';
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001181 p = next + 1;
1182 next = strchr(p, '\n');
1183 } else {
1184 p = NULL;
1185 }
1186 }
Vincent Béron9a624912002-05-31 23:06:46 +00001187
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001188 if( drop_len && drop_len < 65535 ) {
Alexandre Julliard43230042001-05-16 19:52:29 +00001189 TSXQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001190 &x, &y, &u.i, &u.i, &u.i);
Francois Boisverte5811f01999-04-15 15:22:23 +00001191
Alexandre Julliard60e17522000-09-25 23:56:41 +00001192 drop_len += sizeof(DROPFILES) + 1;
François Gougetdea3d782001-01-02 21:00:46 +00001193 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
Alexandre Julliard60e17522000-09-25 23:56:41 +00001194 lpDrop = (DROPFILES *) GlobalLock( hDrop );
1195
1196 if( lpDrop ) {
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001197 WND *pDropWnd = WIN_FindWndPtr( hWnd );
Alexandre Julliard60e17522000-09-25 23:56:41 +00001198 lpDrop->pFiles = sizeof(DROPFILES);
1199 lpDrop->pt.x = (INT)x;
1200 lpDrop->pt.y = (INT)y;
1201 lpDrop->fNC =
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001202 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1203 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1204 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1205 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
Alexandre Julliard60e17522000-09-25 23:56:41 +00001206 lpDrop->fWide = FALSE;
1207 p_drop = (char*)(lpDrop + 1);
Alexandre Julliardfb0ff052001-10-16 21:58:58 +00001208 WIN_ReleaseWndPtr(pDropWnd);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001209 }
Alexandre Julliard60e17522000-09-25 23:56:41 +00001210
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001211 /* create message content */
1212 if (p_drop) {
1213 p = p_data;
1214 next = strchr(p, '\n');
1215 while (p) {
1216 if (next) *next=0;
1217 if (strncmp(p,"file:",5) == 0 ) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001218 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001219 if (len) {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001220 TRACE("drop file %s as %s\n", p+5, p_drop);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001221 p_drop += len+1;
1222 } else {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001223 WARN("can't convert file %s to dos name \n", p+5);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001224 }
1225 } else {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001226 WARN("unknown mime type %s\n", p);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001227 }
Vincent Béron9a624912002-05-31 23:06:46 +00001228 if (next) {
1229 *next = '\n';
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001230 p = next + 1;
1231 next = strchr(p, '\n');
1232 } else {
1233 p = NULL;
1234 }
1235 *p_drop = '\0';
1236 }
1237
Alexandre Julliard60e17522000-09-25 23:56:41 +00001238 GlobalUnlock(hDrop);
François Gougetdea3d782001-01-02 21:00:46 +00001239 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001240 }
1241 }
Vincent Béron9a624912002-05-31 23:06:46 +00001242 if( p_data ) TSXFree(p_data);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001243 }
1244}
1245
1246/**********************************************************************
1247 * EVENT_ClientMessage
1248 */
Francois Boisverte5811f01999-04-15 15:22:23 +00001249static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001250{
1251 if (event->message_type != None && event->format == 32) {
Vincent Béron9a624912002-05-31 23:06:46 +00001252 if ((event->message_type == wmProtocols) &&
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001253 (((Atom) event->data.l[0]) == wmDeleteWindow))
Noel Borthwicka0d03ef1999-04-18 09:21:01 +00001254 {
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001255 /* Ignore the delete window request if the window has been disabled */
1256 if (!(GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED))
1257 PostMessageA( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
Noel Borthwicka0d03ef1999-04-18 09:21:01 +00001258 }
Alexandre Julliarddc4fe772001-06-04 21:55:17 +00001259 else if (event->message_type == dndProtocol)
1260 {
1261 /* query window (drag&drop event contains only drag window) */
1262 Window root, child;
1263 int root_x, root_y, child_x, child_y;
1264 unsigned int u;
1265 TSXQueryPointer( event->display, root_window, &root, &child,
1266 &root_x, &root_y, &child_x, &child_y, &u);
1267 if (TSXFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) return;
1268 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
1269 EVENT_DropFromOffiX(hWnd, event);
1270 else if (event->data.l[0] == DndURL)
1271 EVENT_DropURLs(hWnd, event);
1272 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001273 else {
1274#if 0
1275 /* enable this if you want to see the message */
1276 unsigned char* p_data = NULL;
1277 union {
1278 unsigned long l;
1279 int i;
1280 Atom atom;
1281 } u; /* unused */
Alexandre Julliard43230042001-05-16 19:52:29 +00001282 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001283 dndSelection, 0, 65535, FALSE,
1284 AnyPropertyType, &u.atom, &u.i,
1285 &u.l, &u.l, &p_data);
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001286 TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
Vincent Béron9a624912002-05-31 23:06:46 +00001287 event->message_type, event->data.l[0], event->data.l[1],
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001288 event->data.l[2], event->data.l[3], event->data.l[4],
1289 p_data);
1290#endif
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001291 TRACE("unrecognized ClientMessage\n" );
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001292 }
1293 }
1294}
1295
Alex Korobka44a1b591999-04-01 12:03:52 +00001296
Lionel Ulmeracc74671999-11-07 21:25:57 +00001297/**********************************************************************
Marcus Meissner35870f92000-04-14 14:09:50 +00001298 * X11DRV_EVENT_SetInputMethod
Lionel Ulmeracc74671999-11-07 21:25:57 +00001299 */
Marcus Meissner35870f92000-04-14 14:09:50 +00001300INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
Lionel Ulmeracc74671999-11-07 21:25:57 +00001301{
1302 INPUT_TYPE prev = current_input_type;
1303
1304 /* Flag not used yet */
1305 in_transition = FALSE;
1306 current_input_type = type;
1307
1308 return prev;
1309}
Alex Korobka44a1b591999-04-01 12:03:52 +00001310
Lionel Ulmer3ba4be41999-12-12 19:42:47 +00001311#ifdef HAVE_LIBXXF86DGA2
1312/**********************************************************************
1313 * X11DRV_EVENT_SetDGAStatus
1314 */
1315void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
1316{
1317 if (event_base < 0) {
1318 DGAUsed = FALSE;
1319 DGAhwnd = 0;
1320 } else {
1321 DGAUsed = TRUE;
1322 DGAhwnd = hwnd;
1323 DGAMotionEventType = event_base + MotionNotify;
1324 DGAButtonPressEventType = event_base + ButtonPress;
1325 DGAButtonReleaseEventType = event_base + ButtonRelease;
1326 DGAKeyPressEventType = event_base + KeyPress;
1327 DGAKeyReleaseEventType = event_base + KeyRelease;
1328 }
1329}
Lionel Ulmer3ba4be41999-12-12 19:42:47 +00001330#endif