wineandroid: Add a JNI callback to store the native window we got from the TextureView.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7124a7d90c
commit
9a134711e6
|
@ -50,6 +50,7 @@ public class WineActivity extends Activity
|
|||
{
|
||||
private native String wine_init( String[] cmdline, String[] env );
|
||||
public native void wine_desktop_changed( int width, int height );
|
||||
public native void wine_surface_changed( int hwnd, Surface surface );
|
||||
|
||||
private final String LOGTAG = "wine";
|
||||
private ProgressDialog progress_dialog;
|
||||
|
@ -346,6 +347,7 @@ public void set_surface( SurfaceTexture surftex )
|
|||
if (surftex == null) window_surface = null;
|
||||
else if (window_surface == null) window_surface = new Surface( surftex );
|
||||
Log.i( LOGTAG, String.format( "set window surface hwnd %08x %s", hwnd, window_surface ));
|
||||
wine_surface_changed( hwnd, window_surface );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#include <android/native_window_jni.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
|
@ -41,6 +42,8 @@
|
|||
|
||||
#define DECL_FUNCPTR(f) extern typeof(f) * p##f DECLSPEC_HIDDEN
|
||||
DECL_FUNCPTR( __android_log_print );
|
||||
DECL_FUNCPTR( ANativeWindow_fromSurface );
|
||||
DECL_FUNCPTR( ANativeWindow_release );
|
||||
#undef DECL_FUNCPTR
|
||||
|
||||
|
||||
|
@ -49,6 +52,7 @@ DECL_FUNCPTR( __android_log_print );
|
|||
*/
|
||||
|
||||
extern void start_android_device(void) DECLSPEC_HIDDEN;
|
||||
extern void register_native_window( HWND hwnd, struct ANativeWindow *win ) DECLSPEC_HIDDEN;
|
||||
extern void create_ioctl_window( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern void destroy_ioctl_window( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern int ioctl_window_pos_changed( HWND hwnd, const RECT *window_rect, const RECT *client_rect,
|
||||
|
@ -69,10 +73,12 @@ 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;
|
||||
extern void surface_changed( JNIEnv *env, jobject obj, jint win, jobject surface ) DECLSPEC_HIDDEN;
|
||||
|
||||
enum event_type
|
||||
{
|
||||
DESKTOP_CHANGED,
|
||||
SURFACE_CHANGED,
|
||||
};
|
||||
|
||||
union event_data
|
||||
|
@ -84,6 +90,14 @@ union event_data
|
|||
unsigned int width;
|
||||
unsigned int height;
|
||||
} desktop;
|
||||
struct
|
||||
{
|
||||
enum event_type type;
|
||||
HWND hwnd;
|
||||
ANativeWindow *window;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
} surface;
|
||||
};
|
||||
|
||||
int send_event( const union event_data *data );
|
||||
|
|
|
@ -59,6 +59,13 @@ enum android_ioctl
|
|||
NB_IOCTLS
|
||||
};
|
||||
|
||||
/* data about the native window in the context of the Java process */
|
||||
struct native_win_data
|
||||
{
|
||||
struct ANativeWindow *parent;
|
||||
HWND hwnd;
|
||||
};
|
||||
|
||||
struct ioctl_header
|
||||
{
|
||||
int hwnd;
|
||||
|
@ -101,6 +108,86 @@ static inline void wrap_java_call(void) { }
|
|||
static inline void unwrap_java_call(void) { }
|
||||
#endif /* __i386__ */
|
||||
|
||||
static struct native_win_data *data_map[65536];
|
||||
|
||||
static unsigned int data_map_idx( HWND hwnd )
|
||||
{
|
||||
return LOWORD(hwnd);
|
||||
}
|
||||
|
||||
static struct native_win_data *get_native_win_data( HWND hwnd )
|
||||
{
|
||||
struct native_win_data *data = data_map[data_map_idx( hwnd )];
|
||||
|
||||
if (data && data->hwnd == hwnd) return data;
|
||||
WARN( "unknown win %p\n", hwnd );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct native_win_data *get_ioctl_native_win_data( const struct ioctl_header *hdr )
|
||||
{
|
||||
return get_native_win_data( LongToHandle(hdr->hwnd) );
|
||||
}
|
||||
|
||||
static void release_native_window( struct native_win_data *data )
|
||||
{
|
||||
if (data->parent) pANativeWindow_release( data->parent );
|
||||
}
|
||||
|
||||
static void free_native_win_data( struct native_win_data *data )
|
||||
{
|
||||
unsigned int idx = data_map_idx( data->hwnd );
|
||||
|
||||
release_native_window( data );
|
||||
HeapFree( GetProcessHeap(), 0, data );
|
||||
data_map[idx] = NULL;
|
||||
}
|
||||
|
||||
static struct native_win_data *create_native_win_data( HWND hwnd )
|
||||
{
|
||||
unsigned int idx = data_map_idx( hwnd );
|
||||
struct native_win_data *data = data_map[idx];
|
||||
|
||||
if (data)
|
||||
{
|
||||
WARN( "data for %p not freed correctly\n", data->hwnd );
|
||||
free_native_win_data( data );
|
||||
}
|
||||
if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) ))) return NULL;
|
||||
data->hwnd = hwnd;
|
||||
data_map[idx] = data;
|
||||
return data;
|
||||
}
|
||||
|
||||
static void CALLBACK register_native_window_callback( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 )
|
||||
{
|
||||
HWND hwnd = (HWND)arg1;
|
||||
struct ANativeWindow *win = (struct ANativeWindow *)arg2;
|
||||
struct native_win_data *data = get_native_win_data( hwnd );
|
||||
|
||||
if (!data || data->parent == win)
|
||||
{
|
||||
if (win) pANativeWindow_release( win );
|
||||
TRACE( "%p -> %p win %p (unchanged)\n", hwnd, data, win );
|
||||
return;
|
||||
}
|
||||
|
||||
release_native_window( data );
|
||||
data->parent = win;
|
||||
if (win)
|
||||
{
|
||||
wrap_java_call();
|
||||
win->perform( win, NATIVE_WINDOW_API_CONNECT, NATIVE_WINDOW_API_CPU );
|
||||
unwrap_java_call();
|
||||
}
|
||||
TRACE( "%p -> %p win %p\n", hwnd, data, win );
|
||||
}
|
||||
|
||||
/* register a native window received from the Java side for use in ioctls */
|
||||
void register_native_window( HWND hwnd, struct ANativeWindow *win )
|
||||
{
|
||||
NtQueueApcThread( thread, register_native_window_callback, (ULONG_PTR)hwnd, (ULONG_PTR)win, 0 );
|
||||
}
|
||||
|
||||
static int status_to_android_error( NTSTATUS status )
|
||||
{
|
||||
|
@ -164,10 +251,14 @@ static NTSTATUS createWindow_ioctl( void *data, DWORD in_size, DWORD out_size, U
|
|||
static jmethodID method;
|
||||
jobject object;
|
||||
struct ioctl_android_create_window *res = data;
|
||||
struct native_win_data *win_data;
|
||||
DWORD pid = current_client_id();
|
||||
|
||||
if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (!(win_data = create_native_win_data( LongToHandle(res->hdr.hwnd) )))
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
TRACE( "hwnd %08x parent %08x\n", res->hdr.hwnd, res->parent );
|
||||
|
||||
if (!(object = load_java_method( &method, "createWindow", "(III)V" ))) return STATUS_NOT_SUPPORTED;
|
||||
|
@ -183,9 +274,12 @@ static NTSTATUS destroyWindow_ioctl( void *data, DWORD in_size, DWORD out_size,
|
|||
static jmethodID method;
|
||||
jobject object;
|
||||
struct ioctl_android_destroy_window *res = data;
|
||||
struct native_win_data *win_data;
|
||||
|
||||
if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return STATUS_INVALID_HANDLE;
|
||||
|
||||
TRACE( "hwnd %08x\n", res->hdr.hwnd );
|
||||
|
||||
if (!(object = load_java_method( &method, "destroyWindow", "(I)V" ))) return STATUS_NOT_SUPPORTED;
|
||||
|
@ -193,6 +287,7 @@ static NTSTATUS destroyWindow_ioctl( void *data, DWORD in_size, DWORD out_size,
|
|||
wrap_java_call();
|
||||
(*jni_env)->CallVoidMethod( jni_env, object, method, res->hdr.hwnd );
|
||||
unwrap_java_call();
|
||||
free_native_win_data( win_data );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -390,6 +390,7 @@ const struct gdi_dc_funcs * CDECL ANDROID_get_gdi_driver( unsigned int version )
|
|||
static const JNINativeMethod methods[] =
|
||||
{
|
||||
{ "wine_desktop_changed", "(II)V", desktop_changed },
|
||||
{ "wine_surface_changed", "(ILandroid/view/Surface;)V", surface_changed },
|
||||
};
|
||||
|
||||
#define DECL_FUNCPTR(f) typeof(f) * p##f = NULL
|
||||
|
@ -399,18 +400,27 @@ static const JNINativeMethod methods[] =
|
|||
} while(0)
|
||||
|
||||
DECL_FUNCPTR( __android_log_print );
|
||||
DECL_FUNCPTR( ANativeWindow_fromSurface );
|
||||
DECL_FUNCPTR( ANativeWindow_release );
|
||||
|
||||
static void load_android_libs(void)
|
||||
{
|
||||
void *liblog;
|
||||
void *libandroid, *liblog;
|
||||
char error[1024];
|
||||
|
||||
if (!(libandroid = wine_dlopen( "libandroid.so", RTLD_GLOBAL, error, sizeof(error) )))
|
||||
{
|
||||
ERR( "failed to load libandroid.so: %s\n", error );
|
||||
return;
|
||||
}
|
||||
if (!(liblog = wine_dlopen( "liblog.so", RTLD_GLOBAL, error, sizeof(error) )))
|
||||
{
|
||||
ERR( "failed to load liblog.so: %s\n", error );
|
||||
return;
|
||||
}
|
||||
LOAD_FUNCPTR( liblog, __android_log_print );
|
||||
LOAD_FUNCPTR( libandroid, ANativeWindow_fromSurface );
|
||||
LOAD_FUNCPTR( libandroid, ANativeWindow_release );
|
||||
}
|
||||
|
||||
#undef DECL_FUNCPTR
|
||||
|
|
|
@ -183,6 +183,35 @@ void desktop_changed( JNIEnv *env, jobject obj, jint width, jint height )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* surface_changed
|
||||
*
|
||||
* JNI callback, runs in the context of the Java thread.
|
||||
*/
|
||||
void surface_changed( JNIEnv *env, jobject obj, jint win, jobject surface )
|
||||
{
|
||||
union event_data data;
|
||||
|
||||
memset( &data, 0, sizeof(data) );
|
||||
data.surface.hwnd = LongToHandle( win );
|
||||
if (surface)
|
||||
{
|
||||
int width, height;
|
||||
ANativeWindow *win = pANativeWindow_fromSurface( env, surface );
|
||||
|
||||
if (win->query( win, NATIVE_WINDOW_WIDTH, &width ) < 0) width = 0;
|
||||
if (win->query( win, NATIVE_WINDOW_HEIGHT, &height ) < 0) height = 0;
|
||||
data.surface.window = win;
|
||||
data.surface.width = width;
|
||||
data.surface.height = height;
|
||||
p__android_log_print( ANDROID_LOG_INFO, "wine", "surface_changed: %p %ux%u",
|
||||
data.surface.hwnd, width, height );
|
||||
}
|
||||
data.type = SURFACE_CHANGED;
|
||||
send_event( &data );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* init_event_queue
|
||||
*/
|
||||
|
@ -255,7 +284,14 @@ static int process_events( DWORD mask )
|
|||
|
||||
LIST_FOR_EACH_ENTRY_SAFE( event, next, &event_queue, struct java_event, entry )
|
||||
{
|
||||
if (!(mask & QS_SENDMESSAGE)) continue; /* skip it */
|
||||
switch (event->data.type)
|
||||
{
|
||||
case SURFACE_CHANGED:
|
||||
break; /* always process it to unblock other threads */
|
||||
default:
|
||||
if (mask & QS_SENDMESSAGE) break;
|
||||
continue; /* skip it */
|
||||
}
|
||||
|
||||
/* remove it first, in case we process events recursively */
|
||||
list_remove( &event->entry );
|
||||
|
@ -272,6 +308,13 @@ static int process_events( DWORD mask )
|
|||
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW );
|
||||
break;
|
||||
|
||||
case SURFACE_CHANGED:
|
||||
TRACE("SURFACE_CHANGED %p %p size %ux%u\n", event->data.surface.hwnd,
|
||||
event->data.surface.window, event->data.surface.width, event->data.surface.height );
|
||||
|
||||
register_native_window( event->data.surface.hwnd, event->data.surface.window );
|
||||
break;
|
||||
|
||||
default:
|
||||
FIXME( "got event %u\n", event->data.type );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue