2 * X events handling functions
4 * Copyright 1993 Alexandre Julliard
14 #include <sys/types.h>
16 #include <X11/keysym.h>
18 #include "ts_xresource.h"
20 #include <X11/Xatom.h>
29 #include "clipboard.h"
44 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
46 #define DndNotDnd -1 /* OffiX drag&drop */
58 /* X context to associate a hwnd to an X window */
59 static XContext winContext
= 0;
61 static INT16 captureHT
= HTCLIENT
;
62 static HWND32 captureWnd
= 0;
63 static BOOL32 InputEnabled
= TRUE
;
64 static BOOL32 SwappedButtons
= FALSE
;
66 static Atom wmProtocols
= None
;
67 static Atom wmDeleteWindow
= None
;
68 static Atom dndProtocol
= None
;
69 static Atom dndSelection
= None
;
71 /* EVENT_WaitNetEvent() master fd sets */
73 static fd_set __event_io_set
[3];
74 static int __event_max_fd
= 0;
75 static int __event_x_connection
= 0;
77 static const char * const event_names
[] =
79 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
80 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
81 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
82 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
83 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
84 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
85 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
86 "ClientMessage", "MappingNotify"
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 /***********************************************************************
112 * Initialize network IO.
114 BOOL32
EVENT_Init(void)
117 for( i
= 0; i
< 3; i
++ )
118 FD_ZERO( __event_io_set
+ i
);
120 __event_max_fd
= __event_x_connection
= ConnectionNumber(display
);
121 FD_SET( __event_x_connection
, &__event_io_set
[EVENT_IO_READ
] );
126 /***********************************************************************
129 void EVENT_AddIO( int fd
, unsigned io_type
)
131 FD_SET( fd
, &__event_io_set
[io_type
] );
132 if( __event_max_fd
<= fd
) __event_max_fd
= fd
+ 1;
135 void EVENT_DeleteIO( int fd
, unsigned io_type
)
137 FD_CLR( fd
, &__event_io_set
[io_type
] );
140 /***********************************************************************
143 * Process an X event.
145 void EVENT_ProcessEvent( XEvent
*event
)
149 if (TSXFindContext( display
, event
->xany
.window
, winContext
,
150 (char **)&pWnd
) != 0)
151 return; /* Not for a registered window */
153 TRACE(event
, "Got event %s for hwnd %04x\n",
154 event_names
[event
->type
], pWnd
->hwndSelf
);
160 if (InputEnabled
) EVENT_Key( pWnd
, (XKeyEvent
*)event
);
165 EVENT_ButtonPress( pWnd
, (XButtonEvent
*)event
);
170 EVENT_ButtonRelease( pWnd
, (XButtonEvent
*)event
);
174 /* Wine between two fast machines across the overloaded campus
175 ethernet gets very boged down in MotionEvents. The following
176 simply finds the last motion event in the queue and drops
177 the rest. On a good link events are servered before they build
178 up so this doesn't take place. On a slow link this may cause
179 problems if the event order is important. I'm not yet seen
180 of any problems. Jon 7/6/96.
184 while (TSXCheckTypedWindowEvent(display
,((XAnyEvent
*)event
)->window
,
185 MotionNotify
, event
));
186 EVENT_MotionNotify( pWnd
, (XMotionEvent
*)event
);
191 EVENT_FocusIn( pWnd
, (XFocusChangeEvent
*)event
);
195 EVENT_FocusOut( pWnd
, (XFocusChangeEvent
*)event
);
199 EVENT_Expose( pWnd
, (XExposeEvent
*)event
);
203 EVENT_GraphicsExpose( pWnd
, (XGraphicsExposeEvent
*)event
);
206 case ConfigureNotify
:
207 EVENT_ConfigureNotify( pWnd
, (XConfigureEvent
*)event
);
210 case SelectionRequest
:
211 EVENT_SelectionRequest( pWnd
, (XSelectionRequestEvent
*)event
);
214 case SelectionNotify
:
215 EVENT_SelectionNotify( (XSelectionEvent
*)event
);
219 EVENT_SelectionClear( pWnd
, (XSelectionClearEvent
*) event
);
223 EVENT_ClientMessage( pWnd
, (XClientMessageEvent
*) event
);
227 * EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
233 /* We get all these because of StructureNotifyMask. */
235 case CirculateNotify
:
243 EVENT_MapNotify( pWnd
->hwndSelf
, (XMapEvent
*)event
);
247 WARN(event
, "Unprocessed event %s for hwnd %04x\n",
248 event_names
[event
->type
], pWnd
->hwndSelf
);
254 /***********************************************************************
255 * EVENT_RegisterWindow
257 * Associate an X window to a HWND.
259 void EVENT_RegisterWindow( WND
*pWnd
)
261 if (wmProtocols
== None
)
262 wmProtocols
= TSXInternAtom( display
, "WM_PROTOCOLS", True
);
263 if (wmDeleteWindow
== None
)
264 wmDeleteWindow
= TSXInternAtom( display
, "WM_DELETE_WINDOW", True
);
265 if( dndProtocol
== None
)
266 dndProtocol
= TSXInternAtom( display
, "DndProtocol" , False
);
267 if( dndSelection
== None
)
268 dndSelection
= TSXInternAtom( display
, "DndSelection" , False
);
270 TSXSetWMProtocols( display
, pWnd
->window
, &wmDeleteWindow
, 1 );
272 if (!winContext
) winContext
= TSXUniqueContext();
273 TSXSaveContext( display
, pWnd
->window
, winContext
, (char *)pWnd
);
276 /***********************************************************************
277 * EVENT_DestroyWindow
279 void EVENT_DestroyWindow( WND
*pWnd
)
283 TSXDeleteContext( display
, pWnd
->window
, winContext
);
284 TSXDestroyWindow( display
, pWnd
->window
);
285 while( TSXCheckWindowEvent(display
, pWnd
->window
, NoEventMask
, &xe
) );
289 /***********************************************************************
290 * IsUserIdle (USER.333)
292 * Check if we have pending X events.
294 BOOL16 WINAPI
IsUserIdle(void)
296 struct timeval timeout
= {0, 0};
300 FD_SET(__event_x_connection
, &check_set
);
301 if( select(__event_x_connection
+ 1, &check_set
, NULL
, NULL
, &timeout
) > 0 )
307 /***********************************************************************
310 * Wait for a network event, optionally sleeping until one arrives.
311 * Return TRUE if an event is pending, FALSE on timeout or error
312 * (for instance lost connection with the server).
314 BOOL32
EVENT_WaitNetEvent( BOOL32 sleep
, BOOL32 peek
)
317 LONG maxWait
= sleep
? TIMER_GetNextExpiration() : 0;
318 int pending
= TSXPending(display
);
320 /* Wait for an event or a timeout. If maxWait is -1, we have no timeout;
321 * in this case, we fall through directly to the XNextEvent loop.
324 if ((maxWait
!= -1) && !pending
)
327 struct timeval timeout
;
330 memcpy( io_set
, __event_io_set
, sizeof(io_set
) );
332 timeout
.tv_usec
= (maxWait
% 1000) * 1000;
333 timeout
.tv_sec
= maxWait
/ 1000;
336 sigsetjmp(env_wait_x
, 1);
339 if (DDE_GetRemoteMessage()) {
340 while(DDE_GetRemoteMessage())
344 stop_wait_op
= STOP_WAIT_X
;
345 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
346 num_pending
= select( __event_max_fd
, &io_set
[EVENT_IO_READ
],
347 &io_set
[EVENT_IO_WRITE
],
348 &io_set
[EVENT_IO_EXCEPT
], &timeout
);
349 if ( num_pending
== 0 )
352 TIMER_ExpireTimers();
355 else stop_wait_op
= CONT
;
356 #else /* CONFIG_IPC */
357 num_pending
= select( __event_max_fd
, &io_set
[EVENT_IO_READ
],
358 &io_set
[EVENT_IO_WRITE
],
359 &io_set
[EVENT_IO_EXCEPT
], &timeout
);
360 if ( num_pending
== 0)
362 /* Timeout or error */
363 TIMER_ExpireTimers();
366 #endif /* CONFIG_IPC */
368 /* Winsock asynchronous services */
370 if( FD_ISSET( __event_x_connection
, &io_set
[EVENT_IO_READ
]) )
374 WINSOCK_HandleIO( &__event_max_fd
, num_pending
, io_set
, __event_io_set
);
376 else /* no X events */
377 return WINSOCK_HandleIO( &__event_max_fd
, num_pending
, io_set
, __event_io_set
);
380 { /* Wait for X11 input. */
384 FD_SET(__event_x_connection
, &set
);
385 select(__event_x_connection
+ 1, &set
, 0, 0, 0 );
388 /* Process current X event (and possibly others that occurred in the meantime) */
390 EnterCriticalSection(&X11DRV_CritSection
);
391 while (XPending( display
))
395 if (DDE_GetRemoteMessage())
397 LeaveCriticalSection(&X11DRV_CritSection
);
398 while(DDE_GetRemoteMessage()) ;
401 #endif /* CONFIG_IPC */
403 XNextEvent( display
, &event
);
405 LeaveCriticalSection(&X11DRV_CritSection
);
411 if (TSXFindContext( display
, ((XAnyEvent
*)&event
)->window
, winContext
,
412 (char **)&pWnd
) || (event
.type
== NoExpose
))
415 /* Check only for those events which can be processed
418 if( event
.type
== MotionNotify
||
419 event
.type
== ButtonPress
|| event
.type
== ButtonRelease
||
420 event
.type
== KeyPress
|| event
.type
== KeyRelease
||
421 event
.type
== SelectionRequest
|| event
.type
== SelectionClear
)
423 EVENT_ProcessEvent( &event
);
429 if( (pQ
= (MESSAGEQUEUE
*)GlobalLock16(pWnd
->hmemTaskQ
)) )
431 pQ
->flags
|= QUEUE_FLAG_XEVENT
;
432 PostEvent(pQ
->hTask
);
433 TSXPutBackEvent(display
, &event
);
438 else EVENT_ProcessEvent( &event
);
439 EnterCriticalSection(&X11DRV_CritSection
);
441 LeaveCriticalSection(&X11DRV_CritSection
);
446 /***********************************************************************
449 * Synchronize with the X server. Should not be used too often.
451 void EVENT_Synchronize()
455 /* Use of the X critical section is needed or we have a small
456 * race between XPending() and XNextEvent().
458 EnterCriticalSection( &X11DRV_CritSection
);
459 XSync( display
, False
);
460 while (XPending( display
))
462 XNextEvent( display
, &event
);
463 /* unlock X critsection for EVENT_ProcessEvent() might switch tasks */
464 LeaveCriticalSection( &X11DRV_CritSection
);
465 EVENT_ProcessEvent( &event
);
466 EnterCriticalSection( &X11DRV_CritSection
);
468 LeaveCriticalSection( &X11DRV_CritSection
);
471 /***********************************************************************
474 * Try to synchronize internal z-order with the window manager's.
475 * Probably a futile endeavor.
477 static BOOL32
__check_query_condition( WND
** pWndA
, WND
** pWndB
)
479 /* return TRUE if we have at least two managed windows */
481 for( *pWndB
= NULL
; *pWndA
; *pWndA
= (*pWndA
)->next
)
482 if( (*pWndA
)->flags
& WIN_MANAGED
&&
483 (*pWndA
)->dwStyle
& WS_VISIBLE
) break;
485 for( *pWndB
= (*pWndA
)->next
; *pWndB
; *pWndB
= (*pWndB
)->next
)
486 if( (*pWndB
)->flags
& WIN_MANAGED
&&
487 (*pWndB
)->dwStyle
& WS_VISIBLE
) break;
488 return ((*pWndB
) != NULL
);
491 static Window
__get_common_ancestor( Window A
, Window B
,
492 Window
** children
, unsigned* total
)
494 /* find the real root window */
496 Window root
, *childrenB
;
501 if( *children
) TSXFree( *children
);
502 TSXQueryTree( display
, A
, &root
, &A
, children
, total
);
503 TSXQueryTree( display
, B
, &root
, &B
, &childrenB
, &totalB
);
504 if( childrenB
) TSXFree( childrenB
);
505 } while( A
!= B
&& A
&& B
);
506 return ( A
&& B
) ? A
: 0 ;
509 static Window
__get_top_decoration( Window w
, Window ancestor
)
511 Window
* children
, root
, prev
= w
, parent
= w
;
517 TSXQueryTree( display
, w
, &root
, &parent
, &children
, &total
);
518 if( children
) TSXFree( children
);
519 } while( parent
&& parent
!= ancestor
);
520 TRACE(event
, "\t%08x -> %08x\n", (unsigned)prev
, (unsigned)w
);
521 return ( parent
) ? w
: 0 ;
524 static unsigned __td_lookup( Window w
, Window
* list
, unsigned max
)
527 for( i
= 0; i
< max
; i
++ ) if( list
[i
] == w
) break;
531 static BOOL32
EVENT_QueryZOrder( WND
* pWndCheck
)
534 HWND32 hwndInsertAfter
= HWND_TOP
;
535 WND
* pWnd
, *pWndZ
= WIN_GetDesktop()->child
;
536 Window w
, parent
, *children
= NULL
;
537 unsigned total
, check
, pos
, best
;
539 if( !__check_query_condition(&pWndZ
, &pWnd
) ) return TRUE
;
541 parent
= __get_common_ancestor( pWndZ
->window
, pWnd
->window
,
543 if( parent
&& children
)
545 w
= __get_top_decoration( pWndCheck
->window
, parent
);
546 if( w
!= children
[total
- 1] )
548 check
= __td_lookup( w
, children
, total
);
550 for( pWnd
= pWndZ
; pWnd
; pWnd
= pWnd
->next
)
552 if( pWnd
!= pWndCheck
)
554 if( !(pWnd
->flags
& WIN_MANAGED
) ||
555 !(w
= __get_top_decoration( pWnd
->window
, parent
)) )
557 pos
= __td_lookup( w
, children
, total
);
558 if( pos
< best
&& pos
> check
)
561 hwndInsertAfter
= pWnd
->hwndSelf
;
563 if( check
- best
== 1 ) break;
566 WIN_UnlinkWindow( pWndCheck
->hwndSelf
);
567 WIN_LinkWindow( pWndCheck
->hwndSelf
, hwndInsertAfter
);
570 if( children
) TSXFree( children
);
575 /***********************************************************************
576 * EVENT_XStateToKeyState
578 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
579 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
581 static WORD
EVENT_XStateToKeyState( int state
)
585 if (state
& Button1Mask
) kstate
|= MK_LBUTTON
;
586 if (state
& Button2Mask
) kstate
|= MK_MBUTTON
;
587 if (state
& Button3Mask
) kstate
|= MK_RBUTTON
;
588 if (state
& ShiftMask
) kstate
|= MK_SHIFT
;
589 if (state
& ControlMask
) kstate
|= MK_CONTROL
;
594 /***********************************************************************
597 static void EVENT_Expose( WND
*pWnd
, XExposeEvent
*event
)
601 /* Make position relative to client area instead of window */
602 rect
.left
= event
->x
- (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
);
603 rect
.top
= event
->y
- (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
);
604 rect
.right
= rect
.left
+ event
->width
;
605 rect
.bottom
= rect
.top
+ event
->height
;
607 PAINT_RedrawWindow( pWnd
->hwndSelf
, &rect
, 0,
608 RDW_INVALIDATE
| RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
|
609 (event
->count
? 0 : RDW_ERASENOW
), 0 );
613 /***********************************************************************
614 * EVENT_GraphicsExpose
616 * This is needed when scrolling area is partially obscured
617 * by non-Wine X window.
619 static void EVENT_GraphicsExpose( WND
*pWnd
, XGraphicsExposeEvent
*event
)
623 /* Make position relative to client area instead of window */
624 rect
.left
= event
->x
- (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
);
625 rect
.top
= event
->y
- (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
);
626 rect
.right
= rect
.left
+ event
->width
;
627 rect
.bottom
= rect
.top
+ event
->height
;
629 PAINT_RedrawWindow( pWnd
->hwndSelf
, &rect
, 0,
630 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASE
|
631 (event
->count
? 0 : RDW_ERASENOW
), 0 );
635 /***********************************************************************
638 * Handle a X key event
640 static void EVENT_Key( WND
*pWnd
, XKeyEvent
*event
)
642 KEYBOARD_HandleEvent( pWnd
, event
);
646 /***********************************************************************
649 static void EVENT_MotionNotify( WND
*pWnd
, XMotionEvent
*event
)
651 hardware_event( WM_MOUSEMOVE
, EVENT_XStateToKeyState( event
->state
), 0L,
652 pWnd
->rectWindow
.left
+ event
->x
,
653 pWnd
->rectWindow
.top
+ event
->y
,
654 event
->time
- MSG_WineStartTicks
, pWnd
->hwndSelf
);
658 /***********************************************************************
659 * EVENT_DummyMotionNotify
661 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
663 void EVENT_DummyMotionNotify(void)
666 int rootX
, rootY
, winX
, winY
;
669 if (TSXQueryPointer( display
, rootWindow
, &root
, &child
,
670 &rootX
, &rootY
, &winX
, &winY
, &state
))
672 hardware_event( WM_MOUSEMOVE
, EVENT_XStateToKeyState( state
), 0L,
673 winX
, winY
, GetTickCount(), 0 );
678 /***********************************************************************
681 static void EVENT_ButtonPress( WND
*pWnd
, XButtonEvent
*event
)
683 static WORD messages
[NB_BUTTONS
] =
684 { WM_LBUTTONDOWN
, WM_MBUTTONDOWN
, WM_RBUTTONDOWN
};
685 int buttonNum
= event
->button
- 1;
687 if (buttonNum
>= NB_BUTTONS
) return;
688 if (SwappedButtons
) buttonNum
= NB_BUTTONS
- 1 - buttonNum
;
689 MouseButtonsStates
[buttonNum
] = TRUE
;
690 AsyncMouseButtonsStates
[buttonNum
] = TRUE
;
691 hardware_event( messages
[buttonNum
],
692 EVENT_XStateToKeyState( event
->state
), 0L,
693 pWnd
->rectWindow
.left
+ event
->x
,
694 pWnd
->rectWindow
.top
+ event
->y
,
695 event
->time
- MSG_WineStartTicks
, pWnd
->hwndSelf
);
699 /***********************************************************************
700 * EVENT_ButtonRelease
702 static void EVENT_ButtonRelease( WND
*pWnd
, XButtonEvent
*event
)
704 static const WORD messages
[NB_BUTTONS
] =
705 { WM_LBUTTONUP
, WM_MBUTTONUP
, WM_RBUTTONUP
};
706 int buttonNum
= event
->button
- 1;
708 if (buttonNum
>= NB_BUTTONS
) return;
709 if (SwappedButtons
) buttonNum
= NB_BUTTONS
- 1 - buttonNum
;
710 MouseButtonsStates
[buttonNum
] = FALSE
;
711 hardware_event( messages
[buttonNum
],
712 EVENT_XStateToKeyState( event
->state
), 0L,
713 pWnd
->rectWindow
.left
+ event
->x
,
714 pWnd
->rectWindow
.top
+ event
->y
,
715 event
->time
- MSG_WineStartTicks
, pWnd
->hwndSelf
);
719 /**********************************************************************
722 static void EVENT_FocusIn( WND
*pWnd
, XFocusChangeEvent
*event
)
724 if (Options
.managed
) EVENT_QueryZOrder( pWnd
);
726 if (event
->detail
!= NotifyPointer
)
728 HWND32 hwnd
= pWnd
->hwndSelf
;
730 if (hwnd
!= GetActiveWindow32())
732 WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
733 KEYBOARD_UpdateState();
735 if ((hwnd
!= GetFocus32()) && !IsChild32( hwnd
, GetFocus32()))
741 /**********************************************************************
744 * Note: only top-level override-redirect windows get FocusOut events.
746 static void EVENT_FocusOut( WND
*pWnd
, XFocusChangeEvent
*event
)
748 if (event
->detail
!= NotifyPointer
)
750 HWND32 hwnd
= pWnd
->hwndSelf
;
752 if (hwnd
== GetActiveWindow32())
753 WINPOS_ChangeActiveWindow( 0, FALSE
);
754 if ((hwnd
== GetFocus32()) || IsChild32( hwnd
, GetFocus32()))
759 /**********************************************************************
762 BOOL32
EVENT_CheckFocus(void)
768 TSXGetInputFocus(display
, &xW
, &state
);
770 TSXFindContext(display
, xW
, winContext
, (char **)&pWnd
) )
776 /**********************************************************************
779 * Helper function for ConfigureNotify handling.
780 * Get the new geometry of a window relative to the root window.
782 static void EVENT_GetGeometry( Window win
, int *px
, int *py
,
783 unsigned int *pwidth
, unsigned int *pheight
)
785 Window root
, parent
, *children
;
787 unsigned int width
, height
, border
, depth
, nb_children
;
789 if (!TSXGetGeometry( display
, win
, &root
, px
, py
, pwidth
, pheight
,
790 &border
, &depth
)) return;
791 if (win
== rootWindow
)
799 if (!TSXQueryTree(display
, win
, &root
, &parent
, &children
, &nb_children
))
802 if (parent
== rootWindow
) break;
804 if (!TSXGetGeometry( display
, win
, &root
, &xpos
, &ypos
,
805 &width
, &height
, &border
, &depth
)) return;
812 /**********************************************************************
813 * EVENT_ConfigureNotify
815 * The ConfigureNotify event is only selected on top-level windows
816 * when the -managed flag is used.
818 static void EVENT_ConfigureNotify( WND
*pWnd
, XConfigureEvent
*event
)
821 RECT32 newWindowRect
, newClientRect
;
822 HRGN32 hrgnOldPos
, hrgnNewPos
;
823 Window above
= event
->above
;
825 unsigned int width
, height
;
827 assert (pWnd
->flags
& WIN_MANAGED
);
829 /* We don't rely on the event geometry info, because it is relative
830 * to parent and not to root, and it may be wrong (XFree sets x,y to 0,0
831 * if the window hasn't moved).
833 EVENT_GetGeometry( event
->window
, &x
, &y
, &width
, &height
);
835 /* Fill WINDOWPOS struct */
836 winpos
.flags
= SWP_NOACTIVATE
| SWP_NOZORDER
;
837 winpos
.hwnd
= pWnd
->hwndSelf
;
843 /* Check for unchanged attributes */
844 if (winpos
.x
== pWnd
->rectWindow
.left
&& winpos
.y
== pWnd
->rectWindow
.top
)
845 winpos
.flags
|= SWP_NOMOVE
;
846 if ((winpos
.cx
== pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) &&
847 (winpos
.cy
== pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
))
848 winpos
.flags
|= SWP_NOSIZE
;
851 RECT32 rect
= { 0, 0, pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
,
852 pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
};
853 DCE_InvalidateDCE( pWnd
, &rect
);
856 /* Send WM_WINDOWPOSCHANGING */
857 SendMessage32A( winpos
.hwnd
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)&winpos
);
859 /* Calculate new position and size */
860 newWindowRect
.left
= x
;
861 newWindowRect
.right
= x
+ width
;
862 newWindowRect
.top
= y
;
863 newWindowRect
.bottom
= y
+ height
;
865 WINPOS_SendNCCalcSize( winpos
.hwnd
, TRUE
, &newWindowRect
,
866 &pWnd
->rectWindow
, &pWnd
->rectClient
,
867 &winpos
, &newClientRect
);
869 hrgnOldPos
= CreateRectRgnIndirect32( &pWnd
->rectWindow
);
870 hrgnNewPos
= CreateRectRgnIndirect32( &newWindowRect
);
871 CombineRgn32( hrgnOldPos
, hrgnOldPos
, hrgnNewPos
, RGN_DIFF
);
872 DeleteObject32(hrgnOldPos
);
873 DeleteObject32(hrgnNewPos
);
875 /* Set new size and position */
876 pWnd
->rectWindow
= newWindowRect
;
877 pWnd
->rectClient
= newClientRect
;
878 SendMessage32A( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
880 if (!IsWindow32( winpos
.hwnd
)) return;
881 if( above
== None
) /* absolute bottom */
883 WIN_UnlinkWindow( winpos
.hwnd
);
884 WIN_LinkWindow( winpos
.hwnd
, HWND_BOTTOM
);
886 else EVENT_QueryZOrder( pWnd
); /* try to outsmart window manager */
890 /***********************************************************************
891 * EVENT_SelectionRequest
893 static void EVENT_SelectionRequest( WND
*pWnd
, XSelectionRequestEvent
*event
)
895 XSelectionEvent result
;
897 Window request
= event
->requestor
;
899 if(event
->target
== XA_STRING
)
905 rprop
= event
->property
;
907 if(rprop
== None
) rprop
= event
->target
;
909 if(event
->selection
!=XA_PRIMARY
) rprop
= None
;
910 else if(!CLIPBOARD_IsPresent(CF_OEMTEXT
)) rprop
= None
;
913 /* open to make sure that clipboard is available */
915 BOOL32 couldOpen
= OpenClipboard32( pWnd
->hwndSelf
);
918 hText
= GetClipboardData16(CF_TEXT
);
919 text
= GlobalLock16(hText
);
920 size
= GlobalSize16(hText
);
922 /* remove carriage returns */
924 lpstr
= (char*)HEAP_xalloc( GetProcessHeap(), 0, size
-- );
925 for(i
=0,j
=0; i
< size
&& text
[i
]; i
++ )
927 if( text
[i
] == '\r' &&
928 (text
[i
+1] == '\n' || text
[i
+1] == '\0') ) continue;
929 lpstr
[j
++] = text
[i
];
933 TSXChangeProperty(display
, request
, rprop
,
934 XA_STRING
, 8, PropModeReplace
,
936 HeapFree( GetProcessHeap(), 0, lpstr
);
938 /* close only if we opened before */
940 if(couldOpen
) CloseClipboard32();
945 TRACE(event
,"Request for %s ignored\n", TSXGetAtomName(display
,event
->target
));
947 result
.type
= SelectionNotify
;
948 result
.display
= display
;
949 result
.requestor
= request
;
950 result
.selection
= event
->selection
;
951 result
.property
= rprop
;
952 result
.target
= event
->target
;
953 result
.time
= event
->time
;
954 TSXSendEvent(display
,event
->requestor
,False
,NoEventMask
,(XEvent
*)&result
);
958 /***********************************************************************
959 * EVENT_SelectionNotify
961 static void EVENT_SelectionNotify( XSelectionEvent
*event
)
963 if (event
->selection
!= XA_PRIMARY
) return;
965 if (event
->target
!= XA_STRING
) CLIPBOARD_ReadSelection( 0, None
);
966 else CLIPBOARD_ReadSelection( event
->requestor
, event
->property
);
968 TRACE(clipboard
,"\tSelectionNotify done!\n");
972 /***********************************************************************
973 * EVENT_SelectionClear
975 static void EVENT_SelectionClear( WND
*pWnd
, XSelectionClearEvent
*event
)
977 if (event
->selection
!= XA_PRIMARY
) return;
978 CLIPBOARD_ReleaseSelection( event
->window
, pWnd
->hwndSelf
);
982 /**********************************************************************
983 * EVENT_ClientMessage
985 static void EVENT_ClientMessage( WND
*pWnd
, XClientMessageEvent
*event
)
987 if (event
->message_type
!= None
&& event
->format
== 32)
989 if ((event
->message_type
== wmProtocols
) &&
990 (((Atom
) event
->data
.l
[0]) == wmDeleteWindow
))
991 SendMessage16( pWnd
->hwndSelf
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
992 else if ( event
->message_type
== dndProtocol
&&
993 (event
->data
.l
[0] == DndFile
|| event
->data
.l
[0] == DndFiles
) )
995 unsigned long data_length
;
996 unsigned long aux_long
;
997 unsigned char* p_data
= NULL
;
1005 HGLOBAL16 hDragInfo
= GlobalAlloc16( GMEM_SHARE
| GMEM_ZEROINIT
, sizeof(DRAGINFO
));
1006 LPDRAGINFO lpDragInfo
= (LPDRAGINFO
) GlobalLock16(hDragInfo
);
1007 SEGPTR spDragInfo
= (SEGPTR
) WIN16_GlobalLock16(hDragInfo
);
1008 Window w_aux_root
, w_aux_child
;
1011 if( !lpDragInfo
|| !spDragInfo
) return;
1013 TSXQueryPointer( display
, pWnd
->window
, &w_aux_root
, &w_aux_child
,
1014 &x
, &y
, &u
.pt_aux
.x
, &u
.pt_aux
.y
, (unsigned int*)&aux_long
);
1016 lpDragInfo
->hScope
= pWnd
->hwndSelf
;
1017 lpDragInfo
->pt
.x
= (INT16
)x
; lpDragInfo
->pt
.y
= (INT16
)y
;
1019 /* find out drop point and drop window */
1020 if( x
< 0 || y
< 0 ||
1021 x
> (pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) ||
1022 y
> (pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
) )
1023 { bAccept
= pWnd
->dwExStyle
& WS_EX_ACCEPTFILES
; x
= y
= 0; }
1026 bAccept
= DRAG_QueryUpdate( pWnd
->hwndSelf
, spDragInfo
, TRUE
);
1027 x
= lpDragInfo
->pt
.x
; y
= lpDragInfo
->pt
.y
;
1029 pDropWnd
= WIN_FindWndPtr( lpDragInfo
->hScope
);
1030 GlobalFree16( hDragInfo
);
1034 TSXGetWindowProperty( display
, DefaultRootWindow(display
),
1035 dndSelection
, 0, 65535, FALSE
,
1036 AnyPropertyType
, &u
.atom_aux
, &u
.pt_aux
.y
,
1037 &data_length
, &aux_long
, &p_data
);
1039 if( !aux_long
&& p_data
) /* don't bother if > 64K */
1041 char *p
= (char*) p_data
;
1045 while( *p
) /* calculate buffer size */
1048 if((u
.i
= *p
) != -1 )
1049 u
.i
= DRIVE_FindDriveRoot( (const char **)&p_drop
);
1050 if( u
.i
== -1 ) *p
= -1; /* mark as "bad" */
1053 INT32 len
= GetShortPathName32A( p
, NULL
, 0 );
1054 if (len
) aux_long
+= len
+ 1;
1059 if( aux_long
&& aux_long
< 65535 )
1062 LPDROPFILESTRUCT lpDrop
;
1064 aux_long
+= sizeof(DROPFILESTRUCT
) + 1;
1065 hDrop
= (HDROP16
)GlobalAlloc16( GMEM_SHARE
, aux_long
);
1066 lpDrop
= (LPDROPFILESTRUCT
) GlobalLock16( hDrop
);
1070 lpDrop
->wSize
= sizeof(DROPFILESTRUCT
);
1071 lpDrop
->ptMousePos
.x
= (INT16
)x
;
1072 lpDrop
->ptMousePos
.y
= (INT16
)y
;
1073 lpDrop
->fInNonClientArea
= (BOOL16
)
1074 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
1075 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
1076 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
1077 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
1078 p_drop
= ((char*)lpDrop
) + sizeof(DROPFILESTRUCT
);
1082 if( *p
!= -1 ) /* use only "good" entries */
1084 GetShortPathName32A( p
, p_drop
, 65535 );
1085 p_drop
+= strlen( p_drop
) + 1;
1090 PostMessage16( pWnd
->hwndSelf
, WM_DROPFILES
,
1091 (WPARAM16
)hDrop
, 0L );
1095 if( p_data
) TSXFree(p_data
);
1097 } /* WS_EX_ACCEPTFILES */
1100 TRACE(event
, "unrecognized ClientMessage\n" );
1104 /**********************************************************************
1107 * Install colormap when Wine window is focused in
1108 * self-managed mode with private colormap
1111 void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event )
1113 if( !Options.managed && rootWindow == DefaultRootWindow(display) &&
1114 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() )
1115 TSXInstallColormap( display, COLOR_GetColormap() );
1119 /**********************************************************************
1122 void EVENT_MapNotify( HWND32 hWnd
, XMapEvent
*event
)
1124 HWND32 hwndFocus
= GetFocus32();
1126 if (hwndFocus
&& IsChild32( hWnd
, hwndFocus
))
1127 FOCUS_SetXFocus( (HWND32
)hwndFocus
);
1132 /**********************************************************************
1135 * We need this to be able to generate double click messages
1136 * when menu code captures mouse in the window without CS_DBLCLK style.
1138 HWND32
EVENT_Capture(HWND32 hwnd
, INT16 ht
)
1140 HWND32 capturePrev
= captureWnd
;
1149 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1152 TRACE(win
, "(0x%04x)\n", hwnd
);
1158 if( capturePrev
&& capturePrev
!= captureWnd
)
1160 WND
* wndPtr
= WIN_FindWndPtr( capturePrev
);
1161 if( wndPtr
&& (wndPtr
->flags
& WIN_ISWIN32
) )
1162 SendMessage32A( capturePrev
, WM_CAPTURECHANGED
, 0L, hwnd
);
1167 /**********************************************************************
1168 * EVENT_GetCaptureInfo
1170 INT16
EVENT_GetCaptureInfo()
1175 /**********************************************************************
1176 * SetCapture16 (USER.18)
1178 HWND16 WINAPI
SetCapture16( HWND16 hwnd
)
1180 return (HWND16
)EVENT_Capture( hwnd
, HTCLIENT
);
1184 /**********************************************************************
1185 * SetCapture32 (USER32.464)
1187 HWND32 WINAPI
SetCapture32( HWND32 hwnd
)
1189 return EVENT_Capture( hwnd
, HTCLIENT
);
1193 /**********************************************************************
1194 * ReleaseCapture (USER.19) (USER32.439)
1196 void WINAPI
ReleaseCapture(void)
1198 TRACE(win
, "captureWnd=%04x\n", captureWnd
);
1199 if( captureWnd
) EVENT_Capture( 0, 0 );
1203 /**********************************************************************
1204 * GetCapture16 (USER.236)
1206 HWND16 WINAPI
GetCapture16(void)
1212 /**********************************************************************
1213 * GetCapture32 (USER32.208)
1215 HWND32 WINAPI
GetCapture32(void)
1221 /***********************************************************************
1222 * GetMouseEventProc (USER.337)
1224 FARPROC16 WINAPI
GetMouseEventProc(void)
1226 HMODULE16 hmodule
= GetModuleHandle16("USER");
1227 return NE_GetEntryPoint( hmodule
, NE_GetOrdinal( hmodule
, "Mouse_Event" ));
1231 /***********************************************************************
1232 * Mouse_Event (USER.299)
1234 void WINAPI
Mouse_Event( CONTEXT
*context
)
1238 * BX = horizontal displacement if AX & ME_MOVE
1239 * CX = vertical displacement if AX & ME_MOVE
1240 * DX = button state (?)
1241 * SI = mouse event flags (?)
1244 int rootX
, rootY
, winX
, winY
;
1247 if (AX_reg(context
) & ME_MOVE
)
1249 /* We have to actually move the cursor */
1250 TSXWarpPointer( display
, rootWindow
, None
, 0, 0, 0, 0,
1251 (short)BX_reg(context
), (short)CX_reg(context
) );
1254 if (!TSXQueryPointer( display
, rootWindow
, &root
, &child
,
1255 &rootX
, &rootY
, &winX
, &winY
, &state
)) return;
1256 if (AX_reg(context
) & ME_LDOWN
)
1257 hardware_event( WM_LBUTTONDOWN
, EVENT_XStateToKeyState( state
),
1258 0L, winX
, winY
, GetTickCount(), 0 );
1259 if (AX_reg(context
) & ME_LUP
)
1260 hardware_event( WM_LBUTTONUP
, EVENT_XStateToKeyState( state
),
1261 0L, winX
, winY
, GetTickCount(), 0 );
1262 if (AX_reg(context
) & ME_RDOWN
)
1263 hardware_event( WM_RBUTTONDOWN
, EVENT_XStateToKeyState( state
),
1264 0L, winX
, winY
, GetTickCount(), 0 );
1265 if (AX_reg(context
) & ME_RUP
)
1266 hardware_event( WM_RBUTTONUP
, EVENT_XStateToKeyState( state
),
1267 0L, winX
, winY
, GetTickCount(), 0 );
1271 /**********************************************************************
1272 * EnableHardwareInput (USER.331)
1274 BOOL16 WINAPI
EnableHardwareInput(BOOL16 bEnable
)
1276 BOOL16 bOldState
= InputEnabled
;
1277 FIXME(event
,"(%d) - stub\n", bEnable
);
1278 InputEnabled
= bEnable
;
1283 /***********************************************************************
1284 * SwapMouseButton16 (USER.186)
1286 BOOL16 WINAPI
SwapMouseButton16( BOOL16 fSwap
)
1288 BOOL16 ret
= SwappedButtons
;
1289 SwappedButtons
= fSwap
;
1294 /***********************************************************************
1295 * SwapMouseButton32 (USER32.537)
1297 BOOL32 WINAPI
SwapMouseButton32( BOOL32 fSwap
)
1299 BOOL32 ret
= SwappedButtons
;
1300 SwappedButtons
= fSwap
;