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.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
import android.view.TextureView;
|
||||
import android.view.View;
|
||||
|
@ -51,6 +53,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 );
|
||||
public native boolean wine_motion_event( int hwnd, int action, int x, int y, int state, int vscroll );
|
||||
|
||||
private final String LOGTAG = "wine";
|
||||
private ProgressDialog progress_dialog;
|
||||
|
@ -365,6 +368,12 @@ public void set_surface( SurfaceTexture surftex )
|
|||
Log.i( LOGTAG, String.format( "set window surface hwnd %08x %s", 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
|
||||
|
@ -411,6 +420,36 @@ public boolean onSurfaceTextureDestroyed( 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
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#include <android/input.h>
|
||||
#include <android/native_window_jni.h>
|
||||
|
||||
#include "windef.h"
|
||||
|
@ -84,11 +85,14 @@ 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;
|
||||
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
|
||||
{
|
||||
DESKTOP_CHANGED,
|
||||
SURFACE_CHANGED,
|
||||
MOTION_EVENT,
|
||||
};
|
||||
|
||||
union event_data
|
||||
|
@ -108,6 +112,12 @@ union event_data
|
|||
unsigned int width;
|
||||
unsigned int height;
|
||||
} surface;
|
||||
struct
|
||||
{
|
||||
enum event_type type;
|
||||
HWND hwnd;
|
||||
INPUT input;
|
||||
} motion;
|
||||
};
|
||||
|
||||
int send_event( const union event_data *data );
|
||||
|
|
|
@ -391,6 +391,7 @@ static const JNINativeMethod methods[] =
|
|||
{
|
||||
{ "wine_desktop_changed", "(II)V", desktop_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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
@ -328,6 +396,15 @@ static int process_events( DWORD mask )
|
|||
{
|
||||
case SURFACE_CHANGED:
|
||||
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:
|
||||
if (mask & QS_SENDMESSAGE) break;
|
||||
continue; /* skip it */
|
||||
|
@ -355,6 +432,44 @@ static int process_events( DWORD mask )
|
|||
register_native_window( event->data.surface.hwnd, event->data.surface.window );
|
||||
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:
|
||||
FIXME( "got event %u\n", event->data.type );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue