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 );
|
private native String wine_init( String[] cmdline, String[] env );
|
||||||
public native void wine_desktop_changed( int width, int height );
|
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 final String LOGTAG = "wine";
|
||||||
private ProgressDialog progress_dialog;
|
private ProgressDialog progress_dialog;
|
||||||
|
@ -346,6 +347,7 @@ public void set_surface( SurfaceTexture surftex )
|
||||||
if (surftex == null) window_surface = null;
|
if (surftex == null) window_surface = null;
|
||||||
else if (window_surface == null) window_surface = new Surface( surftex );
|
else if (window_surface == null) window_surface = new Surface( surftex );
|
||||||
Log.i( LOGTAG, String.format( "set window surface hwnd %08x %s", hwnd, window_surface ));
|
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 <stdlib.h>
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
|
#include <android/native_window_jni.h>
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
|
@ -41,6 +42,8 @@
|
||||||
|
|
||||||
#define DECL_FUNCPTR(f) extern typeof(f) * p##f DECLSPEC_HIDDEN
|
#define DECL_FUNCPTR(f) extern typeof(f) * p##f DECLSPEC_HIDDEN
|
||||||
DECL_FUNCPTR( __android_log_print );
|
DECL_FUNCPTR( __android_log_print );
|
||||||
|
DECL_FUNCPTR( ANativeWindow_fromSurface );
|
||||||
|
DECL_FUNCPTR( ANativeWindow_release );
|
||||||
#undef DECL_FUNCPTR
|
#undef DECL_FUNCPTR
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,6 +52,7 @@ DECL_FUNCPTR( __android_log_print );
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern void start_android_device(void) DECLSPEC_HIDDEN;
|
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 create_ioctl_window( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||||
extern void destroy_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,
|
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 */
|
/* JNI entry points */
|
||||||
extern void desktop_changed( JNIEnv *env, jobject obj, jint width, jint height ) DECLSPEC_HIDDEN;
|
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
|
enum event_type
|
||||||
{
|
{
|
||||||
DESKTOP_CHANGED,
|
DESKTOP_CHANGED,
|
||||||
|
SURFACE_CHANGED,
|
||||||
};
|
};
|
||||||
|
|
||||||
union event_data
|
union event_data
|
||||||
|
@ -84,6 +90,14 @@ union event_data
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
} desktop;
|
} 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 );
|
int send_event( const union event_data *data );
|
||||||
|
|
|
@ -59,6 +59,13 @@ enum android_ioctl
|
||||||
NB_IOCTLS
|
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
|
struct ioctl_header
|
||||||
{
|
{
|
||||||
int hwnd;
|
int hwnd;
|
||||||
|
@ -101,6 +108,86 @@ static inline void wrap_java_call(void) { }
|
||||||
static inline void unwrap_java_call(void) { }
|
static inline void unwrap_java_call(void) { }
|
||||||
#endif /* __i386__ */
|
#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 )
|
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;
|
static jmethodID method;
|
||||||
jobject object;
|
jobject object;
|
||||||
struct ioctl_android_create_window *res = data;
|
struct ioctl_android_create_window *res = data;
|
||||||
|
struct native_win_data *win_data;
|
||||||
DWORD pid = current_client_id();
|
DWORD pid = current_client_id();
|
||||||
|
|
||||||
if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER;
|
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 );
|
TRACE( "hwnd %08x parent %08x\n", res->hdr.hwnd, res->parent );
|
||||||
|
|
||||||
if (!(object = load_java_method( &method, "createWindow", "(III)V" ))) return STATUS_NOT_SUPPORTED;
|
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;
|
static jmethodID method;
|
||||||
jobject object;
|
jobject object;
|
||||||
struct ioctl_android_destroy_window *res = data;
|
struct ioctl_android_destroy_window *res = data;
|
||||||
|
struct native_win_data *win_data;
|
||||||
|
|
||||||
if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER;
|
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 );
|
TRACE( "hwnd %08x\n", res->hdr.hwnd );
|
||||||
|
|
||||||
if (!(object = load_java_method( &method, "destroyWindow", "(I)V" ))) return STATUS_NOT_SUPPORTED;
|
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();
|
wrap_java_call();
|
||||||
(*jni_env)->CallVoidMethod( jni_env, object, method, res->hdr.hwnd );
|
(*jni_env)->CallVoidMethod( jni_env, object, method, res->hdr.hwnd );
|
||||||
unwrap_java_call();
|
unwrap_java_call();
|
||||||
|
free_native_win_data( win_data );
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -390,6 +390,7 @@ const struct gdi_dc_funcs * CDECL ANDROID_get_gdi_driver( unsigned int version )
|
||||||
static const JNINativeMethod methods[] =
|
static const JNINativeMethod methods[] =
|
||||||
{
|
{
|
||||||
{ "wine_desktop_changed", "(II)V", desktop_changed },
|
{ "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
|
#define DECL_FUNCPTR(f) typeof(f) * p##f = NULL
|
||||||
|
@ -399,18 +400,27 @@ static const JNINativeMethod methods[] =
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
DECL_FUNCPTR( __android_log_print );
|
DECL_FUNCPTR( __android_log_print );
|
||||||
|
DECL_FUNCPTR( ANativeWindow_fromSurface );
|
||||||
|
DECL_FUNCPTR( ANativeWindow_release );
|
||||||
|
|
||||||
static void load_android_libs(void)
|
static void load_android_libs(void)
|
||||||
{
|
{
|
||||||
void *liblog;
|
void *libandroid, *liblog;
|
||||||
char error[1024];
|
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) )))
|
if (!(liblog = wine_dlopen( "liblog.so", RTLD_GLOBAL, error, sizeof(error) )))
|
||||||
{
|
{
|
||||||
ERR( "failed to load liblog.so: %s\n", error );
|
ERR( "failed to load liblog.so: %s\n", error );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOAD_FUNCPTR( liblog, __android_log_print );
|
LOAD_FUNCPTR( liblog, __android_log_print );
|
||||||
|
LOAD_FUNCPTR( libandroid, ANativeWindow_fromSurface );
|
||||||
|
LOAD_FUNCPTR( libandroid, ANativeWindow_release );
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef DECL_FUNCPTR
|
#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
|
* 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 )
|
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 */
|
/* remove it first, in case we process events recursively */
|
||||||
list_remove( &event->entry );
|
list_remove( &event->entry );
|
||||||
|
@ -272,6 +308,13 @@ static int process_events( DWORD mask )
|
||||||
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW );
|
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW );
|
||||||
break;
|
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:
|
default:
|
||||||
FIXME( "got event %u\n", event->data.type );
|
FIXME( "got event %u\n", event->data.type );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue