4 * Copyright 1993 Alexandre Julliard
9 #ifndef X_DISPLAY_MISSING
11 #include <X11/Xatom.h>
12 #include <X11/keysym.h>
14 #include "ts_xresource.h"
20 #include "clipboard.h"
22 #include "debugtools.h"
37 DECLARE_DEBUG_CHANNEL(event
)
38 DECLARE_DEBUG_CHANNEL(win
)
40 /* X context to associate a hwnd to an X window */
41 extern XContext winContext
;
43 extern Atom wmProtocols
;
44 extern Atom wmDeleteWindow
;
45 extern Atom dndProtocol
;
46 extern Atom dndSelection
;
48 extern void X11DRV_KEYBOARD_UpdateState(void);
49 extern void X11DRV_KEYBOARD_HandleEvent(WND
*pWnd
, XKeyEvent
*event
);
51 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
53 #define DndNotDnd -1 /* OffiX drag&drop */
65 #define DndURL 128 /* KDE drag&drop */
67 /* The last X window which had the focus */
68 static Window glastXFocusWin
= 0;
70 static const char * const event_names
[] =
72 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
73 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
74 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
75 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
76 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
77 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
78 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
79 "ClientMessage", "MappingNotify"
82 static void CALLBACK
EVENT_Flush( ULONG_PTR arg
);
83 static void CALLBACK
EVENT_ProcessAllEvents( ULONG_PTR arg
);
84 static void EVENT_ProcessEvent( XEvent
*event
);
87 static void EVENT_Key( HWND hWnd
, XKeyEvent
*event
);
88 static void EVENT_ButtonPress( HWND hWnd
, XButtonEvent
*event
);
89 static void EVENT_ButtonRelease( HWND hWnd
, XButtonEvent
*event
);
90 static void EVENT_MotionNotify( HWND hWnd
, XMotionEvent
*event
);
91 static void EVENT_FocusIn( HWND hWnd
, XFocusChangeEvent
*event
);
92 static void EVENT_FocusOut( HWND hWnd
, XFocusChangeEvent
*event
);
93 static void EVENT_Expose( HWND hWnd
, XExposeEvent
*event
);
94 static void EVENT_GraphicsExpose( HWND hWnd
, XGraphicsExposeEvent
*event
);
95 static void EVENT_ConfigureNotify( HWND hWnd
, XConfigureEvent
*event
);
96 static void EVENT_SelectionRequest( HWND hWnd
, XSelectionRequestEvent
*event
);
97 static void EVENT_SelectionClear( HWND hWnd
, XSelectionClearEvent
*event
);
98 static void EVENT_ClientMessage( HWND hWnd
, XClientMessageEvent
*event
);
99 static void EVENT_MapNotify( HWND pWnd
, XMapEvent
*event
);
100 static void EVENT_UnmapNotify( HWND pWnd
, XUnmapEvent
*event
);
102 /* Usable only with OLVWM - compile option perhaps?
103 static void EVENT_EnterNotify( HWND hWnd, XCrossingEvent *event );
106 static void EVENT_GetGeometry( Window win
, int *px
, int *py
,
107 unsigned int *pwidth
, unsigned int *pheight
);
110 static BOOL bUserRepaintDisabled
= TRUE
;
113 /***********************************************************************
116 BOOL
X11DRV_EVENT_Init(void)
118 /* Install the X event processing callback */
119 SERVICE_AddObject( FILE_DupUnixHandle( ConnectionNumber(display
),
120 GENERIC_READ
| SYNCHRONIZE
),
121 EVENT_ProcessAllEvents
, 0 );
123 /* Install the XFlush timer callback */
124 if ( Options
.synchronous
)
125 TSXSynchronize( display
, True
);
127 SERVICE_AddTimer( 200000L, EVENT_Flush
, 0 );
132 /***********************************************************************
135 static void CALLBACK
EVENT_Flush( ULONG_PTR arg
)
140 /***********************************************************************
141 * EVENT_ProcessAllEvents
143 static void CALLBACK
EVENT_ProcessAllEvents( ULONG_PTR arg
)
147 TRACE_(event
)( "called.\n" );
149 EnterCriticalSection( &X11DRV_CritSection
);
150 while ( XPending( display
) )
152 XNextEvent( display
, &event
);
154 LeaveCriticalSection( &X11DRV_CritSection
);
155 EVENT_ProcessEvent( &event
);
156 EnterCriticalSection( &X11DRV_CritSection
);
158 LeaveCriticalSection( &X11DRV_CritSection
);
161 /***********************************************************************
164 * Synchronize with the X server. Should not be used too often.
166 void X11DRV_EVENT_Synchronize( void )
168 TSXSync( display
, False
);
169 EVENT_ProcessAllEvents( 0 );
172 /***********************************************************************
173 * EVENT_UserRepaintDisable
175 void X11DRV_EVENT_UserRepaintDisable( BOOL bDisabled
)
177 bUserRepaintDisabled
= bDisabled
;
180 /***********************************************************************
183 * Process an X event.
185 static void EVENT_ProcessEvent( XEvent
*event
)
189 TRACE_(event
)( "called.\n" );
193 case SelectionNotify
: /* all of these should be caught by XCheckTypedWindowEvent() */
194 FIXME_(event
)("Got SelectionNotify - must not happen!\n");
197 /* We get all these because of StructureNotifyMask.
198 This check is placed here to avoid getting error messages below,
199 as X might send some of these even for windows that have already
201 case CirculateNotify
:
209 if ( TSXFindContext( display
, event
->xany
.window
, winContext
,
210 (char **)&hWnd
) != 0) {
211 if ( event
->type
== ClientMessage
) {
212 /* query window (drag&drop event contains only drag window) */
214 int root_x
, root_y
, child_x
, child_y
;
216 TSXQueryPointer( display
, X11DRV_GetXRootWindow(), &root
, &child
,
217 &root_x
, &root_y
, &child_x
, &child_y
, &u
);
218 if (TSXFindContext( display
, child
, winContext
, (char **)&hWnd
) != 0)
221 hWnd
= 0; /* Not for a registered window */
225 if ( !hWnd
&& event
->xany
.window
!= X11DRV_GetXRootWindow() )
226 ERR_(event
)("Got event %s for unknown Window %08lx\n",
227 event_names
[event
->type
], event
->xany
.window
);
229 TRACE_(event
)("Got event %s for hwnd %04x\n",
230 event_names
[event
->type
], hWnd
);
237 EVENT_Key( hWnd
, (XKeyEvent
*)event
);
241 EVENT_ButtonPress( hWnd
, (XButtonEvent
*)event
);
245 EVENT_ButtonRelease( hWnd
, (XButtonEvent
*)event
);
249 /* Wine between two fast machines across the overloaded campus
250 ethernet gets very boged down in MotionEvents. The following
251 simply finds the last motion event in the queue and drops
252 the rest. On a good link events are servered before they build
253 up so this doesn't take place. On a slow link this may cause
254 problems if the event order is important. I'm not yet seen
255 of any problems. Jon 7/6/96.
257 while (TSXCheckTypedWindowEvent(display
,((XAnyEvent
*)event
)->window
,
258 MotionNotify
, event
));
259 EVENT_MotionNotify( hWnd
, (XMotionEvent
*)event
);
264 WND
*pWndLastFocus
= 0;
265 XWindowAttributes win_attr
;
267 XFocusChangeEvent
*xfocChange
= (XFocusChangeEvent
*)event
;
269 if (!hWnd
|| bUserRepaintDisabled
) return;
271 bIsDisabled
= GetWindowLongA( hWnd
, GWL_STYLE
) & WS_DISABLED
;
273 /* If the window has been disabled and we are in managed mode,
274 * revert the X focus back to the last focus window. This is to disallow
275 * the window manager from switching focus away while the app is
278 if ( Options
.managed
&& bIsDisabled
&& glastXFocusWin
)
280 /* Change focus only if saved focus window is registered and viewable */
281 if ( TSXFindContext( xfocChange
->display
, glastXFocusWin
, winContext
,
282 (char **)&pWndLastFocus
) == 0 )
284 if ( TSXGetWindowAttributes( display
, glastXFocusWin
, &win_attr
) &&
285 (win_attr
.map_state
== IsViewable
) )
287 TSXSetInputFocus( xfocChange
->display
, glastXFocusWin
, RevertToParent
, CurrentTime
);
294 EVENT_FocusIn( hWnd
, xfocChange
);
300 /* Save the last window which had the focus */
301 XFocusChangeEvent
*xfocChange
= (XFocusChangeEvent
*)event
;
302 glastXFocusWin
= xfocChange
->window
;
303 if (!hWnd
|| bUserRepaintDisabled
) return;
304 EVENT_FocusOut( hWnd
, (XFocusChangeEvent
*)event
);
309 if (bUserRepaintDisabled
) return;
310 EVENT_Expose( hWnd
, (XExposeEvent
*)event
);
314 if (bUserRepaintDisabled
) return;
315 EVENT_GraphicsExpose( hWnd
, (XGraphicsExposeEvent
*)event
);
318 case ConfigureNotify
:
319 if (!hWnd
|| bUserRepaintDisabled
) return;
320 EVENT_ConfigureNotify( hWnd
, (XConfigureEvent
*)event
);
323 case SelectionRequest
:
324 if (!hWnd
|| bUserRepaintDisabled
) return;
325 EVENT_SelectionRequest( hWnd
, (XSelectionRequestEvent
*)event
);
329 if (!hWnd
|| bUserRepaintDisabled
) return;
330 EVENT_SelectionClear( hWnd
, (XSelectionClearEvent
*) event
);
334 if (!hWnd
|| bUserRepaintDisabled
) return;
335 EVENT_ClientMessage( hWnd
, (XClientMessageEvent
*) event
);
340 EVENT_EnterNotify( hWnd
, (XCrossingEvent
*) event
);
348 if (!hWnd
|| bUserRepaintDisabled
) return;
349 EVENT_MapNotify( hWnd
, (XMapEvent
*)event
);
353 if (!hWnd
|| bUserRepaintDisabled
) return;
354 EVENT_UnmapNotify( hWnd
, (XUnmapEvent
*)event
);
358 WARN_(event
)("Unprocessed event %s for hwnd %04x\n",
359 event_names
[event
->type
], hWnd
);
364 /***********************************************************************
367 * Synchronize internal z-order with the window manager's.
369 static BOOL
__check_query_condition( WND
** pWndA
, WND
** pWndB
)
371 /* return TRUE if we have at least two managed windows */
373 for( *pWndB
= NULL
; *pWndA
; *pWndA
= (*pWndA
)->next
)
374 if( (*pWndA
)->flags
& WIN_MANAGED
&&
375 (*pWndA
)->dwStyle
& WS_VISIBLE
) break;
377 for( *pWndB
= (*pWndA
)->next
; *pWndB
; *pWndB
= (*pWndB
)->next
)
378 if( (*pWndB
)->flags
& WIN_MANAGED
&&
379 (*pWndB
)->dwStyle
& WS_VISIBLE
) break;
380 return ((*pWndB
) != NULL
);
383 static Window
__get_common_ancestor( Window A
, Window B
,
384 Window
** children
, unsigned* total
)
386 /* find the real root window */
388 Window root
, *childrenB
;
393 TSXQueryTree( display
, A
, &root
, &A
, children
, total
);
394 TSXQueryTree( display
, B
, &root
, &B
, &childrenB
, &totalB
);
395 if( childrenB
) TSXFree( childrenB
);
396 if( *children
) TSXFree( *children
), *children
= NULL
;
397 } while( A
!= B
&& A
&& B
);
401 TSXQueryTree( display
, A
, &root
, &B
, children
, total
);
407 static Window
__get_top_decoration( Window w
, Window ancestor
)
409 Window
* children
, root
, prev
= w
, parent
= w
;
415 TSXQueryTree( display
, w
, &root
, &parent
, &children
, &total
);
416 if( children
) TSXFree( children
);
417 } while( parent
&& parent
!= ancestor
);
418 TRACE_(event
)("\t%08x -> %08x\n", (unsigned)prev
, (unsigned)w
);
419 return ( parent
) ? w
: 0 ;
422 static unsigned __td_lookup( Window w
, Window
* list
, unsigned max
)
425 for( i
= max
- 1; i
>= 0; i
-- ) if( list
[i
] == w
) break;
429 static HWND
EVENT_QueryZOrder( HWND hWndCheck
)
431 HWND hwndInsertAfter
= HWND_TOP
;
432 WND
*pWndCheck
= WIN_FindWndPtr(hWndCheck
);
433 WND
*pDesktop
= WIN_GetDesktop();
434 WND
*pWnd
, *pWndZ
= WIN_LockWndPtr(pDesktop
->child
);
435 Window w
, parent
, *children
= NULL
;
436 unsigned total
, check
, pos
, best
;
438 if( !__check_query_condition(&pWndZ
, &pWnd
) )
440 WIN_ReleaseWndPtr(pWndCheck
);
441 WIN_ReleaseWndPtr(pDesktop
->child
);
442 WIN_ReleaseDesktop();
443 return hwndInsertAfter
;
445 WIN_LockWndPtr(pWndZ
);
446 WIN_LockWndPtr(pWnd
);
447 WIN_ReleaseWndPtr(pDesktop
->child
);
448 WIN_ReleaseDesktop();
450 parent
= __get_common_ancestor( X11DRV_WND_GetXWindow(pWndZ
),
451 X11DRV_WND_GetXWindow(pWnd
),
453 if( parent
&& children
)
455 /* w is the ancestor if pWndCheck that is a direct descendant of 'parent' */
457 w
= __get_top_decoration( X11DRV_WND_GetXWindow(pWndCheck
), parent
);
459 if( w
!= children
[total
-1] ) /* check if at the top */
461 /* X child at index 0 is at the bottom, at index total-1 is at the top */
462 check
= __td_lookup( w
, children
, total
);
465 for( WIN_UpdateWndPtr(&pWnd
,pWndZ
); pWnd
;WIN_UpdateWndPtr(&pWnd
,pWnd
->next
))
467 /* go through all windows in Wine z-order... */
469 if( pWnd
!= pWndCheck
)
471 if( !(pWnd
->flags
& WIN_MANAGED
) ||
472 !(w
= __get_top_decoration( X11DRV_WND_GetXWindow(pWnd
), parent
)) )
474 pos
= __td_lookup( w
, children
, total
);
475 if( pos
< best
&& pos
> check
)
477 /* find a nearest Wine window precedes
478 * pWndCheck in the real z-order... */
480 hwndInsertAfter
= pWnd
->hwndSelf
;
482 if( best
- check
== 1 ) break;
487 if( children
) TSXFree( children
);
488 WIN_ReleaseWndPtr(pWnd
);
489 WIN_ReleaseWndPtr(pWndZ
);
490 WIN_ReleaseWndPtr(pWndCheck
);
491 return hwndInsertAfter
;
494 /***********************************************************************
495 * EVENT_XStateToKeyState
497 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
498 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
500 static WORD
EVENT_XStateToKeyState( int state
)
504 if (state
& Button1Mask
) kstate
|= MK_LBUTTON
;
505 if (state
& Button2Mask
) kstate
|= MK_MBUTTON
;
506 if (state
& Button3Mask
) kstate
|= MK_RBUTTON
;
507 if (state
& ShiftMask
) kstate
|= MK_SHIFT
;
508 if (state
& ControlMask
) kstate
|= MK_CONTROL
;
512 /***********************************************************************
513 * X11DRV_EVENT_QueryPointer
515 BOOL
X11DRV_EVENT_QueryPointer(DWORD
*posX
, DWORD
*posY
, DWORD
*state
)
518 int rootX
, rootY
, winX
, winY
;
521 if (!TSXQueryPointer( display
, X11DRV_GetXRootWindow(), &root
, &child
,
522 &rootX
, &rootY
, &winX
, &winY
, &xstate
))
530 *state
= EVENT_XStateToKeyState( xstate
);
535 /***********************************************************************
538 static void EVENT_Expose( HWND hWnd
, XExposeEvent
*event
)
542 WND
*pWnd
= WIN_FindWndPtr(hWnd
);
543 /* Make position relative to client area instead of window */
544 rect
.left
= event
->x
- (pWnd
? (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
) : 0);
545 rect
.top
= event
->y
- (pWnd
? (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
) : 0);
546 rect
.right
= rect
.left
+ event
->width
;
547 rect
.bottom
= rect
.top
+ event
->height
;
548 WIN_ReleaseWndPtr(pWnd
);
550 Callout
.RedrawWindow( hWnd
, &rect
, 0,
551 RDW_INVALIDATE
| RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
|
552 (event
->count
? 0 : RDW_ERASENOW
) );
556 /***********************************************************************
557 * EVENT_GraphicsExpose
559 * This is needed when scrolling area is partially obscured
560 * by non-Wine X window.
562 static void EVENT_GraphicsExpose( HWND hWnd
, XGraphicsExposeEvent
*event
)
565 WND
*pWnd
= WIN_FindWndPtr(hWnd
);
567 /* Make position relative to client area instead of window */
568 rect
.left
= event
->x
- (pWnd
? (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
) : 0);
569 rect
.top
= event
->y
- (pWnd
? (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
) : 0);
570 rect
.right
= rect
.left
+ event
->width
;
571 rect
.bottom
= rect
.top
+ event
->height
;
573 WIN_ReleaseWndPtr(pWnd
);
575 Callout
.RedrawWindow( hWnd
, &rect
, 0,
576 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASE
|
577 (event
->count
? 0 : RDW_ERASENOW
) );
581 /***********************************************************************
584 * Handle a X key event
586 static void EVENT_Key( HWND hWnd
, XKeyEvent
*event
)
588 WND
*pWnd
= WIN_FindWndPtr(hWnd
);
589 X11DRV_KEYBOARD_HandleEvent( pWnd
, event
);
590 WIN_ReleaseWndPtr(pWnd
);
595 /***********************************************************************
598 static void EVENT_MotionNotify( HWND hWnd
, XMotionEvent
*event
)
600 WND
*pWnd
= WIN_FindWndPtr(hWnd
);
601 int xOffset
= pWnd
? pWnd
->rectWindow
.left
: 0;
602 int yOffset
= pWnd
? pWnd
->rectWindow
.top
: 0;
603 WIN_ReleaseWndPtr(pWnd
);
605 MOUSE_SendEvent( MOUSEEVENTF_MOVE
,
606 xOffset
+ event
->x
, yOffset
+ event
->y
,
607 EVENT_XStateToKeyState( event
->state
),
608 event
->time
- MSG_WineStartTicks
,
613 /***********************************************************************
616 static void EVENT_ButtonPress( HWND hWnd
, XButtonEvent
*event
)
618 static WORD statusCodes
[NB_BUTTONS
] =
619 { MOUSEEVENTF_LEFTDOWN
, MOUSEEVENTF_MIDDLEDOWN
, MOUSEEVENTF_RIGHTDOWN
};
620 int buttonNum
= event
->button
- 1;
622 WND
*pWnd
= WIN_FindWndPtr(hWnd
);
623 int xOffset
= pWnd
? pWnd
->rectWindow
.left
: 0;
624 int yOffset
= pWnd
? pWnd
->rectWindow
.top
: 0;
627 WIN_ReleaseWndPtr(pWnd
);
629 if (buttonNum
>= NB_BUTTONS
) return;
632 * Get the compatible keystate
634 keystate
= EVENT_XStateToKeyState( event
->state
);
637 * Make sure that the state of the button that was just
643 keystate
|= MK_LBUTTON
;
646 keystate
|= MK_MBUTTON
;
649 keystate
|= MK_RBUTTON
;
653 MOUSE_SendEvent( statusCodes
[buttonNum
],
654 xOffset
+ event
->x
, yOffset
+ event
->y
,
656 event
->time
- MSG_WineStartTicks
,
661 /***********************************************************************
662 * EVENT_ButtonRelease
664 static void EVENT_ButtonRelease( HWND hWnd
, XButtonEvent
*event
)
666 static WORD statusCodes
[NB_BUTTONS
] =
667 { MOUSEEVENTF_LEFTUP
, MOUSEEVENTF_MIDDLEUP
, MOUSEEVENTF_RIGHTUP
};
668 int buttonNum
= event
->button
- 1;
669 WND
*pWnd
= WIN_FindWndPtr(hWnd
);
670 int xOffset
= pWnd
? pWnd
->rectWindow
.left
: 0;
671 int yOffset
= pWnd
? pWnd
->rectWindow
.top
: 0;
674 WIN_ReleaseWndPtr(pWnd
);
676 if (buttonNum
>= NB_BUTTONS
) return;
679 * Get the compatible keystate
681 keystate
= EVENT_XStateToKeyState( event
->state
);
684 * Make sure that the state of the button that was just
690 keystate
&= ~MK_LBUTTON
;
693 keystate
&= ~MK_MBUTTON
;
696 keystate
&= ~MK_RBUTTON
;
700 MOUSE_SendEvent( statusCodes
[buttonNum
],
701 xOffset
+ event
->x
, yOffset
+ event
->y
,
703 event
->time
- MSG_WineStartTicks
,
708 /**********************************************************************
711 static void EVENT_FocusIn( HWND hWnd
, XFocusChangeEvent
*event
)
713 if (event
->detail
!= NotifyPointer
)
714 if (hWnd
!= GetForegroundWindow())
716 SetForegroundWindow( hWnd
);
717 X11DRV_KEYBOARD_UpdateState();
722 /**********************************************************************
725 * Note: only top-level override-redirect windows get FocusOut events.
727 static void EVENT_FocusOut( HWND hWnd
, XFocusChangeEvent
*event
)
729 if (event
->detail
!= NotifyPointer
)
730 if (hWnd
== GetForegroundWindow())
732 SendMessageA( hWnd
, WM_CANCELMODE
, 0, 0 );
733 SetForegroundWindow( 0 );
737 /**********************************************************************
738 * X11DRV_EVENT_CheckFocus
740 BOOL
X11DRV_EVENT_CheckFocus(void)
746 TSXGetInputFocus(display
, &xW
, &state
);
748 TSXFindContext(display
, xW
, winContext
, (char **)&hWnd
) )
753 /**********************************************************************
756 * Helper function for ConfigureNotify handling.
757 * Get the new geometry of a window relative to the root window.
759 static void EVENT_GetGeometry( Window win
, int *px
, int *py
,
760 unsigned int *pwidth
, unsigned int *pheight
)
763 int x
, y
, width
, height
, border
, depth
;
765 EnterCriticalSection( &X11DRV_CritSection
);
767 /* Get the geometry of the window */
768 XGetGeometry( display
, win
, &root
, &x
, &y
, &width
, &height
,
771 /* Translate the window origin to root coordinates */
772 XTranslateCoordinates( display
, win
, root
, 0, 0, &x
, &y
, &top
);
774 LeaveCriticalSection( &X11DRV_CritSection
);
782 /**********************************************************************
783 * EVENT_ConfigureNotify
785 * The ConfigureNotify event is only selected on top-level windows
786 * when the -managed flag is used.
788 static void EVENT_ConfigureNotify( HWND hWnd
, XConfigureEvent
*event
)
792 unsigned int width
, height
;
793 HWND newInsertAfter
, oldInsertAfter
;
795 /* Get geometry and Z-order according to X */
797 EVENT_GetGeometry( event
->window
, &x
, &y
, &width
, &height
);
798 newInsertAfter
= EVENT_QueryZOrder( hWnd
);
800 /* Get geometry and Z-order according to Wine */
802 GetWindowRect( hWnd
, &rectWindow
);
803 oldInsertAfter
= GetWindow( hWnd
, GW_HWNDPREV
);
804 if ( !oldInsertAfter
) oldInsertAfter
= HWND_TOP
;
806 /* Compare what has changed */
808 if ( rectWindow
.left
== x
&& rectWindow
.top
== y
)
811 TRACE_(win
)( "%04x moving from (%d,%d) to (%d,%d)\n", hWnd
,
812 rectWindow
.left
, rectWindow
.top
, x
, y
);
814 if ( rectWindow
.right
- rectWindow
.left
== width
815 && rectWindow
.bottom
- rectWindow
.top
== height
)
818 TRACE_(win
)( "%04x resizing from (%d,%d) to (%d,%d)\n", hWnd
,
819 rectWindow
.right
- rectWindow
.left
,
820 rectWindow
.bottom
- rectWindow
.top
, width
, height
);
822 if ( newInsertAfter
== oldInsertAfter
)
823 flags
|= SWP_NOZORDER
;
825 TRACE_(win
)( "%04x restacking from after %04x to after %04x\n", hWnd
,
826 oldInsertAfter
, newInsertAfter
);
828 /* If anything changed, call SetWindowPos */
830 if ( flags
!= (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
) )
831 SetWindowPos( hWnd
, newInsertAfter
, x
, y
, width
, height
,
832 flags
| SWP_NOACTIVATE
| SWP_WINE_NOHOSTMOVE
);
836 /***********************************************************************
837 * EVENT_SelectionRequest
839 static void EVENT_SelectionRequest( HWND hWnd
, XSelectionRequestEvent
*event
)
841 XSelectionEvent result
;
843 Window request
= event
->requestor
;
845 if(event
->target
== XA_STRING
)
851 rprop
= event
->property
;
854 rprop
= event
->target
;
856 if( event
->selection
!= XA_PRIMARY
)
859 if( !CLIPBOARD_IsPresent(CF_OEMTEXT
) )
863 /* open to make sure that clipboard is available */
865 BOOL couldOpen
= OpenClipboard( hWnd
);
868 hText
= GetClipboardData16(CF_TEXT
);
869 text
= GlobalLock16(hText
);
870 size
= GlobalSize16(hText
);
872 /* remove carriage returns */
874 lpstr
= (char*)HEAP_xalloc( GetProcessHeap(), 0, size
-- );
875 for(i
=0,j
=0; i
< size
&& text
[i
]; i
++ )
877 if( text
[i
] == '\r' &&
878 (text
[i
+1] == '\n' || text
[i
+1] == '\0') ) continue;
879 lpstr
[j
++] = text
[i
];
883 TSXChangeProperty(display
, request
, rprop
,
884 XA_STRING
, 8, PropModeReplace
,
886 HeapFree( GetProcessHeap(), 0, lpstr
);
888 /* close only if we opened before */
890 if(couldOpen
) CloseClipboard();
895 TRACE_(event
)("Request for %s ignored\n", TSXGetAtomName(display
,event
->target
));
897 /* reply to sender */
899 result
.type
= SelectionNotify
;
900 result
.display
= display
;
901 result
.requestor
= request
;
902 result
.selection
= event
->selection
;
903 result
.property
= rprop
;
904 result
.target
= event
->target
;
905 result
.time
= event
->time
;
906 TSXSendEvent(display
,event
->requestor
,False
,NoEventMask
,(XEvent
*)&result
);
909 /***********************************************************************
910 * EVENT_SelectionClear
912 static void EVENT_SelectionClear( HWND hWnd
, XSelectionClearEvent
*event
)
914 if (event
->selection
!= XA_PRIMARY
) return;
915 X11DRV_CLIPBOARD_ReleaseSelection( event
->window
, hWnd
);
919 /**********************************************************************
920 * EVENT_DropFromOffix
922 * don't know if it still works (last Changlog is from 96/11/04)
924 static void EVENT_DropFromOffiX( HWND hWnd
, XClientMessageEvent
*event
)
926 unsigned long data_length
;
927 unsigned long aux_long
;
928 unsigned char* p_data
= NULL
;
939 HGLOBAL16 hDragInfo
= GlobalAlloc16( GMEM_SHARE
| GMEM_ZEROINIT
, sizeof(DRAGINFO
));
940 LPDRAGINFO lpDragInfo
= (LPDRAGINFO
) GlobalLock16(hDragInfo
);
941 SEGPTR spDragInfo
= (SEGPTR
) WIN16_GlobalLock16(hDragInfo
);
942 Window w_aux_root
, w_aux_child
;
946 if( !lpDragInfo
|| !spDragInfo
) return;
948 pWnd
= WIN_FindWndPtr(hWnd
);
950 TSXQueryPointer( display
, X11DRV_WND_GetXWindow(pWnd
), &w_aux_root
, &w_aux_child
,
951 &x
, &y
, (int *) &u
.pt_aux
.x
, (int *) &u
.pt_aux
.y
,
952 (unsigned int*)&aux_long
);
954 lpDragInfo
->hScope
= hWnd
;
955 lpDragInfo
->pt
.x
= (INT16
)x
; lpDragInfo
->pt
.y
= (INT16
)y
;
957 /* find out drop point and drop window */
958 if( x
< 0 || y
< 0 ||
959 x
> (pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) ||
960 y
> (pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
) )
961 { bAccept
= pWnd
->dwExStyle
& WS_EX_ACCEPTFILES
; x
= y
= 0; }
964 bAccept
= DRAG_QueryUpdate( hWnd
, spDragInfo
, TRUE
);
965 x
= lpDragInfo
->pt
.x
; y
= lpDragInfo
->pt
.y
;
967 pDropWnd
= WIN_FindWndPtr( lpDragInfo
->hScope
);
968 WIN_ReleaseWndPtr(pWnd
);
970 GlobalFree16( hDragInfo
);
974 TSXGetWindowProperty( display
, DefaultRootWindow(display
),
975 dndSelection
, 0, 65535, FALSE
,
976 AnyPropertyType
, &u
.atom_aux
, (int *) &u
.pt_aux
.y
,
977 &data_length
, &aux_long
, &p_data
);
979 if( !aux_long
&& p_data
) /* don't bother if > 64K */
981 char *p
= (char*) p_data
;
985 while( *p
) /* calculate buffer size */
988 if((u
.i
= *p
) != -1 )
989 u
.i
= DRIVE_FindDriveRoot( (const char **)&p_drop
);
990 if( u
.i
== -1 ) *p
= -1; /* mark as "bad" */
993 INT len
= GetShortPathNameA( p
, NULL
, 0 );
994 if (len
) aux_long
+= len
+ 1;
999 if( aux_long
&& aux_long
< 65535 )
1002 LPDROPFILESTRUCT16 lpDrop
;
1004 aux_long
+= sizeof(DROPFILESTRUCT16
) + 1;
1005 hDrop
= (HDROP16
)GlobalAlloc16( GMEM_SHARE
, aux_long
);
1006 lpDrop
= (LPDROPFILESTRUCT16
) GlobalLock16( hDrop
);
1010 lpDrop
->wSize
= sizeof(DROPFILESTRUCT16
);
1011 lpDrop
->ptMousePos
.x
= (INT16
)x
;
1012 lpDrop
->ptMousePos
.y
= (INT16
)y
;
1013 lpDrop
->fInNonClientArea
= (BOOL16
)
1014 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
1015 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
1016 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
1017 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
1018 p_drop
= ((char*)lpDrop
) + sizeof(DROPFILESTRUCT16
);
1022 if( *p
!= -1 ) /* use only "good" entries */
1024 GetShortPathNameA( p
, p_drop
, 65535 );
1025 p_drop
+= strlen( p_drop
) + 1;
1030 PostMessage16( hWnd
, WM_DROPFILES
,
1031 (WPARAM16
)hDrop
, 0L );
1035 if( p_data
) TSXFree(p_data
);
1037 } /* WS_EX_ACCEPTFILES */
1039 WIN_ReleaseWndPtr(pDropWnd
);
1042 /**********************************************************************
1045 * drop items are separated by \n
1046 * each item is prefixed by its mime type
1048 * event->data.l[3], event->data.l[4] contains drop x,y position
1050 static void EVENT_DropURLs( HWND hWnd
, XClientMessageEvent
*event
)
1054 unsigned long data_length
;
1055 unsigned long aux_long
, drop_len
= 0;
1056 unsigned char *p_data
= NULL
; /* property data */
1057 char *p_drop
= NULL
;
1059 int x
, y
, drop32
= FALSE
;
1070 pWnd
= WIN_FindWndPtr(hWnd
);
1071 drop32
= pWnd
->flags
& WIN_ISWIN32
;
1073 if (!(pWnd
->dwExStyle
& WS_EX_ACCEPTFILES
))
1075 WIN_ReleaseWndPtr(pWnd
);
1078 WIN_ReleaseWndPtr(pWnd
);
1080 TSXGetWindowProperty( display
, DefaultRootWindow(display
),
1081 dndSelection
, 0, 65535, FALSE
,
1082 AnyPropertyType
, &u
.atom_aux
, &u
.i
,
1083 &data_length
, &aux_long
, &p_data
);
1085 WARN_(event
)("property too large, truncated!\n");
1086 TRACE_(event
)("urls=%s\n", p_data
);
1088 if( !aux_long
&& p_data
) { /* don't bother if > 64K */
1089 /* calculate length */
1091 next
= strchr(p
, '\n');
1094 if (strncmp(p
,"file:",5) == 0 ) {
1095 INT len
= GetShortPathNameA( p
+5, NULL
, 0 );
1096 if (len
) drop_len
+= len
+ 1;
1101 next
= strchr(p
, '\n');
1107 if( drop_len
&& drop_len
< 65535 ) {
1108 TSXQueryPointer( display
, X11DRV_GetXRootWindow(), &u
.w_aux
, &u
.w_aux
,
1109 &x
, &y
, &u
.i
, &u
.i
, &u
.i
);
1111 pDropWnd
= WIN_FindWndPtr( hWnd
);
1114 LPDROPFILESTRUCT lpDrop
;
1115 drop_len
+= sizeof(DROPFILESTRUCT
) + 1;
1116 hDrop
.h32
= (HDROP
)GlobalAlloc( GMEM_SHARE
, drop_len
);
1117 lpDrop
= (LPDROPFILESTRUCT
) GlobalLock( hDrop
.h32
);
1120 lpDrop
->lSize
= sizeof(DROPFILESTRUCT
);
1121 lpDrop
->ptMousePos
.x
= (INT
)x
;
1122 lpDrop
->ptMousePos
.y
= (INT
)y
;
1123 lpDrop
->fInNonClientArea
= (BOOL
)
1124 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
1125 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
1126 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
1127 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
1128 lpDrop
->fWideChar
= FALSE
;
1129 p_drop
= ((char*)lpDrop
) + sizeof(DROPFILESTRUCT
);
1132 LPDROPFILESTRUCT16 lpDrop
;
1133 drop_len
+= sizeof(DROPFILESTRUCT16
) + 1;
1134 hDrop
.h16
= (HDROP16
)GlobalAlloc16( GMEM_SHARE
, drop_len
);
1135 lpDrop
= (LPDROPFILESTRUCT16
) GlobalLock16( hDrop
.h16
);
1138 lpDrop
->wSize
= sizeof(DROPFILESTRUCT16
);
1139 lpDrop
->ptMousePos
.x
= (INT16
)x
;
1140 lpDrop
->ptMousePos
.y
= (INT16
)y
;
1141 lpDrop
->fInNonClientArea
= (BOOL16
)
1142 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
1143 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
1144 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
1145 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
1146 p_drop
= ((char*)lpDrop
) + sizeof(DROPFILESTRUCT16
);
1150 /* create message content */
1153 next
= strchr(p
, '\n');
1156 if (strncmp(p
,"file:",5) == 0 ) {
1157 INT len
= GetShortPathNameA( p
+5, p_drop
, 65535 );
1159 TRACE_(event
)("drop file %s as %s\n", p
+5, p_drop
);
1162 WARN_(event
)("can't convert file %s to dos name \n", p
+5);
1165 WARN_(event
)("unknown mime type %s\n", p
);
1170 next
= strchr(p
, '\n');
1178 /* can not use PostMessage32A because it is currently based on
1179 * PostMessage16 and WPARAM32 would be truncated to WPARAM16
1181 GlobalUnlock(hDrop
.h32
);
1182 SendMessageA( hWnd
, WM_DROPFILES
,
1183 (WPARAM
)hDrop
.h32
, 0L );
1185 GlobalUnlock16(hDrop
.h16
);
1186 PostMessage16( hWnd
, WM_DROPFILES
,
1187 (WPARAM16
)hDrop
.h16
, 0L );
1190 WIN_ReleaseWndPtr(pDropWnd
);
1192 if( p_data
) TSXFree(p_data
);
1196 /**********************************************************************
1197 * EVENT_ClientMessage
1199 static void EVENT_ClientMessage( HWND hWnd
, XClientMessageEvent
*event
)
1201 if (event
->message_type
!= None
&& event
->format
== 32) {
1202 if ((event
->message_type
== wmProtocols
) &&
1203 (((Atom
) event
->data
.l
[0]) == wmDeleteWindow
))
1205 /* Ignore the delete window request if the window has been disabled
1206 * and we are in managed mode. This is to disallow applications from
1207 * being closed by the window manager while in a modal state.
1210 bIsDisabled
= GetWindowLongA( hWnd
, GWL_STYLE
) & WS_DISABLED
;
1212 if ( !Options
.managed
|| !bIsDisabled
)
1213 SendMessage16( hWnd
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
1215 else if ( event
->message_type
== dndProtocol
&&
1216 (event
->data
.l
[0] == DndFile
|| event
->data
.l
[0] == DndFiles
) )
1217 EVENT_DropFromOffiX(hWnd
, event
);
1218 else if ( event
->message_type
== dndProtocol
&&
1219 event
->data
.l
[0] == DndURL
)
1220 EVENT_DropURLs(hWnd
, event
);
1223 /* enable this if you want to see the message */
1224 unsigned char* p_data
= NULL
;
1230 TSXGetWindowProperty( display
, DefaultRootWindow(display
),
1231 dndSelection
, 0, 65535, FALSE
,
1232 AnyPropertyType
, &u
.atom
, &u
.i
,
1233 &u
.l
, &u
.l
, &p_data
);
1234 TRACE_(event
)("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1235 event
->message_type
, event
->data
.l
[0], event
->data
.l
[1],
1236 event
->data
.l
[2], event
->data
.l
[3], event
->data
.l
[4],
1239 TRACE_(event
)("unrecognized ClientMessage\n" );
1244 /**********************************************************************
1247 * Install colormap when Wine window is focused in
1248 * self-managed mode with private colormap
1251 void EVENT_EnterNotify( HWND hWnd
, XCrossingEvent
*event
)
1253 if( !Options
.managed
&& X11DRV_GetXRootWindow() == DefaultRootWindow(display
) &&
1254 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE
) && GetFocus() )
1255 TSXInstallColormap( display
, X11DRV_PALETTE_GetColormap() );
1259 /**********************************************************************
1262 void EVENT_MapNotify( HWND hWnd
, XMapEvent
*event
)
1264 HWND hwndFocus
= GetFocus();
1265 WND
*wndFocus
= WIN_FindWndPtr(hwndFocus
);
1266 WND
*pWnd
= WIN_FindWndPtr(hWnd
);
1267 if (pWnd
->flags
& WIN_MANAGED
)
1268 pWnd
->dwStyle
&= ~WS_MINIMIZE
;
1269 WIN_ReleaseWndPtr(pWnd
);
1271 if (hwndFocus
&& IsChild( hWnd
, hwndFocus
))
1272 X11DRV_WND_SetFocus(wndFocus
);
1274 WIN_ReleaseWndPtr(wndFocus
);
1280 /**********************************************************************
1283 void EVENT_UnmapNotify( HWND hWnd
, XUnmapEvent
*event
)
1285 WND
*pWnd
= WIN_FindWndPtr(hWnd
);
1286 if (pWnd
->flags
& WIN_MANAGED
)
1289 if( pWnd
->dwStyle
& WS_VISIBLE
)
1290 pWnd
->dwStyle
|= WS_MINIMIZE
;
1292 WIN_ReleaseWndPtr(pWnd
);
1296 #endif /* !defined(X_DISPLAY_MISSING) */