From 5be4a0e38842d2fa241ca769ce4d50e4eb55c68a Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 31 May 2017 11:49:12 +0200 Subject: [PATCH] wineandroid: Add an event queue to support handling Java callbacks in the desktop thread. Signed-off-by: Alexandre Julliard --- dlls/wineandroid.drv/android.h | 18 +++ dlls/wineandroid.drv/window.c | 168 ++++++++++++++++++++++ dlls/wineandroid.drv/wineandroid.drv.spec | 2 + 3 files changed, 188 insertions(+) diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h index ab4a431cc35..9fefb111fa1 100644 --- a/dlls/wineandroid.drv/android.h +++ b/dlls/wineandroid.drv/android.h @@ -57,6 +57,24 @@ extern void init_monitors( int width, int height ) DECLSPEC_HIDDEN; /* JNI entry points */ extern void desktop_changed( JNIEnv *env, jobject obj, jint width, jint height ) DECLSPEC_HIDDEN; +enum event_type +{ + DESKTOP_CHANGED, +}; + +union event_data +{ + enum event_type type; + struct + { + enum event_type type; + unsigned int width; + unsigned int height; + } desktop; +}; + +int send_event( const union event_data *data ); + extern JavaVM *wine_get_java_vm(void); extern jobject wine_get_java_object(void); diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index e7c83b09b02..cf35215a609 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -44,6 +44,7 @@ #include "wine/unicode.h" #include "android.h" +#include "wine/server.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(android); @@ -133,6 +134,35 @@ static void release_win_data( struct android_win_data *data ) } +/* Handling of events coming from the Java side */ + +struct java_event +{ + struct list entry; + union event_data data; +}; + +static struct list event_queue = LIST_INIT( event_queue ); +static struct java_event *current_event; +static int event_pipe[2]; +static DWORD desktop_tid; + +/*********************************************************************** + * send_event + */ +int send_event( const union event_data *data ) +{ + int res; + + if ((res = write( event_pipe[1], data, sizeof(*data) )) != sizeof(*data)) + { + p__android_log_print( ANDROID_LOG_ERROR, "wine", "failed to send event" ); + return -1; + } + return 0; +} + + /*********************************************************************** * desktop_changed * @@ -140,7 +170,145 @@ static void release_win_data( struct android_win_data *data ) */ void desktop_changed( JNIEnv *env, jobject obj, jint width, jint height ) { + union event_data data; + + memset( &data, 0, sizeof(data) ); + data.type = DESKTOP_CHANGED; + data.desktop.width = width; + data.desktop.height = height; p__android_log_print( ANDROID_LOG_INFO, "wine", "desktop_changed: %ux%u", width, height ); + send_event( &data ); +} + + +/*********************************************************************** + * init_event_queue + */ +static void init_event_queue(void) +{ + HANDLE handle; + int ret; + + if (pipe2( event_pipe, O_CLOEXEC | O_NONBLOCK ) == -1) + { + ERR( "could not create data\n" ); + ExitProcess(1); + } + if (wine_server_fd_to_handle( event_pipe[0], GENERIC_READ | SYNCHRONIZE, 0, &handle )) + { + ERR( "Can't allocate handle for event fd\n" ); + ExitProcess(1); + } + SERVER_START_REQ( set_queue_fd ) + { + req->handle = wine_server_obj_handle( handle ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + if (ret) + { + ERR( "Can't store handle for event fd %x\n", ret ); + ExitProcess(1); + } + CloseHandle( handle ); + desktop_tid = GetCurrentThreadId(); +} + + +/*********************************************************************** + * pull_events + * + * Pull events from the event pipe and add them to the queue + */ +static void pull_events(void) +{ + struct java_event *event; + int res; + + for (;;) + { + if (!(event = HeapAlloc( GetProcessHeap(), 0, sizeof(*event) ))) break; + + res = read( event_pipe[0], &event->data, sizeof(event->data) ); + if (res != sizeof(event->data)) break; + list_add_tail( &event_queue, &event->entry ); + } + HeapFree( GetProcessHeap(), 0, event ); +} + + +/*********************************************************************** + * process_events + */ +static int process_events( DWORD mask ) +{ + struct java_event *event, *next, *previous; + unsigned int count = 0; + + assert( GetCurrentThreadId() == desktop_tid ); + + pull_events(); + + previous = current_event; + + LIST_FOR_EACH_ENTRY_SAFE( event, next, &event_queue, struct java_event, entry ) + { + if (!(mask & QS_SENDMESSAGE)) continue; /* skip it */ + + /* remove it first, in case we process events recursively */ + list_remove( &event->entry ); + current_event = event; + + switch (event->data.type) + { + case DESKTOP_CHANGED: + TRACE( "DESKTOP_CHANGED %ux%u\n", event->data.desktop.width, event->data.desktop.height ); + screen_width = event->data.desktop.width; + screen_height = event->data.desktop.height; + init_monitors( screen_width, screen_height ); + SetWindowPos( GetDesktopWindow(), 0, 0, 0, screen_width, screen_height, + SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW ); + break; + + default: + FIXME( "got event %u\n", event->data.type ); + } + HeapFree( GetProcessHeap(), 0, event ); + count++; + } + current_event = previous; + return count; +} + + +/*********************************************************************** + * ANDROID_MsgWaitForMultipleObjectsEx + */ +DWORD CDECL ANDROID_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, + DWORD timeout, DWORD mask, DWORD flags ) +{ + if (GetCurrentThreadId() == desktop_tid) + { + /* don't process nested events */ + if (current_event) mask = 0; + if (process_events( mask )) return count - 1; + } + return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL, + timeout, flags & MWMO_ALERTABLE ); +} + +/********************************************************************** + * ANDROID_CreateWindow + */ +BOOL CDECL ANDROID_CreateWindow( HWND hwnd ) +{ + TRACE( "%p\n", hwnd ); + + if (hwnd == GetDesktopWindow()) + { + init_event_queue(); + } + return TRUE; } diff --git a/dlls/wineandroid.drv/wineandroid.drv.spec b/dlls/wineandroid.drv/wineandroid.drv.spec index b94c9f80280..49402a8c7cb 100644 --- a/dlls/wineandroid.drv/wineandroid.drv.spec +++ b/dlls/wineandroid.drv/wineandroid.drv.spec @@ -6,6 +6,8 @@ @ cdecl EnumDisplayMonitors(long ptr ptr long) ANDROID_EnumDisplayMonitors @ cdecl GetMonitorInfo(long ptr) ANDROID_GetMonitorInfo +@ cdecl CreateWindow(long) ANDROID_CreateWindow @ cdecl DestroyWindow(long) ANDROID_DestroyWindow +@ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) ANDROID_MsgWaitForMultipleObjectsEx @ cdecl WindowPosChanging(long long long ptr ptr ptr ptr) ANDROID_WindowPosChanging @ cdecl WindowPosChanged(long long long ptr ptr ptr ptr ptr) ANDROID_WindowPosChanged