From b50272bd75253edf1772f8a482f33ef2bf6289b5 Mon Sep 17 00:00:00 2001 From: Stephane Lussier Date: Sun, 21 Feb 1999 18:15:26 +0000 Subject: [PATCH] Fix problem where you need mouse activity to unlock some 16 bits thread with multi-threaded apps. --- include/message.h | 2 ++ include/ttydrv.h | 3 +- include/x11drv.h | 1 + loader/task.c | 11 +++--- windows/event.c | 12 +++++++ windows/ttydrv/event.c | 6 ++++ windows/ttydrv/init.c | 3 +- windows/x11drv/event.c | 78 ++++++++++++++++++++++++++++++++++++++++-- windows/x11drv/init.c | 3 +- 9 files changed, 108 insertions(+), 11 deletions(-) diff --git a/include/message.h b/include/message.h index 63b3259d0cb..a6c8dd2700b 100644 --- a/include/message.h +++ b/include/message.h @@ -43,6 +43,7 @@ typedef struct _EVENT_DRIVER { void (*pDummyMotionNotify)(void); BOOL32 (*pPending)(void); BOOL16 (*pIsUserIdle)(void); + void (*pWakeUp)(void); } EVENT_DRIVER; extern void EVENT_AddIO( int fd, unsigned flag ); @@ -54,6 +55,7 @@ extern BOOL32 EVENT_CheckFocus( void ); extern BOOL32 EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *state); extern void EVENT_DummyMotionNotify(void); extern BOOL32 EVENT_Pending(void); +extern void EVENT_WakeUp(void); /* input.c */ diff --git a/include/ttydrv.h b/include/ttydrv.h index 1c38239879a..8600722a0d3 100644 --- a/include/ttydrv.h +++ b/include/ttydrv.h @@ -5,7 +5,7 @@ #ifndef __WINE_TTYDRV_H #define __WINE_TTYDRV_H -#include "windows.h" +#include "wintypes.h" #include "wine/winuser16.h" struct tagCLASS; @@ -57,6 +57,7 @@ extern BOOL32 TTYDRV_EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *state); extern void TTYDRV_EVENT_DummyMotionNotify(void); extern BOOL32 TTYDRV_EVENT_Pending(void); extern BOOL16 TTYDRV_EVENT_IsUserIdle(void); +extern void TTYDRV_EVENT_WakeUp(void); /* TTY keyboard driver */ diff --git a/include/x11drv.h b/include/x11drv.h index a49e5e4506e..b3bf74d3808 100644 --- a/include/x11drv.h +++ b/include/x11drv.h @@ -262,6 +262,7 @@ extern BOOL32 X11DRV_EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *state); extern void X11DRV_EVENT_DummyMotionNotify(void); extern BOOL32 X11DRV_EVENT_Pending(void); extern BOOL16 X11DRV_EVENT_IsUserIdle(void); +extern void X11DRV_EVENT_WakeUp(void); /* X11 keyboard driver */ diff --git a/loader/task.c b/loader/task.c index 3bb95add473..2d65a29ad69 100644 --- a/loader/task.c +++ b/loader/task.c @@ -500,7 +500,8 @@ void TASK_StartTask( HTASK16 hTask ) if ( THREAD_IsWin16( THREAD_Current() ) ) OldYield(); else - FIXME(task, "Don't know how to start 16-bit task from 32-bit thread. Move the mouse!\n"); + /* wake-up the scheduler waiting in EVENT_WaitNetEvent */ + EVENT_WakeUp(); } @@ -944,13 +945,13 @@ void WINAPI PostEvent( HTASK16 hTask ) if (!hTask) hTask = GetCurrentTask(); if (!(pTask = (TDB *)GlobalLock16( hTask ))) return; + pTask->nEvents++; + if ( !THREAD_IsWin16( THREAD_Current() ) ) { - WARN(task, "called for Win32 thread (%04x)!\n", THREAD_Current()->teb_sel); - /* return; */ + /* wake-up the scheduler waiting in EVENT_WaitNetEvent */ + EVENT_WakeUp(); } - - pTask->nEvents++; } diff --git a/windows/event.c b/windows/event.c index 5e683b07050..eeefc6ecc3f 100644 --- a/windows/event.c +++ b/windows/event.c @@ -119,3 +119,15 @@ BOOL16 WINAPI IsUserIdle(void) { return EVENT_GetDriver()->pIsUserIdle(); } + +/*********************************************************************** + * EVENT_WakeUp + * + * Wake up the scheduler (EVENT_WaitNetEvent). Use by 32 bit thread + * when thew want signaled an event to a 16 bit task. This function + * will become obsolete when an Asynchronous thread will be implemented + */ +void EVENT_WakeUp(void) +{ + EVENT_GetDriver()->pWakeUp(); +} diff --git a/windows/ttydrv/event.c b/windows/ttydrv/event.c index 5ebb5b63989..9d73e86b5b6 100644 --- a/windows/ttydrv/event.c +++ b/windows/ttydrv/event.c @@ -91,3 +91,9 @@ BOOL16 TTYDRV_EVENT_IsUserIdle(void) return TRUE; } +/********************************************************************** + * TTYDRV_EVENT_WakeUp + */ +void TTYDRV_EVENT_WakeUp(void) +{ +} diff --git a/windows/ttydrv/init.c b/windows/ttydrv/init.c index 0e1db00fe53..a5203d7a07d 100644 --- a/windows/ttydrv/init.c +++ b/windows/ttydrv/init.c @@ -37,7 +37,8 @@ EVENT_DRIVER TTYDRV_EVENT_Driver = TTYDRV_EVENT_QueryPointer, TTYDRV_EVENT_DummyMotionNotify, TTYDRV_EVENT_Pending, - TTYDRV_EVENT_IsUserIdle + TTYDRV_EVENT_IsUserIdle, + TTYDRV_EVENT_WakeUp }; KEYBOARD_DRIVER TTYDRV_KEYBOARD_Driver = diff --git a/windows/x11drv/event.c b/windows/x11drv/event.c index c12a205db44..a0329324435 100644 --- a/windows/x11drv/event.c +++ b/windows/x11drv/event.c @@ -16,6 +16,7 @@ #include #include +#include #include "callback.h" #include "class.h" #include "clipboard.h" @@ -67,6 +68,7 @@ extern void X11DRV_KEYBOARD_HandleEvent(WND *pWnd, XKeyEvent *event); static fd_set __event_io_set[3]; static int __event_max_fd = 0; static int __event_x_connection = 0; +static int __wakeup_pipe[2]; static const char * const event_names[] = { @@ -119,6 +121,20 @@ BOOL32 X11DRV_EVENT_Init(void) __event_max_fd = __event_x_connection = ConnectionNumber(display); FD_SET( __event_x_connection, &__event_io_set[EVENT_IO_READ] ); + + /* this pipe is used to be able to wake-up the scheduler(WaitNetEvent) by + a 32 bit thread, this will become obsolete when the input thread will be + implemented */ + pipe(__wakeup_pipe); + + /* make the pipe non-blocking */ + fcntl(__wakeup_pipe[0], F_SETFL, O_NONBLOCK); + fcntl(__wakeup_pipe[1], F_SETFL, O_NONBLOCK); + + FD_SET( __wakeup_pipe[0], &__event_io_set[EVENT_IO_READ] ); + if (__wakeup_pipe[0] > __event_max_fd) + __event_max_fd = __wakeup_pipe[0]; + __event_max_fd++; return TRUE; } @@ -155,6 +171,26 @@ BOOL16 X11DRV_EVENT_IsUserIdle(void) return FALSE; } + +/*********************************************************************** + * EVENT_ReadWakeUpPipe + * + * Empty the wake up pipe + */ +void EVENT_ReadWakeUpPipe(void) +{ + char tmpBuf[10]; + ssize_t ret; + + EnterCriticalSection(&X11DRV_CritSection); + + /* Flush the wake-up pipe, it's just dummy data for waking-up this + thread. This will be obsolete when the input thread will be done */ + while ( (ret = read(__wakeup_pipe[0], &tmpBuf, 10)) == 10 ); + + LeaveCriticalSection(&X11DRV_CritSection); +} + /*********************************************************************** * X11DRV_EVENT_WaitNetEvent * @@ -209,6 +245,7 @@ BOOL32 X11DRV_EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek ) num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ], &io_set[EVENT_IO_WRITE], &io_set[EVENT_IO_EXCEPT], &timeout ); + if ( num_pending == 0) { /* Timeout or error */ @@ -217,6 +254,14 @@ BOOL32 X11DRV_EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek ) } #endif /* CONFIG_IPC */ + /* Flush the wake-up pipe, it's just dummy data for waking-up this + thread. This will be obsolete when the input thread will be done */ + if ( FD_ISSET( __wakeup_pipe[0], &io_set[EVENT_IO_READ] ) ) + { + num_pending--; + EVENT_ReadWakeUpPipe(); + } + /* Winsock asynchronous services */ if( FD_ISSET( __event_x_connection, &io_set[EVENT_IO_READ]) ) @@ -234,10 +279,24 @@ BOOL32 X11DRV_EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek ) else if(!pending) { /* Wait for X11 input. */ fd_set set; + int max_fd; FD_ZERO(&set); FD_SET(__event_x_connection, &set); - select(__event_x_connection + 1, &set, 0, 0, 0 ); + + /* wait on wake-up pipe also */ + FD_SET(__wakeup_pipe[0], &set); + if (__event_x_connection > __wakeup_pipe[0]) + max_fd = __event_x_connection + 1; + else + max_fd = __wakeup_pipe[0] + 1; + + select(max_fd, &set, 0, 0, 0 ); + + /* Flush the wake-up pipe, it's just dummy data for waking-up this + thread. This will be obsolete when the input thread will be done */ + if ( FD_ISSET( __wakeup_pipe[0], &set ) ) + EVENT_ReadWakeUpPipe(); } /* Process current X event (and possibly others that occurred in the meantime) */ @@ -1057,7 +1116,8 @@ static void EVENT_DropFromOffiX( WND *pWnd, XClientMessageEvent *event ) if( !lpDragInfo || !spDragInfo ) return; TSXQueryPointer( display, X11DRV_WND_GetXWindow(pWnd), &w_aux_root, &w_aux_child, - &x, &y, &u.pt_aux.x, &u.pt_aux.y, (unsigned int*)&aux_long); + &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y, + (unsigned int*)&aux_long); lpDragInfo->hScope = pWnd->hwndSelf; lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y; @@ -1079,7 +1139,7 @@ static void EVENT_DropFromOffiX( WND *pWnd, XClientMessageEvent *event ) { TSXGetWindowProperty( display, DefaultRootWindow(display), dndSelection, 0, 65535, FALSE, - AnyPropertyType, &u.atom_aux, &u.pt_aux.y, + AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y, &data_length, &aux_long, &p_data); if( !aux_long && p_data) /* don't bother if > 64K */ @@ -1364,4 +1424,16 @@ BOOL32 X11DRV_EVENT_Pending() return TSXPending(display); } +/********************************************************************** + * X11DRV_EVENT_WakeUp + */ +void X11DRV_EVENT_WakeUp(void) +{ + /* wake-up EVENT_WaitNetEvent function, a 32 bit thread post an event + for a 16 bit task */ + if (write (__wakeup_pipe[1], "A", 1) != 1) + ERR(event, "unable to write in wakeup_pipe\n"); +} + + #endif /* !defined(X_DISPLAY_MISSING) */ diff --git a/windows/x11drv/init.c b/windows/x11drv/init.c index 31358d78fa8..e7ac2dbcf39 100644 --- a/windows/x11drv/init.c +++ b/windows/x11drv/init.c @@ -42,7 +42,8 @@ EVENT_DRIVER X11DRV_EVENT_Driver = X11DRV_EVENT_QueryPointer, X11DRV_EVENT_DummyMotionNotify, X11DRV_EVENT_Pending, - X11DRV_EVENT_IsUserIdle + X11DRV_EVENT_IsUserIdle, + X11DRV_EVENT_WakeUp }; KEYBOARD_DRIVER X11DRV_KEYBOARD_Driver =