wineandroid: Add support for mouse events.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
b0690b13da
commit
db742a49c9
@ -30,6 +30,8 @@ import android.os.Build;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.InputDevice;
|
||||||
|
import android.view.MotionEvent;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.TextureView;
|
import android.view.TextureView;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -51,6 +53,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 );
|
public native void wine_surface_changed( int hwnd, Surface surface );
|
||||||
|
public native boolean wine_motion_event( int hwnd, int action, int x, int y, int state, int vscroll );
|
||||||
|
|
||||||
private final String LOGTAG = "wine";
|
private final String LOGTAG = "wine";
|
||||||
private ProgressDialog progress_dialog;
|
private ProgressDialog progress_dialog;
|
||||||
@ -365,6 +368,12 @@ public class WineActivity extends Activity
|
|||||||
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 );
|
wine_surface_changed( hwnd, window_surface );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void get_event_pos( MotionEvent event, int[] pos )
|
||||||
|
{
|
||||||
|
pos[0] = Math.round( event.getX() + window_view.getLeft() );
|
||||||
|
pos[1] = Math.round( event.getY() + window_view.getTop() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// View used for all Wine windows, backed by a TextureView
|
// View used for all Wine windows, backed by a TextureView
|
||||||
@ -411,6 +420,36 @@ public class WineActivity extends Activity
|
|||||||
public void onSurfaceTextureUpdated(SurfaceTexture surftex)
|
public void onSurfaceTextureUpdated(SurfaceTexture surftex)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean onGenericMotionEvent( MotionEvent event )
|
||||||
|
{
|
||||||
|
if (window.parent != null) return false; // let the parent handle it
|
||||||
|
|
||||||
|
if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0)
|
||||||
|
{
|
||||||
|
int[] pos = new int[2];
|
||||||
|
window.get_event_pos( event, pos );
|
||||||
|
Log.i( LOGTAG, String.format( "view motion event win %08x action %d pos %d,%d buttons %04x view %d,%d",
|
||||||
|
window.hwnd, event.getAction(), pos[0], pos[1],
|
||||||
|
event.getButtonState(), getLeft(), getTop() ));
|
||||||
|
return wine_motion_event( window.hwnd, event.getAction(), pos[0], pos[1],
|
||||||
|
event.getButtonState(), (int)event.getAxisValue(MotionEvent.AXIS_VSCROLL) );
|
||||||
|
}
|
||||||
|
return super.onGenericMotionEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onTouchEvent( MotionEvent event )
|
||||||
|
{
|
||||||
|
if (window.parent != null) return false; // let the parent handle it
|
||||||
|
|
||||||
|
int[] pos = new int[2];
|
||||||
|
window.get_event_pos( event, pos );
|
||||||
|
Log.i( LOGTAG, String.format( "view touch event win %08x action %d pos %d,%d buttons %04x view %d,%d",
|
||||||
|
window.hwnd, event.getAction(), pos[0], pos[1],
|
||||||
|
event.getButtonState(), getLeft(), getTop() ));
|
||||||
|
return wine_motion_event( window.hwnd, event.getAction(), pos[0], pos[1],
|
||||||
|
event.getButtonState(), 0 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The top-level desktop view group
|
// The top-level desktop view group
|
||||||
|
@ -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/input.h>
|
||||||
#include <android/native_window_jni.h>
|
#include <android/native_window_jni.h>
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
@ -84,11 +85,14 @@ 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;
|
extern void surface_changed( JNIEnv *env, jobject obj, jint win, jobject surface ) DECLSPEC_HIDDEN;
|
||||||
|
extern jboolean motion_event( JNIEnv *env, jobject obj, jint win, jint action,
|
||||||
|
jint x, jint y, jint state, jint vscroll ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
enum event_type
|
enum event_type
|
||||||
{
|
{
|
||||||
DESKTOP_CHANGED,
|
DESKTOP_CHANGED,
|
||||||
SURFACE_CHANGED,
|
SURFACE_CHANGED,
|
||||||
|
MOTION_EVENT,
|
||||||
};
|
};
|
||||||
|
|
||||||
union event_data
|
union event_data
|
||||||
@ -108,6 +112,12 @@ union event_data
|
|||||||
unsigned int width;
|
unsigned int width;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
} surface;
|
} surface;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
enum event_type type;
|
||||||
|
HWND hwnd;
|
||||||
|
INPUT input;
|
||||||
|
} motion;
|
||||||
};
|
};
|
||||||
|
|
||||||
int send_event( const union event_data *data );
|
int send_event( const union event_data *data );
|
||||||
|
@ -391,6 +391,7 @@ 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 },
|
{ "wine_surface_changed", "(ILandroid/view/Surface;)V", surface_changed },
|
||||||
|
{ "wine_motion_event", "(IIIIII)Z", motion_event },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DECL_FUNCPTR(f) typeof(f) * p##f = NULL
|
#define DECL_FUNCPTR(f) typeof(f) * p##f = NULL
|
||||||
|
@ -252,6 +252,74 @@ void surface_changed( JNIEnv *env, jobject obj, jint win, jobject surface )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* motion_event
|
||||||
|
*
|
||||||
|
* JNI callback, runs in the context of the Java thread.
|
||||||
|
*/
|
||||||
|
jboolean motion_event( JNIEnv *env, jobject obj, jint win, jint action, jint x, jint y, jint state, jint vscroll )
|
||||||
|
{
|
||||||
|
static LONG button_state;
|
||||||
|
union event_data data;
|
||||||
|
int prev_state;
|
||||||
|
|
||||||
|
int mask = action & AMOTION_EVENT_ACTION_MASK;
|
||||||
|
|
||||||
|
if (!( mask == AMOTION_EVENT_ACTION_DOWN ||
|
||||||
|
mask == AMOTION_EVENT_ACTION_UP ||
|
||||||
|
mask == AMOTION_EVENT_ACTION_SCROLL ||
|
||||||
|
mask == AMOTION_EVENT_ACTION_MOVE ||
|
||||||
|
mask == AMOTION_EVENT_ACTION_HOVER_MOVE ))
|
||||||
|
return JNI_FALSE;
|
||||||
|
|
||||||
|
prev_state = InterlockedExchange( &button_state, state );
|
||||||
|
|
||||||
|
data.type = MOTION_EVENT;
|
||||||
|
data.motion.hwnd = LongToHandle( win );
|
||||||
|
data.motion.input.type = INPUT_MOUSE;
|
||||||
|
data.motion.input.u.mi.dx = x;
|
||||||
|
data.motion.input.u.mi.dy = y;
|
||||||
|
data.motion.input.u.mi.mouseData = 0;
|
||||||
|
data.motion.input.u.mi.time = 0;
|
||||||
|
data.motion.input.u.mi.dwExtraInfo = 0;
|
||||||
|
data.motion.input.u.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
|
||||||
|
switch (action & AMOTION_EVENT_ACTION_MASK)
|
||||||
|
{
|
||||||
|
case AMOTION_EVENT_ACTION_DOWN:
|
||||||
|
if ((state & ~prev_state) & AMOTION_EVENT_BUTTON_PRIMARY)
|
||||||
|
data.motion.input.u.mi.dwFlags |= MOUSEEVENTF_LEFTDOWN;
|
||||||
|
if ((state & ~prev_state) & AMOTION_EVENT_BUTTON_SECONDARY)
|
||||||
|
data.motion.input.u.mi.dwFlags |= MOUSEEVENTF_RIGHTDOWN;
|
||||||
|
if ((state & ~prev_state) & AMOTION_EVENT_BUTTON_TERTIARY)
|
||||||
|
data.motion.input.u.mi.dwFlags |= MOUSEEVENTF_MIDDLEDOWN;
|
||||||
|
if (!(state & ~prev_state)) /* touch event */
|
||||||
|
data.motion.input.u.mi.dwFlags |= MOUSEEVENTF_LEFTDOWN;
|
||||||
|
break;
|
||||||
|
case AMOTION_EVENT_ACTION_UP:
|
||||||
|
if ((prev_state & ~state) & AMOTION_EVENT_BUTTON_PRIMARY)
|
||||||
|
data.motion.input.u.mi.dwFlags |= MOUSEEVENTF_LEFTUP;
|
||||||
|
if ((prev_state & ~state) & AMOTION_EVENT_BUTTON_SECONDARY)
|
||||||
|
data.motion.input.u.mi.dwFlags |= MOUSEEVENTF_RIGHTUP;
|
||||||
|
if ((prev_state & ~state) & AMOTION_EVENT_BUTTON_TERTIARY)
|
||||||
|
data.motion.input.u.mi.dwFlags |= MOUSEEVENTF_MIDDLEUP;
|
||||||
|
if (!(prev_state & ~state)) /* touch event */
|
||||||
|
data.motion.input.u.mi.dwFlags |= MOUSEEVENTF_LEFTUP;
|
||||||
|
break;
|
||||||
|
case AMOTION_EVENT_ACTION_SCROLL:
|
||||||
|
data.motion.input.u.mi.dwFlags |= MOUSEEVENTF_WHEEL;
|
||||||
|
data.motion.input.u.mi.mouseData = vscroll < 0 ? -WHEEL_DELTA : WHEEL_DELTA;
|
||||||
|
break;
|
||||||
|
case AMOTION_EVENT_ACTION_MOVE:
|
||||||
|
case AMOTION_EVENT_ACTION_HOVER_MOVE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
send_event( &data );
|
||||||
|
return JNI_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* init_event_queue
|
* init_event_queue
|
||||||
*/
|
*/
|
||||||
@ -328,6 +396,15 @@ static int process_events( DWORD mask )
|
|||||||
{
|
{
|
||||||
case SURFACE_CHANGED:
|
case SURFACE_CHANGED:
|
||||||
break; /* always process it to unblock other threads */
|
break; /* always process it to unblock other threads */
|
||||||
|
case MOTION_EVENT:
|
||||||
|
if (event->data.motion.input.u.mi.dwFlags & (MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_RIGHTDOWN|
|
||||||
|
MOUSEEVENTF_MIDDLEDOWN|MOUSEEVENTF_LEFTUP|
|
||||||
|
MOUSEEVENTF_RIGHTUP|MOUSEEVENTF_MIDDLEUP))
|
||||||
|
{
|
||||||
|
if (mask & QS_MOUSEBUTTON) break;
|
||||||
|
}
|
||||||
|
else if (mask & QS_MOUSEMOVE) break;
|
||||||
|
continue; /* skip it */
|
||||||
default:
|
default:
|
||||||
if (mask & QS_SENDMESSAGE) break;
|
if (mask & QS_SENDMESSAGE) break;
|
||||||
continue; /* skip it */
|
continue; /* skip it */
|
||||||
@ -355,6 +432,44 @@ static int process_events( DWORD mask )
|
|||||||
register_native_window( event->data.surface.hwnd, event->data.surface.window );
|
register_native_window( event->data.surface.hwnd, event->data.surface.window );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MOTION_EVENT:
|
||||||
|
{
|
||||||
|
HWND capture = get_capture_window();
|
||||||
|
|
||||||
|
if (event->data.motion.input.u.mi.dwFlags & (MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_RIGHTDOWN|MOUSEEVENTF_MIDDLEDOWN))
|
||||||
|
TRACE( "BUTTONDOWN pos %d,%d hwnd %p flags %x\n",
|
||||||
|
event->data.motion.input.u.mi.dx, event->data.motion.input.u.mi.dy,
|
||||||
|
event->data.motion.hwnd, event->data.motion.input.u.mi.dwFlags );
|
||||||
|
else if (event->data.motion.input.u.mi.dwFlags & (MOUSEEVENTF_LEFTUP|MOUSEEVENTF_RIGHTUP|MOUSEEVENTF_MIDDLEUP))
|
||||||
|
TRACE( "BUTTONUP pos %d,%d hwnd %p flags %x\n",
|
||||||
|
event->data.motion.input.u.mi.dx, event->data.motion.input.u.mi.dy,
|
||||||
|
event->data.motion.hwnd, event->data.motion.input.u.mi.dwFlags );
|
||||||
|
else
|
||||||
|
TRACE( "MOUSEMOVE pos %d,%d hwnd %p flags %x\n",
|
||||||
|
event->data.motion.input.u.mi.dx, event->data.motion.input.u.mi.dy,
|
||||||
|
event->data.motion.hwnd, event->data.motion.input.u.mi.dwFlags );
|
||||||
|
if (!capture && (event->data.motion.input.u.mi.dwFlags & MOUSEEVENTF_ABSOLUTE))
|
||||||
|
{
|
||||||
|
RECT rect;
|
||||||
|
SetRect( &rect, event->data.motion.input.u.mi.dx, event->data.motion.input.u.mi.dy,
|
||||||
|
event->data.motion.input.u.mi.dx + 1, event->data.motion.input.u.mi.dy + 1 );
|
||||||
|
MapWindowPoints( 0, event->data.motion.hwnd, (POINT *)&rect, 2 );
|
||||||
|
|
||||||
|
SERVER_START_REQ( update_window_zorder )
|
||||||
|
{
|
||||||
|
req->window = wine_server_user_handle( event->data.motion.hwnd );
|
||||||
|
req->rect.left = rect.left;
|
||||||
|
req->rect.top = rect.top;
|
||||||
|
req->rect.right = rect.right;
|
||||||
|
req->rect.bottom = rect.bottom;
|
||||||
|
wine_server_call( req );
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
}
|
||||||
|
__wine_send_input( capture ? capture : event->data.motion.hwnd, &event->data.motion.input );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
FIXME( "got event %u\n", event->data.type );
|
FIXME( "got event %u\n", event->data.type );
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user