4 * Copyright 1993 Alexandre Julliard
10 #ifndef X_DISPLAY_MISSING
12 #include <X11/Xatom.h>
13 #include <X11/keysym.h>
15 #include "ts_xresource.h"
21 #include "clipboard.h"
23 #include "debugtools.h"
38 DECLARE_DEBUG_CHANNEL(event)
39 DECLARE_DEBUG_CHANNEL(win)
41 /* X context to associate a hwnd to an X window */
42 extern XContext winContext;
44 extern Atom wmProtocols;
45 extern Atom wmDeleteWindow;
46 extern Atom dndProtocol;
47 extern Atom dndSelection;
49 extern void X11DRV_KEYBOARD_UpdateState(void);
50 extern void X11DRV_KEYBOARD_HandleEvent(WND *pWnd, XKeyEvent *event);
52 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
54 #define DndNotDnd -1 /* OffiX drag&drop */
66 #define DndURL 128 /* KDE drag&drop */
68 /* The last X window which had the focus */
69 static Window glastXFocusWin = 0;
71 static const char * const event_names[] =
73 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
74 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
75 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
76 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
77 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
78 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
79 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
80 "ClientMessage", "MappingNotify"
84 static void CALLBACK EVENT_Flush( ULONG_PTR arg );
85 static void CALLBACK EVENT_ProcessAllEvents( ULONG_PTR arg );
86 static void EVENT_ProcessEvent( XEvent *event );
89 static void EVENT_Key( HWND hWnd, XKeyEvent *event );
90 static void EVENT_ButtonPress( HWND hWnd, XButtonEvent *event );
91 static void EVENT_ButtonRelease( HWND hWnd, XButtonEvent *event );
92 static void EVENT_MotionNotify( HWND hWnd, XMotionEvent *event );
93 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
94 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
95 static void EVENT_Expose( HWND hWnd, XExposeEvent *event );
96 static void EVENT_GraphicsExpose( HWND hWnd, XGraphicsExposeEvent *event );
97 static void EVENT_ConfigureNotify( HWND hWnd, XConfigureEvent *event );
98 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
99 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
100 static void EVENT_PropertyNotify( XPropertyEvent *event );
101 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
102 static void EVENT_MapNotify( HWND pWnd, XMapEvent *event );
103 static void EVENT_UnmapNotify( HWND pWnd, XUnmapEvent *event );
105 /* Usable only with OLVWM - compile option perhaps?
106 static void EVENT_EnterNotify( HWND hWnd, XCrossingEvent *event );
109 static void EVENT_GetGeometry( Window win, int *px, int *py,
110 unsigned int *pwidth, unsigned int *pheight );
113 static BOOL bUserRepaintDisabled = TRUE;
116 /***********************************************************************
119 BOOL X11DRV_EVENT_Init(void)
121 /* Install the X event processing callback */
122 SERVICE_AddObject( FILE_DupUnixHandle( ConnectionNumber(display),
123 GENERIC_READ | SYNCHRONIZE ),
124 EVENT_ProcessAllEvents, 0 );
126 /* Install the XFlush timer callback */
127 if ( Options.synchronous )
128 TSXSynchronize( display, True );
130 SERVICE_AddTimer( 200000L, EVENT_Flush, 0 );
135 /***********************************************************************
138 static void CALLBACK EVENT_Flush( ULONG_PTR arg )
143 /***********************************************************************
144 * EVENT_ProcessAllEvents
146 static void CALLBACK EVENT_ProcessAllEvents( ULONG_PTR arg )
150 TRACE_(event)( "called.\n" );
152 EnterCriticalSection( &X11DRV_CritSection );
153 while ( XPending( display ) )
155 XNextEvent( display, &event );
157 LeaveCriticalSection( &X11DRV_CritSection );
158 EVENT_ProcessEvent( &event );
159 EnterCriticalSection( &X11DRV_CritSection );
161 LeaveCriticalSection( &X11DRV_CritSection );
164 /***********************************************************************
167 * Synchronize with the X server. Should not be used too often.
169 void X11DRV_EVENT_Synchronize( void )
171 TSXSync( display, False );
172 EVENT_ProcessAllEvents( 0 );
175 /***********************************************************************
176 * EVENT_UserRepaintDisable
178 void X11DRV_EVENT_UserRepaintDisable( BOOL bDisabled )
180 bUserRepaintDisabled = bDisabled;
183 /***********************************************************************
186 * Process an X event.
188 static void EVENT_ProcessEvent( XEvent *event )
192 TRACE_(event)( "called.\n" );
196 case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
197 FIXME_(event)("Got SelectionNotify - must not happen!\n");
200 /* We get all these because of StructureNotifyMask.
201 This check is placed here to avoid getting error messages below,
202 as X might send some of these even for windows that have already
204 case CirculateNotify:
212 if ( TSXFindContext( display, event->xany.window, winContext,
213 (char **)&hWnd ) != 0) {
214 if ( event->type == ClientMessage) {
215 /* query window (drag&drop event contains only drag window) */
217 int root_x, root_y, child_x, child_y;
219 TSXQueryPointer( display, X11DRV_GetXRootWindow(), &root, &child,
220 &root_x, &root_y, &child_x, &child_y, &u);
221 if (TSXFindContext( display, child, winContext, (char **)&hWnd ) != 0)
224 hWnd = 0; /* Not for a registered window */
228 if ( !hWnd && event->xany.window != X11DRV_GetXRootWindow()
229 && event->type != PropertyNotify )
230 ERR_(event)("Got event %s for unknown Window %08lx\n",
231 event_names[event->type], event->xany.window );
233 TRACE_(event)("Got event %s for hwnd %04x\n",
234 event_names[event->type], hWnd );
240 EVENT_Key( hWnd, (XKeyEvent*)event );
244 EVENT_ButtonPress( hWnd, (XButtonEvent*)event );
248 EVENT_ButtonRelease( hWnd, (XButtonEvent*)event );
252 /* Wine between two fast machines across the overloaded campus
253 ethernet gets very boged down in MotionEvents. The following
254 simply finds the last motion event in the queue and drops
255 the rest. On a good link events are servered before they build
256 up so this doesn't take place. On a slow link this may cause
257 problems if the event order is important. I'm not yet seen
258 of any problems. Jon 7/6/96.
260 while (TSXCheckTypedWindowEvent(display,((XAnyEvent *)event)->window,
261 MotionNotify, event));
262 EVENT_MotionNotify( hWnd, (XMotionEvent*)event );
267 WND *pWndLastFocus = 0;
268 XWindowAttributes win_attr;
270 XFocusChangeEvent *xfocChange = (XFocusChangeEvent*)event;
272 if (!hWnd || bUserRepaintDisabled) return;
274 bIsDisabled = GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED;
276 /* If the window has been disabled and we are in managed mode,
277 * revert the X focus back to the last focus window. This is to disallow
278 * the window manager from switching focus away while the app is
281 if ( Options.managed && bIsDisabled && glastXFocusWin)
283 /* Change focus only if saved focus window is registered and viewable */
284 if ( TSXFindContext( xfocChange->display, glastXFocusWin, winContext,
285 (char **)&pWndLastFocus ) == 0 )
287 if ( TSXGetWindowAttributes( display, glastXFocusWin, &win_attr ) &&
288 (win_attr.map_state == IsViewable) )
290 TSXSetInputFocus( xfocChange->display, glastXFocusWin, RevertToParent, CurrentTime );
297 EVENT_FocusIn( hWnd, xfocChange );
303 /* Save the last window which had the focus */
304 XFocusChangeEvent *xfocChange = (XFocusChangeEvent*)event;
305 glastXFocusWin = xfocChange->window;
306 if (!hWnd || bUserRepaintDisabled) return;
307 if (GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED) glastXFocusWin = 0;
308 EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
313 if (bUserRepaintDisabled) return;
314 EVENT_Expose( hWnd, (XExposeEvent *)event );
318 if (bUserRepaintDisabled) return;
319 EVENT_GraphicsExpose( hWnd, (XGraphicsExposeEvent *)event );
322 case ConfigureNotify:
323 if (!hWnd || bUserRepaintDisabled) return;
324 EVENT_ConfigureNotify( hWnd, (XConfigureEvent*)event );
327 case SelectionRequest:
328 if (!hWnd || bUserRepaintDisabled) return;
329 EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
333 if (!hWnd || bUserRepaintDisabled) return;
334 EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
338 EVENT_PropertyNotify( (XPropertyEvent *)event );
342 if (!hWnd || bUserRepaintDisabled) return;
343 EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
348 EVENT_EnterNotify( hWnd, (XCrossingEvent *) event );
356 if (!hWnd || bUserRepaintDisabled) return;
357 EVENT_MapNotify( hWnd, (XMapEvent *)event );
361 if (!hWnd || bUserRepaintDisabled) return;
362 EVENT_UnmapNotify( hWnd, (XUnmapEvent *)event );
366 WARN_(event)("Unprocessed event %s for hwnd %04x\n",
367 event_names[event->type], hWnd );
372 /***********************************************************************
375 * Synchronize internal z-order with the window manager's.
377 static BOOL __check_query_condition( WND** pWndA, WND** pWndB )
379 /* return TRUE if we have at least two managed windows */
381 for( *pWndB = NULL; *pWndA; *pWndA = (*pWndA)->next )
382 if( (*pWndA)->flags & WIN_MANAGED &&
383 (*pWndA)->dwStyle & WS_VISIBLE ) break;
385 for( *pWndB = (*pWndA)->next; *pWndB; *pWndB = (*pWndB)->next )
386 if( (*pWndB)->flags & WIN_MANAGED &&
387 (*pWndB)->dwStyle & WS_VISIBLE ) break;
388 return ((*pWndB) != NULL);
391 static Window __get_common_ancestor( Window A, Window B,
392 Window** children, unsigned* total )
394 /* find the real root window */
396 Window root, *childrenB;
401 TSXQueryTree( display, A, &root, &A, children, total );
402 TSXQueryTree( display, B, &root, &B, &childrenB, &totalB );
403 if( childrenB ) TSXFree( childrenB );
404 if( *children ) TSXFree( *children ), *children = NULL;
405 } while( A != B && A && B );
409 TSXQueryTree( display, A, &root, &B, children, total );
415 static Window __get_top_decoration( Window w, Window ancestor )
417 Window* children, root, prev = w, parent = w;
423 TSXQueryTree( display, w, &root, &parent, &children, &total );
424 if( children ) TSXFree( children );
425 } while( parent && parent != ancestor );
426 TRACE_(event)("\t%08x -> %08x\n", (unsigned)prev, (unsigned)w );
427 return ( parent ) ? w : 0 ;
430 static unsigned __td_lookup( Window w, Window* list, unsigned max )
433 for( i = max - 1; i >= 0; i-- ) if( list[i] == w ) break;
437 static HWND EVENT_QueryZOrder( HWND hWndCheck)
439 HWND hwndInsertAfter = HWND_TOP;
440 WND *pWndCheck = WIN_FindWndPtr(hWndCheck);
441 WND *pDesktop = WIN_GetDesktop();
442 WND *pWnd, *pWndZ = WIN_LockWndPtr(pDesktop->child);
443 Window w, parent, *children = NULL;
444 unsigned total, check, pos, best;
446 if( !__check_query_condition(&pWndZ, &pWnd) )
448 WIN_ReleaseWndPtr(pWndCheck);
449 WIN_ReleaseWndPtr(pDesktop->child);
450 WIN_ReleaseDesktop();
451 return hwndInsertAfter;
453 WIN_LockWndPtr(pWndZ);
454 WIN_LockWndPtr(pWnd);
455 WIN_ReleaseWndPtr(pDesktop->child);
456 WIN_ReleaseDesktop();
458 parent = __get_common_ancestor( X11DRV_WND_GetXWindow(pWndZ),
459 X11DRV_WND_GetXWindow(pWnd),
461 if( parent && children )
463 /* w is the ancestor if pWndCheck that is a direct descendant of 'parent' */
465 w = __get_top_decoration( X11DRV_WND_GetXWindow(pWndCheck), parent );
467 if( w != children[total-1] ) /* check if at the top */
469 /* X child at index 0 is at the bottom, at index total-1 is at the top */
470 check = __td_lookup( w, children, total );
473 for( WIN_UpdateWndPtr(&pWnd,pWndZ); pWnd;WIN_UpdateWndPtr(&pWnd,pWnd->next))
475 /* go through all windows in Wine z-order... */
477 if( pWnd != pWndCheck )
479 if( !(pWnd->flags & WIN_MANAGED) ||
480 !(w = __get_top_decoration( X11DRV_WND_GetXWindow(pWnd), parent )) )
482 pos = __td_lookup( w, children, total );
483 if( pos < best && pos > check )
485 /* find a nearest Wine window precedes
486 * pWndCheck in the real z-order... */
488 hwndInsertAfter = pWnd->hwndSelf;
490 if( best - check == 1 ) break;
495 if( children ) TSXFree( children );
496 WIN_ReleaseWndPtr(pWnd);
497 WIN_ReleaseWndPtr(pWndZ);
498 WIN_ReleaseWndPtr(pWndCheck);
499 return hwndInsertAfter;
502 /***********************************************************************
503 * EVENT_XStateToKeyState
505 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
506 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
508 static WORD EVENT_XStateToKeyState( int state )
512 if (state & Button1Mask) kstate |= MK_LBUTTON;
513 if (state & Button2Mask) kstate |= MK_MBUTTON;
514 if (state & Button3Mask) kstate |= MK_RBUTTON;
515 if (state & ShiftMask) kstate |= MK_SHIFT;
516 if (state & ControlMask) kstate |= MK_CONTROL;
520 /***********************************************************************
521 * X11DRV_EVENT_QueryPointer
523 BOOL X11DRV_EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *state)
526 int rootX, rootY, winX, winY;
529 if (!TSXQueryPointer( display, X11DRV_GetXRootWindow(), &root, &child,
530 &rootX, &rootY, &winX, &winY, &xstate ))
538 *state = EVENT_XStateToKeyState( xstate );
543 /***********************************************************************
546 static void EVENT_Expose( HWND hWnd, XExposeEvent *event )
550 WND *pWnd = WIN_FindWndPtr(hWnd);
551 /* Make position relative to client area instead of window */
552 rect.left = event->x - (pWnd? (pWnd->rectClient.left - pWnd->rectWindow.left) : 0);
553 rect.top = event->y - (pWnd? (pWnd->rectClient.top - pWnd->rectWindow.top) : 0);
554 rect.right = rect.left + event->width;
555 rect.bottom = rect.top + event->height;
556 WIN_ReleaseWndPtr(pWnd);
558 Callout.RedrawWindow( hWnd, &rect, 0,
559 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
560 (event->count ? 0 : RDW_ERASENOW) );
564 /***********************************************************************
565 * EVENT_GraphicsExpose
567 * This is needed when scrolling area is partially obscured
568 * by non-Wine X window.
570 static void EVENT_GraphicsExpose( HWND hWnd, XGraphicsExposeEvent *event )
573 WND *pWnd = WIN_FindWndPtr(hWnd);
575 /* Make position relative to client area instead of window */
576 rect.left = event->x - (pWnd? (pWnd->rectClient.left - pWnd->rectWindow.left) : 0);
577 rect.top = event->y - (pWnd? (pWnd->rectClient.top - pWnd->rectWindow.top) : 0);
578 rect.right = rect.left + event->width;
579 rect.bottom = rect.top + event->height;
581 WIN_ReleaseWndPtr(pWnd);
583 Callout.RedrawWindow( hWnd, &rect, 0,
584 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
585 (event->count ? 0 : RDW_ERASENOW) );
589 /***********************************************************************
592 * Handle a X key event
594 static void EVENT_Key( HWND hWnd, XKeyEvent *event )
596 WND *pWnd = WIN_FindWndPtr(hWnd);
597 X11DRV_KEYBOARD_HandleEvent( pWnd, event );
598 WIN_ReleaseWndPtr(pWnd);
603 /***********************************************************************
606 static void EVENT_MotionNotify( HWND hWnd, XMotionEvent *event )
608 WND *pWnd = WIN_FindWndPtr(hWnd);
609 int xOffset = pWnd? pWnd->rectWindow.left : 0;
610 int yOffset = pWnd? pWnd->rectWindow.top : 0;
611 WIN_ReleaseWndPtr(pWnd);
613 MOUSE_SendEvent( MOUSEEVENTF_MOVE,
614 xOffset + event->x, yOffset + event->y,
615 EVENT_XStateToKeyState( event->state ),
616 event->time - MSG_WineStartTicks,
621 /***********************************************************************
624 static void EVENT_ButtonPress( HWND hWnd, XButtonEvent *event )
626 static WORD statusCodes[NB_BUTTONS] =
627 { MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_RIGHTDOWN };
628 int buttonNum = event->button - 1;
630 WND *pWnd = WIN_FindWndPtr(hWnd);
631 int xOffset = pWnd? pWnd->rectWindow.left : 0;
632 int yOffset = pWnd? pWnd->rectWindow.top : 0;
635 WIN_ReleaseWndPtr(pWnd);
637 if (buttonNum >= NB_BUTTONS) return;
640 * Get the compatible keystate
642 keystate = EVENT_XStateToKeyState( event->state );
645 * Make sure that the state of the button that was just
651 keystate |= MK_LBUTTON;
654 keystate |= MK_MBUTTON;
657 keystate |= MK_RBUTTON;
661 MOUSE_SendEvent( statusCodes[buttonNum],
662 xOffset + event->x, yOffset + event->y,
664 event->time - MSG_WineStartTicks,
669 /***********************************************************************
670 * EVENT_ButtonRelease
672 static void EVENT_ButtonRelease( HWND hWnd, XButtonEvent *event )
674 static WORD statusCodes[NB_BUTTONS] =
675 { MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_RIGHTUP };
676 int buttonNum = event->button - 1;
677 WND *pWnd = WIN_FindWndPtr(hWnd);
678 int xOffset = pWnd? pWnd->rectWindow.left : 0;
679 int yOffset = pWnd? pWnd->rectWindow.top : 0;
682 WIN_ReleaseWndPtr(pWnd);
684 if (buttonNum >= NB_BUTTONS) return;
687 * Get the compatible keystate
689 keystate = EVENT_XStateToKeyState( event->state );
692 * Make sure that the state of the button that was just
698 keystate &= ~MK_LBUTTON;
701 keystate &= ~MK_MBUTTON;
704 keystate &= ~MK_RBUTTON;
708 MOUSE_SendEvent( statusCodes[buttonNum],
709 xOffset + event->x, yOffset + event->y,
711 event->time - MSG_WineStartTicks,
716 /**********************************************************************
719 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event )
721 if (event->detail != NotifyPointer)
722 if (hWnd != GetForegroundWindow())
724 SetForegroundWindow( hWnd );
725 X11DRV_KEYBOARD_UpdateState();
730 /**********************************************************************
733 * Note: only top-level override-redirect windows get FocusOut events.
735 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event )
737 if (event->detail != NotifyPointer)
738 if (hWnd == GetForegroundWindow())
740 WND *pWnd = WIN_FindWndPtr(hWnd);
742 if( ((pWnd->dwStyle & WS_POPUP) == WS_POPUP) &&
743 ((pWnd->dwStyle & WS_POPUPWINDOW) != WS_POPUPWINDOW) )
744 SendMessageA(hWnd, WM_CLOSE, 0, 0 );
746 SendMessageA( hWnd, WM_CANCELMODE, 0, 0 );
747 WIN_ReleaseWndPtr(pWnd);
749 /* Abey : 6-Oct-99. Check again if the focus out window is the
750 Foreground window, because in most cases the messages sent
751 above must have already changed the foreground window, in which
752 case we don't have to change the foreground window to 0 */
754 if (hWnd == GetForegroundWindow())
755 SetForegroundWindow( 0 );
759 /**********************************************************************
760 * X11DRV_EVENT_CheckFocus
762 BOOL X11DRV_EVENT_CheckFocus(void)
768 TSXGetInputFocus(display, &xW, &state);
770 TSXFindContext(display, xW, winContext, (char **)&hWnd) )
775 /**********************************************************************
778 * Helper function for ConfigureNotify handling.
779 * Get the new geometry of a window relative to the root window.
781 static void EVENT_GetGeometry( Window win, int *px, int *py,
782 unsigned int *pwidth, unsigned int *pheight )
785 int x, y, width, height, border, depth;
787 EnterCriticalSection( &X11DRV_CritSection );
789 /* Get the geometry of the window */
790 XGetGeometry( display, win, &root, &x, &y, &width, &height,
793 /* Translate the window origin to root coordinates */
794 XTranslateCoordinates( display, win, root, 0, 0, &x, &y, &top );
796 LeaveCriticalSection( &X11DRV_CritSection );
804 /**********************************************************************
805 * EVENT_ConfigureNotify
807 * The ConfigureNotify event is only selected on top-level windows
808 * when the -managed flag is used.
810 static void EVENT_ConfigureNotify( HWND hWnd, XConfigureEvent *event )
814 unsigned int width, height;
815 HWND newInsertAfter, oldInsertAfter;
817 /* Get geometry and Z-order according to X */
819 EVENT_GetGeometry( event->window, &x, &y, &width, &height );
820 newInsertAfter = EVENT_QueryZOrder( hWnd );
822 /* Get geometry and Z-order according to Wine */
825 * Needs to find the first Visible Window above the current one
827 oldInsertAfter = hWnd;
830 oldInsertAfter = GetWindow( oldInsertAfter, GW_HWNDPREV );
833 oldInsertAfter = HWND_TOP;
836 if (GetWindowLongA( oldInsertAfter, GWL_STYLE ) & WS_VISIBLE) break;
839 /* Compare what has changed */
841 GetWindowRect( hWnd, &rectWindow );
842 if ( rectWindow.left == x && rectWindow.top == y )
845 TRACE_(win)( "%04x moving from (%d,%d) to (%d,%d)\n", hWnd,
846 rectWindow.left, rectWindow.top, x, y );
848 if ( rectWindow.right - rectWindow.left == width
849 && rectWindow.bottom - rectWindow.top == height )
852 TRACE_(win)( "%04x resizing from (%d,%d) to (%d,%d)\n", hWnd,
853 rectWindow.right - rectWindow.left,
854 rectWindow.bottom - rectWindow.top, width, height );
856 if ( newInsertAfter == oldInsertAfter )
857 flags |= SWP_NOZORDER;
859 TRACE_(win)( "%04x restacking from after %04x to after %04x\n", hWnd,
860 oldInsertAfter, newInsertAfter );
862 /* If anything changed, call SetWindowPos */
864 if ( flags != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER) )
865 SetWindowPos( hWnd, newInsertAfter, x, y, width, height,
866 flags | SWP_NOACTIVATE | SWP_WINE_NOHOSTMOVE );
870 /***********************************************************************
871 * EVENT_SelectionRequest_TARGETS
872 * Service a TARGETS selection request event
874 static Atom EVENT_SelectionRequest_TARGETS( Window requestor, Atom target, Atom rprop )
876 Atom xaTargets = TSXInternAtom(display, "TARGETS", False);
880 unsigned long cTargets;
884 TRACE_(event)("Request for %s\n", TSXGetAtomName(display, target));
887 * Count the number of items we wish to expose as selection targets.
888 * We include the TARGETS item, and a PIXMAP if we have CF_DIB or CF_BITMAP
890 cTargets = CountClipboardFormats() + 1;
891 if ( CLIPBOARD_IsPresent(CF_DIB) || CLIPBOARD_IsPresent(CF_BITMAP) )
894 /* Allocate temp buffer */
895 targets = (Atom*)HEAP_xalloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
897 /* Create TARGETS property list (First item in list is TARGETS itself) */
899 for ( targets[0] = xaTargets, cTargets = 1, wFormat = 0, bHavePixmap = FALSE;
900 (wFormat = EnumClipboardFormats( wFormat )); )
902 if ( (prop = X11DRV_CLIPBOARD_MapFormatToProperty(wFormat)) != None )
904 /* Scan through what we have so far to avoid duplicates */
907 for (i = 0, bExists = FALSE; i < cTargets; i++)
909 if (targets[i] == prop)
917 targets[cTargets++] = prop;
919 /* Add PIXMAP prop for bitmaps additionally */
920 if ( (wFormat == CF_DIB || wFormat == CF_BITMAP )
923 targets[cTargets++] = XA_PIXMAP;
933 for ( i = 0; i < cTargets; i++)
937 char *itemFmtName = TSXGetAtomName(display, targets[i]);
938 TRACE_(event)("\tAtom# %d: Type %s\n", i, itemFmtName);
939 TSXFree(itemFmtName);
945 /* Update the X property */
946 TRACE_(event)("\tUpdating property %s...", TSXGetAtomName(display, rprop));
948 /* We may want to consider setting the type to xaTargets instead,
949 * in case some apps expect this instead of XA_ATOM */
950 xRc = TSXChangeProperty(display, requestor, rprop,
951 XA_ATOM, 32, PropModeReplace,
952 (unsigned char *)targets, cTargets);
953 TRACE_(event)("(Rc=%d)\n", xRc);
955 HeapFree( GetProcessHeap(), 0, targets );
961 /***********************************************************************
962 * EVENT_SelectionRequest_STRING
963 * Service a STRING selection request event
965 static Atom EVENT_SelectionRequest_STRING( Window requestor, Atom target, Atom rprop )
975 * Map the requested X selection property type atom name to a
976 * windows clipboard format ID.
978 itemFmtName = TSXGetAtomName(display, target);
979 TRACE_(event)("Request for %s (wFormat=%x %s)\n",
980 itemFmtName, CF_TEXT, CLIPBOARD_GetFormatName(CF_TEXT));
981 TSXFree(itemFmtName);
983 if ( !CLIPBOARD_IsPresent(CF_TEXT) )
989 hText = GetClipboardData16(CF_TEXT);
990 text = GlobalLock16(hText);
991 size = GlobalSize16(hText);
993 /* remove carriage returns */
995 lpstr = (char*)HEAP_xalloc( GetProcessHeap(), 0, size-- );
996 for(i=0,j=0; i < size && text[i]; i++ )
998 if( text[i] == '\r' &&
999 (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
1000 lpstr[j++] = text[i];
1004 /* Update the X property */
1005 TRACE_(event)("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
1006 xRc = TSXChangeProperty(display, requestor, rprop,
1007 XA_STRING, 8, PropModeReplace,
1009 TRACE_(event)("(Rc=%d)\n", xRc);
1011 GlobalUnlock16(hText);
1012 HeapFree( GetProcessHeap(), 0, lpstr );
1018 /***********************************************************************
1019 * EVENT_SelectionRequest_PIXMAP
1020 * Service a PIXMAP selection request event
1022 static Atom EVENT_SelectionRequest_PIXMAP( Window requestor, Atom target, Atom rprop )
1024 HANDLE hClipData = 0;
1025 Pixmap pixmap = NULL;
1030 XSetWindowAttributes win_attr;
1031 XWindowAttributes win_attr_src;
1035 * Map the requested X selection property type atom name to a
1036 * windows clipboard format ID.
1038 itemFmtName = TSXGetAtomName(display, target);
1039 wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
1040 TRACE_(event)("Request for %s (wFormat=%x %s)\n",
1041 itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat));
1042 TSXFree(itemFmtName);
1044 hClipData = GetClipboardData(wFormat);
1047 TRACE_(event)("Could not retrieve a Pixmap compatible format from clipboard!\n");
1048 rprop = None; /* Fail the request */
1052 if (wFormat == CF_DIB)
1054 HWND hwnd = GetOpenClipboardWindow();
1055 HDC hdc = GetDC(hwnd);
1057 /* For convert from packed DIB to Pixmap */
1058 pixmap = X11DRV_DIB_CreatePixmapFromDIB(hClipData, hdc);
1060 ReleaseDC(hdc, hwnd);
1062 else if (wFormat == CF_BITMAP)
1064 HWND hwnd = GetOpenClipboardWindow();
1065 HDC hdc = GetDC(hwnd);
1067 pixmap = X11DRV_BITMAP_CreatePixmapFromBitmap(hClipData, hdc);
1069 ReleaseDC(hdc, hwnd);
1073 FIXME_(event)("%s to PIXMAP conversion not yet implemented!\n",
1074 CLIPBOARD_GetFormatName(wFormat));
1079 TRACE_(event)("\tUpdating property %s on Window %ld with %s %ld...\n",
1080 TSXGetAtomName(display, rprop), (long)requestor,
1081 TSXGetAtomName(display, target),
1084 /* Store the Pixmap handle in the property */
1085 xRc = TSXChangeProperty(display, requestor, rprop, target,
1086 32, PropModeReplace,
1087 (unsigned char *)&pixmap, 1);
1088 TRACE_(event)("(Rc=%d)\n", xRc);
1090 /* Enable the code below if you want to handle destroying Pixmap resources
1091 * in response to property notify events. Clients like XPaint don't
1092 * appear to be duplicating Pixmaps so they don't like us deleting,
1093 * the resource in response to the property being deleted.
1096 /* Express interest in property notify events so that we can delete the
1097 * pixmap when the client deletes the property atom.
1099 xRc = TSXGetWindowAttributes(display, requestor, &win_attr_src);
1100 TRACE_(event)("Turning on PropertyChangeEvent notifications from window %ld\n",
1102 win_attr.event_mask = win_attr_src.your_event_mask | PropertyChangeMask;
1103 TSXChangeWindowAttributes(display, requestor, CWEventMask, &win_attr);
1105 /* Register the Pixmap we created with the request property Atom.
1106 * When this property is destroyed we also destroy the Pixmap in
1107 * response to the PropertyNotify event.
1109 X11DRV_CLIPBOARD_RegisterPixmapResource( rprop, pixmap );
1117 /***********************************************************************
1118 * EVENT_SelectionRequest_WCF
1119 * Service a Wine Clipboard Format selection request event.
1120 * For <WCF>* data types we simply copy the data to X without conversion.
1122 static Atom EVENT_SelectionRequest_WCF( Window requestor, Atom target, Atom rprop )
1124 HANDLE hClipData = 0;
1132 * Map the requested X selection property type atom name to a
1133 * windows clipboard format ID.
1135 itemFmtName = TSXGetAtomName(display, target);
1136 wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
1137 TRACE_(event)("Request for %s (wFormat=%x %s)\n",
1138 itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat));
1139 TSXFree(itemFmtName);
1141 hClipData = GetClipboardData16(wFormat);
1143 if( hClipData && (lpClipData = GlobalLock16(hClipData)) )
1145 cBytes = GlobalSize16(hClipData);
1147 TRACE_(event)("\tUpdating property %s, %d bytes...\n",
1148 TSXGetAtomName(display, rprop), cBytes);
1150 xRc = TSXChangeProperty(display, requestor, rprop,
1151 target, 8, PropModeReplace,
1152 (unsigned char *)lpClipData, cBytes);
1153 TRACE_(event)("(Rc=%d)\n", xRc);
1155 GlobalUnlock16(hClipData);
1159 TRACE_(event)("\tCould not retrieve native format!\n");
1160 rprop = None; /* Fail the request */
1167 /***********************************************************************
1168 * EVENT_SelectionRequest_MULTIPLE
1169 * Service a MULTIPLE selection request event
1170 * rprop contains a list of (target,property) atom pairs.
1171 * The first atom names a target and the second names a property.
1172 * The effect is as if we have received a sequence of SelectionRequest events
1173 * (one for each atom pair) except that:
1174 * 1. We reply with a SelectionNotify only when all the requested conversions
1175 * have been performed.
1176 * 2. If we fail to convert the target named by an atom in the MULTIPLE property,
1177 * we replace the atom in the property by None.
1179 static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
1182 Atom atype=AnyPropertyType;
1184 unsigned long remain;
1185 Atom* targetPropList=NULL;
1186 unsigned long cTargetPropList = 0;
1187 /* Atom xAtomPair = TSXInternAtom(display, "ATOM_PAIR", False); */
1189 /* If the specified property is None the requestor is an obsolete client.
1190 * We support these by using the specified target atom as the reply property.
1192 rprop = pevent->property;
1194 rprop = pevent->target;
1198 /* Read the MULTIPLE property contents. This should contain a list of
1199 * (target,property) atom pairs.
1201 if(TSXGetWindowProperty(display, pevent->requestor, rprop,
1202 0, 0x3FFF, False, AnyPropertyType, &atype, &aformat,
1203 &cTargetPropList, &remain, (unsigned char**)&targetPropList) != Success)
1204 TRACE_(event)("\tCouldn't read MULTIPLE property\n");
1207 TRACE_(event)("\tType %s,Format %d,nItems %ld, Remain %ld\n",
1208 TSXGetAtomName(display,atype),aformat,cTargetPropList,remain);
1211 * Make sure we got what we expect.
1212 * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
1213 * in a MULTIPLE selection request should be of type ATOM_PAIR.
1214 * However some X apps(such as XPaint) are not compliant with this and return
1215 * a user defined atom in atype when XGetWindowProperty is called.
1216 * The data *is* an atom pair but is not denoted as such.
1218 if(aformat == 32 /* atype == xAtomPair */ )
1222 /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
1223 * for each (target,property) pair */
1225 for (i = 0; i < cTargetPropList; i+=2)
1227 char *targetName = TSXGetAtomName(display, targetPropList[i]);
1228 char *propName = TSXGetAtomName(display, targetPropList[i+1]);
1229 XSelectionRequestEvent event;
1231 TRACE_(event)("MULTIPLE(%d): Target='%s' Prop='%s'\n", i/2, targetName, propName);
1232 TSXFree(targetName);
1235 /* We must have a non "None" property to service a MULTIPLE target atom */
1236 if ( !targetPropList[i+1] )
1238 TRACE_(event)("\tMULTIPLE(%d): Skipping target with empty property!", i);
1242 /* Set up an XSelectionRequestEvent for this (target,property) pair */
1243 memcpy( &event, pevent, sizeof(XSelectionRequestEvent) );
1244 event.target = targetPropList[i];
1245 event.property = targetPropList[i+1];
1247 /* Fire a SelectionRequest, informing the handler that we are processing
1248 * a MULTIPLE selection request event.
1250 EVENT_SelectionRequest( hWnd, &event, TRUE );
1254 /* Free the list of targets/properties */
1255 TSXFree(targetPropList);
1263 /***********************************************************************
1264 * EVENT_SelectionRequest
1265 * Process an event selection request event.
1266 * The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
1267 * recursively while servicing a "MULTIPLE" selection target.
1269 * Note: We only receive this event when WINE owns the X selection
1271 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
1273 XSelectionEvent result;
1275 Window request = event->requestor;
1276 BOOL couldOpen = FALSE;
1277 Atom xaClipboard = TSXInternAtom(display, "CLIPBOARD", False);
1278 Atom xaTargets = TSXInternAtom(display, "TARGETS", False);
1279 Atom xaMultiple = TSXInternAtom(display, "MULTIPLE", False);
1282 * We can only handle the selection request if :
1283 * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
1284 * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
1285 * since this has been already done.
1289 if ( ( (event->selection != XA_PRIMARY) && (event->selection != xaClipboard) )
1290 || !(couldOpen = OpenClipboard(hWnd)) )
1294 /* If the specified property is None the requestor is an obsolete client.
1295 * We support these by using the specified target atom as the reply property.
1297 rprop = event->property;
1299 rprop = event->target;
1301 if(event->target == xaTargets) /* Return a list of all supported targets */
1303 /* TARGETS selection request */
1304 rprop = EVENT_SelectionRequest_TARGETS( request, event->target, rprop );
1306 else if(event->target == xaMultiple) /* rprop contains a list of (target, property) atom pairs */
1308 /* MULTIPLE selection request */
1309 rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
1311 else if(event->target == XA_STRING) /* treat CF_TEXT as Unix text */
1313 /* XA_STRING selection request */
1314 rprop = EVENT_SelectionRequest_STRING( request, event->target, rprop );
1316 else if(event->target == XA_PIXMAP) /* Convert DIB's to Pixmaps */
1318 /* XA_PIXMAP selection request */
1319 rprop = EVENT_SelectionRequest_PIXMAP( request, event->target, rprop );
1321 else if(event->target == XA_BITMAP) /* Convert DIB's to 1-bit Pixmaps */
1323 /* XA_BITMAP selection request - TODO: create a monochrome Pixmap */
1324 rprop = EVENT_SelectionRequest_PIXMAP( request, XA_PIXMAP, rprop );
1326 else if(X11DRV_CLIPBOARD_IsNativeProperty(event->target)) /* <WCF>* */
1328 /* All <WCF> selection requests */
1329 rprop = EVENT_SelectionRequest_WCF( request, event->target, rprop );
1332 rprop = None; /* Don't support this format */
1335 /* close clipboard only if we opened before */
1336 if(couldOpen) CloseClipboard();
1339 TRACE_(event)("\tRequest ignored\n");
1342 * SelectionNotify should be sent only at the end of a MULTIPLE request
1346 result.type = SelectionNotify;
1347 result.display = display;
1348 result.requestor = request;
1349 result.selection = event->selection;
1350 result.property = rprop;
1351 result.target = event->target;
1352 result.time = event->time;
1353 TRACE_(event)("Sending SelectionNotify event...\n");
1354 TSXSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
1358 /***********************************************************************
1359 * EVENT_SelectionClear
1361 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
1363 Atom xaClipboard = TSXInternAtom(display, "CLIPBOARD", False);
1365 if (event->selection == XA_PRIMARY || event->selection == xaClipboard)
1366 X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
1369 /***********************************************************************
1370 * EVENT_PropertyNotify
1371 * We use this to release resources like Pixmaps when a selection
1372 * client no longer needs them.
1374 static void EVENT_PropertyNotify( XPropertyEvent *event )
1376 /* Check if we have any resources to free */
1377 TRACE_(event)("Received PropertyNotify event: ");
1379 switch(event->state)
1381 case PropertyDelete:
1383 TRACE_(event)("\tPropertyDelete for atom %s on window %ld\n",
1384 TSXGetAtomName(event->display, event->atom), (long)event->window);
1386 if (X11DRV_CLIPBOARD_IsSelectionowner())
1387 X11DRV_CLIPBOARD_FreeResources( event->atom );
1391 case PropertyNewValue:
1393 TRACE_(event)("\tPropertyNewValue for atom %s on window %ld\n\n",
1394 TSXGetAtomName(event->display, event->atom), (long)event->window);
1403 /**********************************************************************
1404 * EVENT_DropFromOffix
1406 * don't know if it still works (last Changlog is from 96/11/04)
1408 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
1410 unsigned long data_length;
1411 unsigned long aux_long;
1412 unsigned char* p_data = NULL;
1423 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO));
1424 LPDRAGINFO lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
1425 SEGPTR spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
1426 Window w_aux_root, w_aux_child;
1430 if( !lpDragInfo || !spDragInfo ) return;
1432 pWnd = WIN_FindWndPtr(hWnd);
1434 TSXQueryPointer( display, X11DRV_WND_GetXWindow(pWnd), &w_aux_root, &w_aux_child,
1435 &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
1436 (unsigned int*)&aux_long);
1438 lpDragInfo->hScope = hWnd;
1439 lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y;
1441 /* find out drop point and drop window */
1442 if( x < 0 || y < 0 ||
1443 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1444 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1445 { bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
1448 bAccept = DRAG_QueryUpdate( hWnd, spDragInfo, TRUE );
1449 x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
1451 pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
1452 WIN_ReleaseWndPtr(pWnd);
1454 GlobalFree16( hDragInfo );
1458 TSXGetWindowProperty( display, DefaultRootWindow(display),
1459 dndSelection, 0, 65535, FALSE,
1460 AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1461 &data_length, &aux_long, &p_data);
1463 if( !aux_long && p_data) /* don't bother if > 64K */
1465 char *p = (char*) p_data;
1469 while( *p ) /* calculate buffer size */
1472 if((u.i = *p) != -1 )
1473 u.i = DRIVE_FindDriveRoot( (const char **)&p_drop );
1474 if( u.i == -1 ) *p = -1; /* mark as "bad" */
1477 INT len = GetShortPathNameA( p, NULL, 0 );
1478 if (len) aux_long += len + 1;
1483 if( aux_long && aux_long < 65535 )
1486 LPDROPFILESTRUCT16 lpDrop;
1488 aux_long += sizeof(DROPFILESTRUCT16) + 1;
1489 hDrop = (HDROP16)GlobalAlloc16( GMEM_SHARE, aux_long );
1490 lpDrop = (LPDROPFILESTRUCT16) GlobalLock16( hDrop );
1494 lpDrop->wSize = sizeof(DROPFILESTRUCT16);
1495 lpDrop->ptMousePos.x = (INT16)x;
1496 lpDrop->ptMousePos.y = (INT16)y;
1497 lpDrop->fInNonClientArea = (BOOL16)
1498 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1499 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1500 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1501 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1502 p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT16);
1506 if( *p != -1 ) /* use only "good" entries */
1508 GetShortPathNameA( p, p_drop, 65535 );
1509 p_drop += strlen( p_drop ) + 1;
1514 PostMessage16( hWnd, WM_DROPFILES,
1515 (WPARAM16)hDrop, 0L );
1519 if( p_data ) TSXFree(p_data);
1521 } /* WS_EX_ACCEPTFILES */
1523 WIN_ReleaseWndPtr(pDropWnd);
1526 /**********************************************************************
1529 * drop items are separated by \n
1530 * each item is prefixed by its mime type
1532 * event->data.l[3], event->data.l[4] contains drop x,y position
1534 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
1538 unsigned long data_length;
1539 unsigned long aux_long, drop_len = 0;
1540 unsigned char *p_data = NULL; /* property data */
1541 char *p_drop = NULL;
1543 int x, y, drop32 = FALSE ;
1554 pWnd = WIN_FindWndPtr(hWnd);
1555 drop32 = pWnd->flags & WIN_ISWIN32;
1557 if (!(pWnd->dwExStyle & WS_EX_ACCEPTFILES))
1559 WIN_ReleaseWndPtr(pWnd);
1562 WIN_ReleaseWndPtr(pWnd);
1564 TSXGetWindowProperty( display, DefaultRootWindow(display),
1565 dndSelection, 0, 65535, FALSE,
1566 AnyPropertyType, &u.atom_aux, &u.i,
1567 &data_length, &aux_long, &p_data);
1569 WARN_(event)("property too large, truncated!\n");
1570 TRACE_(event)("urls=%s\n", p_data);
1572 if( !aux_long && p_data) { /* don't bother if > 64K */
1573 /* calculate length */
1575 next = strchr(p, '\n');
1578 if (strncmp(p,"file:",5) == 0 ) {
1579 INT len = GetShortPathNameA( p+5, NULL, 0 );
1580 if (len) drop_len += len + 1;
1585 next = strchr(p, '\n');
1591 if( drop_len && drop_len < 65535 ) {
1592 TSXQueryPointer( display, X11DRV_GetXRootWindow(), &u.w_aux, &u.w_aux,
1593 &x, &y, &u.i, &u.i, &u.i);
1595 pDropWnd = WIN_FindWndPtr( hWnd );
1598 LPDROPFILESTRUCT lpDrop;
1599 drop_len += sizeof(DROPFILESTRUCT) + 1;
1600 hDrop.h32 = (HDROP)GlobalAlloc( GMEM_SHARE, drop_len );
1601 lpDrop = (LPDROPFILESTRUCT) GlobalLock( hDrop.h32 );
1604 lpDrop->lSize = sizeof(DROPFILESTRUCT);
1605 lpDrop->ptMousePos.x = (INT)x;
1606 lpDrop->ptMousePos.y = (INT)y;
1607 lpDrop->fInNonClientArea = (BOOL)
1608 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1609 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1610 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1611 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1612 lpDrop->fWideChar = FALSE;
1613 p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT);
1616 LPDROPFILESTRUCT16 lpDrop;
1617 drop_len += sizeof(DROPFILESTRUCT16) + 1;
1618 hDrop.h16 = (HDROP16)GlobalAlloc16( GMEM_SHARE, drop_len );
1619 lpDrop = (LPDROPFILESTRUCT16) GlobalLock16( hDrop.h16 );
1622 lpDrop->wSize = sizeof(DROPFILESTRUCT16);
1623 lpDrop->ptMousePos.x = (INT16)x;
1624 lpDrop->ptMousePos.y = (INT16)y;
1625 lpDrop->fInNonClientArea = (BOOL16)
1626 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1627 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1628 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1629 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1630 p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT16);
1634 /* create message content */
1637 next = strchr(p, '\n');
1640 if (strncmp(p,"file:",5) == 0 ) {
1641 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
1643 TRACE_(event)("drop file %s as %s\n", p+5, p_drop);
1646 WARN_(event)("can't convert file %s to dos name \n", p+5);
1649 WARN_(event)("unknown mime type %s\n", p);
1654 next = strchr(p, '\n');
1662 /* can not use PostMessage32A because it is currently based on
1663 * PostMessage16 and WPARAM32 would be truncated to WPARAM16
1665 GlobalUnlock(hDrop.h32);
1666 SendMessageA( hWnd, WM_DROPFILES,
1667 (WPARAM)hDrop.h32, 0L );
1669 GlobalUnlock16(hDrop.h16);
1670 PostMessage16( hWnd, WM_DROPFILES,
1671 (WPARAM16)hDrop.h16, 0L );
1674 WIN_ReleaseWndPtr(pDropWnd);
1676 if( p_data ) TSXFree(p_data);
1680 /**********************************************************************
1681 * EVENT_ClientMessage
1683 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
1685 if (event->message_type != None && event->format == 32) {
1686 if ((event->message_type == wmProtocols) &&
1687 (((Atom) event->data.l[0]) == wmDeleteWindow))
1689 /* Ignore the delete window request if the window has been disabled
1690 * and we are in managed mode. This is to disallow applications from
1691 * being closed by the window manager while in a modal state.
1694 bIsDisabled = GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED;
1696 if ( !Options.managed || !bIsDisabled )
1697 PostMessage16( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
1699 else if ( event->message_type == dndProtocol &&
1700 (event->data.l[0] == DndFile || event->data.l[0] == DndFiles) )
1701 EVENT_DropFromOffiX(hWnd, event);
1702 else if ( event->message_type == dndProtocol &&
1703 event->data.l[0] == DndURL )
1704 EVENT_DropURLs(hWnd, event);
1707 /* enable this if you want to see the message */
1708 unsigned char* p_data = NULL;
1714 TSXGetWindowProperty( display, DefaultRootWindow(display),
1715 dndSelection, 0, 65535, FALSE,
1716 AnyPropertyType, &u.atom, &u.i,
1717 &u.l, &u.l, &p_data);
1718 TRACE_(event)("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1719 event->message_type, event->data.l[0], event->data.l[1],
1720 event->data.l[2], event->data.l[3], event->data.l[4],
1723 TRACE_(event)("unrecognized ClientMessage\n" );
1728 /**********************************************************************
1731 * Install colormap when Wine window is focused in
1732 * self-managed mode with private colormap
1735 void EVENT_EnterNotify( HWND hWnd, XCrossingEvent *event )
1737 if( !Options.managed && X11DRV_GetXRootWindow() == DefaultRootWindow(display) &&
1738 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus() )
1739 TSXInstallColormap( display, X11DRV_PALETTE_GetColormap() );
1743 /**********************************************************************
1746 void EVENT_MapNotify( HWND hWnd, XMapEvent *event )
1748 HWND hwndFocus = GetFocus();
1749 WND *wndFocus = WIN_FindWndPtr(hwndFocus);
1750 WND *pWnd = WIN_FindWndPtr(hWnd);
1751 if (pWnd->flags & WIN_MANAGED)
1753 pWnd->dwStyle &= ~WS_MINIMIZE;
1754 ShowOwnedPopups(hWnd,TRUE);
1756 WIN_ReleaseWndPtr(pWnd);
1758 if (hwndFocus && IsChild( hWnd, hwndFocus ))
1759 X11DRV_WND_SetFocus(wndFocus);
1761 WIN_ReleaseWndPtr(wndFocus);
1767 /**********************************************************************
1770 void EVENT_UnmapNotify( HWND hWnd, XUnmapEvent *event )
1772 WND *pWnd = WIN_FindWndPtr(hWnd);
1773 if (pWnd->flags & WIN_MANAGED)
1776 if( pWnd->dwStyle & WS_VISIBLE )
1778 pWnd->dwStyle |= WS_MINIMIZE;
1779 ShowOwnedPopups(hWnd,FALSE);
1782 WIN_ReleaseWndPtr(pWnd);
1786 #endif /* !defined(X_DISPLAY_MISSING) */