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"
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 extern void FOCUS_SetXFocus( HWND32
);
110 extern BOOL16
DRAG_QueryUpdate( HWND16
, SEGPTR
, BOOL32
);
111 extern BOOL32
WINSOCK_HandleIO( int* max_fd
, int num_pending
, fd_set p
[3], fd_set e
[3] );
113 /***********************************************************************
116 * Initialize network IO.
118 BOOL32
EVENT_Init(void)
121 for( i
= 0; i
< 3; i
++ )
122 FD_ZERO( __event_io_set
+ i
);
124 __event_max_fd
= __event_x_connection
= ConnectionNumber(display
);
125 FD_SET( __event_x_connection
, &__event_io_set
[EVENT_IO_READ
] );
130 /***********************************************************************
133 void EVENT_AddIO( int fd
, int io_type
)
135 FD_SET( fd
, &__event_io_set
[io_type
] );
136 if( __event_max_fd
<= fd
) __event_max_fd
= fd
+ 1;
139 void EVENT_DeleteIO( int fd
, int io_type
)
141 FD_CLR( fd
, &__event_io_set
[io_type
] );
144 /***********************************************************************
147 * Process an X event.
149 void EVENT_ProcessEvent( XEvent
*event
)
153 if (TSXFindContext( display
, event
->xany
.window
, winContext
,
154 (char **)&pWnd
) != 0)
155 return; /* Not for a registered window */
157 TRACE(event
, "Got event %s for hwnd %04x\n",
158 event_names
[event
->type
], pWnd
->hwndSelf
);
164 if (InputEnabled
) EVENT_Key( pWnd
, (XKeyEvent
*)event
);
169 EVENT_ButtonPress( pWnd
, (XButtonEvent
*)event
);
174 EVENT_ButtonRelease( pWnd
, (XButtonEvent
*)event
);
178 /* Wine between two fast machines across the overloaded campus
179 ethernet gets very boged down in MotionEvents. The following
180 simply finds the last motion event in the queue and drops
181 the rest. On a good link events are servered before they build
182 up so this doesn't take place. On a slow link this may cause
183 problems if the event order is important. I'm not yet seen
184 of any problems. Jon 7/6/96.
188 while (TSXCheckTypedWindowEvent(display
,((XAnyEvent
*)event
)->window
,
189 MotionNotify
, event
));
190 EVENT_MotionNotify( pWnd
, (XMotionEvent
*)event
);
195 EVENT_FocusIn( pWnd
, (XFocusChangeEvent
*)event
);
199 EVENT_FocusOut( pWnd
, (XFocusChangeEvent
*)event
);
203 EVENT_Expose( pWnd
, (XExposeEvent
*)event
);
207 EVENT_GraphicsExpose( pWnd
, (XGraphicsExposeEvent
*)event
);
210 case ConfigureNotify
:
211 EVENT_ConfigureNotify( pWnd
, (XConfigureEvent
*)event
);
214 case SelectionRequest
:
215 EVENT_SelectionRequest( pWnd
, (XSelectionRequestEvent
*)event
);
218 case SelectionNotify
:
219 EVENT_SelectionNotify( (XSelectionEvent
*)event
);
223 EVENT_SelectionClear( pWnd
, (XSelectionClearEvent
*) event
);
227 EVENT_ClientMessage( pWnd
, (XClientMessageEvent
*) event
);
231 * EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
237 /* We get all these because of StructureNotifyMask. */
239 case CirculateNotify
:
247 EVENT_MapNotify( pWnd
->hwndSelf
, (XMapEvent
*)event
);
251 WARN(event
, "Unprocessed event %s for hwnd %04x\n",
252 event_names
[event
->type
], pWnd
->hwndSelf
);
258 /***********************************************************************
259 * EVENT_RegisterWindow
261 * Associate an X window to a HWND.
263 void EVENT_RegisterWindow( WND
*pWnd
)
265 if (wmProtocols
== None
)
266 wmProtocols
= TSXInternAtom( display
, "WM_PROTOCOLS", True
);
267 if (wmDeleteWindow
== None
)
268 wmDeleteWindow
= TSXInternAtom( display
, "WM_DELETE_WINDOW", True
);
269 if( dndProtocol
== None
)
270 dndProtocol
= TSXInternAtom( display
, "DndProtocol" , False
);
271 if( dndSelection
== None
)
272 dndSelection
= TSXInternAtom( display
, "DndSelection" , False
);
274 TSXSetWMProtocols( display
, pWnd
->window
, &wmDeleteWindow
, 1 );
276 if (!winContext
) winContext
= TSXUniqueContext();
277 TSXSaveContext( display
, pWnd
->window
, winContext
, (char *)pWnd
);
280 /***********************************************************************
281 * EVENT_DestroyWindow
283 void EVENT_DestroyWindow( WND
*pWnd
)
287 TSXDeleteContext( display
, pWnd
->window
, winContext
);
288 TSXDestroyWindow( display
, pWnd
->window
);
289 while( TSXCheckWindowEvent(display
, pWnd
->window
, NoEventMask
, &xe
) );
293 /***********************************************************************
294 * IsUserIdle (USER.333)
296 * Check if we have pending X events.
298 BOOL16 WINAPI
IsUserIdle(void)
300 struct timeval timeout
= {0, 0};
304 FD_SET(__event_x_connection
, &check_set
);
305 if( select(__event_x_connection
+ 1, &check_set
, NULL
, NULL
, &timeout
) > 0 )
311 /***********************************************************************
314 * Wait for a network event, optionally sleeping until one arrives.
315 * Return TRUE if an event is pending, FALSE on timeout or error
316 * (for instance lost connection with the server).
318 BOOL32
EVENT_WaitNetEvent( BOOL32 sleep
, BOOL32 peek
)
321 LONG maxWait
= sleep
? TIMER_GetNextExpiration() : 0;
322 int pending
= TSXPending(display
);
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) && !pending
)
331 struct timeval timeout
;
334 memcpy( io_set
, __event_io_set
, sizeof(io_set
) );
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
, &io_set
[EVENT_IO_READ
],
351 &io_set
[EVENT_IO_WRITE
],
352 &io_set
[EVENT_IO_EXCEPT
], &timeout
);
353 if ( num_pending
== 0 )
356 TIMER_ExpireTimers();
359 else stop_wait_op
= CONT
;
360 #else /* CONFIG_IPC */
361 num_pending
= select( __event_max_fd
, &io_set
[EVENT_IO_READ
],
362 &io_set
[EVENT_IO_WRITE
],
363 &io_set
[EVENT_IO_EXCEPT
], &timeout
);
364 if ( num_pending
== 0)
366 /* Timeout or error */
367 TIMER_ExpireTimers();
370 #endif /* CONFIG_IPC */
372 /* Winsock asynchronous services */
374 if( FD_ISSET( __event_x_connection
, &io_set
[EVENT_IO_READ
]) )
378 WINSOCK_HandleIO( &__event_max_fd
, num_pending
, io_set
, __event_io_set
);
380 else /* no X events */
381 return WINSOCK_HandleIO( &__event_max_fd
, num_pending
, io_set
, __event_io_set
);
384 { /* Wait for X11 input. */
388 FD_SET(__event_x_connection
, &set
);
389 select(__event_x_connection
+ 1, &set
, 0, 0, 0 );
392 /* Process current X event (and possibly others that occurred in the meantime) */
398 if (DDE_GetRemoteMessage())
400 while(DDE_GetRemoteMessage()) ;
403 #endif /* CONFIG_IPC */
405 TSXNextEvent( display
, &event
);
412 if (TSXFindContext( display
, ((XAnyEvent
*)&event
)->window
, winContext
,
413 (char **)&pWnd
) || (event
.type
== NoExpose
))
416 /* Check only for those events which can be processed
419 if( event
.type
== MotionNotify
||
420 event
.type
== ButtonPress
|| event
.type
== ButtonRelease
||
421 event
.type
== KeyPress
|| event
.type
== KeyRelease
||
422 event
.type
== SelectionRequest
|| event
.type
== SelectionClear
)
424 EVENT_ProcessEvent( &event
);
430 if( (pQ
= (MESSAGEQUEUE
*)GlobalLock16(pWnd
->hmemTaskQ
)) )
432 pQ
->flags
|= QUEUE_FLAG_XEVENT
;
433 PostEvent(pQ
->hTask
);
434 TSXPutBackEvent(display
, &event
);
439 else EVENT_ProcessEvent( &event
);
441 while (TSXPending( display
));
446 /***********************************************************************
449 * Synchronize with the X server. Should not be used too often.
451 void EVENT_Synchronize()
455 TSXSync( display
, False
);
456 while (TSXPending( display
))
458 TSXNextEvent( display
, &event
);
459 EVENT_ProcessEvent( &event
);
463 /***********************************************************************
466 * Try to synchronize internal z-order with the window manager's.
467 * Probably a futile endeavor.
469 static BOOL32
__check_query_condition( WND
** pWndA
, WND
** pWndB
)
471 /* return TRUE if we have at least two managed windows */
473 for( *pWndB
= NULL
; *pWndA
; *pWndA
= (*pWndA
)->next
)
474 if( (*pWndA
)->flags
& WIN_MANAGED
&&
475 (*pWndA
)->dwStyle
& WS_VISIBLE
) break;
477 for( *pWndB
= (*pWndA
)->next
; *pWndB
; *pWndB
= (*pWndB
)->next
)
478 if( (*pWndB
)->flags
& WIN_MANAGED
&&
479 (*pWndB
)->dwStyle
& WS_VISIBLE
) break;
480 return ((*pWndB
) != NULL
);
483 static Window
__get_common_ancestor( Window A
, Window B
,
484 Window
** children
, unsigned* total
)
486 /* find the real root window */
488 Window root
, *childrenB
;
493 if( *children
) TSXFree( *children
);
494 TSXQueryTree( display
, A
, &root
, &A
, children
, total
);
495 TSXQueryTree( display
, B
, &root
, &B
, &childrenB
, &totalB
);
496 if( childrenB
) TSXFree( childrenB
);
497 } while( A
!= B
&& A
&& B
);
498 return ( A
&& B
) ? A
: 0 ;
501 static Window
__get_top_decoration( Window w
, Window ancestor
)
503 Window
* children
, root
, prev
= w
, parent
= w
;
509 TSXQueryTree( display
, w
, &root
, &parent
, &children
, &total
);
510 if( children
) TSXFree( children
);
511 } while( parent
&& parent
!= ancestor
);
512 TRACE(event
, "\t%08x -> %08x\n", (unsigned)prev
, (unsigned)w
);
513 return ( parent
) ? w
: 0 ;
516 static unsigned __td_lookup( Window w
, Window
* list
, unsigned max
)
519 for( i
= 0; i
< max
; i
++ ) if( list
[i
] == w
) break;
523 static BOOL32
EVENT_QueryZOrder( WND
* pWndCheck
)
526 HWND32 hwndInsertAfter
= HWND_TOP
;
527 WND
* pWnd
, *pWndZ
= WIN_GetDesktop()->child
;
528 Window w
, parent
, *children
= NULL
;
529 unsigned total
, check
, pos
, best
;
531 if( !__check_query_condition(&pWndZ
, &pWnd
) ) return TRUE
;
533 parent
= __get_common_ancestor( pWndZ
->window
, pWnd
->window
,
535 if( parent
&& children
)
537 w
= __get_top_decoration( pWndCheck
->window
, parent
);
538 if( w
!= children
[total
- 1] )
540 check
= __td_lookup( w
, children
, total
);
542 for( pWnd
= pWndZ
; pWnd
; pWnd
= pWnd
->next
)
544 if( pWnd
!= pWndCheck
)
546 if( !(pWnd
->flags
& WIN_MANAGED
) ||
547 !(w
= __get_top_decoration( pWnd
->window
, parent
)) )
549 pos
= __td_lookup( w
, children
, total
);
550 if( pos
< best
&& pos
> check
)
553 hwndInsertAfter
= pWnd
->hwndSelf
;
555 if( check
- best
== 1 ) break;
558 WIN_UnlinkWindow( pWndCheck
->hwndSelf
);
559 WIN_LinkWindow( pWndCheck
->hwndSelf
, hwndInsertAfter
);
562 if( children
) TSXFree( children
);
567 /***********************************************************************
568 * EVENT_XStateToKeyState
570 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
571 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
573 static WORD
EVENT_XStateToKeyState( int state
)
577 if (state
& Button1Mask
) kstate
|= MK_LBUTTON
;
578 if (state
& Button2Mask
) kstate
|= MK_MBUTTON
;
579 if (state
& Button3Mask
) kstate
|= MK_RBUTTON
;
580 if (state
& ShiftMask
) kstate
|= MK_SHIFT
;
581 if (state
& ControlMask
) kstate
|= MK_CONTROL
;
586 /***********************************************************************
589 static void EVENT_Expose( WND
*pWnd
, XExposeEvent
*event
)
593 /* Make position relative to client area instead of window */
594 rect
.left
= event
->x
- (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
);
595 rect
.top
= event
->y
- (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
);
596 rect
.right
= rect
.left
+ event
->width
;
597 rect
.bottom
= rect
.top
+ event
->height
;
599 PAINT_RedrawWindow( pWnd
->hwndSelf
, &rect
, 0,
600 RDW_INVALIDATE
| RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
|
601 (event
->count
? 0 : RDW_ERASENOW
), 0 );
605 /***********************************************************************
606 * EVENT_GraphicsExpose
608 * This is needed when scrolling area is partially obscured
609 * by non-Wine X window.
611 static void EVENT_GraphicsExpose( WND
*pWnd
, XGraphicsExposeEvent
*event
)
615 /* Make position relative to client area instead of window */
616 rect
.left
= event
->x
- (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
);
617 rect
.top
= event
->y
- (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
);
618 rect
.right
= rect
.left
+ event
->width
;
619 rect
.bottom
= rect
.top
+ event
->height
;
621 PAINT_RedrawWindow( pWnd
->hwndSelf
, &rect
, 0,
622 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASE
|
623 (event
->count
? 0 : RDW_ERASENOW
), 0 );
627 /***********************************************************************
630 * Handle a X key event
632 static void EVENT_Key( WND
*pWnd
, XKeyEvent
*event
)
634 KEYBOARD_HandleEvent( pWnd
, event
);
638 /***********************************************************************
641 static void EVENT_MotionNotify( WND
*pWnd
, XMotionEvent
*event
)
643 hardware_event( WM_MOUSEMOVE
, EVENT_XStateToKeyState( event
->state
), 0L,
644 pWnd
->rectWindow
.left
+ event
->x
,
645 pWnd
->rectWindow
.top
+ event
->y
,
646 event
->time
- MSG_WineStartTicks
, pWnd
->hwndSelf
);
650 /***********************************************************************
651 * EVENT_DummyMotionNotify
653 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
655 void EVENT_DummyMotionNotify(void)
658 int rootX
, rootY
, winX
, winY
;
661 if (TSXQueryPointer( display
, rootWindow
, &root
, &child
,
662 &rootX
, &rootY
, &winX
, &winY
, &state
))
664 hardware_event( WM_MOUSEMOVE
, EVENT_XStateToKeyState( state
), 0L,
665 winX
, winY
, GetTickCount(), 0 );
670 /***********************************************************************
673 static void EVENT_ButtonPress( WND
*pWnd
, XButtonEvent
*event
)
675 static WORD messages
[NB_BUTTONS
] =
676 { WM_LBUTTONDOWN
, WM_MBUTTONDOWN
, WM_RBUTTONDOWN
};
677 int buttonNum
= event
->button
- 1;
679 if (buttonNum
>= NB_BUTTONS
) return;
680 if (SwappedButtons
) buttonNum
= NB_BUTTONS
- 1 - buttonNum
;
681 MouseButtonsStates
[buttonNum
] = TRUE
;
682 AsyncMouseButtonsStates
[buttonNum
] = TRUE
;
683 hardware_event( messages
[buttonNum
],
684 EVENT_XStateToKeyState( event
->state
), 0L,
685 pWnd
->rectWindow
.left
+ event
->x
,
686 pWnd
->rectWindow
.top
+ event
->y
,
687 event
->time
- MSG_WineStartTicks
, pWnd
->hwndSelf
);
691 /***********************************************************************
692 * EVENT_ButtonRelease
694 static void EVENT_ButtonRelease( WND
*pWnd
, XButtonEvent
*event
)
696 static const WORD messages
[NB_BUTTONS
] =
697 { WM_LBUTTONUP
, WM_MBUTTONUP
, WM_RBUTTONUP
};
698 int buttonNum
= event
->button
- 1;
700 if (buttonNum
>= NB_BUTTONS
) return;
701 if (SwappedButtons
) buttonNum
= NB_BUTTONS
- 1 - buttonNum
;
702 MouseButtonsStates
[buttonNum
] = FALSE
;
703 hardware_event( messages
[buttonNum
],
704 EVENT_XStateToKeyState( event
->state
), 0L,
705 pWnd
->rectWindow
.left
+ event
->x
,
706 pWnd
->rectWindow
.top
+ event
->y
,
707 event
->time
- MSG_WineStartTicks
, pWnd
->hwndSelf
);
711 /**********************************************************************
714 static void EVENT_FocusIn( WND
*pWnd
, XFocusChangeEvent
*event
)
716 if (Options
.managed
) EVENT_QueryZOrder( pWnd
);
718 if (event
->detail
!= NotifyPointer
)
720 HWND32 hwnd
= pWnd
->hwndSelf
;
722 if (hwnd
!= GetActiveWindow32())
723 WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
724 if ((hwnd
!= GetFocus32()) && !IsChild32( hwnd
, GetFocus32()))
730 /**********************************************************************
733 * Note: only top-level override-redirect windows get FocusOut events.
735 static void EVENT_FocusOut( WND
*pWnd
, XFocusChangeEvent
*event
)
737 if (event
->detail
!= NotifyPointer
)
739 HWND32 hwnd
= pWnd
->hwndSelf
;
741 if (hwnd
== GetActiveWindow32())
742 WINPOS_ChangeActiveWindow( 0, FALSE
);
743 if ((hwnd
== GetFocus32()) || IsChild32( hwnd
, GetFocus32()))
748 /**********************************************************************
751 BOOL32
EVENT_CheckFocus(void)
757 TSXGetInputFocus(display
, &xW
, &state
);
759 TSXFindContext(display
, xW
, winContext
, (char **)&pWnd
) )
765 /**********************************************************************
768 * Helper function for ConfigureNotify handling.
769 * Get the new geometry of a window relative to the root window.
771 static void EVENT_GetGeometry( Window win
, int *px
, int *py
,
772 unsigned int *pwidth
, unsigned int *pheight
)
774 Window root
, parent
, *children
;
776 unsigned int width
, height
, border
, depth
, nb_children
;
778 if (!TSXGetGeometry( display
, win
, &root
, px
, py
, pwidth
, pheight
,
779 &border
, &depth
)) return;
780 if (win
== rootWindow
)
788 if (!TSXQueryTree(display
, win
, &root
, &parent
, &children
, &nb_children
))
791 if (parent
== rootWindow
) break;
793 if (!TSXGetGeometry( display
, win
, &root
, &xpos
, &ypos
,
794 &width
, &height
, &border
, &depth
)) return;
801 /**********************************************************************
802 * EVENT_ConfigureNotify
804 * The ConfigureNotify event is only selected on top-level windows
805 * when the -managed flag is used.
807 static void EVENT_ConfigureNotify( WND
*pWnd
, XConfigureEvent
*event
)
810 RECT32 newWindowRect
, newClientRect
;
811 HRGN32 hrgnOldPos
, hrgnNewPos
;
812 Window above
= event
->above
;
814 unsigned int width
, height
;
816 assert (pWnd
->flags
& WIN_MANAGED
);
818 /* We don't rely on the event geometry info, because it is relative
819 * to parent and not to root, and it may be wrong (XFree sets x,y to 0,0
820 * if the window hasn't moved).
822 EVENT_GetGeometry( event
->window
, &x
, &y
, &width
, &height
);
824 /* Fill WINDOWPOS struct */
825 winpos
.flags
= SWP_NOACTIVATE
| SWP_NOZORDER
;
826 winpos
.hwnd
= pWnd
->hwndSelf
;
832 /* Check for unchanged attributes */
833 if (winpos
.x
== pWnd
->rectWindow
.left
&& winpos
.y
== pWnd
->rectWindow
.top
)
834 winpos
.flags
|= SWP_NOMOVE
;
835 if ((winpos
.cx
== pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) &&
836 (winpos
.cy
== pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
))
837 winpos
.flags
|= SWP_NOSIZE
;
840 RECT32 rect
= { 0, 0, pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
,
841 pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
};
842 DCE_InvalidateDCE( pWnd
, &rect
);
845 /* Send WM_WINDOWPOSCHANGING */
846 SendMessage32A( winpos
.hwnd
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)&winpos
);
848 /* Calculate new position and size */
849 newWindowRect
.left
= x
;
850 newWindowRect
.right
= x
+ width
;
851 newWindowRect
.top
= y
;
852 newWindowRect
.bottom
= y
+ height
;
854 WINPOS_SendNCCalcSize( winpos
.hwnd
, TRUE
, &newWindowRect
,
855 &pWnd
->rectWindow
, &pWnd
->rectClient
,
856 &winpos
, &newClientRect
);
858 hrgnOldPos
= CreateRectRgnIndirect32( &pWnd
->rectWindow
);
859 hrgnNewPos
= CreateRectRgnIndirect32( &newWindowRect
);
860 CombineRgn32( hrgnOldPos
, hrgnOldPos
, hrgnNewPos
, RGN_DIFF
);
861 DeleteObject32(hrgnOldPos
);
862 DeleteObject32(hrgnNewPos
);
864 /* Set new size and position */
865 pWnd
->rectWindow
= newWindowRect
;
866 pWnd
->rectClient
= newClientRect
;
867 SendMessage32A( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
869 if (!IsWindow32( winpos
.hwnd
)) return;
870 if( above
== None
) /* absolute bottom */
872 WIN_UnlinkWindow( winpos
.hwnd
);
873 WIN_LinkWindow( winpos
.hwnd
, HWND_BOTTOM
);
875 else EVENT_QueryZOrder( pWnd
); /* try to outsmart window manager */
879 /***********************************************************************
880 * EVENT_SelectionRequest
882 static void EVENT_SelectionRequest( WND
*pWnd
, XSelectionRequestEvent
*event
)
884 XSelectionEvent result
;
886 Window request
= event
->requestor
;
888 if(event
->target
== XA_STRING
)
894 rprop
= event
->property
;
896 if(rprop
== None
) rprop
= event
->target
;
898 if(event
->selection
!=XA_PRIMARY
) rprop
= None
;
899 else if(!CLIPBOARD_IsPresent(CF_OEMTEXT
)) rprop
= None
;
902 /* open to make sure that clipboard is available */
904 BOOL32 couldOpen
= OpenClipboard32( pWnd
->hwndSelf
);
907 hText
= GetClipboardData16(CF_TEXT
);
908 text
= GlobalLock16(hText
);
909 size
= GlobalSize16(hText
);
911 /* remove carriage returns */
913 lpstr
= (char*)HEAP_xalloc( GetProcessHeap(), 0, size
-- );
914 for(i
=0,j
=0; i
< size
&& text
[i
]; i
++ )
916 if( text
[i
] == '\r' &&
917 (text
[i
+1] == '\n' || text
[i
+1] == '\0') ) continue;
918 lpstr
[j
++] = text
[i
];
922 TSXChangeProperty(display
, request
, rprop
,
923 XA_STRING
, 8, PropModeReplace
,
925 HeapFree( GetProcessHeap(), 0, lpstr
);
927 /* close only if we opened before */
929 if(couldOpen
) CloseClipboard32();
934 TRACE(event
,"Request for %s ignored\n", TSXGetAtomName(display
,event
->target
));
936 result
.type
= SelectionNotify
;
937 result
.display
= display
;
938 result
.requestor
= request
;
939 result
.selection
= event
->selection
;
940 result
.property
= rprop
;
941 result
.target
= event
->target
;
942 result
.time
= event
->time
;
943 TSXSendEvent(display
,event
->requestor
,False
,NoEventMask
,(XEvent
*)&result
);
947 /***********************************************************************
948 * EVENT_SelectionNotify
950 static void EVENT_SelectionNotify( XSelectionEvent
*event
)
952 if (event
->selection
!= XA_PRIMARY
) return;
954 if (event
->target
!= XA_STRING
) CLIPBOARD_ReadSelection( 0, None
);
955 else CLIPBOARD_ReadSelection( event
->requestor
, event
->property
);
957 TRACE(clipboard
,"\tSelectionNotify done!\n");
961 /***********************************************************************
962 * EVENT_SelectionClear
964 static void EVENT_SelectionClear( WND
*pWnd
, XSelectionClearEvent
*event
)
966 if (event
->selection
!= XA_PRIMARY
) return;
967 CLIPBOARD_ReleaseSelection( event
->window
, pWnd
->hwndSelf
);
971 /**********************************************************************
972 * EVENT_ClientMessage
974 static void EVENT_ClientMessage( WND
*pWnd
, XClientMessageEvent
*event
)
976 if (event
->message_type
!= None
&& event
->format
== 32)
978 if ((event
->message_type
== wmProtocols
) &&
979 (((Atom
) event
->data
.l
[0]) == wmDeleteWindow
))
980 SendMessage16( pWnd
->hwndSelf
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
981 else if ( event
->message_type
== dndProtocol
&&
982 (event
->data
.l
[0] == DndFile
|| event
->data
.l
[0] == DndFiles
) )
984 unsigned long data_length
;
985 unsigned long aux_long
;
986 unsigned char* p_data
= NULL
;
994 HGLOBAL16 hDragInfo
= GlobalAlloc16( GMEM_SHARE
| GMEM_ZEROINIT
, sizeof(DRAGINFO
));
995 LPDRAGINFO lpDragInfo
= (LPDRAGINFO
) GlobalLock16(hDragInfo
);
996 SEGPTR spDragInfo
= (SEGPTR
) WIN16_GlobalLock16(hDragInfo
);
997 Window w_aux_root
, w_aux_child
;
1000 if( !lpDragInfo
|| !spDragInfo
) return;
1002 TSXQueryPointer( display
, pWnd
->window
, &w_aux_root
, &w_aux_child
,
1003 &x
, &y
, &u
.pt_aux
.x
, &u
.pt_aux
.y
, (unsigned int*)&aux_long
);
1005 lpDragInfo
->hScope
= pWnd
->hwndSelf
;
1006 lpDragInfo
->pt
.x
= (INT16
)x
; lpDragInfo
->pt
.y
= (INT16
)y
;
1008 /* find out drop point and drop window */
1009 if( x
< 0 || y
< 0 ||
1010 x
> (pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) ||
1011 y
> (pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
) )
1012 { bAccept
= pWnd
->dwExStyle
& WS_EX_ACCEPTFILES
; x
= y
= 0; }
1015 bAccept
= DRAG_QueryUpdate( pWnd
->hwndSelf
, spDragInfo
, TRUE
);
1016 x
= lpDragInfo
->pt
.x
; y
= lpDragInfo
->pt
.y
;
1018 pDropWnd
= WIN_FindWndPtr( lpDragInfo
->hScope
);
1019 GlobalFree16( hDragInfo
);
1023 TSXGetWindowProperty( display
, DefaultRootWindow(display
),
1024 dndSelection
, 0, 65535, FALSE
,
1025 AnyPropertyType
, &u
.atom_aux
, &u
.pt_aux
.y
,
1026 &data_length
, &aux_long
, &p_data
);
1028 if( !aux_long
&& p_data
) /* don't bother if > 64K */
1030 char *p
= (char*) p_data
;
1034 while( *p
) /* calculate buffer size */
1037 if((u
.i
= *p
) != -1 )
1038 u
.i
= DRIVE_FindDriveRoot( (const char **)&p_drop
);
1039 if( u
.i
== -1 ) *p
= -1; /* mark as "bad" */
1042 INT32 len
= GetShortPathName32A( p
, NULL
, 0 );
1043 if (len
) aux_long
+= len
+ 1;
1048 if( aux_long
&& aux_long
< 65535 )
1051 LPDROPFILESTRUCT lpDrop
;
1053 aux_long
+= sizeof(DROPFILESTRUCT
) + 1;
1054 hDrop
= (HDROP16
)GlobalAlloc16( GMEM_SHARE
, aux_long
);
1055 lpDrop
= (LPDROPFILESTRUCT
) GlobalLock16( hDrop
);
1059 lpDrop
->wSize
= sizeof(DROPFILESTRUCT
);
1060 lpDrop
->ptMousePos
.x
= (INT16
)x
;
1061 lpDrop
->ptMousePos
.y
= (INT16
)y
;
1062 lpDrop
->fInNonClientArea
= (BOOL16
)
1063 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
1064 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
1065 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
1066 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
1067 p_drop
= ((char*)lpDrop
) + sizeof(DROPFILESTRUCT
);
1071 if( *p
!= -1 ) /* use only "good" entries */
1073 GetShortPathName32A( p
, p_drop
, 65535 );
1074 p_drop
+= strlen( p_drop
) + 1;
1079 PostMessage16( pWnd
->hwndSelf
, WM_DROPFILES
,
1080 (WPARAM16
)hDrop
, 0L );
1084 if( p_data
) TSXFree(p_data
);
1086 } /* WS_EX_ACCEPTFILES */
1089 TRACE(event
, "unrecognized ClientMessage\n" );
1093 /**********************************************************************
1096 * Install colormap when Wine window is focused in
1097 * self-managed mode with private colormap
1100 void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event )
1102 if( !Options.managed && rootWindow == DefaultRootWindow(display) &&
1103 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() )
1104 TSXInstallColormap( display, COLOR_GetColormap() );
1108 /**********************************************************************
1111 void EVENT_MapNotify( HWND32 hWnd
, XMapEvent
*event
)
1113 HWND32 hwndFocus
= GetFocus32();
1115 if (hwndFocus
&& IsChild32( hWnd
, hwndFocus
))
1116 FOCUS_SetXFocus( (HWND32
)hwndFocus
);
1121 /**********************************************************************
1124 * We need this to be able to generate double click messages
1125 * when menu code captures mouse in the window without CS_DBLCLK style.
1127 HWND32
EVENT_Capture(HWND32 hwnd
, INT16 ht
)
1130 HWND32 capturePrev
= captureWnd
;
1134 TSXUngrabPointer(display
, CurrentTime
);
1135 captureWnd
= NULL
; captureHT
= 0;
1137 else if ((win
= WIN_GetXWindow( hwnd
)))
1139 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1142 (TSXGrabPointer(display
, win
, False
,
1143 ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
,
1144 GrabModeAsync
, GrabModeAsync
,
1145 None
, None
, CurrentTime
) == GrabSuccess
) )
1147 TRACE(win
, "(0x%04x)\n", hwnd
);
1153 if( capturePrev
&& capturePrev
!= captureWnd
)
1155 WND
* wndPtr
= WIN_FindWndPtr( capturePrev
);
1156 if( wndPtr
&& (wndPtr
->flags
& WIN_ISWIN32
) )
1157 SendMessage32A( capturePrev
, WM_CAPTURECHANGED
, 0L, hwnd
);
1162 /**********************************************************************
1163 * EVENT_GetCaptureInfo
1165 INT16
EVENT_GetCaptureInfo()
1170 /**********************************************************************
1171 * SetCapture16 (USER.18)
1173 HWND16 WINAPI
SetCapture16( HWND16 hwnd
)
1175 return (HWND16
)EVENT_Capture( hwnd
, HTCLIENT
);
1179 /**********************************************************************
1180 * SetCapture32 (USER32.463)
1182 HWND32 WINAPI
SetCapture32( HWND32 hwnd
)
1184 return EVENT_Capture( hwnd
, HTCLIENT
);
1188 /**********************************************************************
1189 * ReleaseCapture (USER.19) (USER32.438)
1191 void WINAPI
ReleaseCapture(void)
1193 TRACE(win
, "captureWnd=%04x\n", captureWnd
);
1194 if( captureWnd
) EVENT_Capture( 0, 0 );
1198 /**********************************************************************
1199 * GetCapture16 (USER.236)
1201 HWND16 WINAPI
GetCapture16(void)
1207 /**********************************************************************
1208 * GetCapture32 (USER32.207)
1210 HWND32 WINAPI
GetCapture32(void)
1216 /***********************************************************************
1217 * GetMouseEventProc (USER.337)
1219 FARPROC16 WINAPI
GetMouseEventProc(void)
1221 HMODULE16 hmodule
= GetModuleHandle16("USER");
1222 return MODULE_GetEntryPoint( hmodule
,
1223 MODULE_GetOrdinal( hmodule
, "Mouse_Event" ) );
1227 /***********************************************************************
1228 * Mouse_Event (USER.299)
1230 void WINAPI
Mouse_Event( CONTEXT
*context
)
1234 * BX = horizontal displacement if AX & ME_MOVE
1235 * CX = vertical displacement if AX & ME_MOVE
1236 * DX = button state (?)
1237 * SI = mouse event flags (?)
1240 int rootX
, rootY
, winX
, winY
;
1243 if (AX_reg(context
) & ME_MOVE
)
1245 /* We have to actually move the cursor */
1246 TSXWarpPointer( display
, rootWindow
, None
, 0, 0, 0, 0,
1247 (short)BX_reg(context
), (short)CX_reg(context
) );
1250 if (!TSXQueryPointer( display
, rootWindow
, &root
, &child
,
1251 &rootX
, &rootY
, &winX
, &winY
, &state
)) return;
1252 if (AX_reg(context
) & ME_LDOWN
)
1253 hardware_event( WM_LBUTTONDOWN
, EVENT_XStateToKeyState( state
),
1254 0L, winX
, winY
, GetTickCount(), 0 );
1255 if (AX_reg(context
) & ME_LUP
)
1256 hardware_event( WM_LBUTTONUP
, EVENT_XStateToKeyState( state
),
1257 0L, winX
, winY
, GetTickCount(), 0 );
1258 if (AX_reg(context
) & ME_RDOWN
)
1259 hardware_event( WM_RBUTTONDOWN
, EVENT_XStateToKeyState( state
),
1260 0L, winX
, winY
, GetTickCount(), 0 );
1261 if (AX_reg(context
) & ME_RUP
)
1262 hardware_event( WM_RBUTTONUP
, EVENT_XStateToKeyState( state
),
1263 0L, winX
, winY
, GetTickCount(), 0 );
1267 /**********************************************************************
1268 * EnableHardwareInput (USER.331)
1270 BOOL16 WINAPI
EnableHardwareInput(BOOL16 bEnable
)
1272 BOOL16 bOldState
= InputEnabled
;
1273 FIXME(event
,"(%d) - stub\n", bEnable
);
1274 InputEnabled
= bEnable
;
1279 /***********************************************************************
1280 * SwapMouseButton16 (USER.186)
1282 BOOL16 WINAPI
SwapMouseButton16( BOOL16 fSwap
)
1284 BOOL16 ret
= SwappedButtons
;
1285 SwappedButtons
= fSwap
;
1290 /***********************************************************************
1291 * SwapMouseButton32 (USER32.536)
1293 BOOL32 WINAPI
SwapMouseButton32( BOOL32 fSwap
)
1295 BOOL32 ret
= SwappedButtons
;
1296 SwappedButtons
= fSwap
;