2 * X events handling functions
4 * Copyright 1993 Alexandre Julliard
15 #include <sys/types.h>
17 #include <X11/keysym.h>
19 #include <X11/Xresource.h>
20 #include <X11/Xutil.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 io_set
[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 (XFindContext( 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 (XCheckTypedWindowEvent(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
= XInternAtom( display
, "WM_PROTOCOLS", True
);
268 if (wmDeleteWindow
== None
)
269 wmDeleteWindow
= XInternAtom( display
, "WM_DELETE_WINDOW", True
);
270 if( dndProtocol
== None
)
271 dndProtocol
= XInternAtom( display
, "DndProtocol" , False
);
272 if( dndSelection
== None
)
273 dndSelection
= XInternAtom( display
, "DndSelection" , False
);
275 XSetWMProtocols( display
, pWnd
->window
, &wmDeleteWindow
, 1 );
277 if (!winContext
) winContext
= XUniqueContext();
278 XSaveContext( display
, pWnd
->window
, winContext
, (char *)pWnd
);
281 /***********************************************************************
282 * EVENT_DestroyWindow
284 void EVENT_DestroyWindow( WND
*pWnd
)
288 XDeleteContext( display
, pWnd
->window
, winContext
);
289 XDestroyWindow( display
, pWnd
->window
);
290 while( XCheckWindowEvent(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;
324 /* Wait for an event or a timeout. If maxWait is -1, we have no timeout;
325 * in this case, we fall through directly to the XNextEvent loop.
328 if ((maxWait
!= -1) && !XPending(display
))
331 struct timeval timeout
;
332 fd_set read_set
= __event_io_set
[EVENT_IO_READ
];
333 fd_set write_set
= __event_io_set
[EVENT_IO_WRITE
];
334 fd_set except_set
= __event_io_set
[EVENT_IO_EXCEPT
];
336 timeout
.tv_usec
= (maxWait
% 1000) * 1000;
337 timeout
.tv_sec
= maxWait
/ 1000;
340 sigsetjmp(env_wait_x
, 1);
343 if (DDE_GetRemoteMessage()) {
344 while(DDE_GetRemoteMessage())
348 stop_wait_op
= STOP_WAIT_X
;
349 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
350 num_pending
= select( __event_max_fd
, &read_set
, NULL
, NULL
, &timeout
);
351 if ( num_pending
== 0 )
354 TIMER_ExpireTimers();
357 else stop_wait_op
= CONT
;
358 #else /* CONFIG_IPC */
359 num_pending
= select( __event_max_fd
,
360 &read_set
, &write_set
, &except_set
, &timeout
);
361 if ( num_pending
== 0)
363 /* Timeout or error */
364 TIMER_ExpireTimers();
367 #endif /* CONFIG_IPC */
369 /* Winsock asynchronous services */
371 if( FD_ISSET( __event_x_connection
, &read_set
) )
375 WINSOCK_HandleIO( &__event_max_fd
, num_pending
, __event_io_set
);
377 else /* no X events */
378 return WINSOCK_HandleIO( &__event_max_fd
, num_pending
, __event_io_set
);
381 /* Process current X event (and possibly others that occurred in the meantime) */
387 if (DDE_GetRemoteMessage())
389 while(DDE_GetRemoteMessage()) ;
392 #endif /* CONFIG_IPC */
394 XNextEvent( display
, &event
);
401 if (XFindContext( display
, ((XAnyEvent
*)&event
)->window
, winContext
,
402 (char **)&pWnd
) || (event
.type
== NoExpose
))
405 /* Check only for those events which can be processed
408 if( event
.type
== MotionNotify
||
409 event
.type
== ButtonPress
|| event
.type
== ButtonRelease
||
410 event
.type
== KeyPress
|| event
.type
== KeyRelease
||
411 event
.type
== SelectionRequest
|| event
.type
== SelectionClear
)
413 EVENT_ProcessEvent( &event
);
419 if( (pQ
= (MESSAGEQUEUE
*)GlobalLock16(pWnd
->hmemTaskQ
)) )
421 pQ
->flags
|= QUEUE_FLAG_XEVENT
;
422 PostEvent(pQ
->hTask
);
423 XPutBackEvent(display
, &event
);
428 else EVENT_ProcessEvent( &event
);
430 while (XPending( display
));
435 /***********************************************************************
438 * Synchronize with the X server. Should not be used too often.
440 void EVENT_Synchronize()
444 XSync( display
, False
);
445 while (XPending( display
))
447 XNextEvent( display
, &event
);
448 EVENT_ProcessEvent( &event
);
452 /***********************************************************************
455 * Try to synchronize internal z-order with the window manager's.
457 static BOOL32
__check_query_condition( WND
** pWndA
, WND
** pWndB
)
459 /* return TRUE if we have at least two managed windows */
461 for( *pWndB
= NULL
; *pWndA
; *pWndA
= (*pWndA
)->next
)
462 if( (*pWndA
)->flags
& WIN_MANAGED
&&
463 (*pWndA
)->dwStyle
& WS_VISIBLE
) break;
465 for( *pWndB
= (*pWndA
)->next
; *pWndB
; *pWndB
= (*pWndB
)->next
)
466 if( (*pWndB
)->flags
& WIN_MANAGED
&&
467 (*pWndB
)->dwStyle
& WS_VISIBLE
) break;
468 return ((*pWndB
) != NULL
);
471 static Window
__get_common_ancestor( Window A
, Window B
,
472 Window
** children
, unsigned* total
)
474 /* find the real root window */
476 Window root
, *childrenB
;
481 if( *children
) XFree( *children
);
482 XQueryTree( display
, A
, &root
, &A
, children
, total
);
483 XQueryTree( display
, B
, &root
, &B
, &childrenB
, &totalB
);
484 if( childrenB
) XFree( childrenB
);
485 } while( A
!= B
&& A
&& B
);
486 return ( A
&& B
) ? A
: 0 ;
489 static Window
__get_top_decoration( Window w
, Window ancestor
)
491 Window
* children
, root
, prev
= w
, parent
= w
;
497 XQueryTree( display
, w
, &root
, &parent
, &children
, &total
);
498 if( children
) XFree( children
);
499 } while( parent
&& parent
!= ancestor
);
500 dprintf_event( stddeb
, "\t%08x -> %08x\n", (unsigned)prev
, (unsigned)w
);
501 return ( parent
) ? w
: 0 ;
504 static unsigned __td_lookup( Window w
, Window
* list
, unsigned max
)
507 for( i
= 0; i
< max
; i
++ ) if( list
[i
] == w
) break;
511 static BOOL32
EVENT_QueryZOrder( WND
* pWndCheck
)
514 HWND32 hwndInsertAfter
= HWND_TOP
;
515 WND
* pWnd
, *pWndZ
= WIN_GetDesktop()->child
;
516 Window w
, parent
, *children
= NULL
;
517 unsigned total
, check
, pos
, best
;
519 if( !__check_query_condition(&pWndZ
, &pWnd
) ) return TRUE
;
521 parent
= __get_common_ancestor( pWndZ
->window
, pWnd
->window
,
523 if( parent
&& children
)
525 w
= __get_top_decoration( pWndCheck
->window
, parent
);
526 if( w
!= children
[total
- 1] )
528 check
= __td_lookup( w
, children
, total
);
530 for( pWnd
= pWndZ
; pWnd
; pWnd
= pWnd
->next
)
532 if( pWnd
!= pWndCheck
)
534 if( !(pWnd
->flags
& WIN_MANAGED
) ||
535 !(w
= __get_top_decoration( pWnd
->window
, parent
)) )
537 pos
= __td_lookup( w
, children
, total
);
538 if( pos
< best
&& pos
> check
)
541 hwndInsertAfter
= pWnd
->hwndSelf
;
543 if( check
- best
== 1 ) break;
546 WIN_UnlinkWindow( pWndCheck
->hwndSelf
);
547 WIN_LinkWindow( pWndCheck
->hwndSelf
, hwndInsertAfter
);
550 if( children
) XFree( children
);
555 /***********************************************************************
556 * EVENT_XStateToKeyState
558 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
559 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
561 static WORD
EVENT_XStateToKeyState( int state
)
565 if (state
& Button1Mask
) kstate
|= MK_LBUTTON
;
566 if (state
& Button2Mask
) kstate
|= MK_MBUTTON
;
567 if (state
& Button3Mask
) kstate
|= MK_RBUTTON
;
568 if (state
& ShiftMask
) kstate
|= MK_SHIFT
;
569 if (state
& ControlMask
) kstate
|= MK_CONTROL
;
574 /***********************************************************************
577 static void EVENT_Expose( WND
*pWnd
, XExposeEvent
*event
)
581 /* Make position relative to client area instead of window */
582 rect
.left
= event
->x
- (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
);
583 rect
.top
= event
->y
- (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
);
584 rect
.right
= rect
.left
+ event
->width
;
585 rect
.bottom
= rect
.top
+ event
->height
;
587 PAINT_RedrawWindow( pWnd
->hwndSelf
, &rect
, 0,
588 RDW_INVALIDATE
| RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
|
589 (event
->count
? 0 : RDW_ERASENOW
), 0 );
593 /***********************************************************************
594 * EVENT_GraphicsExpose
596 * This is needed when scrolling area is partially obscured
597 * by non-Wine X window.
599 static void EVENT_GraphicsExpose( WND
*pWnd
, XGraphicsExposeEvent
*event
)
603 /* Make position relative to client area instead of window */
604 rect
.left
= event
->x
- (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
);
605 rect
.top
= event
->y
- (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
);
606 rect
.right
= rect
.left
+ event
->width
;
607 rect
.bottom
= rect
.top
+ event
->height
;
609 PAINT_RedrawWindow( pWnd
->hwndSelf
, &rect
, 0,
610 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASE
|
611 (event
->count
? 0 : RDW_ERASENOW
), 0 );
615 /***********************************************************************
618 * Handle a X key event
620 static void EVENT_Key( WND
*pWnd
, XKeyEvent
*event
)
622 KEYBOARD_HandleEvent( pWnd
, event
);
626 /***********************************************************************
629 static void EVENT_MotionNotify( WND
*pWnd
, XMotionEvent
*event
)
631 hardware_event( WM_MOUSEMOVE
, EVENT_XStateToKeyState( event
->state
), 0L,
632 pWnd
->rectWindow
.left
+ event
->x
,
633 pWnd
->rectWindow
.top
+ event
->y
,
634 event
->time
- MSG_WineStartTicks
, pWnd
->hwndSelf
);
638 /***********************************************************************
639 * EVENT_DummyMotionNotify
641 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
643 void EVENT_DummyMotionNotify(void)
646 int rootX
, rootY
, winX
, winY
;
649 if (XQueryPointer( display
, rootWindow
, &root
, &child
,
650 &rootX
, &rootY
, &winX
, &winY
, &state
))
652 hardware_event( WM_MOUSEMOVE
, EVENT_XStateToKeyState( state
), 0L,
653 winX
, winY
, GetTickCount(), 0 );
658 /***********************************************************************
661 static void EVENT_ButtonPress( WND
*pWnd
, XButtonEvent
*event
)
663 static WORD messages
[NB_BUTTONS
] =
664 { WM_LBUTTONDOWN
, WM_MBUTTONDOWN
, WM_RBUTTONDOWN
};
665 int buttonNum
= event
->button
- 1;
667 if (buttonNum
>= NB_BUTTONS
) return;
668 if (SwappedButtons
) buttonNum
= NB_BUTTONS
- 1 - buttonNum
;
669 MouseButtonsStates
[buttonNum
] = TRUE
;
670 AsyncMouseButtonsStates
[buttonNum
] = TRUE
;
671 hardware_event( messages
[buttonNum
],
672 EVENT_XStateToKeyState( event
->state
), 0L,
673 pWnd
->rectWindow
.left
+ event
->x
,
674 pWnd
->rectWindow
.top
+ event
->y
,
675 event
->time
- MSG_WineStartTicks
, pWnd
->hwndSelf
);
679 /***********************************************************************
680 * EVENT_ButtonRelease
682 static void EVENT_ButtonRelease( WND
*pWnd
, XButtonEvent
*event
)
684 static const WORD messages
[NB_BUTTONS
] =
685 { WM_LBUTTONUP
, WM_MBUTTONUP
, WM_RBUTTONUP
};
686 int buttonNum
= event
->button
- 1;
688 if (buttonNum
>= NB_BUTTONS
) return;
689 if (SwappedButtons
) buttonNum
= NB_BUTTONS
- 1 - buttonNum
;
690 MouseButtonsStates
[buttonNum
] = FALSE
;
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 /**********************************************************************
702 static void EVENT_FocusIn( WND
*pWnd
, XFocusChangeEvent
*event
)
704 if (Options
.managed
) EVENT_QueryZOrder( pWnd
);
706 if (event
->detail
!= NotifyPointer
)
708 HWND32 hwnd
= pWnd
->hwndSelf
;
710 if (hwnd
!= GetActiveWindow32())
711 WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
712 if ((hwnd
!= GetFocus32()) && !IsChild32( hwnd
, GetFocus32()))
718 /**********************************************************************
721 * Note: only top-level override-redirect windows get FocusOut events.
723 static void EVENT_FocusOut( WND
*pWnd
, XFocusChangeEvent
*event
)
725 if (event
->detail
!= NotifyPointer
)
727 HWND32 hwnd
= pWnd
->hwndSelf
;
729 if (hwnd
== GetActiveWindow32())
730 WINPOS_ChangeActiveWindow( 0, FALSE
);
731 if ((hwnd
== GetFocus32()) || IsChild32( hwnd
, GetFocus32()))
736 /**********************************************************************
739 BOOL32
EVENT_CheckFocus(void)
745 XGetInputFocus(display
, &xW
, &state
);
747 XFindContext(display
, xW
, winContext
, (char **)&pWnd
) )
753 /**********************************************************************
756 * Helper function for ConfigureNotify handling.
757 * Get the new geometry of a window relative to the root window.
759 static void EVENT_GetGeometry( Window win
, int *px
, int *py
,
760 unsigned int *pwidth
, unsigned int *pheight
)
762 Window root
, parent
, *children
;
764 unsigned int width
, height
, border
, depth
, nb_children
;
766 if (!XGetGeometry( display
, win
, &root
, px
, py
, pwidth
, pheight
,
767 &border
, &depth
)) return;
768 if (win
== rootWindow
)
776 if (!XQueryTree(display
, win
, &root
, &parent
, &children
, &nb_children
))
779 if (parent
== rootWindow
) break;
781 if (!XGetGeometry( display
, win
, &root
, &xpos
, &ypos
,
782 &width
, &height
, &border
, &depth
)) return;
789 /**********************************************************************
790 * EVENT_ConfigureNotify
792 * The ConfigureNotify event is only selected on top-level windows
793 * when the -managed flag is used.
795 static void EVENT_ConfigureNotify( WND
*pWnd
, XConfigureEvent
*event
)
798 RECT32 newWindowRect
, newClientRect
;
799 HRGN32 hrgnOldPos
, hrgnNewPos
;
800 Window above
= event
->above
;
802 unsigned int width
, height
;
804 assert (pWnd
->flags
& WIN_MANAGED
);
806 /* We don't rely on the event geometry info, because it is relative
807 * to parent and not to root, and it may be wrong (XFree sets x,y to 0,0
808 * if the window hasn't moved).
810 EVENT_GetGeometry( event
->window
, &x
, &y
, &width
, &height
);
812 /* Fill WINDOWPOS struct */
813 winpos
.flags
= SWP_NOACTIVATE
| SWP_NOZORDER
;
814 winpos
.hwnd
= pWnd
->hwndSelf
;
820 /* Check for unchanged attributes */
821 if (winpos
.x
== pWnd
->rectWindow
.left
&& winpos
.y
== pWnd
->rectWindow
.top
)
822 winpos
.flags
|= SWP_NOMOVE
;
823 if ((winpos
.cx
== pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) &&
824 (winpos
.cy
== pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
))
825 winpos
.flags
|= SWP_NOSIZE
;
828 RECT32 rect
= { 0, 0, pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
,
829 pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
};
830 DCE_InvalidateDCE( pWnd
, &rect
);
833 /* Send WM_WINDOWPOSCHANGING */
834 SendMessage32A( winpos
.hwnd
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)&winpos
);
836 /* Calculate new position and size */
837 newWindowRect
.left
= x
;
838 newWindowRect
.right
= x
+ width
;
839 newWindowRect
.top
= y
;
840 newWindowRect
.bottom
= y
+ height
;
842 WINPOS_SendNCCalcSize( winpos
.hwnd
, TRUE
, &newWindowRect
,
843 &pWnd
->rectWindow
, &pWnd
->rectClient
,
844 &winpos
, &newClientRect
);
846 hrgnOldPos
= CreateRectRgnIndirect32( &pWnd
->rectWindow
);
847 hrgnNewPos
= CreateRectRgnIndirect32( &newWindowRect
);
848 CombineRgn32( hrgnOldPos
, hrgnOldPos
, hrgnNewPos
, RGN_DIFF
);
849 DeleteObject32(hrgnOldPos
);
850 DeleteObject32(hrgnNewPos
);
852 /* Set new size and position */
853 pWnd
->rectWindow
= newWindowRect
;
854 pWnd
->rectClient
= newClientRect
;
855 SendMessage32A( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
857 if (!IsWindow32( winpos
.hwnd
)) return;
858 if( above
== None
) /* absolute bottom */
860 WIN_UnlinkWindow( winpos
.hwnd
);
861 WIN_LinkWindow( winpos
.hwnd
, HWND_BOTTOM
);
863 else EVENT_QueryZOrder( pWnd
); /* try to outsmart window manager */
867 /***********************************************************************
868 * EVENT_SelectionRequest
870 static void EVENT_SelectionRequest( WND
*pWnd
, XSelectionRequestEvent
*event
)
872 XSelectionEvent result
;
874 Window request
= event
->requestor
;
876 if(event
->target
== XA_STRING
)
882 rprop
= event
->property
;
884 if(rprop
== None
) rprop
= event
->target
;
886 if(event
->selection
!=XA_PRIMARY
) rprop
= None
;
887 else if(!CLIPBOARD_IsPresent(CF_OEMTEXT
)) rprop
= None
;
890 /* open to make sure that clipboard is available */
892 BOOL32 couldOpen
= OpenClipboard32( pWnd
->hwndSelf
);
895 hText
= GetClipboardData16(CF_TEXT
);
896 text
= GlobalLock16(hText
);
897 size
= GlobalSize16(hText
);
899 /* remove carriage returns */
901 lpstr
= (char*)HEAP_xalloc( GetProcessHeap(), 0, size
-- );
902 for(i
=0,j
=0; i
< size
&& text
[i
]; i
++ )
904 if( text
[i
] == '\r' &&
905 (text
[i
+1] == '\n' || text
[i
+1] == '\0') ) continue;
906 lpstr
[j
++] = text
[i
];
910 XChangeProperty(display
, request
, rprop
,
911 XA_STRING
, 8, PropModeReplace
,
913 HeapFree( GetProcessHeap(), 0, lpstr
);
915 /* close only if we opened before */
917 if(couldOpen
) CloseClipboard32();
922 dprintf_event(stddeb
,"Request for %s ignored\n", XGetAtomName(display
,event
->target
));
924 result
.type
= SelectionNotify
;
925 result
.display
= display
;
926 result
.requestor
= request
;
927 result
.selection
= event
->selection
;
928 result
.property
= rprop
;
929 result
.target
= event
->target
;
930 result
.time
= event
->time
;
931 XSendEvent(display
,event
->requestor
,False
,NoEventMask
,(XEvent
*)&result
);
935 /***********************************************************************
936 * EVENT_SelectionNotify
938 static void EVENT_SelectionNotify( XSelectionEvent
*event
)
940 if (event
->selection
!= XA_PRIMARY
) return;
942 if (event
->target
!= XA_STRING
) CLIPBOARD_ReadSelection( 0, None
);
943 else CLIPBOARD_ReadSelection( event
->requestor
, event
->property
);
945 dprintf_clipboard(stddeb
,"\tSelectionNotify done!\n");
949 /***********************************************************************
950 * EVENT_SelectionClear
952 static void EVENT_SelectionClear( WND
*pWnd
, XSelectionClearEvent
*event
)
954 if (event
->selection
!= XA_PRIMARY
) return;
955 CLIPBOARD_ReleaseSelection( event
->window
, pWnd
->hwndSelf
);
959 /**********************************************************************
960 * EVENT_ClientMessage
962 static void EVENT_ClientMessage( WND
*pWnd
, XClientMessageEvent
*event
)
964 if (event
->message_type
!= None
&& event
->format
== 32)
966 if ((event
->message_type
== wmProtocols
) &&
967 (((Atom
) event
->data
.l
[0]) == wmDeleteWindow
))
968 SendMessage16( pWnd
->hwndSelf
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
969 else if ( event
->message_type
== dndProtocol
&&
970 (event
->data
.l
[0] == DndFile
|| event
->data
.l
[0] == DndFiles
) )
972 unsigned long data_length
;
973 unsigned long aux_long
;
974 unsigned char* p_data
= NULL
;
982 HGLOBAL16 hDragInfo
= GlobalAlloc16( GMEM_SHARE
| GMEM_ZEROINIT
, sizeof(DRAGINFO
));
983 LPDRAGINFO lpDragInfo
= (LPDRAGINFO
) GlobalLock16(hDragInfo
);
984 SEGPTR spDragInfo
= (SEGPTR
) WIN16_GlobalLock16(hDragInfo
);
985 Window w_aux_root
, w_aux_child
;
988 if( !lpDragInfo
|| !spDragInfo
) return;
990 XQueryPointer( display
, pWnd
->window
, &w_aux_root
, &w_aux_child
,
991 &x
, &y
, &u
.pt_aux
.x
, &u
.pt_aux
.y
, (unsigned int*)&aux_long
);
993 lpDragInfo
->hScope
= pWnd
->hwndSelf
;
994 lpDragInfo
->pt
.x
= (INT16
)x
; lpDragInfo
->pt
.y
= (INT16
)y
;
996 /* find out drop point and drop window */
997 if( x
< 0 || y
< 0 ||
998 x
> (pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) ||
999 y
> (pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
) )
1000 { bAccept
= pWnd
->dwExStyle
& WS_EX_ACCEPTFILES
; x
= y
= 0; }
1003 bAccept
= DRAG_QueryUpdate( pWnd
->hwndSelf
, spDragInfo
, TRUE
);
1004 x
= lpDragInfo
->pt
.x
; y
= lpDragInfo
->pt
.y
;
1006 pDropWnd
= WIN_FindWndPtr( lpDragInfo
->hScope
);
1007 GlobalFree16( hDragInfo
);
1011 XGetWindowProperty( display
, DefaultRootWindow(display
),
1012 dndSelection
, 0, 65535, FALSE
,
1013 AnyPropertyType
, &u
.atom_aux
, &u
.pt_aux
.y
,
1014 &data_length
, &aux_long
, &p_data
);
1016 if( !aux_long
&& p_data
) /* don't bother if > 64K */
1018 char *p
= (char*) p_data
;
1022 while( *p
) /* calculate buffer size */
1025 if((u
.i
= *p
) != -1 )
1026 u
.i
= DRIVE_FindDriveRoot( (const char **)&p_drop
);
1027 if( u
.i
== -1 ) *p
= -1; /* mark as "bad" */
1030 INT32 len
= GetShortPathName32A( p
, NULL
, 0 );
1031 if (len
) aux_long
+= len
+ 1;
1036 if( aux_long
&& aux_long
< 65535 )
1039 LPDROPFILESTRUCT lpDrop
;
1041 aux_long
+= sizeof(DROPFILESTRUCT
) + 1;
1042 hDrop
= (HDROP16
)GlobalAlloc16( GMEM_SHARE
, aux_long
);
1043 lpDrop
= (LPDROPFILESTRUCT
) GlobalLock16( hDrop
);
1047 lpDrop
->wSize
= sizeof(DROPFILESTRUCT
);
1048 lpDrop
->ptMousePos
.x
= (INT16
)x
;
1049 lpDrop
->ptMousePos
.y
= (INT16
)y
;
1050 lpDrop
->fInNonClientArea
= (BOOL16
)
1051 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
1052 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
1053 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
1054 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
1055 p_drop
= ((char*)lpDrop
) + sizeof(DROPFILESTRUCT
);
1059 if( *p
!= -1 ) /* use only "good" entries */
1061 GetShortPathName32A( p
, p_drop
, 65535 );
1062 p_drop
+= strlen( p_drop
) + 1;
1067 PostMessage16( pWnd
->hwndSelf
, WM_DROPFILES
,
1068 (WPARAM16
)hDrop
, 0L );
1072 if( p_data
) XFree(p_data
);
1074 } /* WS_EX_ACCEPTFILES */
1077 dprintf_event( stddeb
, "unrecognized ClientMessage\n" );
1081 /**********************************************************************
1084 * Install colormap when Wine window is focused in
1085 * self-managed mode with private colormap
1088 void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event )
1090 if( !Options.managed && rootWindow == DefaultRootWindow(display) &&
1091 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() )
1092 XInstallColormap( display, COLOR_GetColormap() );
1096 /**********************************************************************
1099 void EVENT_MapNotify( HWND32 hWnd
, XMapEvent
*event
)
1101 HWND32 hwndFocus
= GetFocus32();
1103 if (hwndFocus
&& IsChild32( hWnd
, hwndFocus
))
1104 FOCUS_SetXFocus( (HWND32
)hwndFocus
);
1109 /**********************************************************************
1112 * We need this to be able to generate double click messages
1113 * when menu code captures mouse in the window without CS_DBLCLK style.
1115 HWND32
EVENT_Capture(HWND32 hwnd
, INT16 ht
)
1118 HWND32 capturePrev
= captureWnd
;
1122 XUngrabPointer(display
, CurrentTime
);
1123 captureWnd
= NULL
; captureHT
= 0;
1125 else if ((win
= WIN_GetXWindow( hwnd
)))
1127 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1130 (XGrabPointer(display
, win
, False
,
1131 ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
,
1132 GrabModeAsync
, GrabModeAsync
,
1133 None
, None
, CurrentTime
) == GrabSuccess
) )
1135 dprintf_win(stddeb
, "SetCapture(0x%04x)\n", hwnd
);
1141 if( capturePrev
&& capturePrev
!= captureWnd
)
1143 WND
* wndPtr
= WIN_FindWndPtr( capturePrev
);
1144 if( wndPtr
&& (wndPtr
->flags
& WIN_ISWIN32
) )
1145 SendMessage32A( capturePrev
, WM_CAPTURECHANGED
, 0L, hwnd
);
1150 /**********************************************************************
1151 * EVENT_GetCaptureInfo
1153 INT16
EVENT_GetCaptureInfo()
1158 /**********************************************************************
1159 * SetCapture16 (USER.18)
1161 HWND16 WINAPI
SetCapture16( HWND16 hwnd
)
1163 return (HWND16
)EVENT_Capture( hwnd
, HTCLIENT
);
1167 /**********************************************************************
1168 * SetCapture32 (USER32.463)
1170 HWND32 WINAPI
SetCapture32( HWND32 hwnd
)
1172 return EVENT_Capture( hwnd
, HTCLIENT
);
1176 /**********************************************************************
1177 * ReleaseCapture (USER.19) (USER32.438)
1179 void WINAPI
ReleaseCapture(void)
1181 dprintf_win(stddeb
, "ReleaseCapture() [%04x]\n", captureWnd
);
1182 if( captureWnd
) EVENT_Capture( 0, 0 );
1186 /**********************************************************************
1187 * GetCapture16 (USER.236)
1189 HWND16 WINAPI
GetCapture16(void)
1195 /**********************************************************************
1196 * GetCapture32 (USER32.207)
1198 HWND32 WINAPI
GetCapture32(void)
1204 /***********************************************************************
1205 * GetMouseEventProc (USER.337)
1207 FARPROC16 WINAPI
GetMouseEventProc(void)
1209 HMODULE16 hmodule
= GetModuleHandle16("USER");
1210 return MODULE_GetEntryPoint( hmodule
,
1211 MODULE_GetOrdinal( hmodule
, "Mouse_Event" ) );
1215 /***********************************************************************
1216 * Mouse_Event (USER.299)
1218 void WINAPI
Mouse_Event( CONTEXT
*context
)
1222 * BX = horizontal displacement if AX & ME_MOVE
1223 * CX = vertical displacement if AX & ME_MOVE
1224 * DX = button state (?)
1225 * SI = mouse event flags (?)
1228 int rootX
, rootY
, winX
, winY
;
1231 if (AX_reg(context
) & ME_MOVE
)
1233 /* We have to actually move the cursor */
1234 XWarpPointer( display
, rootWindow
, None
, 0, 0, 0, 0,
1235 (short)BX_reg(context
), (short)CX_reg(context
) );
1238 if (!XQueryPointer( display
, rootWindow
, &root
, &child
,
1239 &rootX
, &rootY
, &winX
, &winY
, &state
)) return;
1240 if (AX_reg(context
) & ME_LDOWN
)
1241 hardware_event( WM_LBUTTONDOWN
, EVENT_XStateToKeyState( state
),
1242 0L, winX
, winY
, GetTickCount(), 0 );
1243 if (AX_reg(context
) & ME_LUP
)
1244 hardware_event( WM_LBUTTONUP
, EVENT_XStateToKeyState( state
),
1245 0L, winX
, winY
, GetTickCount(), 0 );
1246 if (AX_reg(context
) & ME_RDOWN
)
1247 hardware_event( WM_RBUTTONDOWN
, EVENT_XStateToKeyState( state
),
1248 0L, winX
, winY
, GetTickCount(), 0 );
1249 if (AX_reg(context
) & ME_RUP
)
1250 hardware_event( WM_RBUTTONUP
, EVENT_XStateToKeyState( state
),
1251 0L, winX
, winY
, GetTickCount(), 0 );
1255 /**********************************************************************
1256 * EnableHardwareInput (USER.331)
1258 BOOL16 WINAPI
EnableHardwareInput(BOOL16 bEnable
)
1260 BOOL16 bOldState
= InputEnabled
;
1261 dprintf_event(stdnimp
,"EnableHardwareInput(%d);\n", bEnable
);
1262 InputEnabled
= bEnable
;
1267 /***********************************************************************
1268 * SwapMouseButton16 (USER.186)
1270 BOOL16 WINAPI
SwapMouseButton16( BOOL16 fSwap
)
1272 BOOL16 ret
= SwappedButtons
;
1273 SwappedButtons
= fSwap
;
1278 /***********************************************************************
1279 * SwapMouseButton32 (USER32.536)
1281 BOOL32 WINAPI
SwapMouseButton32( BOOL32 fSwap
)
1283 BOOL32 ret
= SwappedButtons
;
1284 SwappedButtons
= fSwap
;