- Rename WIN_Handle16 to HWDN_16 and make it a macro.
[wine] / dlls / x11drv / event.c
1 /*
2  * X11 event driver
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1999 Noel Borthwick
6  *
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
20  */
21
22 #include "config.h"
23
24 #include <X11/Xatom.h>
25 #include <X11/keysym.h>
26
27 #include "ts_xlib.h"
28 #include "ts_xresource.h"
29 #include "ts_xutil.h"
30 #ifdef HAVE_LIBXXF86DGA2
31 #include "ts_xf86dga2.h"
32 #endif
33
34 #include <assert.h>
35 #include <string.h>
36 #include "wine/winuser16.h"
37 #include "shlobj.h"  /* DROPFILES */
38
39 #include "clipboard.h"
40 #include "dce.h"
41 #include "wine/debug.h"
42 #include "input.h"
43 #include "win.h"
44 #include "winpos.h"
45 #include "windef.h"
46 #include "winreg.h"
47 #include "x11drv.h"
48 #include "shellapi.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(event);
51 WINE_DECLARE_DEBUG_CHANNEL(win);
52
53 /* X context to associate a hwnd to an X window */
54 extern XContext winContext;
55
56 extern Atom wmProtocols;
57 extern Atom wmDeleteWindow;
58 extern Atom dndProtocol;
59 extern Atom dndSelection;
60
61 #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
75 /* The last X window which had the focus */
76 static Window glastXFocusWin = 0;
77
78 static 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
90
91 static void EVENT_ProcessEvent( XEvent *event );
92 static BOOL X11DRV_CheckFocus(void);
93
94   /* Event handlers */
95 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
96 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
97 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
98 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
99 static void EVENT_PropertyNotify( XPropertyEvent *event );
100 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
101
102 extern void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event );
103 extern void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event );
104 extern void X11DRV_MotionNotify( HWND hwnd, XMotionEvent *event );
105 extern void X11DRV_EnterNotify( HWND hwnd, XCrossingEvent *event );
106 extern void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event );
107 extern void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event );
108 extern void X11DRV_Expose( HWND hwnd, XExposeEvent *event );
109 extern void X11DRV_MapNotify( HWND hwnd, XMapEvent *event );
110 extern void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event );
111 extern void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
112 extern void X11DRV_MappingNotify( XMappingEvent *event );
113
114 #ifdef HAVE_LIBXXF86DGA2
115 static int DGAMotionEventType;
116 static int DGAButtonPressEventType;
117 static int DGAButtonReleaseEventType;
118 static int DGAKeyPressEventType;
119 static int DGAKeyReleaseEventType;
120
121 static BOOL DGAUsed = FALSE;
122 static HWND DGAhwnd = 0;
123
124 extern void X11DRV_DGAMotionEvent( HWND hwnd, XDGAMotionEvent *event );
125 extern void X11DRV_DGAButtonPressEvent( HWND hwnd, XDGAButtonEvent *event );
126 extern void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XDGAButtonEvent *event );
127 #endif
128
129 /* Static used for the current input method */
130 static INPUT_TYPE current_input_type = X11DRV_INPUT_ABSOLUTE;
131 static BOOL in_transition = FALSE; /* This is not used as for today */
132
133
134 /***********************************************************************
135  *           process_events
136  */
137 static int process_events( struct x11drv_thread_data *data )
138 {
139     XEvent event;
140     int count = 0;
141
142     wine_tsx11_lock();
143     while ( XPending( data->display ) )
144     {
145         XNextEvent( data->display, &event );
146         wine_tsx11_unlock();
147         EVENT_ProcessEvent( &event );
148         count++;
149         wine_tsx11_lock();
150     }
151     wine_tsx11_unlock();
152     return count;
153 }
154
155
156 /***********************************************************************
157  *           MsgWaitForMultipleObjectsEx   (X11DRV.@)
158  */
159 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
160                                           DWORD timeout, DWORD mask, DWORD flags )
161 {
162     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)
167         return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
168                                          timeout, flags & MWMO_ALERTABLE );
169
170     for (i = 0; i < count; i++) new_handles[i] = handles[i];
171     new_handles[count] = data->display_fd;
172
173     wine_tsx11_lock();
174     XFlush( gdi_display );
175     XFlush( data->display );
176     wine_tsx11_unlock();
177
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     }
186     data->process_event_count--;
187     return ret;
188 }
189
190
191 /***********************************************************************
192  *           EVENT_ProcessEvent
193  *
194  * Process an X event.
195  */
196 static void EVENT_ProcessEvent( XEvent *event )
197 {
198   HWND hWnd;
199   Display *display = event->xany.display;
200
201   TRACE( "called.\n" );
202
203   switch (event->type)
204   {
205     case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
206          FIXME("Got SelectionNotify - must not happen!\n");
207          /* fall through */
208
209       /* 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 ... */
213     case CirculateNotify:
214     case CreateNotify:
215     case DestroyNotify:
216     case GravityNotify:
217     case ReparentNotify:
218       return;
219   }
220
221 #ifdef HAVE_LIBXXF86DGA2
222   if (DGAUsed) {
223     if (event->type == DGAMotionEventType) {
224       TRACE("DGAMotionEvent received.\n");
225       X11DRV_DGAMotionEvent( DGAhwnd, (XDGAMotionEvent *)event );
226       return;
227     }
228     if (event->type == DGAButtonPressEventType) {
229       TRACE("DGAButtonPressEvent received.\n");
230       X11DRV_DGAButtonPressEvent( DGAhwnd, (XDGAButtonEvent *)event );
231       return;
232     }
233     if (event->type == DGAButtonReleaseEventType) {
234       TRACE("DGAButtonReleaseEvent received.\n");
235       X11DRV_DGAButtonReleaseEvent( DGAhwnd, (XDGAButtonEvent *)event );
236       return;
237     }
238     if ((event->type == DGAKeyPressEventType) ||
239         (event->type == DGAKeyReleaseEventType)) {
240       /* Fill a XKeyEvent to send to EVENT_Key */
241       XKeyEvent ke;
242       XDGAKeyEvent *evt = (XDGAKeyEvent *) event;
243
244       TRACE("DGAKeyPress/ReleaseEvent received.\n");
245
246       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;
257       ke.x = -1;
258       ke.y = -1;
259       ke.x_root = -1;
260       ke.y_root = -1;
261       ke.state = evt->state;
262       ke.keycode = evt->keycode;
263       ke.same_screen = TRUE;
264       X11DRV_KeyEvent( 0, &ke );
265       return;
266     }
267   }
268 #endif
269
270   if (TSXFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
271       hWnd = 0;  /* Not for a registered window */
272
273   if ( !hWnd && event->xany.window != root_window
274              && event->type != PropertyNotify
275              && event->type != MappingNotify)
276       WARN( "Got event %s for unknown Window %08lx\n",
277             event_names[event->type], event->xany.window );
278   else
279       TRACE("Got event %s for hwnd %04x\n",
280             event_names[event->type], hWnd );
281
282   switch(event->type)
283     {
284     case KeyPress:
285     case KeyRelease:
286       /* FIXME: should generate a motion event if event point is different from current pos */
287       X11DRV_KeyEvent( hWnd, (XKeyEvent*)event );
288       break;
289
290     case ButtonPress:
291       X11DRV_ButtonPress( hWnd, (XButtonEvent*)event );
292       break;
293
294     case ButtonRelease:
295       X11DRV_ButtonRelease( hWnd, (XButtonEvent*)event );
296       break;
297
298     case MotionNotify:
299       X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
300       break;
301
302     case EnterNotify:
303       X11DRV_EnterNotify( hWnd, (XCrossingEvent*)event );
304       break;
305
306     case FocusIn:
307       EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
308       break;
309
310     case FocusOut:
311       EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
312       break;
313
314     case Expose:
315       X11DRV_Expose( hWnd, &event->xexpose );
316       break;
317
318     case ConfigureNotify:
319       if (!hWnd) return;
320       X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
321       break;
322
323     case SelectionRequest:
324       if (!hWnd) return;
325       EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
326       break;
327
328     case SelectionClear:
329       if (!hWnd) return;
330       EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
331       break;
332
333     case PropertyNotify:
334       EVENT_PropertyNotify( (XPropertyEvent *)event );
335       break;
336
337     case ClientMessage:
338       if (!hWnd) return;
339       EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
340       break;
341
342     case NoExpose:
343       break;
344
345     case MapNotify:
346       X11DRV_MapNotify( hWnd, (XMapEvent *)event );
347       break;
348
349     case UnmapNotify:
350       X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
351       break;
352
353     case KeymapNotify:
354       X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
355       break;
356
357     case MappingNotify:
358       X11DRV_MappingNotify( (XMappingEvent *) event );
359       break;
360
361     default:
362       WARN("Unprocessed event %s for hwnd %04x\n",
363            event_names[event->type], hWnd );
364       break;
365     }
366     TRACE( "returns.\n" );
367 }
368
369
370 /**********************************************************************
371  *              EVENT_FocusIn
372  */
373 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event )
374 {
375     WND *pWndLastFocus;
376     XWindowAttributes win_attr;
377     BOOL bIsDisabled;
378
379     if (!hWnd) return;
380
381     bIsDisabled = GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED;
382
383     /* If the window has been disabled, revert the X focus back to the last
384      * focus window. This is to disallow the window manager from switching
385      * focus away while the app is in a modal state.
386      */
387     if (bIsDisabled && glastXFocusWin)
388     {
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 )
393         {
394             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             }
401         }
402         wine_tsx11_unlock();
403     }
404
405     if (event->detail != NotifyPointer && hWnd != GetForegroundWindow())
406         SetForegroundWindow( hWnd );
407 }
408
409
410 /**********************************************************************
411  *              EVENT_FocusOut
412  *
413  * Note: only top-level override-redirect windows get FocusOut events.
414  */
415 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event )
416 {
417     /* 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;
421
422     if (event->detail != NotifyPointer && hWnd == GetForegroundWindow())
423     {
424         /* don't reset the foreground window, if the window which is
425                getting the focus is a Wine window */
426         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 */
433
434             if (hWnd == GetForegroundWindow())
435                 SetForegroundWindow( 0 );
436         }
437     }
438 }
439
440 /**********************************************************************
441  *              CheckFocus (X11DRV.@)
442  */
443 static BOOL X11DRV_CheckFocus(void)
444 {
445     Display *display = thread_display();
446   HWND   hWnd;
447   Window xW;
448   int      state;
449
450   TSXGetInputFocus(display, &xW, &state);
451     if( xW == None ||
452         TSXFindContext(display, xW, winContext, (char **)&hWnd) )
453       return FALSE;
454     return TRUE;
455 }
456
457
458 /***********************************************************************
459  *           EVENT_SelectionRequest_TARGETS
460  *  Service a TARGETS selection request event
461  */
462 static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
463                                             Atom target, Atom rprop )
464 {
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
473     TRACE("Request for %s\n", TSXGetAtomName(display, target));
474
475     /*
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++;
482
483     /* Allocate temp buffer */
484     targets = (Atom*)HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
485     if(targets == NULL) return None;
486
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;
508
509                 /* 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
520     if (TRACE_ON(event))
521     {
522         int i;
523         for ( i = 0; i < cTargets; i++)
524         {
525             if (targets[i])
526             {
527                 char *itemFmtName = TSXGetAtomName(display, targets[i]);
528                 TRACE("\tAtom# %d:  Type %s\n", i, itemFmtName);
529                 TSXFree(itemFmtName);
530             }
531         }
532     }
533
534     /* Update the X property */
535     TRACE("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
536
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);
542     TRACE("(Rc=%d)\n", xRc);
543
544     HeapFree( GetProcessHeap(), 0, targets );
545
546     return rprop;
547 }
548
549
550 /***********************************************************************
551  *           EVENT_SelectionRequest_STRING
552  *  Service a STRING selection request event
553  */
554 static Atom EVENT_SelectionRequest_STRING( Display *display, Window requestor,
555                                            Atom target, Atom rprop )
556 {
557     static UINT text_cp = (UINT)-1;
558     HANDLE hUnicodeText;
559     LPWSTR uni_text;
560     LPSTR  text;
561     int    size,i,j;
562     char* lpstr = 0;
563     char *itemFmtName;
564     int xRc;
565
566     if(text_cp == (UINT)-1)
567     {
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     }
580
581     /*
582      * Map the requested X selection property type atom name to a
583      * windows clipboard format ID.
584      */
585     itemFmtName = TSXGetAtomName(display, target);
586     TRACE("Request for %s (wFormat=%x %s)\n",
587         itemFmtName, CF_UNICODETEXT, CLIPBOARD_GetFormatName(CF_UNICODETEXT, NULL, 0));
588     TSXFree(itemFmtName);
589
590     hUnicodeText = GetClipboardData(CF_UNICODETEXT);
591     if(!hUnicodeText)
592        return None;
593     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);
599     if (!text)
600        return None;
601     WideCharToMultiByte(text_cp, 0, uni_text, -1, text, size, NULL, NULL);
602
603     /* remove carriage returns */
604
605     lpstr = (char*)HeapAlloc( GetProcessHeap(), 0, size-- );
606     if(lpstr == NULL) return None;
607     for(i=0,j=0; i < size && text[i]; i++ )
608     {
609         if( text[i] == '\r' &&
610             (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
611         lpstr[j++] = text[i];
612     }
613     lpstr[j]='\0';
614
615     /* Update the X property */
616     TRACE("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
617     xRc = TSXChangeProperty(display, requestor, rprop,
618                             XA_STRING, 8, PropModeReplace,
619                             lpstr, j);
620     TRACE("(Rc=%d)\n", xRc);
621
622     GlobalUnlock(hUnicodeText);
623     HeapFree(GetProcessHeap(), 0, text);
624     HeapFree( GetProcessHeap(), 0, lpstr );
625
626     return rprop;
627 }
628
629 /***********************************************************************
630  *           EVENT_SelectionRequest_PIXMAP
631  *  Service a PIXMAP selection request event
632  */
633 static Atom EVENT_SelectionRequest_PIXMAP( Display *display, Window requestor,
634                                            Atom target, Atom rprop )
635 {
636     HANDLE hClipData = 0;
637     Pixmap pixmap = 0;
638     UINT   wFormat;
639     char * itemFmtName;
640     int xRc;
641 #if(0)
642     XSetWindowAttributes win_attr;
643     XWindowAttributes win_attr_src;
644 #endif
645
646     /*
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);
652     TRACE("Request for %s (wFormat=%x %s)\n",
653                   itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat, NULL, 0 ));
654     TSXFree(itemFmtName);
655
656     hClipData = GetClipboardData(wFormat);
657     if ( !hClipData )
658     {
659         TRACE("Could not retrieve a Pixmap compatible format from clipboard!\n");
660         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);
668
669         /* For convert from packed DIB to Pixmap */
670         pixmap = X11DRV_DIB_CreatePixmapFromDIB(hClipData, hdc);
671
672         ReleaseDC(hwnd, hdc);
673     }
674     else if (wFormat == CF_BITMAP)
675     {
676         HWND hwnd = GetOpenClipboardWindow();
677         HDC hdc = GetDC(hwnd);
678
679         pixmap = X11DRV_BITMAP_CreatePixmapFromBitmap(hClipData, hdc);
680
681         ReleaseDC(hwnd, hdc);
682     }
683     else
684     {
685         FIXME("%s to PIXMAP conversion not yet implemented!\n",
686                       CLIPBOARD_GetFormatName(wFormat, NULL, 0));
687         rprop = None;
688         goto END;
689     }
690
691     TRACE("\tUpdating property %s on Window %ld with %s %ld...\n",
692           TSXGetAtomName(display, rprop), (long)requestor,
693           TSXGetAtomName(display, target), pixmap);
694
695     /* Store the Pixmap handle in the property */
696     xRc = TSXChangeProperty(display, requestor, rprop, target,
697                             32, PropModeReplace,
698                             (unsigned char *)&pixmap, 1);
699     TRACE("(Rc=%d)\n", xRc);
700
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);
711     TRACE("Turning on PropertyChangeEvent notifications from window %ld\n",
712           (long)requestor);
713     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
722
723 END:
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  */
733 static Atom EVENT_SelectionRequest_WCF( Display *display, Window requestor,
734                                         Atom target, Atom rprop )
735 {
736     HANDLE hClipData = 0;
737     void*  lpClipData;
738     UINT   wFormat;
739     char * itemFmtName;
740     int cBytes;
741     int xRc;
742     int bemf;
743
744     /*
745      * Map the requested X selection property type atom name to a
746      * windows clipboard format ID.
747      */
748     itemFmtName = TSXGetAtomName(display, target);
749     wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
750     TRACE("Request for %s (wFormat=%x %s)\n",
751           itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat, NULL, 0));
752     TSXFree(itemFmtName);
753
754     hClipData = GetClipboardData(wFormat);
755
756     bemf = wFormat == CF_METAFILEPICT || wFormat == CF_ENHMETAFILE;
757     if (bemf)
758         hClipData = X11DRV_CLIPBOARD_SerializeMetafile(wFormat, hClipData, sizeof(hClipData), TRUE);
759
760     if( hClipData && (lpClipData = GlobalLock(hClipData)) )
761     {
762         cBytes = GlobalSize(hClipData);
763
764         TRACE("\tUpdating property %s, %d bytes...\n",
765               TSXGetAtomName(display, rprop), cBytes);
766
767         xRc = TSXChangeProperty(display, requestor, rprop,
768                                 target, 8, PropModeReplace,
769                                 (unsigned char *)lpClipData, cBytes);
770         TRACE("(Rc=%d)\n", xRc);
771
772         GlobalUnlock(hClipData);
773     }
774     else
775     {
776         TRACE("\tCould not retrieve native format!\n");
777         rprop = None; /* Fail the request */
778     }
779
780     if (bemf) /* We must free serialized metafile data */
781         GlobalFree(hClipData);
782
783     return rprop;
784 }
785
786
787 /***********************************************************************
788  *           EVENT_SelectionRequest_MULTIPLE
789  *  Service a MULTIPLE selection request event
790  *  rprop contains a list of (target,property) atom pairs.
791  *  The first atom names a target and the second names a property.
792  *  The effect is as if we have received a sequence of SelectionRequest events
793  *  (one for each atom pair) except that:
794  *  1. We reply with a SelectionNotify only when all the requested conversions
795  *  have been performed.
796  *  2. If we fail to convert the target named by an atom in the MULTIPLE property,
797  *  we replace the atom in the property by None.
798  */
799 static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
800 {
801     Display *display = pevent->display;
802     Atom           rprop;
803     Atom           atype=AnyPropertyType;
804     int            aformat;
805     unsigned long  remain;
806     Atom*          targetPropList=NULL;
807     unsigned long  cTargetPropList = 0;
808 /*  Atom           xAtomPair = TSXInternAtom(display, "ATOM_PAIR", False); */
809
810    /* If the specified property is None the requestor is an obsolete client.
811     * We support these by using the specified target atom as the reply property.
812     */
813     rprop = pevent->property;
814     if( rprop == None )
815         rprop = pevent->target;
816     if (!rprop)
817         goto END;
818
819     /* Read the MULTIPLE property contents. This should contain a list of
820      * (target,property) atom pairs.
821      */
822     if(TSXGetWindowProperty(display, pevent->requestor, rprop,
823                             0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
824                             &cTargetPropList, &remain,
825                             (unsigned char**)&targetPropList) != Success)
826         TRACE("\tCouldn't read MULTIPLE property\n");
827     else
828     {
829        TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
830              TSXGetAtomName(display, atype), aformat, cTargetPropList, remain);
831
832        /*
833         * Make sure we got what we expect.
834         * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
835         * in a MULTIPLE selection request should be of type ATOM_PAIR.
836         * However some X apps(such as XPaint) are not compliant with this and return
837         * a user defined atom in atype when XGetWindowProperty is called.
838         * The data *is* an atom pair but is not denoted as such.
839         */
840        if(aformat == 32 /* atype == xAtomPair */ )
841        {
842           int i;
843
844           /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
845            * for each (target,property) pair */
846
847           for (i = 0; i < cTargetPropList; i+=2)
848           {
849               char *targetName = TSXGetAtomName(display, targetPropList[i]);
850               char *propName = TSXGetAtomName(display, targetPropList[i+1]);
851               XSelectionRequestEvent event;
852
853               TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
854                     i/2, targetName, propName);
855               TSXFree(targetName);
856               TSXFree(propName);
857
858               /* We must have a non "None" property to service a MULTIPLE target atom */
859               if ( !targetPropList[i+1] )
860               {
861                   TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
862                   continue;
863               }
864
865               /* Set up an XSelectionRequestEvent for this (target,property) pair */
866               memcpy( &event, pevent, sizeof(XSelectionRequestEvent) );
867               event.target = targetPropList[i];
868               event.property = targetPropList[i+1];
869
870               /* Fire a SelectionRequest, informing the handler that we are processing
871                * a MULTIPLE selection request event.
872                */
873               EVENT_SelectionRequest( hWnd, &event, TRUE );
874           }
875        }
876
877        /* Free the list of targets/properties */
878        TSXFree(targetPropList);
879     }
880
881 END:
882     return rprop;
883 }
884
885
886 /***********************************************************************
887  *           EVENT_SelectionRequest
888  *  Process an event selection request event.
889  *  The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
890  *  recursively while servicing a "MULTIPLE" selection target.
891  *
892  *  Note: We only receive this event when WINE owns the X selection
893  */
894 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
895 {
896     Display *display = event->display;
897   XSelectionEvent result;
898   Atom            rprop = None;
899   Window          request = event->requestor;
900   BOOL            couldOpen = FALSE;
901   Atom            xaClipboard = TSXInternAtom(display, "CLIPBOARD", False);
902   Atom            xaTargets = TSXInternAtom(display, "TARGETS", False);
903   Atom            xaMultiple = TSXInternAtom(display, "MULTIPLE", False);
904
905   /*
906    * We can only handle the selection request if :
907    * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
908    * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
909    * since this has been already done.
910    */
911   if ( !bIsMultiple )
912   {
913     if ( ( (event->selection != XA_PRIMARY) && (event->selection != xaClipboard) )
914         || !(couldOpen = OpenClipboard(hWnd)) )
915        goto END;
916   }
917
918   /* If the specified property is None the requestor is an obsolete client.
919    * We support these by using the specified target atom as the reply property.
920    */
921   rprop = event->property;
922   if( rprop == None )
923       rprop = event->target;
924
925   if(event->target == xaTargets)  /*  Return a list of all supported targets */
926   {
927       /* TARGETS selection request */
928       rprop = EVENT_SelectionRequest_TARGETS( display, request, event->target, rprop );
929   }
930   else if(event->target == xaMultiple)  /*  rprop contains a list of (target, property) atom pairs */
931   {
932       /* MULTIPLE selection request */
933       rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
934   }
935   else if(event->target == XA_STRING)  /* treat CF_TEXT as Unix text */
936   {
937       /* XA_STRING selection request */
938       rprop = EVENT_SelectionRequest_STRING( display, request, event->target, rprop );
939   }
940   else if(event->target == XA_PIXMAP)  /*  Convert DIB's to Pixmaps */
941   {
942       /* XA_PIXMAP selection request */
943       rprop = EVENT_SelectionRequest_PIXMAP( display, request, event->target, rprop );
944   }
945   else if(event->target == XA_BITMAP)  /*  Convert DIB's to 1-bit Pixmaps */
946   {
947       /* XA_BITMAP selection request - TODO: create a monochrome Pixmap */
948       rprop = EVENT_SelectionRequest_PIXMAP( display, request, XA_PIXMAP, rprop );
949   }
950   else if(X11DRV_CLIPBOARD_IsNativeProperty(event->target)) /* <WCF>* */
951   {
952       /* All <WCF> selection requests */
953       rprop = EVENT_SelectionRequest_WCF( display, request, event->target, rprop );
954   }
955   else
956       rprop = None;  /* Don't support this format */
957
958 END:
959   /* close clipboard only if we opened before */
960   if(couldOpen) CloseClipboard();
961
962   if( rprop == None)
963       TRACE("\tRequest ignored\n");
964
965   /* reply to sender
966    * SelectionNotify should be sent only at the end of a MULTIPLE request
967    */
968   if ( !bIsMultiple )
969   {
970     result.type = SelectionNotify;
971     result.display = display;
972     result.requestor = request;
973     result.selection = event->selection;
974     result.property = rprop;
975     result.target = event->target;
976     result.time = event->time;
977     TRACE("Sending SelectionNotify event...\n");
978     TSXSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
979   }
980 }
981
982 /***********************************************************************
983  *           EVENT_SelectionClear
984  */
985 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
986 {
987   Atom xaClipboard = TSXInternAtom(event->display, "CLIPBOARD", False);
988
989   if (event->selection == XA_PRIMARY || event->selection == xaClipboard)
990       X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
991 }
992
993 /***********************************************************************
994  *           EVENT_PropertyNotify
995  *   We use this to release resources like Pixmaps when a selection
996  *   client no longer needs them.
997  */
998 static void EVENT_PropertyNotify( XPropertyEvent *event )
999 {
1000   /* Check if we have any resources to free */
1001   TRACE("Received PropertyNotify event: \n");
1002
1003   switch(event->state)
1004   {
1005     case PropertyDelete:
1006     {
1007       TRACE("\tPropertyDelete for atom %s on window %ld\n",
1008             TSXGetAtomName(event->display, event->atom), (long)event->window);
1009
1010       if (X11DRV_IsSelectionOwner())
1011           X11DRV_CLIPBOARD_FreeResources( event->atom );
1012       break;
1013     }
1014
1015     case PropertyNewValue:
1016     {
1017       TRACE("\tPropertyNewValue for atom %s on window %ld\n\n",
1018             TSXGetAtomName(event->display, event->atom), (long)event->window);
1019       break;
1020     }
1021
1022     default:
1023       break;
1024   }
1025 }
1026
1027 /**********************************************************************
1028  *           EVENT_DropFromOffix
1029  *
1030  * don't know if it still works (last Changlog is from 96/11/04)
1031  */
1032 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
1033 {
1034   unsigned long         data_length;
1035   unsigned long         aux_long;
1036   unsigned char*        p_data = NULL;
1037   union {
1038     Atom                atom_aux;
1039     struct {
1040       int x;
1041       int y;
1042     } pt_aux;
1043     int         i;
1044   }             u;
1045   int                   x, y;
1046   BOOL16                bAccept;
1047   HGLOBAL16             hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO16));
1048   LPDRAGINFO16          lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
1049   SEGPTR                spDragInfo = K32WOWGlobalLock16(hDragInfo);
1050   Window                w_aux_root, w_aux_child;
1051   WND*                  pWnd;
1052
1053   if( !lpDragInfo || !spDragInfo ) return;
1054
1055   pWnd = WIN_FindWndPtr(hWnd);
1056
1057   TSXQueryPointer( event->display, get_whole_window(pWnd), &w_aux_root, &w_aux_child,
1058                    &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
1059                    (unsigned int*)&aux_long);
1060
1061   lpDragInfo->hScope = HWND_16(hWnd);
1062   lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y;
1063
1064   /* find out drop point and drop window */
1065   if( x < 0 || y < 0 ||
1066       x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1067       y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1068     {   bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
1069   else
1070     {
1071       bAccept = DRAG_QueryUpdate( hWnd, spDragInfo, TRUE );
1072       x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
1073     }
1074   WIN_ReleaseWndPtr(pWnd);
1075
1076   GlobalFree16( hDragInfo );
1077
1078     if (!bAccept) return;
1079
1080     TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1081                           dndSelection, 0, 65535, FALSE,
1082                           AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1083                           &data_length, &aux_long, &p_data);
1084
1085     if( !aux_long && p_data)  /* don't bother if > 64K */
1086     {
1087         signed char *p = (signed char*) p_data;
1088         char *p_drop;
1089
1090         aux_long = 0;
1091         while( *p )  /* calculate buffer size */
1092         {
1093             p_drop = p;
1094             if((u.i = *p) != -1 )
1095             {
1096                 INT len = GetShortPathNameA( p, NULL, 0 );
1097                 if (len) aux_long += len + 1;
1098                 else *p = -1;
1099             }
1100             p += strlen(p) + 1;
1101         }
1102         if( aux_long && aux_long < 65535 )
1103         {
1104             HDROP                 hDrop;
1105             DROPFILES *lpDrop;
1106
1107             aux_long += sizeof(DROPFILES) + 1;
1108             hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
1109             lpDrop = (DROPFILES*)GlobalLock( hDrop );
1110
1111             if( lpDrop )
1112             {
1113                 WND *pDropWnd = WIN_FindWndPtr( HWND_32(lpDragInfo->hScope) );
1114                 lpDrop->pFiles = sizeof(DROPFILES);
1115                 lpDrop->pt.x = x;
1116                 lpDrop->pt.y = y;
1117                 lpDrop->fNC =
1118                     ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left)  ||
1119                       y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top)    ||
1120                       x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1121                       y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1122                 lpDrop->fWide = FALSE;
1123                 WIN_ReleaseWndPtr(pDropWnd);
1124                 p_drop = (char *)(lpDrop + 1);
1125                 p = p_data;
1126                 while(*p)
1127                 {
1128                     if( *p != -1 ) /* use only "good" entries */
1129                     {
1130                         GetShortPathNameA( p, p_drop, 65535 );
1131                         p_drop += strlen( p_drop ) + 1;
1132                     }
1133                     p += strlen(p) + 1;
1134                 }
1135                 *p_drop = '\0';
1136                 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1137             }
1138         }
1139     }
1140     if( p_data ) TSXFree(p_data);
1141 }
1142
1143 /**********************************************************************
1144  *           EVENT_DropURLs
1145  *
1146  * drop items are separated by \n
1147  * each item is prefixed by its mime type
1148  *
1149  * event->data.l[3], event->data.l[4] contains drop x,y position
1150  */
1151 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
1152 {
1153   unsigned long data_length;
1154   unsigned long aux_long, drop_len = 0;
1155   unsigned char *p_data = NULL; /* property data */
1156   char          *p_drop = NULL;
1157   char          *p, *next;
1158   int           x, y;
1159   DROPFILES *lpDrop;
1160   HDROP hDrop;
1161   union {
1162     Atom        atom_aux;
1163     int         i;
1164     Window      w_aux;
1165   }             u; /* unused */
1166
1167   if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
1168
1169   TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1170                         dndSelection, 0, 65535, FALSE,
1171                         AnyPropertyType, &u.atom_aux, &u.i,
1172                         &data_length, &aux_long, &p_data);
1173   if (aux_long)
1174     WARN("property too large, truncated!\n");
1175   TRACE("urls=%s\n", p_data);
1176
1177   if( !aux_long && p_data) {    /* don't bother if > 64K */
1178     /* calculate length */
1179     p = p_data;
1180     next = strchr(p, '\n');
1181     while (p) {
1182       if (next) *next=0;
1183       if (strncmp(p,"file:",5) == 0 ) {
1184         INT len = GetShortPathNameA( p+5, NULL, 0 );
1185         if (len) drop_len += len + 1;
1186       }
1187       if (next) {
1188         *next = '\n';
1189         p = next + 1;
1190         next = strchr(p, '\n');
1191       } else {
1192         p = NULL;
1193       }
1194     }
1195
1196     if( drop_len && drop_len < 65535 ) {
1197       TSXQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
1198                        &x, &y, &u.i, &u.i, &u.i);
1199
1200       drop_len += sizeof(DROPFILES) + 1;
1201       hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
1202       lpDrop = (DROPFILES *) GlobalLock( hDrop );
1203
1204       if( lpDrop ) {
1205           WND *pDropWnd = WIN_FindWndPtr( hWnd );
1206           lpDrop->pFiles = sizeof(DROPFILES);
1207           lpDrop->pt.x = (INT)x;
1208           lpDrop->pt.y = (INT)y;
1209           lpDrop->fNC =
1210             ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left)  ||
1211               y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top)    ||
1212               x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1213               y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1214           lpDrop->fWide = FALSE;
1215           p_drop = (char*)(lpDrop + 1);
1216           WIN_ReleaseWndPtr(pDropWnd);
1217       }
1218
1219       /* create message content */
1220       if (p_drop) {
1221         p = p_data;
1222         next = strchr(p, '\n');
1223         while (p) {
1224           if (next) *next=0;
1225           if (strncmp(p,"file:",5) == 0 ) {
1226             INT len = GetShortPathNameA( p+5, p_drop, 65535 );
1227             if (len) {
1228               TRACE("drop file %s as %s\n", p+5, p_drop);
1229               p_drop += len+1;
1230             } else {
1231               WARN("can't convert file %s to dos name \n", p+5);
1232             }
1233           } else {
1234             WARN("unknown mime type %s\n", p);
1235           }
1236           if (next) {
1237             *next = '\n';
1238             p = next + 1;
1239             next = strchr(p, '\n');
1240           } else {
1241             p = NULL;
1242           }
1243           *p_drop = '\0';
1244         }
1245
1246         GlobalUnlock(hDrop);
1247         PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1248       }
1249     }
1250     if( p_data ) TSXFree(p_data);
1251   }
1252 }
1253
1254 /**********************************************************************
1255  *           EVENT_ClientMessage
1256  */
1257 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
1258 {
1259   if (event->message_type != None && event->format == 32) {
1260     if ((event->message_type == wmProtocols) &&
1261         (((Atom) event->data.l[0]) == wmDeleteWindow))
1262     {
1263         /* Ignore the delete window request if the window has been disabled */
1264         if (!(GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED))
1265             PostMessageA( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
1266     }
1267     else if (event->message_type == dndProtocol)
1268     {
1269         /* query window (drag&drop event contains only drag window) */
1270         Window root, child;
1271         int root_x, root_y, child_x, child_y;
1272         unsigned int u;
1273         TSXQueryPointer( event->display, root_window, &root, &child,
1274                          &root_x, &root_y, &child_x, &child_y, &u);
1275         if (TSXFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) return;
1276         if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
1277             EVENT_DropFromOffiX(hWnd, event);
1278         else if (event->data.l[0] == DndURL)
1279             EVENT_DropURLs(hWnd, event);
1280     }
1281     else {
1282 #if 0
1283       /* enable this if you want to see the message */
1284       unsigned char* p_data = NULL;
1285       union {
1286         unsigned long   l;
1287         int             i;
1288         Atom            atom;
1289       } u; /* unused */
1290       TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1291                             dndSelection, 0, 65535, FALSE,
1292                             AnyPropertyType, &u.atom, &u.i,
1293                             &u.l, &u.l, &p_data);
1294       TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1295             event->message_type, event->data.l[0], event->data.l[1],
1296             event->data.l[2], event->data.l[3], event->data.l[4],
1297             p_data);
1298 #endif
1299       TRACE("unrecognized ClientMessage\n" );
1300     }
1301   }
1302 }
1303
1304
1305 /**********************************************************************
1306  *              X11DRV_EVENT_SetInputMethod
1307  */
1308 INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
1309 {
1310   INPUT_TYPE prev = current_input_type;
1311
1312   /* Flag not used yet */
1313   in_transition = FALSE;
1314   current_input_type = type;
1315
1316   return prev;
1317 }
1318
1319 #ifdef HAVE_LIBXXF86DGA2
1320 /**********************************************************************
1321  *              X11DRV_EVENT_SetDGAStatus
1322  */
1323 void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
1324 {
1325   if (event_base < 0) {
1326     DGAUsed = FALSE;
1327     DGAhwnd = 0;
1328   } else {
1329     DGAUsed = TRUE;
1330     DGAhwnd = hwnd;
1331     DGAMotionEventType = event_base + MotionNotify;
1332     DGAButtonPressEventType = event_base + ButtonPress;
1333     DGAButtonReleaseEventType = event_base + ButtonRelease;
1334     DGAKeyPressEventType = event_base + KeyPress;
1335     DGAKeyReleaseEventType = event_base + KeyRelease;
1336   }
1337 }
1338 #endif