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"
23 #include <sys/types.h>
45 /* X context to associate a hwnd to an X window */
46 extern XContext winContext
;
48 extern Atom wmProtocols
;
49 extern Atom wmDeleteWindow
;
50 extern Atom dndProtocol
;
51 extern Atom dndSelection
;
53 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
55 #define DndNotDnd -1 /* OffiX drag&drop */
67 #define DndURL 128 /* KDE drag&drop */
69 /* EVENT_WaitNetEvent() master fd sets */
71 static fd_set __event_io_set
[3];
72 static int __event_max_fd
= 0;
73 static int __event_x_connection
= 0;
75 static const char * const event_names
[] =
77 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
78 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
79 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
80 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
81 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
82 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
83 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
84 "ClientMessage", "MappingNotify"
87 static void EVENT_ProcessEvent( XEvent
*event
);
90 static void EVENT_Key( WND
*pWnd
, XKeyEvent
*event
);
91 static void EVENT_ButtonPress( WND
*pWnd
, XButtonEvent
*event
);
92 static void EVENT_ButtonRelease( WND
*pWnd
, XButtonEvent
*event
);
93 static void EVENT_MotionNotify( WND
*pWnd
, XMotionEvent
*event
);
94 static void EVENT_FocusIn( WND
*pWnd
, XFocusChangeEvent
*event
);
95 static void EVENT_FocusOut( WND
*pWnd
, XFocusChangeEvent
*event
);
96 static void EVENT_Expose( WND
*pWnd
, XExposeEvent
*event
);
97 static void EVENT_GraphicsExpose( WND
*pWnd
, XGraphicsExposeEvent
*event
);
98 static void EVENT_ConfigureNotify( WND
*pWnd
, XConfigureEvent
*event
);
99 static void EVENT_SelectionRequest( WND
*pWnd
, XSelectionRequestEvent
*event
);
100 static void EVENT_SelectionNotify( XSelectionEvent
*event
);
101 static void EVENT_SelectionClear( WND
*pWnd
, XSelectionClearEvent
*event
);
102 static void EVENT_ClientMessage( WND
*pWnd
, XClientMessageEvent
*event
);
103 static void EVENT_MapNotify( HWND32 hwnd
, XMapEvent
*event
);
105 /* Usable only with OLVWM - compile option perhaps?
106 static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event );
109 static void EVENT_GetGeometry( Window win
, int *px
, int *py
,
110 unsigned int *pwidth
, unsigned int *pheight
);
113 static BOOL32 (WINAPI
*EVENT_RedrawWindow
)( HWND32 hwnd
, const RECT32
*rectUpdate
,
114 HRGN32 hrgnUpdate
, UINT32 flags
) = NULL
;
117 /***********************************************************************
120 * Initialize network IO.
122 BOOL32
X11DRV_EVENT_Init(void)
125 for( i
= 0; i
< 3; i
++ )
126 FD_ZERO( __event_io_set
+ i
);
128 __event_max_fd
= __event_x_connection
= ConnectionNumber(display
);
129 FD_SET( __event_x_connection
, &__event_io_set
[EVENT_IO_READ
] );
134 /***********************************************************************
137 void X11DRV_EVENT_AddIO( int fd
, unsigned io_type
)
139 FD_SET( fd
, &__event_io_set
[io_type
] );
140 if( __event_max_fd
<= fd
) __event_max_fd
= fd
+ 1;
143 /***********************************************************************
144 * X11DRV_EVENT_DeleteIO
146 void X11DRV_EVENT_DeleteIO( int fd
, unsigned io_type
)
148 FD_CLR( fd
, &__event_io_set
[io_type
] );
151 /***********************************************************************
152 * X11DRV_EVENT_IsUserIdle
154 BOOL16
X11DRV_EVENT_IsUserIdle(void)
156 struct timeval timeout
= {0, 0};
160 FD_SET(__event_x_connection
, &check_set
);
161 if( select(__event_x_connection
+ 1, &check_set
, NULL
, NULL
, &timeout
) > 0 )
166 /***********************************************************************
167 * X11DRV_EVENT_WaitNetEvent
169 * Wait for a network event, optionally sleeping until one arrives.
170 * Returns TRUE if an event is pending that cannot be processed in
171 * 'peek' mode, FALSE otherwise.
174 BOOL32
X11DRV_EVENT_WaitNetEvent( BOOL32 sleep
, BOOL32 peek
)
177 LONG maxWait
= sleep
? TIMER_GetNextExpiration() : 0;
178 int pending
= TSXPending(display
);
180 /* Wait for an event or a timeout. If maxWait is -1, we have no timeout;
181 * in this case, we fall through directly to the XNextEvent loop.
184 if ((maxWait
!= -1) && !pending
)
187 struct timeval timeout
;
190 memcpy( io_set
, __event_io_set
, sizeof(io_set
) );
192 timeout
.tv_usec
= (maxWait
% 1000) * 1000;
193 timeout
.tv_sec
= maxWait
/ 1000;
196 sigsetjmp(env_wait_x
, 1);
199 if (DDE_GetRemoteMessage()) {
200 while(DDE_GetRemoteMessage())
204 stop_wait_op
= STOP_WAIT_X
;
205 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
206 num_pending
= select( __event_max_fd
, &io_set
[EVENT_IO_READ
],
207 &io_set
[EVENT_IO_WRITE
],
208 &io_set
[EVENT_IO_EXCEPT
], &timeout
);
209 if ( num_pending
== 0 )
212 TIMER_ExpireTimers();
215 else stop_wait_op
= CONT
;
216 #else /* CONFIG_IPC */
217 num_pending
= select( __event_max_fd
, &io_set
[EVENT_IO_READ
],
218 &io_set
[EVENT_IO_WRITE
],
219 &io_set
[EVENT_IO_EXCEPT
], &timeout
);
220 if ( num_pending
== 0)
222 /* Timeout or error */
223 TIMER_ExpireTimers();
226 #endif /* CONFIG_IPC */
228 /* Winsock asynchronous services */
230 if( FD_ISSET( __event_x_connection
, &io_set
[EVENT_IO_READ
]) )
234 WINSOCK_HandleIO( &__event_max_fd
, num_pending
, io_set
, __event_io_set
);
236 else /* no X events */
238 WINSOCK_HandleIO( &__event_max_fd
, num_pending
, io_set
, __event_io_set
);
243 { /* Wait for X11 input. */
247 FD_SET(__event_x_connection
, &set
);
248 select(__event_x_connection
+ 1, &set
, 0, 0, 0 );
251 /* Process current X event (and possibly others that occurred in the meantime) */
253 EnterCriticalSection(&X11DRV_CritSection
);
254 while (XPending( display
))
258 if (DDE_GetRemoteMessage())
260 LeaveCriticalSection(&X11DRV_CritSection
);
261 while(DDE_GetRemoteMessage()) ;
264 #endif /* CONFIG_IPC */
266 XNextEvent( display
, &event
);
270 /* Check only for those events which can be processed
273 if( event
.type
== MotionNotify
||
274 event
.type
== ButtonPress
|| event
.type
== ButtonRelease
||
275 event
.type
== KeyPress
|| event
.type
== KeyRelease
||
276 event
.type
== SelectionRequest
|| event
.type
== SelectionClear
||
277 event
.type
== ClientMessage
)
279 LeaveCriticalSection(&X11DRV_CritSection
);
280 EVENT_ProcessEvent( &event
);
281 EnterCriticalSection(&X11DRV_CritSection
);
285 if ( event
.type
== NoExpose
)
288 XPutBackEvent(display
, &event
);
289 LeaveCriticalSection(&X11DRV_CritSection
);
294 LeaveCriticalSection(&X11DRV_CritSection
);
295 EVENT_ProcessEvent( &event
);
296 EnterCriticalSection(&X11DRV_CritSection
);
299 LeaveCriticalSection(&X11DRV_CritSection
);
304 /***********************************************************************
307 * Synchronize with the X server. Should not be used too often.
309 void X11DRV_EVENT_Synchronize()
313 /* Use of the X critical section is needed or we have a small
314 * race between XPending() and XNextEvent().
316 EnterCriticalSection( &X11DRV_CritSection
);
317 XSync( display
, False
);
318 while (XPending( display
))
320 XNextEvent( display
, &event
);
321 /* unlock X critsection for EVENT_ProcessEvent() might switch tasks */
322 LeaveCriticalSection( &X11DRV_CritSection
);
323 EVENT_ProcessEvent( &event
);
324 EnterCriticalSection( &X11DRV_CritSection
);
326 LeaveCriticalSection( &X11DRV_CritSection
);
329 /***********************************************************************
332 * Process an X event.
334 static void EVENT_ProcessEvent( XEvent
*event
)
338 if ( TSXFindContext( display
, event
->xany
.window
, winContext
,
339 (char **)&pWnd
) != 0) {
340 if ( event
->type
== ClientMessage
) {
341 /* query window (drag&drop event contains only drag window) */
343 int root_x
, root_y
, child_x
, child_y
;
345 TSXQueryPointer( display
, rootWindow
, &root
, &child
,
346 &root_x
, &root_y
, &child_x
, &child_y
, &u
);
347 if (TSXFindContext( display
, child
, winContext
, (char **)&pWnd
) != 0)
350 pWnd
= NULL
; /* Not for a registered window */
354 TRACE(event
, "Got event %s for hwnd %04x\n",
355 event_names
[event
->type
], pWnd
? pWnd
->hwndSelf
: 0 );
361 EVENT_Key( pWnd
, (XKeyEvent
*)event
);
365 EVENT_ButtonPress( pWnd
, (XButtonEvent
*)event
);
369 EVENT_ButtonRelease( pWnd
, (XButtonEvent
*)event
);
373 /* Wine between two fast machines across the overloaded campus
374 ethernet gets very boged down in MotionEvents. The following
375 simply finds the last motion event in the queue and drops
376 the rest. On a good link events are servered before they build
377 up so this doesn't take place. On a slow link this may cause
378 problems if the event order is important. I'm not yet seen
379 of any problems. Jon 7/6/96.
381 while (TSXCheckTypedWindowEvent(display
,((XAnyEvent
*)event
)->window
,
382 MotionNotify
, event
));
383 EVENT_MotionNotify( pWnd
, (XMotionEvent
*)event
);
388 EVENT_FocusIn( pWnd
, (XFocusChangeEvent
*)event
);
393 EVENT_FocusOut( pWnd
, (XFocusChangeEvent
*)event
);
397 EVENT_Expose( pWnd
, (XExposeEvent
*)event
);
401 EVENT_GraphicsExpose( pWnd
, (XGraphicsExposeEvent
*)event
);
404 case ConfigureNotify
:
406 EVENT_ConfigureNotify( pWnd
, (XConfigureEvent
*)event
);
409 case SelectionRequest
:
411 EVENT_SelectionRequest( pWnd
, (XSelectionRequestEvent
*)event
);
414 case SelectionNotify
:
416 EVENT_SelectionNotify( (XSelectionEvent
*)event
);
421 EVENT_SelectionClear( pWnd
, (XSelectionClearEvent
*) event
);
426 EVENT_ClientMessage( pWnd
, (XClientMessageEvent
*) event
);
431 EVENT_EnterNotify( pWnd
, (XCrossingEvent
*) event
);
438 /* We get all these because of StructureNotifyMask. */
440 case CirculateNotify
:
449 EVENT_MapNotify( pWnd
->hwndSelf
, (XMapEvent
*)event
);
453 WARN(event
, "Unprocessed event %s for hwnd %04x\n",
454 event_names
[event
->type
], pWnd
? pWnd
->hwndSelf
: 0 );
459 /***********************************************************************
462 * Try to synchronize internal z-order with the window manager's.
463 * Probably a futile endeavor.
465 static BOOL32
__check_query_condition( WND
** pWndA
, WND
** pWndB
)
467 /* return TRUE if we have at least two managed windows */
469 for( *pWndB
= NULL
; *pWndA
; *pWndA
= (*pWndA
)->next
)
470 if( (*pWndA
)->flags
& WIN_MANAGED
&&
471 (*pWndA
)->dwStyle
& WS_VISIBLE
) break;
473 for( *pWndB
= (*pWndA
)->next
; *pWndB
; *pWndB
= (*pWndB
)->next
)
474 if( (*pWndB
)->flags
& WIN_MANAGED
&&
475 (*pWndB
)->dwStyle
& WS_VISIBLE
) break;
476 return ((*pWndB
) != NULL
);
479 static Window
__get_common_ancestor( Window A
, Window B
,
480 Window
** children
, unsigned* total
)
482 /* find the real root window */
484 Window root
, *childrenB
;
489 if( *children
) TSXFree( *children
);
490 TSXQueryTree( display
, A
, &root
, &A
, children
, total
);
491 TSXQueryTree( display
, B
, &root
, &B
, &childrenB
, &totalB
);
492 if( childrenB
) TSXFree( childrenB
);
493 } while( A
!= B
&& A
&& B
);
494 return ( A
&& B
) ? A
: 0 ;
497 static Window
__get_top_decoration( Window w
, Window ancestor
)
499 Window
* children
, root
, prev
= w
, parent
= w
;
505 TSXQueryTree( display
, w
, &root
, &parent
, &children
, &total
);
506 if( children
) TSXFree( children
);
507 } while( parent
&& parent
!= ancestor
);
508 TRACE(event
, "\t%08x -> %08x\n", (unsigned)prev
, (unsigned)w
);
509 return ( parent
) ? w
: 0 ;
512 static unsigned __td_lookup( Window w
, Window
* list
, unsigned max
)
515 for( i
= 0; i
< max
; i
++ ) if( list
[i
] == w
) break;
519 static BOOL32
EVENT_QueryZOrder( WND
* pWndCheck
)
522 HWND32 hwndInsertAfter
= HWND_TOP
;
523 WND
* pWnd
, *pWndZ
= WIN_GetDesktop()->child
;
524 Window w
, parent
, *children
= NULL
;
525 unsigned total
, check
, pos
, best
;
527 if( !__check_query_condition(&pWndZ
, &pWnd
) ) return TRUE
;
529 parent
= __get_common_ancestor( pWndZ
->window
, pWnd
->window
,
531 if( parent
&& children
)
533 w
= __get_top_decoration( pWndCheck
->window
, parent
);
534 if( w
!= children
[total
- 1] )
536 check
= __td_lookup( w
, children
, total
);
538 for( pWnd
= pWndZ
; pWnd
; pWnd
= pWnd
->next
)
540 if( pWnd
!= pWndCheck
)
542 if( !(pWnd
->flags
& WIN_MANAGED
) ||
543 !(w
= __get_top_decoration( pWnd
->window
, parent
)) )
545 pos
= __td_lookup( w
, children
, total
);
546 if( pos
< best
&& pos
> check
)
549 hwndInsertAfter
= pWnd
->hwndSelf
;
551 if( check
- best
== 1 ) break;
554 WIN_UnlinkWindow( pWndCheck
->hwndSelf
);
555 WIN_LinkWindow( pWndCheck
->hwndSelf
, hwndInsertAfter
);
558 if( children
) TSXFree( children
);
563 /***********************************************************************
564 * EVENT_XStateToKeyState
566 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
567 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
569 static WORD
EVENT_XStateToKeyState( int state
)
573 if (state
& Button1Mask
) kstate
|= MK_LBUTTON
;
574 if (state
& Button2Mask
) kstate
|= MK_MBUTTON
;
575 if (state
& Button3Mask
) kstate
|= MK_RBUTTON
;
576 if (state
& ShiftMask
) kstate
|= MK_SHIFT
;
577 if (state
& ControlMask
) kstate
|= MK_CONTROL
;
581 /***********************************************************************
582 * X11DRV_EVENT_QueryPointer
584 BOOL32
X11DRV_EVENT_QueryPointer(DWORD
*posX
, DWORD
*posY
, DWORD
*state
)
587 int rootX
, rootY
, winX
, winY
;
590 if (!TSXQueryPointer( display
, rootWindow
, &root
, &child
,
591 &rootX
, &rootY
, &winX
, &winY
, &xstate
))
599 *state
= EVENT_XStateToKeyState( xstate
);
604 /***********************************************************************
607 static void EVENT_Expose( WND
*pWnd
, XExposeEvent
*event
)
611 /* Make position relative to client area instead of window */
612 rect
.left
= event
->x
- (pWnd
? (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
) : 0);
613 rect
.top
= event
->y
- (pWnd
? (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
) : 0);
614 rect
.right
= rect
.left
+ event
->width
;
615 rect
.bottom
= rect
.top
+ event
->height
;
617 if ( !EVENT_RedrawWindow
)
619 HMODULE32 hModule
= GetModuleHandle32A( "USER32" );
620 EVENT_RedrawWindow
= GetProcAddress32( hModule
, "RedrawWindow" );
623 EVENT_RedrawWindow( pWnd
? pWnd
->hwndSelf
: 0, &rect
, 0,
624 RDW_INVALIDATE
| RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
|
625 (event
->count
? 0 : RDW_ERASENOW
) );
629 /***********************************************************************
630 * EVENT_GraphicsExpose
632 * This is needed when scrolling area is partially obscured
633 * by non-Wine X window.
635 static void EVENT_GraphicsExpose( WND
*pWnd
, XGraphicsExposeEvent
*event
)
639 /* Make position relative to client area instead of window */
640 rect
.left
= event
->x
- (pWnd
? (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
) : 0);
641 rect
.top
= event
->y
- (pWnd
? (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
) : 0);
642 rect
.right
= rect
.left
+ event
->width
;
643 rect
.bottom
= rect
.top
+ event
->height
;
645 if ( !EVENT_RedrawWindow
)
647 HMODULE32 hModule
= GetModuleHandle32A( "USER32" );
648 EVENT_RedrawWindow
= GetProcAddress32( hModule
, "RedrawWindow" );
651 EVENT_RedrawWindow( pWnd
? pWnd
->hwndSelf
: 0, &rect
, 0,
652 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASE
|
653 (event
->count
? 0 : RDW_ERASENOW
) );
657 /***********************************************************************
660 * Handle a X key event
662 static void EVENT_Key( WND
*pWnd
, XKeyEvent
*event
)
664 KEYBOARD_HandleEvent( pWnd
, event
);
668 /***********************************************************************
671 static void EVENT_MotionNotify( WND
*pWnd
, XMotionEvent
*event
)
673 int xOffset
= pWnd
? pWnd
->rectWindow
.left
: 0;
674 int yOffset
= pWnd
? pWnd
->rectWindow
.top
: 0;
676 MOUSE_SendEvent( MOUSEEVENTF_MOVE
,
677 xOffset
+ event
->x
, yOffset
+ event
->y
,
678 EVENT_XStateToKeyState( event
->state
),
679 event
->time
- MSG_WineStartTicks
,
680 pWnd
? pWnd
->hwndSelf
: 0 );
684 /***********************************************************************
685 * X11DRV_EVENT_DummyMotionNotify
687 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
689 void X11DRV_EVENT_DummyMotionNotify(void)
691 DWORD winX
, winY
, state
;
693 if ( EVENT_QueryPointer( &winX
, &winY
, &state
) )
695 MOUSE_SendEvent( MOUSEEVENTF_MOVE
, winX
, winY
, state
,
701 /***********************************************************************
704 static void EVENT_ButtonPress( WND
*pWnd
, XButtonEvent
*event
)
706 static WORD statusCodes
[NB_BUTTONS
] =
707 { MOUSEEVENTF_LEFTDOWN
, MOUSEEVENTF_MIDDLEDOWN
, MOUSEEVENTF_RIGHTDOWN
};
708 int buttonNum
= event
->button
- 1;
710 int xOffset
= pWnd
? pWnd
->rectWindow
.left
: 0;
711 int yOffset
= pWnd
? pWnd
->rectWindow
.top
: 0;
713 if (buttonNum
>= NB_BUTTONS
) return;
715 MOUSE_SendEvent( statusCodes
[buttonNum
],
716 xOffset
+ event
->x
, yOffset
+ event
->y
,
717 EVENT_XStateToKeyState( event
->state
),
718 event
->time
- MSG_WineStartTicks
,
719 pWnd
? pWnd
->hwndSelf
: 0 );
723 /***********************************************************************
724 * EVENT_ButtonRelease
726 static void EVENT_ButtonRelease( WND
*pWnd
, XButtonEvent
*event
)
728 static WORD statusCodes
[NB_BUTTONS
] =
729 { MOUSEEVENTF_LEFTUP
, MOUSEEVENTF_MIDDLEUP
, MOUSEEVENTF_RIGHTUP
};
730 int buttonNum
= event
->button
- 1;
732 int xOffset
= pWnd
? pWnd
->rectWindow
.left
: 0;
733 int yOffset
= pWnd
? pWnd
->rectWindow
.top
: 0;
735 if (buttonNum
>= NB_BUTTONS
) return;
737 MOUSE_SendEvent( statusCodes
[buttonNum
],
738 xOffset
+ event
->x
, yOffset
+ event
->y
,
739 EVENT_XStateToKeyState( event
->state
),
740 event
->time
- MSG_WineStartTicks
,
741 pWnd
? pWnd
->hwndSelf
: 0 );
745 /**********************************************************************
748 static void EVENT_FocusIn( WND
*pWnd
, XFocusChangeEvent
*event
)
750 if (Options
.managed
) EVENT_QueryZOrder( pWnd
);
752 if (event
->detail
!= NotifyPointer
)
754 HWND32 hwnd
= pWnd
->hwndSelf
;
756 if (hwnd
!= GetActiveWindow32())
758 WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
759 KEYBOARD_UpdateState();
761 if ((hwnd
!= GetFocus32()) && !IsChild32( hwnd
, GetFocus32()))
767 /**********************************************************************
770 * Note: only top-level override-redirect windows get FocusOut events.
772 static void EVENT_FocusOut( WND
*pWnd
, XFocusChangeEvent
*event
)
774 if (event
->detail
!= NotifyPointer
)
776 HWND32 hwnd
= pWnd
->hwndSelf
;
778 if (hwnd
== GetActiveWindow32())
779 WINPOS_ChangeActiveWindow( 0, FALSE
);
780 if ((hwnd
== GetFocus32()) || IsChild32( hwnd
, GetFocus32()))
785 /**********************************************************************
786 * X11DRV_EVENT_CheckFocus
788 BOOL32
X11DRV_EVENT_CheckFocus(void)
794 TSXGetInputFocus(display
, &xW
, &state
);
796 TSXFindContext(display
, xW
, winContext
, (char **)&pWnd
) )
801 /**********************************************************************
804 * Helper function for ConfigureNotify handling.
805 * Get the new geometry of a window relative to the root window.
807 static void EVENT_GetGeometry( Window win
, int *px
, int *py
,
808 unsigned int *pwidth
, unsigned int *pheight
)
810 Window root
, parent
, *children
;
812 unsigned int width
, height
, border
, depth
, nb_children
;
814 if (!TSXGetGeometry( display
, win
, &root
, px
, py
, pwidth
, pheight
,
815 &border
, &depth
)) return;
816 if (win
== rootWindow
)
824 if (!TSXQueryTree(display
, win
, &root
, &parent
, &children
, &nb_children
))
827 if (parent
== rootWindow
) break;
829 if (!TSXGetGeometry( display
, win
, &root
, &xpos
, &ypos
,
830 &width
, &height
, &border
, &depth
)) return;
837 /**********************************************************************
838 * EVENT_ConfigureNotify
840 * The ConfigureNotify event is only selected on top-level windows
841 * when the -managed flag is used.
843 static void EVENT_ConfigureNotify( WND
*pWnd
, XConfigureEvent
*event
)
846 RECT32 newWindowRect
, newClientRect
;
847 HRGN32 hrgnOldPos
, hrgnNewPos
;
848 Window above
= event
->above
;
850 unsigned int width
, height
;
852 assert (pWnd
->flags
& WIN_MANAGED
);
854 /* We don't rely on the event geometry info, because it is relative
855 * to parent and not to root, and it may be wrong (XFree sets x,y to 0,0
856 * if the window hasn't moved).
858 EVENT_GetGeometry( event
->window
, &x
, &y
, &width
, &height
);
860 /* Fill WINDOWPOS struct */
861 winpos
.flags
= SWP_NOACTIVATE
| SWP_NOZORDER
;
862 winpos
.hwnd
= pWnd
->hwndSelf
;
868 /* Check for unchanged attributes */
869 if (winpos
.x
== pWnd
->rectWindow
.left
&& winpos
.y
== pWnd
->rectWindow
.top
)
870 winpos
.flags
|= SWP_NOMOVE
;
871 if ((winpos
.cx
== pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) &&
872 (winpos
.cy
== pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
))
873 winpos
.flags
|= SWP_NOSIZE
;
876 RECT32 rect
= { 0, 0, pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
,
877 pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
};
878 DCE_InvalidateDCE( pWnd
, &rect
);
881 /* Send WM_WINDOWPOSCHANGING */
882 SendMessage32A( winpos
.hwnd
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)&winpos
);
884 /* Calculate new position and size */
885 newWindowRect
.left
= x
;
886 newWindowRect
.right
= x
+ width
;
887 newWindowRect
.top
= y
;
888 newWindowRect
.bottom
= y
+ height
;
890 WINPOS_SendNCCalcSize( winpos
.hwnd
, TRUE
, &newWindowRect
,
891 &pWnd
->rectWindow
, &pWnd
->rectClient
,
892 &winpos
, &newClientRect
);
894 hrgnOldPos
= CreateRectRgnIndirect32( &pWnd
->rectWindow
);
895 hrgnNewPos
= CreateRectRgnIndirect32( &newWindowRect
);
896 CombineRgn32( hrgnOldPos
, hrgnOldPos
, hrgnNewPos
, RGN_DIFF
);
897 DeleteObject32(hrgnOldPos
);
898 DeleteObject32(hrgnNewPos
);
900 /* Set new size and position */
901 pWnd
->rectWindow
= newWindowRect
;
902 pWnd
->rectClient
= newClientRect
;
903 SendMessage32A( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
905 if (!IsWindow32( winpos
.hwnd
)) return;
906 if( above
== None
) /* absolute bottom */
908 WIN_UnlinkWindow( winpos
.hwnd
);
909 WIN_LinkWindow( winpos
.hwnd
, HWND_BOTTOM
);
911 else EVENT_QueryZOrder( pWnd
); /* try to outsmart window manager */
915 /***********************************************************************
916 * EVENT_SelectionRequest
918 static void EVENT_SelectionRequest( WND
*pWnd
, XSelectionRequestEvent
*event
)
920 XSelectionEvent result
;
922 Window request
= event
->requestor
;
924 if(event
->target
== XA_STRING
)
930 rprop
= event
->property
;
932 if(rprop
== None
) rprop
= event
->target
;
934 if(event
->selection
!=XA_PRIMARY
) rprop
= None
;
935 else if(!CLIPBOARD_IsPresent(CF_OEMTEXT
)) rprop
= None
;
938 /* open to make sure that clipboard is available */
940 BOOL32 couldOpen
= OpenClipboard32( pWnd
->hwndSelf
);
943 hText
= GetClipboardData16(CF_TEXT
);
944 text
= GlobalLock16(hText
);
945 size
= GlobalSize16(hText
);
947 /* remove carriage returns */
949 lpstr
= (char*)HEAP_xalloc( GetProcessHeap(), 0, size
-- );
950 for(i
=0,j
=0; i
< size
&& text
[i
]; i
++ )
952 if( text
[i
] == '\r' &&
953 (text
[i
+1] == '\n' || text
[i
+1] == '\0') ) continue;
954 lpstr
[j
++] = text
[i
];
958 TSXChangeProperty(display
, request
, rprop
,
959 XA_STRING
, 8, PropModeReplace
,
961 HeapFree( GetProcessHeap(), 0, lpstr
);
963 /* close only if we opened before */
965 if(couldOpen
) CloseClipboard32();
970 TRACE(event
,"Request for %s ignored\n", TSXGetAtomName(display
,event
->target
));
972 result
.type
= SelectionNotify
;
973 result
.display
= display
;
974 result
.requestor
= request
;
975 result
.selection
= event
->selection
;
976 result
.property
= rprop
;
977 result
.target
= event
->target
;
978 result
.time
= event
->time
;
979 TSXSendEvent(display
,event
->requestor
,False
,NoEventMask
,(XEvent
*)&result
);
983 /***********************************************************************
984 * EVENT_SelectionNotify
986 static void EVENT_SelectionNotify( XSelectionEvent
*event
)
988 if (event
->selection
!= XA_PRIMARY
) return;
990 if (event
->target
!= XA_STRING
) X11DRV_CLIPBOARD_ReadSelection( 0, None
);
991 else X11DRV_CLIPBOARD_ReadSelection( event
->requestor
, event
->property
);
993 TRACE(clipboard
,"\tSelectionNotify done!\n");
997 /***********************************************************************
998 * EVENT_SelectionClear
1000 static void EVENT_SelectionClear( WND
*pWnd
, XSelectionClearEvent
*event
)
1002 if (event
->selection
!= XA_PRIMARY
) return;
1003 X11DRV_CLIPBOARD_ReleaseSelection( event
->window
, pWnd
->hwndSelf
);
1007 /**********************************************************************
1008 * EVENT_DropFromOffix
1010 * don't know if it still works (last Changlog is from 96/11/04)
1012 static void EVENT_DropFromOffiX( WND
*pWnd
, XClientMessageEvent
*event
)
1014 unsigned long data_length
;
1015 unsigned long aux_long
;
1016 unsigned char* p_data
= NULL
;
1024 HGLOBAL16 hDragInfo
= GlobalAlloc16( GMEM_SHARE
| GMEM_ZEROINIT
, sizeof(DRAGINFO
));
1025 LPDRAGINFO lpDragInfo
= (LPDRAGINFO
) GlobalLock16(hDragInfo
);
1026 SEGPTR spDragInfo
= (SEGPTR
) WIN16_GlobalLock16(hDragInfo
);
1027 Window w_aux_root
, w_aux_child
;
1030 if( !lpDragInfo
|| !spDragInfo
) return;
1032 TSXQueryPointer( display
, pWnd
->window
, &w_aux_root
, &w_aux_child
,
1033 &x
, &y
, &u
.pt_aux
.x
, &u
.pt_aux
.y
, (unsigned int*)&aux_long
);
1035 lpDragInfo
->hScope
= pWnd
->hwndSelf
;
1036 lpDragInfo
->pt
.x
= (INT16
)x
; lpDragInfo
->pt
.y
= (INT16
)y
;
1038 /* find out drop point and drop window */
1039 if( x
< 0 || y
< 0 ||
1040 x
> (pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) ||
1041 y
> (pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
) )
1042 { bAccept
= pWnd
->dwExStyle
& WS_EX_ACCEPTFILES
; x
= y
= 0; }
1045 bAccept
= DRAG_QueryUpdate( pWnd
->hwndSelf
, spDragInfo
, TRUE
);
1046 x
= lpDragInfo
->pt
.x
; y
= lpDragInfo
->pt
.y
;
1048 pDropWnd
= WIN_FindWndPtr( lpDragInfo
->hScope
);
1049 GlobalFree16( hDragInfo
);
1053 TSXGetWindowProperty( display
, DefaultRootWindow(display
),
1054 dndSelection
, 0, 65535, FALSE
,
1055 AnyPropertyType
, &u
.atom_aux
, &u
.pt_aux
.y
,
1056 &data_length
, &aux_long
, &p_data
);
1058 if( !aux_long
&& p_data
) /* don't bother if > 64K */
1060 char *p
= (char*) p_data
;
1064 while( *p
) /* calculate buffer size */
1067 if((u
.i
= *p
) != -1 )
1068 u
.i
= DRIVE_FindDriveRoot( (const char **)&p_drop
);
1069 if( u
.i
== -1 ) *p
= -1; /* mark as "bad" */
1072 INT32 len
= GetShortPathName32A( p
, NULL
, 0 );
1073 if (len
) aux_long
+= len
+ 1;
1078 if( aux_long
&& aux_long
< 65535 )
1081 LPDROPFILESTRUCT16 lpDrop
;
1083 aux_long
+= sizeof(DROPFILESTRUCT16
) + 1;
1084 hDrop
= (HDROP16
)GlobalAlloc16( GMEM_SHARE
, aux_long
);
1085 lpDrop
= (LPDROPFILESTRUCT16
) GlobalLock16( hDrop
);
1089 lpDrop
->wSize
= sizeof(DROPFILESTRUCT16
);
1090 lpDrop
->ptMousePos
.x
= (INT16
)x
;
1091 lpDrop
->ptMousePos
.y
= (INT16
)y
;
1092 lpDrop
->fInNonClientArea
= (BOOL16
)
1093 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
1094 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
1095 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
1096 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
1097 p_drop
= ((char*)lpDrop
) + sizeof(DROPFILESTRUCT16
);
1101 if( *p
!= -1 ) /* use only "good" entries */
1103 GetShortPathName32A( p
, p_drop
, 65535 );
1104 p_drop
+= strlen( p_drop
) + 1;
1109 PostMessage16( pWnd
->hwndSelf
, WM_DROPFILES
,
1110 (WPARAM16
)hDrop
, 0L );
1114 if( p_data
) TSXFree(p_data
);
1116 } /* WS_EX_ACCEPTFILES */
1119 /**********************************************************************
1122 * drop items are separated by \n
1123 * each item is prefixed by its mime type
1125 * event->data.l[3], event->data.l[4] contains drop x,y position
1127 static void EVENT_DropURLs( WND
*pWnd
, XClientMessageEvent
*event
)
1130 unsigned long data_length
;
1131 unsigned long aux_long
, drop_len
= 0;
1132 unsigned char *p_data
= NULL
; /* property data */
1133 char *p_drop
= NULL
;
1135 int x
, y
, drop32
= FALSE
;
1147 drop32
= pWnd
->flags
& WIN_ISWIN32
;
1149 if (!(pWnd
->dwExStyle
& WS_EX_ACCEPTFILES
))
1152 TSXGetWindowProperty( display
, DefaultRootWindow(display
),
1153 dndSelection
, 0, 65535, FALSE
,
1154 AnyPropertyType
, &u
.atom_aux
, &u
.i
,
1155 &data_length
, &aux_long
, &p_data
);
1157 WARN(event
,"property too large, truncated!\n");
1158 TRACE(event
,"urls=%s\n", p_data
);
1160 if( !aux_long
&& p_data
) { /* don't bother if > 64K */
1161 /* calculate length */
1163 next
= strchr(p
, '\n');
1166 if (strncmp(p
,"file:",5) == 0 ) {
1167 INT32 len
= GetShortPathName32A( p
+5, NULL
, 0 );
1168 if (len
) drop_len
+= len
+ 1;
1173 next
= strchr(p
, '\n');
1179 if( drop_len
&& drop_len
< 65535 ) {
1180 TSXQueryPointer( display
, rootWindow
, &u
.w_aux
, &u
.w_aux
,
1181 &x
, &y
, &u
.i
, &u
.i
, &u
.i
);
1182 pDropWnd
= WIN_FindWndPtr( pWnd
->hwndSelf
);
1185 LPDROPFILESTRUCT32 lpDrop
;
1186 drop_len
+= sizeof(DROPFILESTRUCT32
) + 1;
1187 hDrop
.h32
= (HDROP32
)GlobalAlloc32( GMEM_SHARE
, drop_len
);
1188 lpDrop
= (LPDROPFILESTRUCT32
) GlobalLock32( hDrop
.h32
);
1191 lpDrop
->lSize
= sizeof(DROPFILESTRUCT32
);
1192 lpDrop
->ptMousePos
.x
= (INT32
)x
;
1193 lpDrop
->ptMousePos
.y
= (INT32
)y
;
1194 lpDrop
->fInNonClientArea
= (BOOL32
)
1195 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
1196 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
1197 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
1198 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
1199 lpDrop
->fWideChar
= FALSE
;
1200 p_drop
= ((char*)lpDrop
) + sizeof(DROPFILESTRUCT32
);
1203 LPDROPFILESTRUCT16 lpDrop
;
1204 drop_len
+= sizeof(DROPFILESTRUCT16
) + 1;
1205 hDrop
.h16
= (HDROP16
)GlobalAlloc16( GMEM_SHARE
, drop_len
);
1206 lpDrop
= (LPDROPFILESTRUCT16
) GlobalLock16( hDrop
.h16
);
1209 lpDrop
->wSize
= sizeof(DROPFILESTRUCT16
);
1210 lpDrop
->ptMousePos
.x
= (INT16
)x
;
1211 lpDrop
->ptMousePos
.y
= (INT16
)y
;
1212 lpDrop
->fInNonClientArea
= (BOOL16
)
1213 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
1214 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
1215 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
1216 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
1217 p_drop
= ((char*)lpDrop
) + sizeof(DROPFILESTRUCT16
);
1221 /* create message content */
1224 next
= strchr(p
, '\n');
1227 if (strncmp(p
,"file:",5) == 0 ) {
1228 INT32 len
= GetShortPathName32A( p
+5, p_drop
, 65535 );
1230 TRACE(event
, "drop file %s as %s\n", p
+5, p_drop
);
1233 WARN(event
, "can't convert file %s to dos name \n", p
+5);
1236 WARN(event
, "unknown mime type %s\n", p
);
1241 next
= strchr(p
, '\n');
1249 /* can not use PostMessage32A because it is currently based on
1250 * PostMessage16 and WPARAM32 would be truncated to WPARAM16
1252 GlobalUnlock32(hDrop
.h32
);
1253 SendMessage32A( pWnd
->hwndSelf
, WM_DROPFILES
,
1254 (WPARAM32
)hDrop
.h32
, 0L );
1256 GlobalUnlock16(hDrop
.h16
);
1257 PostMessage16( pWnd
->hwndSelf
, WM_DROPFILES
,
1258 (WPARAM16
)hDrop
.h16
, 0L );
1262 if( p_data
) TSXFree(p_data
);
1266 /**********************************************************************
1267 * EVENT_ClientMessage
1269 static void EVENT_ClientMessage( WND
*pWnd
, XClientMessageEvent
*event
)
1271 if (event
->message_type
!= None
&& event
->format
== 32) {
1272 if ((event
->message_type
== wmProtocols
) &&
1273 (((Atom
) event
->data
.l
[0]) == wmDeleteWindow
))
1274 SendMessage16( pWnd
->hwndSelf
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
1275 else if ( event
->message_type
== dndProtocol
&&
1276 (event
->data
.l
[0] == DndFile
|| event
->data
.l
[0] == DndFiles
) )
1277 EVENT_DropFromOffiX(pWnd
, event
);
1278 else if ( event
->message_type
== dndProtocol
&&
1279 event
->data
.l
[0] == DndURL
)
1280 EVENT_DropURLs(pWnd
, event
);
1283 /* enable this if you want to see the message */
1284 unsigned char* p_data
= NULL
;
1290 TSXGetWindowProperty( display
, DefaultRootWindow(display
),
1291 dndSelection
, 0, 65535, FALSE
,
1292 AnyPropertyType
, &u
.atom
, &u
.i
,
1293 &u
.l
, &u
.l
, &p_data
);
1294 TRACE(event
, "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],
1299 TRACE(event
, "unrecognized ClientMessage\n" );
1304 /**********************************************************************
1307 * Install colormap when Wine window is focused in
1308 * self-managed mode with private colormap
1311 void EVENT_EnterNotify( WND
*pWnd
, XCrossingEvent
*event
)
1313 if( !Options
.managed
&& rootWindow
== DefaultRootWindow(display
) &&
1314 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE
) && GetFocus32() )
1315 TSXInstallColormap( display
, COLOR_GetColormap() );
1319 /**********************************************************************
1322 void EVENT_MapNotify( HWND32 hWnd
, XMapEvent
*event
)
1324 HWND32 hwndFocus
= GetFocus32();
1326 if (hwndFocus
&& IsChild32( hWnd
, hwndFocus
))
1327 X11DRV_WND_SetFocus( WIN_FindWndPtr( hwndFocus
) );
1332 /**********************************************************************
1333 * X11DRV_EVENT_Pending
1335 BOOL32
X11DRV_EVENT_Pending()
1337 return TSXPending(display
);
1340 #endif /* !defined(X_DISPLAY_MISSING) */