2 * X events handling functions
4 * Copyright 1993 Alexandre Julliard
15 #include <sys/types.h>
17 #include <X11/keysym.h>
19 #include "ts_xresource.h"
21 #include <X11/Xatom.h>
30 #include "clipboard.h"
45 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
47 #define DndNotDnd -1 /* OffiX drag&drop */
59 /* X context to associate a hwnd to an X window */
60 static XContext winContext
= 0;
62 static INT16 captureHT
= HTCLIENT
;
63 static HWND32 captureWnd
= 0;
64 static BOOL32 InputEnabled
= TRUE
;
65 static BOOL32 SwappedButtons
= FALSE
;
67 static Atom wmProtocols
= None
;
68 static Atom wmDeleteWindow
= None
;
69 static Atom dndProtocol
= None
;
70 static Atom dndSelection
= None
;
72 /* EVENT_WaitNetEvent() master fd sets */
74 static fd_set __event_io_set
[3];
75 static int __event_max_fd
= 0;
76 static int __event_x_connection
= 0;
78 static const char * const event_names
[] =
80 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
81 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
82 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
83 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
84 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
85 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
86 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
87 "ClientMessage", "MappingNotify"
91 static void EVENT_Key( WND
*pWnd
, XKeyEvent
*event
);
92 static void EVENT_ButtonPress( WND
*pWnd
, XButtonEvent
*event
);
93 static void EVENT_ButtonRelease( WND
*pWnd
, XButtonEvent
*event
);
94 static void EVENT_MotionNotify( WND
*pWnd
, XMotionEvent
*event
);
95 static void EVENT_FocusIn( WND
*pWnd
, XFocusChangeEvent
*event
);
96 static void EVENT_FocusOut( WND
*pWnd
, XFocusChangeEvent
*event
);
97 static void EVENT_Expose( WND
*pWnd
, XExposeEvent
*event
);
98 static void EVENT_GraphicsExpose( WND
*pWnd
, XGraphicsExposeEvent
*event
);
99 static void EVENT_ConfigureNotify( WND
*pWnd
, XConfigureEvent
*event
);
100 static void EVENT_SelectionRequest( WND
*pWnd
, XSelectionRequestEvent
*event
);
101 static void EVENT_SelectionNotify( XSelectionEvent
*event
);
102 static void EVENT_SelectionClear( WND
*pWnd
, XSelectionClearEvent
*event
);
103 static void EVENT_ClientMessage( WND
*pWnd
, XClientMessageEvent
*event
);
104 static void EVENT_MapNotify( HWND32 hwnd
, XMapEvent
*event
);
106 /* Usable only with OLVWM - compile option perhaps?
107 static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event );
110 extern void FOCUS_SetXFocus( HWND32
);
111 extern BOOL16
DRAG_QueryUpdate( HWND16
, SEGPTR
, BOOL32
);
112 extern BOOL32
WINSOCK_HandleIO( int* max_fd
, int num_pending
, fd_set p
[3], fd_set e
[3] );
114 /***********************************************************************
117 * Initialize network IO.
119 BOOL32
EVENT_Init(void)
122 for( i
= 0; i
< 3; i
++ )
123 FD_ZERO( __event_io_set
+ i
);
125 __event_max_fd
= __event_x_connection
= ConnectionNumber(display
);
126 FD_SET( __event_x_connection
, &__event_io_set
[EVENT_IO_READ
] );
131 /***********************************************************************
134 void EVENT_AddIO( int fd
, int io_type
)
136 FD_SET( fd
, &__event_io_set
[io_type
] );
137 if( __event_max_fd
<= fd
) __event_max_fd
= fd
+ 1;
140 void EVENT_DeleteIO( int fd
, int io_type
)
142 FD_CLR( fd
, &__event_io_set
[io_type
] );
145 /***********************************************************************
148 * Process an X event.
150 void EVENT_ProcessEvent( XEvent
*event
)
154 if (TSXFindContext( display
, event
->xany
.window
, winContext
,
155 (char **)&pWnd
) != 0)
156 return; /* Not for a registered window */
158 dprintf_event( stddeb
, "Got event %s for hwnd %04x\n",
159 event_names
[event
->type
], pWnd
->hwndSelf
);
165 if (InputEnabled
) EVENT_Key( pWnd
, (XKeyEvent
*)event
);
170 EVENT_ButtonPress( pWnd
, (XButtonEvent
*)event
);
175 EVENT_ButtonRelease( pWnd
, (XButtonEvent
*)event
);
179 /* Wine between two fast machines across the overloaded campus
180 ethernet gets very boged down in MotionEvents. The following
181 simply finds the last motion event in the queue and drops
182 the rest. On a good link events are servered before they build
183 up so this doesn't take place. On a slow link this may cause
184 problems if the event order is important. I'm not yet seen
185 of any problems. Jon 7/6/96.
189 while (TSXCheckTypedWindowEvent(display
,((XAnyEvent
*)event
)->window
,
190 MotionNotify
, event
));
191 EVENT_MotionNotify( pWnd
, (XMotionEvent
*)event
);
196 EVENT_FocusIn( pWnd
, (XFocusChangeEvent
*)event
);
200 EVENT_FocusOut( pWnd
, (XFocusChangeEvent
*)event
);
204 EVENT_Expose( pWnd
, (XExposeEvent
*)event
);
208 EVENT_GraphicsExpose( pWnd
, (XGraphicsExposeEvent
*)event
);
211 case ConfigureNotify
:
212 EVENT_ConfigureNotify( pWnd
, (XConfigureEvent
*)event
);
215 case SelectionRequest
:
216 EVENT_SelectionRequest( pWnd
, (XSelectionRequestEvent
*)event
);
219 case SelectionNotify
:
220 EVENT_SelectionNotify( (XSelectionEvent
*)event
);
224 EVENT_SelectionClear( pWnd
, (XSelectionClearEvent
*) event
);
228 EVENT_ClientMessage( pWnd
, (XClientMessageEvent
*) event
);
232 * EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
238 /* We get all these because of StructureNotifyMask. */
240 case CirculateNotify
:
248 EVENT_MapNotify( pWnd
->hwndSelf
, (XMapEvent
*)event
);
252 dprintf_event(stddeb
, "Unprocessed event %s for hwnd %04x\n",
253 event_names
[event
->type
], pWnd
->hwndSelf
);
259 /***********************************************************************
260 * EVENT_RegisterWindow
262 * Associate an X window to a HWND.
264 void EVENT_RegisterWindow( WND
*pWnd
)
266 if (wmProtocols
== None
)
267 wmProtocols
= TSXInternAtom( display
, "WM_PROTOCOLS", True
);
268 if (wmDeleteWindow
== None
)
269 wmDeleteWindow
= TSXInternAtom( display
, "WM_DELETE_WINDOW", True
);
270 if( dndProtocol
== None
)
271 dndProtocol
= TSXInternAtom( display
, "DndProtocol" , False
);
272 if( dndSelection
== None
)
273 dndSelection
= TSXInternAtom( display
, "DndSelection" , False
);
275 TSXSetWMProtocols( display
, pWnd
->window
, &wmDeleteWindow
, 1 );
277 if (!winContext
) winContext
= TSXUniqueContext();
278 TSXSaveContext( display
, pWnd
->window
, winContext
, (char *)pWnd
);
281 /***********************************************************************
282 * EVENT_DestroyWindow
284 void EVENT_DestroyWindow( WND
*pWnd
)
288 TSXDeleteContext( display
, pWnd
->window
, winContext
);
289 TSXDestroyWindow( display
, pWnd
->window
);
290 while( TSXCheckWindowEvent(display
, pWnd
->window
, NoEventMask
, &xe
) );
294 /***********************************************************************
295 * IsUserIdle (USER.333)
297 * Check if we have pending X events.
299 BOOL16 WINAPI
IsUserIdle(void)
301 struct timeval timeout
= {0, 0};
305 FD_SET(__event_x_connection
, &check_set
);
306 if( select(__event_x_connection
+ 1, &check_set
, NULL
, NULL
, &timeout
) > 0 )
312 /***********************************************************************
315 * Wait for a network event, optionally sleeping until one arrives.
316 * Return TRUE if an event is pending, FALSE on timeout or error
317 * (for instance lost connection with the server).
319 BOOL32
EVENT_WaitNetEvent( BOOL32 sleep
, BOOL32 peek
)
322 LONG maxWait
= sleep
? TIMER_GetNextExpiration() : 0;
323 int pending
= TSXPending(display
);
325 /* Wait for an event or a timeout. If maxWait is -1, we have no timeout;
326 * in this case, we fall through directly to the XNextEvent loop.
329 if ((maxWait
!= -1) && !pending
)
332 struct timeval timeout
;
335 memcpy( io_set
, __event_io_set
, sizeof(io_set
) );
337 timeout
.tv_usec
= (maxWait
% 1000) * 1000;
338 timeout
.tv_sec
= maxWait
/ 1000;
341 sigsetjmp(env_wait_x
, 1);
344 if (DDE_GetRemoteMessage()) {
345 while(DDE_GetRemoteMessage())
349 stop_wait_op
= STOP_WAIT_X
;
350 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
351 num_pending
= select( __event_max_fd
, &io_set
[EVENT_IO_READ
],
352 &io_set
[EVENT_IO_WRITE
],
353 &io_set
[EVENT_IO_EXCEPT
], &timeout
);
354 if ( num_pending
== 0 )
357 TIMER_ExpireTimers();
360 else stop_wait_op
= CONT
;
361 #else /* CONFIG_IPC */
362 num_pending
= select( __event_max_fd
, &io_set
[EVENT_IO_READ
],
363 &io_set
[EVENT_IO_WRITE
],
364 &io_set
[EVENT_IO_EXCEPT
], &timeout
);
365 if ( num_pending
== 0)
367 /* Timeout or error */
368 TIMER_ExpireTimers();
371 #endif /* CONFIG_IPC */
373 /* Winsock asynchronous services */
375 if( FD_ISSET( __event_x_connection
, &io_set
[EVENT_IO_READ
]) )
379 WINSOCK_HandleIO( &__event_max_fd
, num_pending
, io_set
, __event_io_set
);
381 else /* no X events */
382 return WINSOCK_HandleIO( &__event_max_fd
, num_pending
, io_set
, __event_io_set
);
385 { /* Wait for X11 input. */
389 FD_SET(__event_x_connection
, &set
);
390 select(__event_x_connection
+ 1, &set
, 0, 0, 0 );
393 /* Process current X event (and possibly others that occurred in the meantime) */
399 if (DDE_GetRemoteMessage())
401 while(DDE_GetRemoteMessage()) ;
404 #endif /* CONFIG_IPC */
406 TSXNextEvent( display
, &event
);
413 if (TSXFindContext( display
, ((XAnyEvent
*)&event
)->window
, winContext
,
414 (char **)&pWnd
) || (event
.type
== NoExpose
))
417 /* Check only for those events which can be processed
420 if( event
.type
== MotionNotify
||
421 event
.type
== ButtonPress
|| event
.type
== ButtonRelease
||
422 event
.type
== KeyPress
|| event
.type
== KeyRelease
||
423 event
.type
== SelectionRequest
|| event
.type
== SelectionClear
)
425 EVENT_ProcessEvent( &event
);
431 if( (pQ
= (MESSAGEQUEUE
*)GlobalLock16(pWnd
->hmemTaskQ
)) )
433 pQ
->flags
|= QUEUE_FLAG_XEVENT
;
434 PostEvent(pQ
->hTask
);
435 TSXPutBackEvent(display
, &event
);
440 else EVENT_ProcessEvent( &event
);
442 while (TSXPending( display
));
447 /***********************************************************************
450 * Synchronize with the X server. Should not be used too often.
452 void EVENT_Synchronize()
456 TSXSync( display
, False
);
457 while (TSXPending( display
))
459 TSXNextEvent( display
, &event
);
460 EVENT_ProcessEvent( &event
);
464 /***********************************************************************
467 * Try to synchronize internal z-order with the window manager's.
468 * Probably a futile endeavor.
470 static BOOL32
__check_query_condition( WND
** pWndA
, WND
** pWndB
)
472 /* return TRUE if we have at least two managed windows */
474 for( *pWndB
= NULL
; *pWndA
; *pWndA
= (*pWndA
)->next
)
475 if( (*pWndA
)->flags
& WIN_MANAGED
&&
476 (*pWndA
)->dwStyle
& WS_VISIBLE
) break;
478 for( *pWndB
= (*pWndA
)->next
; *pWndB
; *pWndB
= (*pWndB
)->next
)
479 if( (*pWndB
)->flags
& WIN_MANAGED
&&
480 (*pWndB
)->dwStyle
& WS_VISIBLE
) break;
481 return ((*pWndB
) != NULL
);
484 static Window
__get_common_ancestor( Window A
, Window B
,
485 Window
** children
, unsigned* total
)
487 /* find the real root window */
489 Window root
, *childrenB
;
494 if( *children
) TSXFree( *children
);
495 TSXQueryTree( display
, A
, &root
, &A
, children
, total
);
496 TSXQueryTree( display
, B
, &root
, &B
, &childrenB
, &totalB
);
497 if( childrenB
) TSXFree( childrenB
);
498 } while( A
!= B
&& A
&& B
);
499 return ( A
&& B
) ? A
: 0 ;
502 static Window
__get_top_decoration( Window w
, Window ancestor
)
504 Window
* children
, root
, prev
= w
, parent
= w
;
510 TSXQueryTree( display
, w
, &root
, &parent
, &children
, &total
);
511 if( children
) TSXFree( children
);
512 } while( parent
&& parent
!= ancestor
);
513 dprintf_event( stddeb
, "\t%08x -> %08x\n", (unsigned)prev
, (unsigned)w
);
514 return ( parent
) ? w
: 0 ;
517 static unsigned __td_lookup( Window w
, Window
* list
, unsigned max
)
520 for( i
= 0; i
< max
; i
++ ) if( list
[i
] == w
) break;
524 static BOOL32
EVENT_QueryZOrder( WND
* pWndCheck
)
527 HWND32 hwndInsertAfter
= HWND_TOP
;
528 WND
* pWnd
, *pWndZ
= WIN_GetDesktop()->child
;
529 Window w
, parent
, *children
= NULL
;
530 unsigned total
, check
, pos
, best
;
532 if( !__check_query_condition(&pWndZ
, &pWnd
) ) return TRUE
;
534 parent
= __get_common_ancestor( pWndZ
->window
, pWnd
->window
,
536 if( parent
&& children
)
538 w
= __get_top_decoration( pWndCheck
->window
, parent
);
539 if( w
!= children
[total
- 1] )
541 check
= __td_lookup( w
, children
, total
);
543 for( pWnd
= pWndZ
; pWnd
; pWnd
= pWnd
->next
)
545 if( pWnd
!= pWndCheck
)
547 if( !(pWnd
->flags
& WIN_MANAGED
) ||
548 !(w
= __get_top_decoration( pWnd
->window
, parent
)) )
550 pos
= __td_lookup( w
, children
, total
);
551 if( pos
< best
&& pos
> check
)
554 hwndInsertAfter
= pWnd
->hwndSelf
;
556 if( check
- best
== 1 ) break;
559 WIN_UnlinkWindow( pWndCheck
->hwndSelf
);
560 WIN_LinkWindow( pWndCheck
->hwndSelf
, hwndInsertAfter
);
563 if( children
) TSXFree( children
);
568 /***********************************************************************
569 * EVENT_XStateToKeyState
571 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
572 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
574 static WORD
EVENT_XStateToKeyState( int state
)
578 if (state
& Button1Mask
) kstate
|= MK_LBUTTON
;
579 if (state
& Button2Mask
) kstate
|= MK_MBUTTON
;
580 if (state
& Button3Mask
) kstate
|= MK_RBUTTON
;
581 if (state
& ShiftMask
) kstate
|= MK_SHIFT
;
582 if (state
& ControlMask
) kstate
|= MK_CONTROL
;
587 /***********************************************************************
590 static void EVENT_Expose( WND
*pWnd
, XExposeEvent
*event
)
594 /* Make position relative to client area instead of window */
595 rect
.left
= event
->x
- (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
);
596 rect
.top
= event
->y
- (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
);
597 rect
.right
= rect
.left
+ event
->width
;
598 rect
.bottom
= rect
.top
+ event
->height
;
600 PAINT_RedrawWindow( pWnd
->hwndSelf
, &rect
, 0,
601 RDW_INVALIDATE
| RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
|
602 (event
->count
? 0 : RDW_ERASENOW
), 0 );
606 /***********************************************************************
607 * EVENT_GraphicsExpose
609 * This is needed when scrolling area is partially obscured
610 * by non-Wine X window.
612 static void EVENT_GraphicsExpose( WND
*pWnd
, XGraphicsExposeEvent
*event
)
616 /* Make position relative to client area instead of window */
617 rect
.left
= event
->x
- (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
);
618 rect
.top
= event
->y
- (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
);
619 rect
.right
= rect
.left
+ event
->width
;
620 rect
.bottom
= rect
.top
+ event
->height
;
622 PAINT_RedrawWindow( pWnd
->hwndSelf
, &rect
, 0,
623 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASE
|
624 (event
->count
? 0 : RDW_ERASENOW
), 0 );
628 /***********************************************************************
631 * Handle a X key event
633 static void EVENT_Key( WND
*pWnd
, XKeyEvent
*event
)
635 KEYBOARD_HandleEvent( pWnd
, event
);
639 /***********************************************************************
642 static void EVENT_MotionNotify( WND
*pWnd
, XMotionEvent
*event
)
644 hardware_event( WM_MOUSEMOVE
, EVENT_XStateToKeyState( event
->state
), 0L,
645 pWnd
->rectWindow
.left
+ event
->x
,
646 pWnd
->rectWindow
.top
+ event
->y
,
647 event
->time
- MSG_WineStartTicks
, pWnd
->hwndSelf
);
651 /***********************************************************************
652 * EVENT_DummyMotionNotify
654 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
656 void EVENT_DummyMotionNotify(void)
659 int rootX
, rootY
, winX
, winY
;
662 if (TSXQueryPointer( display
, rootWindow
, &root
, &child
,
663 &rootX
, &rootY
, &winX
, &winY
, &state
))
665 hardware_event( WM_MOUSEMOVE
, EVENT_XStateToKeyState( state
), 0L,
666 winX
, winY
, GetTickCount(), 0 );
671 /***********************************************************************
674 static void EVENT_ButtonPress( WND
*pWnd
, XButtonEvent
*event
)
676 static WORD messages
[NB_BUTTONS
] =
677 { WM_LBUTTONDOWN
, WM_MBUTTONDOWN
, WM_RBUTTONDOWN
};
678 int buttonNum
= event
->button
- 1;
680 if (buttonNum
>= NB_BUTTONS
) return;
681 if (SwappedButtons
) buttonNum
= NB_BUTTONS
- 1 - buttonNum
;
682 MouseButtonsStates
[buttonNum
] = TRUE
;
683 AsyncMouseButtonsStates
[buttonNum
] = TRUE
;
684 hardware_event( messages
[buttonNum
],
685 EVENT_XStateToKeyState( event
->state
), 0L,
686 pWnd
->rectWindow
.left
+ event
->x
,
687 pWnd
->rectWindow
.top
+ event
->y
,
688 event
->time
- MSG_WineStartTicks
, pWnd
->hwndSelf
);
692 /***********************************************************************
693 * EVENT_ButtonRelease
695 static void EVENT_ButtonRelease( WND
*pWnd
, XButtonEvent
*event
)
697 static const WORD messages
[NB_BUTTONS
] =
698 { WM_LBUTTONUP
, WM_MBUTTONUP
, WM_RBUTTONUP
};
699 int buttonNum
= event
->button
- 1;
701 if (buttonNum
>= NB_BUTTONS
) return;
702 if (SwappedButtons
) buttonNum
= NB_BUTTONS
- 1 - buttonNum
;
703 MouseButtonsStates
[buttonNum
] = FALSE
;
704 hardware_event( messages
[buttonNum
],
705 EVENT_XStateToKeyState( event
->state
), 0L,
706 pWnd
->rectWindow
.left
+ event
->x
,
707 pWnd
->rectWindow
.top
+ event
->y
,
708 event
->time
- MSG_WineStartTicks
, pWnd
->hwndSelf
);
712 /**********************************************************************
715 static void EVENT_FocusIn( WND
*pWnd
, XFocusChangeEvent
*event
)
717 if (Options
.managed
) EVENT_QueryZOrder( pWnd
);
719 if (event
->detail
!= NotifyPointer
)
721 HWND32 hwnd
= pWnd
->hwndSelf
;
723 if (hwnd
!= GetActiveWindow32())
724 WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
725 if ((hwnd
!= GetFocus32()) && !IsChild32( hwnd
, GetFocus32()))
731 /**********************************************************************
734 * Note: only top-level override-redirect windows get FocusOut events.
736 static void EVENT_FocusOut( WND
*pWnd
, XFocusChangeEvent
*event
)
738 if (event
->detail
!= NotifyPointer
)
740 HWND32 hwnd
= pWnd
->hwndSelf
;
742 if (hwnd
== GetActiveWindow32())
743 WINPOS_ChangeActiveWindow( 0, FALSE
);
744 if ((hwnd
== GetFocus32()) || IsChild32( hwnd
, GetFocus32()))
749 /**********************************************************************
752 BOOL32
EVENT_CheckFocus(void)
758 TSXGetInputFocus(display
, &xW
, &state
);
760 TSXFindContext(display
, xW
, winContext
, (char **)&pWnd
) )
766 /**********************************************************************
769 * Helper function for ConfigureNotify handling.
770 * Get the new geometry of a window relative to the root window.
772 static void EVENT_GetGeometry( Window win
, int *px
, int *py
,
773 unsigned int *pwidth
, unsigned int *pheight
)
775 Window root
, parent
, *children
;
777 unsigned int width
, height
, border
, depth
, nb_children
;
779 if (!TSXGetGeometry( display
, win
, &root
, px
, py
, pwidth
, pheight
,
780 &border
, &depth
)) return;
781 if (win
== rootWindow
)
789 if (!TSXQueryTree(display
, win
, &root
, &parent
, &children
, &nb_children
))
792 if (parent
== rootWindow
) break;
794 if (!TSXGetGeometry( display
, win
, &root
, &xpos
, &ypos
,
795 &width
, &height
, &border
, &depth
)) return;
802 /**********************************************************************
803 * EVENT_ConfigureNotify
805 * The ConfigureNotify event is only selected on top-level windows
806 * when the -managed flag is used.
808 static void EVENT_ConfigureNotify( WND
*pWnd
, XConfigureEvent
*event
)
811 RECT32 newWindowRect
, newClientRect
;
812 HRGN32 hrgnOldPos
, hrgnNewPos
;
813 Window above
= event
->above
;
815 unsigned int width
, height
;
817 assert (pWnd
->flags
& WIN_MANAGED
);
819 /* We don't rely on the event geometry info, because it is relative
820 * to parent and not to root, and it may be wrong (XFree sets x,y to 0,0
821 * if the window hasn't moved).
823 EVENT_GetGeometry( event
->window
, &x
, &y
, &width
, &height
);
825 /* Fill WINDOWPOS struct */
826 winpos
.flags
= SWP_NOACTIVATE
| SWP_NOZORDER
;
827 winpos
.hwnd
= pWnd
->hwndSelf
;
833 /* Check for unchanged attributes */
834 if (winpos
.x
== pWnd
->rectWindow
.left
&& winpos
.y
== pWnd
->rectWindow
.top
)
835 winpos
.flags
|= SWP_NOMOVE
;
836 if ((winpos
.cx
== pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) &&
837 (winpos
.cy
== pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
))
838 winpos
.flags
|= SWP_NOSIZE
;
841 RECT32 rect
= { 0, 0, pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
,
842 pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
};
843 DCE_InvalidateDCE( pWnd
, &rect
);
846 /* Send WM_WINDOWPOSCHANGING */
847 SendMessage32A( winpos
.hwnd
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)&winpos
);
849 /* Calculate new position and size */
850 newWindowRect
.left
= x
;
851 newWindowRect
.right
= x
+ width
;
852 newWindowRect
.top
= y
;
853 newWindowRect
.bottom
= y
+ height
;
855 WINPOS_SendNCCalcSize( winpos
.hwnd
, TRUE
, &newWindowRect
,
856 &pWnd
->rectWindow
, &pWnd
->rectClient
,
857 &winpos
, &newClientRect
);
859 hrgnOldPos
= CreateRectRgnIndirect32( &pWnd
->rectWindow
);
860 hrgnNewPos
= CreateRectRgnIndirect32( &newWindowRect
);
861 CombineRgn32( hrgnOldPos
, hrgnOldPos
, hrgnNewPos
, RGN_DIFF
);
862 DeleteObject32(hrgnOldPos
);
863 DeleteObject32(hrgnNewPos
);
865 /* Set new size and position */
866 pWnd
->rectWindow
= newWindowRect
;
867 pWnd
->rectClient
= newClientRect
;
868 SendMessage32A( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
870 if (!IsWindow32( winpos
.hwnd
)) return;
871 if( above
== None
) /* absolute bottom */
873 WIN_UnlinkWindow( winpos
.hwnd
);
874 WIN_LinkWindow( winpos
.hwnd
, HWND_BOTTOM
);
876 else EVENT_QueryZOrder( pWnd
); /* try to outsmart window manager */
880 /***********************************************************************
881 * EVENT_SelectionRequest
883 static void EVENT_SelectionRequest( WND
*pWnd
, XSelectionRequestEvent
*event
)
885 XSelectionEvent result
;
887 Window request
= event
->requestor
;
889 if(event
->target
== XA_STRING
)
895 rprop
= event
->property
;
897 if(rprop
== None
) rprop
= event
->target
;
899 if(event
->selection
!=XA_PRIMARY
) rprop
= None
;
900 else if(!CLIPBOARD_IsPresent(CF_OEMTEXT
)) rprop
= None
;
903 /* open to make sure that clipboard is available */
905 BOOL32 couldOpen
= OpenClipboard32( pWnd
->hwndSelf
);
908 hText
= GetClipboardData16(CF_TEXT
);
909 text
= GlobalLock16(hText
);
910 size
= GlobalSize16(hText
);
912 /* remove carriage returns */
914 lpstr
= (char*)HEAP_xalloc( GetProcessHeap(), 0, size
-- );
915 for(i
=0,j
=0; i
< size
&& text
[i
]; i
++ )
917 if( text
[i
] == '\r' &&
918 (text
[i
+1] == '\n' || text
[i
+1] == '\0') ) continue;
919 lpstr
[j
++] = text
[i
];
923 TSXChangeProperty(display
, request
, rprop
,
924 XA_STRING
, 8, PropModeReplace
,
926 HeapFree( GetProcessHeap(), 0, lpstr
);
928 /* close only if we opened before */
930 if(couldOpen
) CloseClipboard32();
935 dprintf_event(stddeb
,"Request for %s ignored\n", TSXGetAtomName(display
,event
->target
));
937 result
.type
= SelectionNotify
;
938 result
.display
= display
;
939 result
.requestor
= request
;
940 result
.selection
= event
->selection
;
941 result
.property
= rprop
;
942 result
.target
= event
->target
;
943 result
.time
= event
->time
;
944 TSXSendEvent(display
,event
->requestor
,False
,NoEventMask
,(XEvent
*)&result
);
948 /***********************************************************************
949 * EVENT_SelectionNotify
951 static void EVENT_SelectionNotify( XSelectionEvent
*event
)
953 if (event
->selection
!= XA_PRIMARY
) return;
955 if (event
->target
!= XA_STRING
) CLIPBOARD_ReadSelection( 0, None
);
956 else CLIPBOARD_ReadSelection( event
->requestor
, event
->property
);
958 dprintf_clipboard(stddeb
,"\tSelectionNotify done!\n");
962 /***********************************************************************
963 * EVENT_SelectionClear
965 static void EVENT_SelectionClear( WND
*pWnd
, XSelectionClearEvent
*event
)
967 if (event
->selection
!= XA_PRIMARY
) return;
968 CLIPBOARD_ReleaseSelection( event
->window
, pWnd
->hwndSelf
);
972 /**********************************************************************
973 * EVENT_ClientMessage
975 static void EVENT_ClientMessage( WND
*pWnd
, XClientMessageEvent
*event
)
977 if (event
->message_type
!= None
&& event
->format
== 32)
979 if ((event
->message_type
== wmProtocols
) &&
980 (((Atom
) event
->data
.l
[0]) == wmDeleteWindow
))
981 SendMessage16( pWnd
->hwndSelf
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
982 else if ( event
->message_type
== dndProtocol
&&
983 (event
->data
.l
[0] == DndFile
|| event
->data
.l
[0] == DndFiles
) )
985 unsigned long data_length
;
986 unsigned long aux_long
;
987 unsigned char* p_data
= NULL
;
995 HGLOBAL16 hDragInfo
= GlobalAlloc16( GMEM_SHARE
| GMEM_ZEROINIT
, sizeof(DRAGINFO
));
996 LPDRAGINFO lpDragInfo
= (LPDRAGINFO
) GlobalLock16(hDragInfo
);
997 SEGPTR spDragInfo
= (SEGPTR
) WIN16_GlobalLock16(hDragInfo
);
998 Window w_aux_root
, w_aux_child
;
1001 if( !lpDragInfo
|| !spDragInfo
) return;
1003 TSXQueryPointer( display
, pWnd
->window
, &w_aux_root
, &w_aux_child
,
1004 &x
, &y
, &u
.pt_aux
.x
, &u
.pt_aux
.y
, (unsigned int*)&aux_long
);
1006 lpDragInfo
->hScope
= pWnd
->hwndSelf
;
1007 lpDragInfo
->pt
.x
= (INT16
)x
; lpDragInfo
->pt
.y
= (INT16
)y
;
1009 /* find out drop point and drop window */
1010 if( x
< 0 || y
< 0 ||
1011 x
> (pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) ||
1012 y
> (pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
) )
1013 { bAccept
= pWnd
->dwExStyle
& WS_EX_ACCEPTFILES
; x
= y
= 0; }
1016 bAccept
= DRAG_QueryUpdate( pWnd
->hwndSelf
, spDragInfo
, TRUE
);
1017 x
= lpDragInfo
->pt
.x
; y
= lpDragInfo
->pt
.y
;
1019 pDropWnd
= WIN_FindWndPtr( lpDragInfo
->hScope
);
1020 GlobalFree16( hDragInfo
);
1024 TSXGetWindowProperty( display
, DefaultRootWindow(display
),
1025 dndSelection
, 0, 65535, FALSE
,
1026 AnyPropertyType
, &u
.atom_aux
, &u
.pt_aux
.y
,
1027 &data_length
, &aux_long
, &p_data
);
1029 if( !aux_long
&& p_data
) /* don't bother if > 64K */
1031 char *p
= (char*) p_data
;
1035 while( *p
) /* calculate buffer size */
1038 if((u
.i
= *p
) != -1 )
1039 u
.i
= DRIVE_FindDriveRoot( (const char **)&p_drop
);
1040 if( u
.i
== -1 ) *p
= -1; /* mark as "bad" */
1043 INT32 len
= GetShortPathName32A( p
, NULL
, 0 );
1044 if (len
) aux_long
+= len
+ 1;
1049 if( aux_long
&& aux_long
< 65535 )
1052 LPDROPFILESTRUCT lpDrop
;
1054 aux_long
+= sizeof(DROPFILESTRUCT
) + 1;
1055 hDrop
= (HDROP16
)GlobalAlloc16( GMEM_SHARE
, aux_long
);
1056 lpDrop
= (LPDROPFILESTRUCT
) GlobalLock16( hDrop
);
1060 lpDrop
->wSize
= sizeof(DROPFILESTRUCT
);
1061 lpDrop
->ptMousePos
.x
= (INT16
)x
;
1062 lpDrop
->ptMousePos
.y
= (INT16
)y
;
1063 lpDrop
->fInNonClientArea
= (BOOL16
)
1064 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
1065 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
1066 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
1067 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
1068 p_drop
= ((char*)lpDrop
) + sizeof(DROPFILESTRUCT
);
1072 if( *p
!= -1 ) /* use only "good" entries */
1074 GetShortPathName32A( p
, p_drop
, 65535 );
1075 p_drop
+= strlen( p_drop
) + 1;
1080 PostMessage16( pWnd
->hwndSelf
, WM_DROPFILES
,
1081 (WPARAM16
)hDrop
, 0L );
1085 if( p_data
) TSXFree(p_data
);
1087 } /* WS_EX_ACCEPTFILES */
1090 dprintf_event( stddeb
, "unrecognized ClientMessage\n" );
1094 /**********************************************************************
1097 * Install colormap when Wine window is focused in
1098 * self-managed mode with private colormap
1101 void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event )
1103 if( !Options.managed && rootWindow == DefaultRootWindow(display) &&
1104 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() )
1105 TSXInstallColormap( display, COLOR_GetColormap() );
1109 /**********************************************************************
1112 void EVENT_MapNotify( HWND32 hWnd
, XMapEvent
*event
)
1114 HWND32 hwndFocus
= GetFocus32();
1116 if (hwndFocus
&& IsChild32( hWnd
, hwndFocus
))
1117 FOCUS_SetXFocus( (HWND32
)hwndFocus
);
1122 /**********************************************************************
1125 * We need this to be able to generate double click messages
1126 * when menu code captures mouse in the window without CS_DBLCLK style.
1128 HWND32
EVENT_Capture(HWND32 hwnd
, INT16 ht
)
1131 HWND32 capturePrev
= captureWnd
;
1135 TSXUngrabPointer(display
, CurrentTime
);
1136 captureWnd
= NULL
; captureHT
= 0;
1138 else if ((win
= WIN_GetXWindow( hwnd
)))
1140 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1143 (TSXGrabPointer(display
, win
, False
,
1144 ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
,
1145 GrabModeAsync
, GrabModeAsync
,
1146 None
, None
, CurrentTime
) == GrabSuccess
) )
1148 dprintf_win(stddeb
, "SetCapture(0x%04x)\n", hwnd
);
1154 if( capturePrev
&& capturePrev
!= captureWnd
)
1156 WND
* wndPtr
= WIN_FindWndPtr( capturePrev
);
1157 if( wndPtr
&& (wndPtr
->flags
& WIN_ISWIN32
) )
1158 SendMessage32A( capturePrev
, WM_CAPTURECHANGED
, 0L, hwnd
);
1163 /**********************************************************************
1164 * EVENT_GetCaptureInfo
1166 INT16
EVENT_GetCaptureInfo()
1171 /**********************************************************************
1172 * SetCapture16 (USER.18)
1174 HWND16 WINAPI
SetCapture16( HWND16 hwnd
)
1176 return (HWND16
)EVENT_Capture( hwnd
, HTCLIENT
);
1180 /**********************************************************************
1181 * SetCapture32 (USER32.463)
1183 HWND32 WINAPI
SetCapture32( HWND32 hwnd
)
1185 return EVENT_Capture( hwnd
, HTCLIENT
);
1189 /**********************************************************************
1190 * ReleaseCapture (USER.19) (USER32.438)
1192 void WINAPI
ReleaseCapture(void)
1194 dprintf_win(stddeb
, "ReleaseCapture() [%04x]\n", captureWnd
);
1195 if( captureWnd
) EVENT_Capture( 0, 0 );
1199 /**********************************************************************
1200 * GetCapture16 (USER.236)
1202 HWND16 WINAPI
GetCapture16(void)
1208 /**********************************************************************
1209 * GetCapture32 (USER32.207)
1211 HWND32 WINAPI
GetCapture32(void)
1217 /***********************************************************************
1218 * GetMouseEventProc (USER.337)
1220 FARPROC16 WINAPI
GetMouseEventProc(void)
1222 HMODULE16 hmodule
= GetModuleHandle16("USER");
1223 return MODULE_GetEntryPoint( hmodule
,
1224 MODULE_GetOrdinal( hmodule
, "Mouse_Event" ) );
1228 /***********************************************************************
1229 * Mouse_Event (USER.299)
1231 void WINAPI
Mouse_Event( CONTEXT
*context
)
1235 * BX = horizontal displacement if AX & ME_MOVE
1236 * CX = vertical displacement if AX & ME_MOVE
1237 * DX = button state (?)
1238 * SI = mouse event flags (?)
1241 int rootX
, rootY
, winX
, winY
;
1244 if (AX_reg(context
) & ME_MOVE
)
1246 /* We have to actually move the cursor */
1247 TSXWarpPointer( display
, rootWindow
, None
, 0, 0, 0, 0,
1248 (short)BX_reg(context
), (short)CX_reg(context
) );
1251 if (!TSXQueryPointer( display
, rootWindow
, &root
, &child
,
1252 &rootX
, &rootY
, &winX
, &winY
, &state
)) return;
1253 if (AX_reg(context
) & ME_LDOWN
)
1254 hardware_event( WM_LBUTTONDOWN
, EVENT_XStateToKeyState( state
),
1255 0L, winX
, winY
, GetTickCount(), 0 );
1256 if (AX_reg(context
) & ME_LUP
)
1257 hardware_event( WM_LBUTTONUP
, EVENT_XStateToKeyState( state
),
1258 0L, winX
, winY
, GetTickCount(), 0 );
1259 if (AX_reg(context
) & ME_RDOWN
)
1260 hardware_event( WM_RBUTTONDOWN
, EVENT_XStateToKeyState( state
),
1261 0L, winX
, winY
, GetTickCount(), 0 );
1262 if (AX_reg(context
) & ME_RUP
)
1263 hardware_event( WM_RBUTTONUP
, EVENT_XStateToKeyState( state
),
1264 0L, winX
, winY
, GetTickCount(), 0 );
1268 /**********************************************************************
1269 * EnableHardwareInput (USER.331)
1271 BOOL16 WINAPI
EnableHardwareInput(BOOL16 bEnable
)
1273 BOOL16 bOldState
= InputEnabled
;
1274 dprintf_event(stdnimp
,"EnableHardwareInput(%d);\n", bEnable
);
1275 InputEnabled
= bEnable
;
1280 /***********************************************************************
1281 * SwapMouseButton16 (USER.186)
1283 BOOL16 WINAPI
SwapMouseButton16( BOOL16 fSwap
)
1285 BOOL16 ret
= SwappedButtons
;
1286 SwappedButtons
= fSwap
;
1291 /***********************************************************************
1292 * SwapMouseButton32 (USER32.536)
1294 BOOL32 WINAPI
SwapMouseButton32( BOOL32 fSwap
)
1296 BOOL32 ret
= SwappedButtons
;
1297 SwappedButtons
= fSwap
;