Added internal Wine messages to perform SetWindowPos, ShowWindow and
[wine/multimedia.git] / windows / x11drv / event.c
blobe567a7c6854ede85f37fff99076acc922a9608c3
1 /*
2 * X11 event driver
4 * Copyright 1993 Alexandre Julliard
5 * 1999 Noel Borthwick
6 */
8 #include "config.h"
10 #include <X11/Xatom.h>
11 #include <X11/keysym.h>
13 #include "ts_xlib.h"
14 #include "ts_xresource.h"
15 #include "ts_xutil.h"
16 #ifdef HAVE_LIBXXF86DGA2
17 #include "ts_xf86dga2.h"
18 #endif
20 #include <assert.h>
21 #include <string.h>
22 #include "wine/winuser16.h"
23 #include "shlobj.h" /* DROPFILES */
25 #include "clipboard.h"
26 #include "dce.h"
27 #include "debugtools.h"
28 #include "input.h"
29 #include "keyboard.h"
30 #include "mouse.h"
31 #include "options.h"
32 #include "win.h"
33 #include "winpos.h"
34 #include "windef.h"
35 #include "winreg.h"
36 #include "x11drv.h"
37 #include "shellapi.h"
39 DEFAULT_DEBUG_CHANNEL(event);
40 DECLARE_DEBUG_CHANNEL(win);
42 /* X context to associate a hwnd to an X window */
43 extern XContext winContext;
45 extern Atom wmProtocols;
46 extern Atom wmDeleteWindow;
47 extern Atom dndProtocol;
48 extern Atom dndSelection;
50 extern void X11DRV_KEYBOARD_UpdateState(void);
51 extern void X11DRV_KEYBOARD_HandleEvent( XKeyEvent *event, int x, int y );
53 #define NB_BUTTONS 5 /* Windows can handle 3 buttons and the wheel too */
56 #define DndNotDnd -1 /* OffiX drag&drop */
57 #define DndUnknown 0
58 #define DndRawData 1
59 #define DndFile 2
60 #define DndFiles 3
61 #define DndText 4
62 #define DndDir 5
63 #define DndLink 6
64 #define DndExe 7
66 #define DndEND 8
68 #define DndURL 128 /* KDE drag&drop */
70 /* The last X window which had the focus */
71 static Window glastXFocusWin = 0;
73 static const char * const event_names[] =
75 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
76 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
77 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
78 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
79 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
80 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
81 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
82 "ClientMessage", "MappingNotify"
86 static void EVENT_ProcessEvent( XEvent *event );
87 static BOOL X11DRV_CheckFocus(void);
89 /* Event handlers */
90 static void EVENT_Key( HWND hWnd, XKeyEvent *event );
91 static void EVENT_ButtonPress( HWND hWnd, XButtonEvent *event );
92 static void EVENT_ButtonRelease( HWND hWnd, XButtonEvent *event );
93 static void EVENT_MotionNotify( HWND hWnd, XMotionEvent *event );
94 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
95 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
96 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
97 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
98 static void EVENT_PropertyNotify( XPropertyEvent *event );
99 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
100 static void EVENT_MappingNotify( XMappingEvent *event );
102 extern void X11DRV_Expose( HWND hwnd, XExposeEvent *event );
103 extern void X11DRV_MapNotify( HWND hwnd, XMapEvent *event );
104 extern void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event );
105 extern void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
107 #ifdef HAVE_LIBXXF86DGA2
108 static int DGAMotionEventType;
109 static int DGAButtonPressEventType;
110 static int DGAButtonReleaseEventType;
111 static int DGAKeyPressEventType;
112 static int DGAKeyReleaseEventType;
114 static BOOL DGAUsed = FALSE;
115 static HWND DGAhwnd = 0;
117 static void EVENT_DGAMotionEvent( XDGAMotionEvent *event );
118 static void EVENT_DGAButtonPressEvent( XDGAButtonEvent *event );
119 static void EVENT_DGAButtonReleaseEvent( XDGAButtonEvent *event );
120 #endif
122 /* Static used for the current input method */
123 static INPUT_TYPE current_input_type = X11DRV_INPUT_ABSOLUTE;
124 static BOOL in_transition = FALSE; /* This is not used as for today */
127 /***********************************************************************
128 * process_events
130 static int process_events( struct x11drv_thread_data *data )
132 XEvent event;
133 int count = 0;
135 wine_tsx11_lock();
136 while ( XPending( data->display ) )
138 XNextEvent( data->display, &event );
139 wine_tsx11_unlock();
140 EVENT_ProcessEvent( &event );
141 count++;
142 wine_tsx11_lock();
144 wine_tsx11_unlock();
145 return count;
149 /***********************************************************************
150 * MsgWaitForMultipleObjectsEx (X11DRV.@)
152 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
153 DWORD timeout, DWORD mask, DWORD flags )
155 HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1]; /* FIXME! */
156 DWORD i, ret;
157 struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
159 if (!data || data->process_event_count)
160 return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
161 timeout, flags & MWMO_ALERTABLE );
163 for (i = 0; i < count; i++) new_handles[i] = handles[i];
164 new_handles[count] = data->display_fd;
166 wine_tsx11_lock();
167 XFlush( gdi_display );
168 XFlush( data->display );
169 wine_tsx11_unlock();
171 data->process_event_count++;
172 if (process_events( data )) ret = count;
173 else
175 ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
176 timeout, flags & MWMO_ALERTABLE );
177 if (ret == count) process_events( data );
179 data->process_event_count--;
180 return ret;
184 /***********************************************************************
185 * EVENT_ProcessEvent
187 * Process an X event.
189 static void EVENT_ProcessEvent( XEvent *event )
191 HWND hWnd;
192 Display *display = event->xany.display;
194 TRACE( "called.\n" );
196 switch (event->type)
198 case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
199 FIXME("Got SelectionNotify - must not happen!\n");
200 /* fall through */
202 /* We get all these because of StructureNotifyMask.
203 This check is placed here to avoid getting error messages below,
204 as X might send some of these even for windows that have already
205 been deleted ... */
206 case CirculateNotify:
207 case CreateNotify:
208 case DestroyNotify:
209 case GravityNotify:
210 case ReparentNotify:
211 return;
214 #ifdef HAVE_LIBXXF86DGA2
215 if (DGAUsed) {
216 if (event->type == DGAMotionEventType) {
217 TRACE("DGAMotionEvent received.\n");
218 EVENT_DGAMotionEvent((XDGAMotionEvent *) event);
219 return;
221 if (event->type == DGAButtonPressEventType) {
222 TRACE("DGAButtonPressEvent received.\n");
223 EVENT_DGAButtonPressEvent((XDGAButtonEvent *) event);
224 return;
226 if (event->type == DGAButtonReleaseEventType) {
227 TRACE("DGAButtonReleaseEvent received.\n");
228 EVENT_DGAButtonReleaseEvent((XDGAButtonEvent *) event);
229 return;
231 if ((event->type == DGAKeyPressEventType) ||
232 (event->type == DGAKeyReleaseEventType)) {
233 /* Fill a XKeyEvent to send to EVENT_Key */
234 POINT pt;
235 XKeyEvent ke;
236 XDGAKeyEvent *evt = (XDGAKeyEvent *) event;
238 TRACE("DGAKeyPress/ReleaseEvent received.\n");
240 GetCursorPos( &pt );
241 if (evt->type == DGAKeyReleaseEventType)
242 ke.type = KeyRelease;
243 else
244 ke.type = KeyPress;
245 ke.serial = evt->serial;
246 ke.send_event = FALSE;
247 ke.display = evt->display;
248 ke.window = 0;
249 ke.root = 0;
250 ke.subwindow = 0;
251 ke.time = evt->time;
252 ke.x = pt.x;
253 ke.y = pt.y;
254 ke.x_root = -1;
255 ke.y_root = -1;
256 ke.state = evt->state;
257 ke.keycode = evt->keycode;
258 ke.same_screen = TRUE;
260 X11DRV_KEYBOARD_HandleEvent(&ke,pt.x,pt.y);
261 return;
264 #endif
266 if (TSXFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
267 hWnd = 0; /* Not for a registered window */
269 if ( !hWnd && event->xany.window != root_window
270 && event->type != PropertyNotify
271 && event->type != MappingNotify)
272 WARN( "Got event %s for unknown Window %08lx\n",
273 event_names[event->type], event->xany.window );
274 else
275 TRACE("Got event %s for hwnd %04x\n",
276 event_names[event->type], hWnd );
278 switch(event->type)
280 case KeyPress:
281 case KeyRelease:
282 EVENT_Key( hWnd, (XKeyEvent*)event );
283 break;
285 case ButtonPress:
286 EVENT_ButtonPress( hWnd, (XButtonEvent*)event );
287 break;
289 case ButtonRelease:
290 EVENT_ButtonRelease( hWnd, (XButtonEvent*)event );
291 break;
293 case MotionNotify:
294 EVENT_MotionNotify( hWnd, (XMotionEvent*)event );
295 break;
297 case FocusIn:
298 EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
299 break;
301 case FocusOut:
302 EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
303 break;
305 case Expose:
306 X11DRV_Expose( hWnd, &event->xexpose );
307 break;
309 case ConfigureNotify:
310 if (!hWnd) return;
311 X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
312 break;
314 case SelectionRequest:
315 if (!hWnd) return;
316 EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
317 break;
319 case SelectionClear:
320 if (!hWnd) return;
321 EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
322 break;
324 case PropertyNotify:
325 EVENT_PropertyNotify( (XPropertyEvent *)event );
326 break;
328 case ClientMessage:
329 if (!hWnd) return;
330 EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
331 break;
333 case NoExpose:
334 break;
336 case MapNotify:
337 X11DRV_MapNotify( hWnd, (XMapEvent *)event );
338 break;
340 case UnmapNotify:
341 X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
342 break;
344 case MappingNotify:
345 EVENT_MappingNotify( (XMappingEvent *) event );
346 break;
348 default:
349 WARN("Unprocessed event %s for hwnd %04x\n",
350 event_names[event->type], hWnd );
351 break;
353 TRACE( "returns.\n" );
356 /***********************************************************************
357 * X11DRV_EVENT_XStateToKeyState
359 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
360 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
362 WORD X11DRV_EVENT_XStateToKeyState( int state )
364 int kstate = 0;
366 if (state & Button1Mask) kstate |= MK_LBUTTON;
367 if (state & Button2Mask) kstate |= MK_MBUTTON;
368 if (state & Button3Mask) kstate |= MK_RBUTTON;
369 if (state & ShiftMask) kstate |= MK_SHIFT;
370 if (state & ControlMask) kstate |= MK_CONTROL;
371 return kstate;
375 /* get the coordinates of a mouse event */
376 static void get_coords( HWND *hwnd, Window window, int x, int y, POINT *pt )
378 struct x11drv_win_data *data;
379 WND *win;
381 if (!(win = WIN_FindWndPtr( *hwnd ))) return;
382 data = win->pDriverData;
384 if (window == data->whole_window)
386 x -= data->client_rect.left;
387 y -= data->client_rect.top;
389 WIN_ReleaseWndPtr( win );
391 pt->x = x;
392 pt->y = y;
393 if (*hwnd != GetDesktopWindow())
395 ClientToScreen( *hwnd, pt );
396 *hwnd = GetAncestor( *hwnd, GA_ROOT );
401 /***********************************************************************
402 * EVENT_Key
404 * Handle a X key event
406 static void EVENT_Key( HWND hWnd, XKeyEvent *event )
408 POINT pt;
409 get_coords( &hWnd, event->window, event->x, event->y, &pt );
410 X11DRV_KEYBOARD_HandleEvent( event, pt.x, pt.y );
414 /***********************************************************************
415 * EVENT_MotionNotify
417 static void EVENT_MotionNotify( HWND hWnd, XMotionEvent *event )
419 POINT pt;
421 if (current_input_type == X11DRV_INPUT_ABSOLUTE)
423 get_coords( &hWnd, event->window, event->x, event->y, &pt );
424 X11DRV_SendEvent( MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, pt.x, pt.y,
425 X11DRV_EVENT_XStateToKeyState( event->state ), 0,
426 event->time - X11DRV_server_startticks, hWnd);
428 else
430 X11DRV_SendEvent( MOUSEEVENTF_MOVE,
431 event->x_root, event->y_root,
432 X11DRV_EVENT_XStateToKeyState( event->state ), 0,
433 event->time - X11DRV_server_startticks, hWnd);
438 /***********************************************************************
439 * EVENT_ButtonPress
441 static void EVENT_ButtonPress( HWND hWnd, XButtonEvent *event )
443 static const WORD statusCodes[NB_BUTTONS] = { MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_MIDDLEDOWN,
444 MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_WHEEL,
445 MOUSEEVENTF_WHEEL};
446 int buttonNum = event->button - 1;
447 WORD keystate, wData = 0;
448 POINT pt;
450 if (buttonNum >= NB_BUTTONS) return;
452 get_coords( &hWnd, event->window, event->x, event->y, &pt );
454 /* Get the compatible keystate */
455 keystate = X11DRV_EVENT_XStateToKeyState( event->state );
458 * Make sure that the state of the button that was just
459 * pressed is "down".
461 switch (buttonNum)
463 case 0:
464 keystate |= MK_LBUTTON;
465 break;
466 case 1:
467 keystate |= MK_MBUTTON;
468 break;
469 case 2:
470 keystate |= MK_RBUTTON;
471 break;
472 case 3:
473 wData = WHEEL_DELTA;
474 break;
475 case 4:
476 wData = -WHEEL_DELTA;
477 break;
480 X11DRV_SendEvent( statusCodes[buttonNum] | MOUSEEVENTF_ABSOLUTE, pt.x, pt.y,
481 keystate, wData, event->time - X11DRV_server_startticks, hWnd);
485 /***********************************************************************
486 * EVENT_ButtonRelease
488 static void EVENT_ButtonRelease( HWND hWnd, XButtonEvent *event )
490 static const WORD statusCodes[NB_BUTTONS] = { MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEUP,
491 MOUSEEVENTF_RIGHTUP, 0, 0 };
492 int buttonNum = event->button - 1;
493 WORD keystate;
494 POINT pt;
496 if (buttonNum >= NB_BUTTONS) return;
498 get_coords( &hWnd, event->window, event->x, event->y, &pt );
500 /* Get the compatible keystate */
501 keystate = X11DRV_EVENT_XStateToKeyState( event->state );
504 * Make sure that the state of the button that was just
505 * released is "up".
507 switch (buttonNum)
509 case 0:
510 keystate &= ~MK_LBUTTON;
511 break;
512 case 1:
513 keystate &= ~MK_MBUTTON;
514 break;
515 case 2:
516 keystate &= ~MK_RBUTTON;
517 break;
518 default:
519 return;
521 X11DRV_SendEvent( statusCodes[buttonNum] | MOUSEEVENTF_ABSOLUTE, pt.x, pt.y,
522 keystate, 0, event->time - X11DRV_server_startticks, hWnd);
526 /**********************************************************************
527 * EVENT_FocusIn
529 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event )
531 WND *pWndLastFocus;
532 XWindowAttributes win_attr;
533 BOOL bIsDisabled;
535 if (!hWnd) return;
537 bIsDisabled = GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED;
539 /* If the window has been disabled and we are in managed mode,
540 * revert the X focus back to the last focus window. This is to disallow
541 * the window manager from switching focus away while the app is
542 * in a modal state.
544 if ( Options.managed && bIsDisabled && glastXFocusWin)
546 /* Change focus only if saved focus window is registered and viewable */
547 wine_tsx11_lock();
548 if (XFindContext( event->display, glastXFocusWin, winContext,
549 (char **)&pWndLastFocus ) == 0 )
551 if (XGetWindowAttributes( event->display, glastXFocusWin, &win_attr ) &&
552 (win_attr.map_state == IsViewable) )
554 XSetInputFocus( event->display, glastXFocusWin, RevertToParent, CurrentTime );
555 wine_tsx11_unlock();
556 return;
559 wine_tsx11_unlock();
562 if (event->detail != NotifyPointer && hWnd != GetForegroundWindow())
564 SetForegroundWindow( hWnd );
565 X11DRV_KEYBOARD_UpdateState();
570 /**********************************************************************
571 * EVENT_FocusOut
573 * Note: only top-level override-redirect windows get FocusOut events.
575 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event )
577 /* Save the last window which had the focus */
578 glastXFocusWin = event->window;
579 if (!hWnd) return;
580 if (GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED) glastXFocusWin = 0;
582 if (event->detail != NotifyPointer && hWnd == GetForegroundWindow())
584 /* don't reset the foreground window, if the window which is
585 getting the focus is a Wine window */
586 if (!X11DRV_CheckFocus())
588 SendMessageA( hWnd, WM_CANCELMODE, 0, 0 );
589 /* Abey : 6-Oct-99. Check again if the focus out window is the
590 Foreground window, because in most cases the messages sent
591 above must have already changed the foreground window, in which
592 case we don't have to change the foreground window to 0 */
594 if (hWnd == GetForegroundWindow())
595 SetForegroundWindow( 0 );
600 /**********************************************************************
601 * CheckFocus (X11DRV.@)
603 static BOOL X11DRV_CheckFocus(void)
605 Display *display = thread_display();
606 HWND hWnd;
607 Window xW;
608 int state;
610 TSXGetInputFocus(display, &xW, &state);
611 if( xW == None ||
612 TSXFindContext(display, xW, winContext, (char **)&hWnd) )
613 return FALSE;
614 return TRUE;
618 /***********************************************************************
619 * EVENT_SelectionRequest_TARGETS
620 * Service a TARGETS selection request event
622 static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
623 Atom target, Atom rprop )
625 Atom xaTargets = TSXInternAtom(display, "TARGETS", False);
626 Atom* targets;
627 Atom prop;
628 UINT wFormat;
629 unsigned long cTargets;
630 BOOL bHavePixmap;
631 int xRc;
633 TRACE("Request for %s\n", TSXGetAtomName(display, target));
636 * Count the number of items we wish to expose as selection targets.
637 * We include the TARGETS item, and a PIXMAP if we have CF_DIB or CF_BITMAP
639 cTargets = CountClipboardFormats() + 1;
640 if ( CLIPBOARD_IsPresent(CF_DIB) || CLIPBOARD_IsPresent(CF_BITMAP) )
641 cTargets++;
643 /* Allocate temp buffer */
644 targets = (Atom*)HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
645 if(targets == NULL) return None;
647 /* Create TARGETS property list (First item in list is TARGETS itself) */
649 for ( targets[0] = xaTargets, cTargets = 1, wFormat = 0, bHavePixmap = FALSE;
650 (wFormat = EnumClipboardFormats( wFormat )); )
652 if ( (prop = X11DRV_CLIPBOARD_MapFormatToProperty(wFormat)) != None )
654 /* Scan through what we have so far to avoid duplicates */
655 int i;
656 BOOL bExists;
657 for (i = 0, bExists = FALSE; i < cTargets; i++)
659 if (targets[i] == prop)
661 bExists = TRUE;
662 break;
665 if (!bExists)
667 targets[cTargets++] = prop;
669 /* Add PIXMAP prop for bitmaps additionally */
670 if ( (wFormat == CF_DIB || wFormat == CF_BITMAP )
671 && !bHavePixmap )
673 targets[cTargets++] = XA_PIXMAP;
674 bHavePixmap = TRUE;
680 if (TRACE_ON(event))
682 int i;
683 for ( i = 0; i < cTargets; i++)
685 if (targets[i])
687 char *itemFmtName = TSXGetAtomName(display, targets[i]);
688 TRACE("\tAtom# %d: Type %s\n", i, itemFmtName);
689 TSXFree(itemFmtName);
694 /* Update the X property */
695 TRACE("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
697 /* We may want to consider setting the type to xaTargets instead,
698 * in case some apps expect this instead of XA_ATOM */
699 xRc = TSXChangeProperty(display, requestor, rprop,
700 XA_ATOM, 32, PropModeReplace,
701 (unsigned char *)targets, cTargets);
702 TRACE("(Rc=%d)\n", xRc);
704 HeapFree( GetProcessHeap(), 0, targets );
706 return rprop;
710 /***********************************************************************
711 * EVENT_SelectionRequest_STRING
712 * Service a STRING selection request event
714 static Atom EVENT_SelectionRequest_STRING( Display *display, Window requestor,
715 Atom target, Atom rprop )
717 static UINT text_cp = (UINT)-1;
718 HANDLE hUnicodeText;
719 LPWSTR uni_text;
720 LPSTR text;
721 int size,i,j;
722 char* lpstr = 0;
723 char *itemFmtName;
724 int xRc;
726 if(text_cp == (UINT)-1)
728 HKEY hkey;
729 /* default value */
730 text_cp = CP_ACP;
731 if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\x11drv", &hkey))
733 char buf[20];
734 DWORD type, count = sizeof(buf);
735 if(!RegQueryValueExA(hkey, "TextCP", 0, &type, buf, &count))
736 text_cp = atoi(buf);
737 RegCloseKey(hkey);
742 * Map the requested X selection property type atom name to a
743 * windows clipboard format ID.
745 itemFmtName = TSXGetAtomName(display, target);
746 TRACE("Request for %s (wFormat=%x %s)\n",
747 itemFmtName, CF_UNICODETEXT, CLIPBOARD_GetFormatName(CF_UNICODETEXT));
748 TSXFree(itemFmtName);
750 hUnicodeText = GetClipboardData(CF_UNICODETEXT);
751 if(!hUnicodeText)
752 return None;
753 uni_text = GlobalLock(hUnicodeText);
754 if(!uni_text)
755 return None;
757 size = WideCharToMultiByte(text_cp, 0, uni_text, -1, NULL, 0, NULL, NULL);
758 text = HeapAlloc(GetProcessHeap(), 0, size);
759 if (!text)
760 return None;
761 WideCharToMultiByte(text_cp, 0, uni_text, -1, text, size, NULL, NULL);
763 /* remove carriage returns */
765 lpstr = (char*)HeapAlloc( GetProcessHeap(), 0, size-- );
766 if(lpstr == NULL) return None;
767 for(i=0,j=0; i < size && text[i]; i++ )
769 if( text[i] == '\r' &&
770 (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
771 lpstr[j++] = text[i];
773 lpstr[j]='\0';
775 /* Update the X property */
776 TRACE("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
777 xRc = TSXChangeProperty(display, requestor, rprop,
778 XA_STRING, 8, PropModeReplace,
779 lpstr, j);
780 TRACE("(Rc=%d)\n", xRc);
782 GlobalUnlock(hUnicodeText);
783 HeapFree(GetProcessHeap(), 0, text);
784 HeapFree( GetProcessHeap(), 0, lpstr );
786 return rprop;
789 /***********************************************************************
790 * EVENT_SelectionRequest_PIXMAP
791 * Service a PIXMAP selection request event
793 static Atom EVENT_SelectionRequest_PIXMAP( Display *display, Window requestor,
794 Atom target, Atom rprop )
796 HANDLE hClipData = 0;
797 Pixmap pixmap = 0;
798 UINT wFormat;
799 char * itemFmtName;
800 int xRc;
801 #if(0)
802 XSetWindowAttributes win_attr;
803 XWindowAttributes win_attr_src;
804 #endif
807 * Map the requested X selection property type atom name to a
808 * windows clipboard format ID.
810 itemFmtName = TSXGetAtomName(display, target);
811 wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
812 TRACE("Request for %s (wFormat=%x %s)\n",
813 itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat));
814 TSXFree(itemFmtName);
816 hClipData = GetClipboardData(wFormat);
817 if ( !hClipData )
819 TRACE("Could not retrieve a Pixmap compatible format from clipboard!\n");
820 rprop = None; /* Fail the request */
821 goto END;
824 if (wFormat == CF_DIB)
826 HWND hwnd = GetOpenClipboardWindow();
827 HDC hdc = GetDC(hwnd);
829 /* For convert from packed DIB to Pixmap */
830 pixmap = X11DRV_DIB_CreatePixmapFromDIB(hClipData, hdc);
832 ReleaseDC(hwnd, hdc);
834 else if (wFormat == CF_BITMAP)
836 HWND hwnd = GetOpenClipboardWindow();
837 HDC hdc = GetDC(hwnd);
839 pixmap = X11DRV_BITMAP_CreatePixmapFromBitmap(hClipData, hdc);
841 ReleaseDC(hwnd, hdc);
843 else
845 FIXME("%s to PIXMAP conversion not yet implemented!\n",
846 CLIPBOARD_GetFormatName(wFormat));
847 rprop = None;
848 goto END;
851 TRACE("\tUpdating property %s on Window %ld with %s %ld...\n",
852 TSXGetAtomName(display, rprop), (long)requestor,
853 TSXGetAtomName(display, target), pixmap);
855 /* Store the Pixmap handle in the property */
856 xRc = TSXChangeProperty(display, requestor, rprop, target,
857 32, PropModeReplace,
858 (unsigned char *)&pixmap, 1);
859 TRACE("(Rc=%d)\n", xRc);
861 /* Enable the code below if you want to handle destroying Pixmap resources
862 * in response to property notify events. Clients like XPaint don't
863 * appear to be duplicating Pixmaps so they don't like us deleting,
864 * the resource in response to the property being deleted.
866 #if(0)
867 /* Express interest in property notify events so that we can delete the
868 * pixmap when the client deletes the property atom.
870 xRc = TSXGetWindowAttributes(display, requestor, &win_attr_src);
871 TRACE("Turning on PropertyChangeEvent notifications from window %ld\n",
872 (long)requestor);
873 win_attr.event_mask = win_attr_src.your_event_mask | PropertyChangeMask;
874 TSXChangeWindowAttributes(display, requestor, CWEventMask, &win_attr);
876 /* Register the Pixmap we created with the request property Atom.
877 * When this property is destroyed we also destroy the Pixmap in
878 * response to the PropertyNotify event.
880 X11DRV_CLIPBOARD_RegisterPixmapResource( rprop, pixmap );
881 #endif
883 END:
884 return rprop;
888 /***********************************************************************
889 * EVENT_SelectionRequest_WCF
890 * Service a Wine Clipboard Format selection request event.
891 * For <WCF>* data types we simply copy the data to X without conversion.
893 static Atom EVENT_SelectionRequest_WCF( Display *display, Window requestor,
894 Atom target, Atom rprop )
896 HANDLE hClipData = 0;
897 void* lpClipData;
898 UINT wFormat;
899 char * itemFmtName;
900 int cBytes;
901 int xRc;
904 * Map the requested X selection property type atom name to a
905 * windows clipboard format ID.
907 itemFmtName = TSXGetAtomName(display, target);
908 wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
909 TRACE("Request for %s (wFormat=%x %s)\n",
910 itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat));
911 TSXFree(itemFmtName);
913 hClipData = GetClipboardData(wFormat);
915 if( hClipData && (lpClipData = GlobalLock(hClipData)) )
917 cBytes = GlobalSize(hClipData);
919 TRACE("\tUpdating property %s, %d bytes...\n",
920 TSXGetAtomName(display, rprop), cBytes);
922 xRc = TSXChangeProperty(display, requestor, rprop,
923 target, 8, PropModeReplace,
924 (unsigned char *)lpClipData, cBytes);
925 TRACE("(Rc=%d)\n", xRc);
927 GlobalUnlock(hClipData);
929 else
931 TRACE("\tCould not retrieve native format!\n");
932 rprop = None; /* Fail the request */
935 return rprop;
939 /***********************************************************************
940 * EVENT_SelectionRequest_MULTIPLE
941 * Service a MULTIPLE selection request event
942 * rprop contains a list of (target,property) atom pairs.
943 * The first atom names a target and the second names a property.
944 * The effect is as if we have received a sequence of SelectionRequest events
945 * (one for each atom pair) except that:
946 * 1. We reply with a SelectionNotify only when all the requested conversions
947 * have been performed.
948 * 2. If we fail to convert the target named by an atom in the MULTIPLE property,
949 * we replace the atom in the property by None.
951 static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
953 Display *display = pevent->display;
954 Atom rprop;
955 Atom atype=AnyPropertyType;
956 int aformat;
957 unsigned long remain;
958 Atom* targetPropList=NULL;
959 unsigned long cTargetPropList = 0;
960 /* Atom xAtomPair = TSXInternAtom(display, "ATOM_PAIR", False); */
962 /* If the specified property is None the requestor is an obsolete client.
963 * We support these by using the specified target atom as the reply property.
965 rprop = pevent->property;
966 if( rprop == None )
967 rprop = pevent->target;
968 if (!rprop)
969 goto END;
971 /* Read the MULTIPLE property contents. This should contain a list of
972 * (target,property) atom pairs.
974 if(TSXGetWindowProperty(display, pevent->requestor, rprop,
975 0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
976 &cTargetPropList, &remain,
977 (unsigned char**)&targetPropList) != Success)
978 TRACE("\tCouldn't read MULTIPLE property\n");
979 else
981 TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
982 TSXGetAtomName(display, atype), aformat, cTargetPropList, remain);
985 * Make sure we got what we expect.
986 * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
987 * in a MULTIPLE selection request should be of type ATOM_PAIR.
988 * However some X apps(such as XPaint) are not compliant with this and return
989 * a user defined atom in atype when XGetWindowProperty is called.
990 * The data *is* an atom pair but is not denoted as such.
992 if(aformat == 32 /* atype == xAtomPair */ )
994 int i;
996 /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
997 * for each (target,property) pair */
999 for (i = 0; i < cTargetPropList; i+=2)
1001 char *targetName = TSXGetAtomName(display, targetPropList[i]);
1002 char *propName = TSXGetAtomName(display, targetPropList[i+1]);
1003 XSelectionRequestEvent event;
1005 TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
1006 i/2, targetName, propName);
1007 TSXFree(targetName);
1008 TSXFree(propName);
1010 /* We must have a non "None" property to service a MULTIPLE target atom */
1011 if ( !targetPropList[i+1] )
1013 TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
1014 continue;
1017 /* Set up an XSelectionRequestEvent for this (target,property) pair */
1018 memcpy( &event, pevent, sizeof(XSelectionRequestEvent) );
1019 event.target = targetPropList[i];
1020 event.property = targetPropList[i+1];
1022 /* Fire a SelectionRequest, informing the handler that we are processing
1023 * a MULTIPLE selection request event.
1025 EVENT_SelectionRequest( hWnd, &event, TRUE );
1029 /* Free the list of targets/properties */
1030 TSXFree(targetPropList);
1033 END:
1034 return rprop;
1038 /***********************************************************************
1039 * EVENT_SelectionRequest
1040 * Process an event selection request event.
1041 * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
1042 * recursively while servicing a "MULTIPLE" selection target.
1044 * Note: We only receive this event when WINE owns the X selection
1046 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
1048 Display *display = event->display;
1049 XSelectionEvent result;
1050 Atom rprop = None;
1051 Window request = event->requestor;
1052 BOOL couldOpen = FALSE;
1053 Atom xaClipboard = TSXInternAtom(display, "CLIPBOARD", False);
1054 Atom xaTargets = TSXInternAtom(display, "TARGETS", False);
1055 Atom xaMultiple = TSXInternAtom(display, "MULTIPLE", False);
1058 * We can only handle the selection request if :
1059 * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
1060 * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
1061 * since this has been already done.
1063 if ( !bIsMultiple )
1065 if ( ( (event->selection != XA_PRIMARY) && (event->selection != xaClipboard) )
1066 || !(couldOpen = OpenClipboard(hWnd)) )
1067 goto END;
1070 /* If the specified property is None the requestor is an obsolete client.
1071 * We support these by using the specified target atom as the reply property.
1073 rprop = event->property;
1074 if( rprop == None )
1075 rprop = event->target;
1077 if(event->target == xaTargets) /* Return a list of all supported targets */
1079 /* TARGETS selection request */
1080 rprop = EVENT_SelectionRequest_TARGETS( display, request, event->target, rprop );
1082 else if(event->target == xaMultiple) /* rprop contains a list of (target, property) atom pairs */
1084 /* MULTIPLE selection request */
1085 rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
1087 else if(event->target == XA_STRING) /* treat CF_TEXT as Unix text */
1089 /* XA_STRING selection request */
1090 rprop = EVENT_SelectionRequest_STRING( display, request, event->target, rprop );
1092 else if(event->target == XA_PIXMAP) /* Convert DIB's to Pixmaps */
1094 /* XA_PIXMAP selection request */
1095 rprop = EVENT_SelectionRequest_PIXMAP( display, request, event->target, rprop );
1097 else if(event->target == XA_BITMAP) /* Convert DIB's to 1-bit Pixmaps */
1099 /* XA_BITMAP selection request - TODO: create a monochrome Pixmap */
1100 rprop = EVENT_SelectionRequest_PIXMAP( display, request, XA_PIXMAP, rprop );
1102 else if(X11DRV_CLIPBOARD_IsNativeProperty(event->target)) /* <WCF>* */
1104 /* All <WCF> selection requests */
1105 rprop = EVENT_SelectionRequest_WCF( display, request, event->target, rprop );
1107 else
1108 rprop = None; /* Don't support this format */
1110 END:
1111 /* close clipboard only if we opened before */
1112 if(couldOpen) CloseClipboard();
1114 if( rprop == None)
1115 TRACE("\tRequest ignored\n");
1117 /* reply to sender
1118 * SelectionNotify should be sent only at the end of a MULTIPLE request
1120 if ( !bIsMultiple )
1122 result.type = SelectionNotify;
1123 result.display = display;
1124 result.requestor = request;
1125 result.selection = event->selection;
1126 result.property = rprop;
1127 result.target = event->target;
1128 result.time = event->time;
1129 TRACE("Sending SelectionNotify event...\n");
1130 TSXSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
1134 /***********************************************************************
1135 * EVENT_SelectionClear
1137 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
1139 Atom xaClipboard = TSXInternAtom(event->display, "CLIPBOARD", False);
1141 if (event->selection == XA_PRIMARY || event->selection == xaClipboard)
1142 X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
1145 /***********************************************************************
1146 * EVENT_PropertyNotify
1147 * We use this to release resources like Pixmaps when a selection
1148 * client no longer needs them.
1150 static void EVENT_PropertyNotify( XPropertyEvent *event )
1152 /* Check if we have any resources to free */
1153 TRACE("Received PropertyNotify event: \n");
1155 switch(event->state)
1157 case PropertyDelete:
1159 TRACE("\tPropertyDelete for atom %s on window %ld\n",
1160 TSXGetAtomName(event->display, event->atom), (long)event->window);
1162 if (X11DRV_IsSelectionOwner())
1163 X11DRV_CLIPBOARD_FreeResources( event->atom );
1164 break;
1167 case PropertyNewValue:
1169 TRACE("\tPropertyNewValue for atom %s on window %ld\n\n",
1170 TSXGetAtomName(event->display, event->atom), (long)event->window);
1171 break;
1174 default:
1175 break;
1179 /**********************************************************************
1180 * EVENT_DropFromOffix
1182 * don't know if it still works (last Changlog is from 96/11/04)
1184 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
1186 unsigned long data_length;
1187 unsigned long aux_long;
1188 unsigned char* p_data = NULL;
1189 union {
1190 Atom atom_aux;
1191 struct {
1192 int x;
1193 int y;
1194 } pt_aux;
1195 int i;
1196 } u;
1197 int x, y;
1198 BOOL16 bAccept;
1199 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO16));
1200 LPDRAGINFO16 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
1201 SEGPTR spDragInfo = K32WOWGlobalLock16(hDragInfo);
1202 Window w_aux_root, w_aux_child;
1203 WND* pWnd;
1205 if( !lpDragInfo || !spDragInfo ) return;
1207 pWnd = WIN_FindWndPtr(hWnd);
1209 TSXQueryPointer( event->display, get_whole_window(pWnd), &w_aux_root, &w_aux_child,
1210 &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
1211 (unsigned int*)&aux_long);
1213 lpDragInfo->hScope = hWnd;
1214 lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y;
1216 /* find out drop point and drop window */
1217 if( x < 0 || y < 0 ||
1218 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1219 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1220 { bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
1221 else
1223 bAccept = DRAG_QueryUpdate( hWnd, spDragInfo, TRUE );
1224 x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
1226 WIN_ReleaseWndPtr(pWnd);
1228 GlobalFree16( hDragInfo );
1230 if (!bAccept) return;
1232 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1233 dndSelection, 0, 65535, FALSE,
1234 AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1235 &data_length, &aux_long, &p_data);
1237 if( !aux_long && p_data) /* don't bother if > 64K */
1239 signed char *p = (signed char*) p_data;
1240 char *p_drop;
1242 aux_long = 0;
1243 while( *p ) /* calculate buffer size */
1245 p_drop = p;
1246 if((u.i = *p) != -1 )
1248 INT len = GetShortPathNameA( p, NULL, 0 );
1249 if (len) aux_long += len + 1;
1250 else *p = -1;
1252 p += strlen(p) + 1;
1254 if( aux_long && aux_long < 65535 )
1256 HDROP hDrop;
1257 DROPFILES *lpDrop;
1259 aux_long += sizeof(DROPFILES) + 1;
1260 hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
1261 lpDrop = (DROPFILES*)GlobalLock( hDrop );
1263 if( lpDrop )
1265 WND *pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
1266 lpDrop->pFiles = sizeof(DROPFILES);
1267 lpDrop->pt.x = x;
1268 lpDrop->pt.y = y;
1269 lpDrop->fNC =
1270 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1271 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1272 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1273 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1274 lpDrop->fWide = FALSE;
1275 WIN_ReleaseWndPtr(pDropWnd);
1276 p_drop = (char *)(lpDrop + 1);
1277 p = p_data;
1278 while(*p)
1280 if( *p != -1 ) /* use only "good" entries */
1282 GetShortPathNameA( p, p_drop, 65535 );
1283 p_drop += strlen( p_drop ) + 1;
1285 p += strlen(p) + 1;
1287 *p_drop = '\0';
1288 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1292 if( p_data ) TSXFree(p_data);
1295 /**********************************************************************
1296 * EVENT_DropURLs
1298 * drop items are separated by \n
1299 * each item is prefixed by its mime type
1301 * event->data.l[3], event->data.l[4] contains drop x,y position
1303 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
1305 unsigned long data_length;
1306 unsigned long aux_long, drop_len = 0;
1307 unsigned char *p_data = NULL; /* property data */
1308 char *p_drop = NULL;
1309 char *p, *next;
1310 int x, y;
1311 DROPFILES *lpDrop;
1312 HDROP hDrop;
1313 union {
1314 Atom atom_aux;
1315 int i;
1316 Window w_aux;
1317 } u; /* unused */
1319 if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
1321 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1322 dndSelection, 0, 65535, FALSE,
1323 AnyPropertyType, &u.atom_aux, &u.i,
1324 &data_length, &aux_long, &p_data);
1325 if (aux_long)
1326 WARN("property too large, truncated!\n");
1327 TRACE("urls=%s\n", p_data);
1329 if( !aux_long && p_data) { /* don't bother if > 64K */
1330 /* calculate length */
1331 p = p_data;
1332 next = strchr(p, '\n');
1333 while (p) {
1334 if (next) *next=0;
1335 if (strncmp(p,"file:",5) == 0 ) {
1336 INT len = GetShortPathNameA( p+5, NULL, 0 );
1337 if (len) drop_len += len + 1;
1339 if (next) {
1340 *next = '\n';
1341 p = next + 1;
1342 next = strchr(p, '\n');
1343 } else {
1344 p = NULL;
1348 if( drop_len && drop_len < 65535 ) {
1349 TSXQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
1350 &x, &y, &u.i, &u.i, &u.i);
1352 drop_len += sizeof(DROPFILES) + 1;
1353 hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
1354 lpDrop = (DROPFILES *) GlobalLock( hDrop );
1356 if( lpDrop ) {
1357 WND *pDropWnd = WIN_FindWndPtr( hWnd );
1358 lpDrop->pFiles = sizeof(DROPFILES);
1359 lpDrop->pt.x = (INT)x;
1360 lpDrop->pt.y = (INT)y;
1361 lpDrop->fNC =
1362 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1363 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1364 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1365 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1366 lpDrop->fWide = FALSE;
1367 p_drop = (char*)(lpDrop + 1);
1368 WIN_ReleaseWndPtr(pDropWnd);
1371 /* create message content */
1372 if (p_drop) {
1373 p = p_data;
1374 next = strchr(p, '\n');
1375 while (p) {
1376 if (next) *next=0;
1377 if (strncmp(p,"file:",5) == 0 ) {
1378 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
1379 if (len) {
1380 TRACE("drop file %s as %s\n", p+5, p_drop);
1381 p_drop += len+1;
1382 } else {
1383 WARN("can't convert file %s to dos name \n", p+5);
1385 } else {
1386 WARN("unknown mime type %s\n", p);
1388 if (next) {
1389 *next = '\n';
1390 p = next + 1;
1391 next = strchr(p, '\n');
1392 } else {
1393 p = NULL;
1395 *p_drop = '\0';
1398 GlobalUnlock(hDrop);
1399 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1402 if( p_data ) TSXFree(p_data);
1406 /**********************************************************************
1407 * EVENT_ClientMessage
1409 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
1411 if (event->message_type != None && event->format == 32) {
1412 if ((event->message_type == wmProtocols) &&
1413 (((Atom) event->data.l[0]) == wmDeleteWindow))
1415 /* Ignore the delete window request if the window has been disabled */
1416 if (!(GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED))
1417 PostMessageA( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
1419 else if (event->message_type == dndProtocol)
1421 /* query window (drag&drop event contains only drag window) */
1422 Window root, child;
1423 int root_x, root_y, child_x, child_y;
1424 unsigned int u;
1425 TSXQueryPointer( event->display, root_window, &root, &child,
1426 &root_x, &root_y, &child_x, &child_y, &u);
1427 if (TSXFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) return;
1428 if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
1429 EVENT_DropFromOffiX(hWnd, event);
1430 else if (event->data.l[0] == DndURL)
1431 EVENT_DropURLs(hWnd, event);
1433 else {
1434 #if 0
1435 /* enable this if you want to see the message */
1436 unsigned char* p_data = NULL;
1437 union {
1438 unsigned long l;
1439 int i;
1440 Atom atom;
1441 } u; /* unused */
1442 TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1443 dndSelection, 0, 65535, FALSE,
1444 AnyPropertyType, &u.atom, &u.i,
1445 &u.l, &u.l, &p_data);
1446 TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1447 event->message_type, event->data.l[0], event->data.l[1],
1448 event->data.l[2], event->data.l[3], event->data.l[4],
1449 p_data);
1450 #endif
1451 TRACE("unrecognized ClientMessage\n" );
1457 /***********************************************************************
1458 * EVENT_MappingNotify
1460 static void EVENT_MappingNotify( XMappingEvent *event )
1462 TSXRefreshKeyboardMapping(event);
1464 /* reinitialize Wine-X11 driver keyboard table */
1465 X11DRV_InitKeyboard();
1469 /**********************************************************************
1470 * X11DRV_EVENT_SetInputMethod
1472 INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
1474 INPUT_TYPE prev = current_input_type;
1476 /* Flag not used yet */
1477 in_transition = FALSE;
1478 current_input_type = type;
1480 return prev;
1483 #ifdef HAVE_LIBXXF86DGA2
1484 /**********************************************************************
1485 * X11DRV_EVENT_SetDGAStatus
1487 void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
1489 if (event_base < 0) {
1490 DGAUsed = FALSE;
1491 DGAhwnd = 0;
1492 } else {
1493 DGAUsed = TRUE;
1494 DGAhwnd = hwnd;
1495 DGAMotionEventType = event_base + MotionNotify;
1496 DGAButtonPressEventType = event_base + ButtonPress;
1497 DGAButtonReleaseEventType = event_base + ButtonRelease;
1498 DGAKeyPressEventType = event_base + KeyPress;
1499 DGAKeyReleaseEventType = event_base + KeyRelease;
1503 /* DGA2 event handlers */
1504 static void EVENT_DGAMotionEvent( XDGAMotionEvent *event )
1506 X11DRV_SendEvent( MOUSEEVENTF_MOVE, event->dx, event->dy,
1507 X11DRV_EVENT_XStateToKeyState( event->state ), 0,
1508 event->time - X11DRV_server_startticks, DGAhwnd );
1511 static void EVENT_DGAButtonPressEvent( XDGAButtonEvent *event )
1513 static WORD statusCodes[NB_BUTTONS] =
1514 { MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_RIGHTDOWN };
1515 int buttonNum = event->button - 1;
1517 WORD keystate;
1519 if (buttonNum >= NB_BUTTONS) return;
1521 keystate = X11DRV_EVENT_XStateToKeyState( event->state );
1523 switch (buttonNum)
1525 case 0:
1526 keystate |= MK_LBUTTON;
1527 break;
1528 case 1:
1529 keystate |= MK_MBUTTON;
1530 break;
1531 case 2:
1532 keystate |= MK_RBUTTON;
1533 break;
1536 X11DRV_SendEvent( statusCodes[buttonNum], 0, 0, keystate, 0,
1537 event->time - X11DRV_server_startticks, DGAhwnd );
1540 static void EVENT_DGAButtonReleaseEvent( XDGAButtonEvent *event )
1542 static WORD statusCodes[NB_BUTTONS] =
1543 { MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_RIGHTUP };
1544 int buttonNum = event->button - 1;
1546 WORD keystate;
1548 if (buttonNum >= NB_BUTTONS) return;
1550 keystate = X11DRV_EVENT_XStateToKeyState( event->state );
1552 switch (buttonNum)
1554 case 0:
1555 keystate &= ~MK_LBUTTON;
1556 break;
1557 case 1:
1558 keystate &= ~MK_MBUTTON;
1559 break;
1560 case 2:
1561 keystate &= ~MK_RBUTTON;
1562 break;
1565 X11DRV_SendEvent( statusCodes[buttonNum], 0, 0, keystate, 0,
1566 event->time - X11DRV_server_startticks, DGAhwnd );
1569 #endif