wineandroid: Support for setting the cursor on Android >= N.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
2b8d787b17
commit
61888e0012
|
@ -25,6 +25,7 @@
|
|||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.os.Build;
|
||||
|
@ -34,6 +35,7 @@
|
|||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.PointerIcon;
|
||||
import android.view.Surface;
|
||||
import android.view.TextureView;
|
||||
import android.view.View;
|
||||
|
@ -64,6 +66,7 @@ public class WineActivity extends Activity
|
|||
|
||||
protected WineWindow desktop_window;
|
||||
protected WineWindow message_window;
|
||||
private PointerIcon current_cursor;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
|
@ -684,6 +687,12 @@ public void onSurfaceTextureUpdated(SurfaceTexture surftex)
|
|||
{
|
||||
}
|
||||
|
||||
@TargetApi(24)
|
||||
public PointerIcon onResolvePointerIcon( MotionEvent event, int index )
|
||||
{
|
||||
return current_cursor;
|
||||
}
|
||||
|
||||
public boolean onGenericMotionEvent( MotionEvent event )
|
||||
{
|
||||
if (is_client) return false; // let the whole window handle it
|
||||
|
@ -799,6 +808,18 @@ public void set_window_parent( int hwnd, int parent, float scale, int pid )
|
|||
if (win.parent == desktop_window) win.create_whole_view();
|
||||
}
|
||||
|
||||
@TargetApi(24)
|
||||
public void set_cursor( int id, int width, int height, int hotspotx, int hotspoty, int bits[] )
|
||||
{
|
||||
Log.i( LOGTAG, String.format( "set_cursor id %d size %dx%d hotspot %dx%d", id, width, height, hotspotx, hotspoty ));
|
||||
if (bits != null)
|
||||
{
|
||||
Bitmap bitmap = Bitmap.createBitmap( bits, width, height, Bitmap.Config.ARGB_8888 );
|
||||
current_cursor = PointerIcon.create( bitmap, hotspotx, hotspoty );
|
||||
}
|
||||
else current_cursor = PointerIcon.getSystemIcon( this, id );
|
||||
}
|
||||
|
||||
public void window_pos_changed( int hwnd, int flags, int insert_after, int owner, int style,
|
||||
Rect window_rect, Rect client_rect, Rect visible_rect )
|
||||
{
|
||||
|
@ -827,6 +848,13 @@ public void setParent( final int hwnd, final int parent, final float scale, fina
|
|||
runOnUiThread( new Runnable() { public void run() { set_window_parent( hwnd, parent, scale, pid ); }} );
|
||||
}
|
||||
|
||||
public void setCursor( final int id, final int width, final int height,
|
||||
final int hotspotx, final int hotspoty, final int bits[] )
|
||||
{
|
||||
if (Build.VERSION.SDK_INT < 24) return;
|
||||
runOnUiThread( new Runnable() { public void run() { set_cursor( id, width, height, hotspotx, hotspoty, bits ); }} );
|
||||
}
|
||||
|
||||
public void windowPosChanged( final int hwnd, final int flags, final int insert_after,
|
||||
final int owner, final int style,
|
||||
final int window_left, final int window_top,
|
||||
|
|
|
@ -72,6 +72,8 @@ extern int ioctl_window_pos_changed( HWND hwnd, const RECT *window_rect, const R
|
|||
HWND after, HWND owner ) DECLSPEC_HIDDEN;
|
||||
extern int ioctl_set_window_parent( HWND hwnd, HWND parent, float scale ) DECLSPEC_HIDDEN;
|
||||
extern int ioctl_set_capture( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern int ioctl_set_cursor( int id, int width, int height,
|
||||
int hotspotx, int hotspoty, const unsigned int *bits ) DECLSPEC_HIDDEN;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -151,7 +153,7 @@ union event_data
|
|||
} kbd;
|
||||
};
|
||||
|
||||
int send_event( const union event_data *data );
|
||||
int send_event( const union event_data *data ) DECLSPEC_HIDDEN;
|
||||
|
||||
extern JavaVM *wine_get_java_vm(void);
|
||||
extern jobject wine_get_java_object(void);
|
||||
|
|
|
@ -58,7 +58,7 @@ tasks.whenTaskAdded { t ->
|
|||
|
||||
android
|
||||
{
|
||||
compileSdkVersion 21
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.3"
|
||||
|
||||
defaultConfig
|
||||
|
|
|
@ -70,6 +70,7 @@ enum android_ioctl
|
|||
IOCTL_PERFORM,
|
||||
IOCTL_SET_SWAP_INT,
|
||||
IOCTL_SET_CAPTURE,
|
||||
IOCTL_SET_CURSOR,
|
||||
NB_IOCTLS
|
||||
};
|
||||
|
||||
|
@ -212,6 +213,17 @@ struct ioctl_android_set_capture
|
|||
struct ioctl_header hdr;
|
||||
};
|
||||
|
||||
struct ioctl_android_set_cursor
|
||||
{
|
||||
struct ioctl_header hdr;
|
||||
int id;
|
||||
int width;
|
||||
int height;
|
||||
int hotspotx;
|
||||
int hotspoty;
|
||||
int bits[1];
|
||||
};
|
||||
|
||||
static struct gralloc_module_t *gralloc_module;
|
||||
static struct gralloc1_device *gralloc1_device;
|
||||
static BOOL gralloc1_caps[GRALLOC1_LAST_CAPABILITY + 1];
|
||||
|
@ -1041,6 +1053,44 @@ static NTSTATUS setCapture_ioctl( void *data, DWORD in_size, DWORD out_size, ULO
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS setCursor_ioctl( void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size )
|
||||
{
|
||||
static jmethodID method;
|
||||
jobject object;
|
||||
int size;
|
||||
struct ioctl_android_set_cursor *res = data;
|
||||
|
||||
if (in_size < offsetof( struct ioctl_android_set_cursor, bits )) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (res->width < 0 || res->height < 0 || res->width > 256 || res->height > 256)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
size = res->width * res->height;
|
||||
if (in_size != offsetof( struct ioctl_android_set_cursor, bits[size] ))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
TRACE( "hwnd %08x size %d\n", res->hdr.hwnd, size );
|
||||
|
||||
if (!(object = load_java_method( &method, "setCursor", "(IIIII[I)V" )))
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
|
||||
wrap_java_call();
|
||||
|
||||
if (size)
|
||||
{
|
||||
jintArray array = (*jni_env)->NewIntArray( jni_env, size );
|
||||
(*jni_env)->SetIntArrayRegion( jni_env, array, 0, size, (jint *)res->bits );
|
||||
(*jni_env)->CallVoidMethod( jni_env, object, method, 0, res->width, res->height,
|
||||
res->hotspotx, res->hotspoty, array );
|
||||
(*jni_env)->DeleteLocalRef( jni_env, array );
|
||||
}
|
||||
else (*jni_env)->CallVoidMethod( jni_env, object, method, res->id, 0, 0, 0, 0, 0 );
|
||||
|
||||
unwrap_java_call();
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
typedef NTSTATUS (*ioctl_func)( void *in, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size );
|
||||
static const ioctl_func ioctl_funcs[] =
|
||||
{
|
||||
|
@ -1055,6 +1105,7 @@ static const ioctl_func ioctl_funcs[] =
|
|||
perform_ioctl, /* IOCTL_PERFORM */
|
||||
setSwapInterval_ioctl, /* IOCTL_SET_SWAP_INT */
|
||||
setCapture_ioctl, /* IOCTL_SET_CAPTURE */
|
||||
setCursor_ioctl, /* IOCTL_SET_CURSOR */
|
||||
};
|
||||
|
||||
static NTSTATUS WINAPI ioctl_callback( DEVICE_OBJECT *device, IRP *irp )
|
||||
|
@ -1584,3 +1635,24 @@ int ioctl_set_capture( HWND hwnd )
|
|||
req.hdr.opengl = FALSE;
|
||||
return android_ioctl( IOCTL_SET_CAPTURE, &req, sizeof(req), NULL, NULL );
|
||||
}
|
||||
|
||||
int ioctl_set_cursor( int id, int width, int height,
|
||||
int hotspotx, int hotspoty, const unsigned int *bits )
|
||||
{
|
||||
struct ioctl_android_set_cursor *req;
|
||||
unsigned int size = offsetof( struct ioctl_android_set_cursor, bits[width * height] );
|
||||
int ret;
|
||||
|
||||
if (!(req = HeapAlloc( GetProcessHeap(), 0, size ))) return -ENOMEM;
|
||||
req->hdr.hwnd = 0; /* unused */
|
||||
req->hdr.opengl = FALSE;
|
||||
req->id = id;
|
||||
req->width = width;
|
||||
req->height = height;
|
||||
req->hotspotx = hotspotx;
|
||||
req->hotspoty = hotspoty;
|
||||
memcpy( req->bits, bits, width * height * sizeof(req->bits[0]) );
|
||||
ret = android_ioctl( IOCTL_SET_CURSOR, req, size, NULL, NULL );
|
||||
HeapFree( GetProcessHeap(), 0, req );
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define OEMRESOURCE
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wingdi.h"
|
||||
|
@ -966,6 +967,226 @@ static void set_surface_layered( struct window_surface *window_surface, BYTE alp
|
|||
window_surface->funcs->unlock( window_surface );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* get_mono_icon_argb
|
||||
*
|
||||
* Return a monochrome icon/cursor bitmap bits in ARGB format.
|
||||
*/
|
||||
static unsigned int *get_mono_icon_argb( HDC hdc, HBITMAP bmp, unsigned int *width, unsigned int *height )
|
||||
{
|
||||
BITMAP bm;
|
||||
char *mask;
|
||||
unsigned int i, j, stride, mask_size, bits_size, *bits = NULL, *ptr;
|
||||
|
||||
if (!GetObjectW( bmp, sizeof(bm), &bm )) return NULL;
|
||||
stride = ((bm.bmWidth + 15) >> 3) & ~1;
|
||||
mask_size = stride * bm.bmHeight;
|
||||
if (!(mask = HeapAlloc( GetProcessHeap(), 0, mask_size ))) return NULL;
|
||||
if (!GetBitmapBits( bmp, mask_size, mask )) goto done;
|
||||
|
||||
bm.bmHeight /= 2;
|
||||
bits_size = bm.bmWidth * bm.bmHeight * sizeof(*bits);
|
||||
if (!(bits = HeapAlloc( GetProcessHeap(), 0, bits_size ))) goto done;
|
||||
|
||||
ptr = bits;
|
||||
for (i = 0; i < bm.bmHeight; i++)
|
||||
for (j = 0; j < bm.bmWidth; j++, ptr++)
|
||||
{
|
||||
int and = ((mask[i * stride + j / 8] << (j % 8)) & 0x80);
|
||||
int xor = ((mask[(i + bm.bmHeight) * stride + j / 8] << (j % 8)) & 0x80);
|
||||
if (!xor && and)
|
||||
*ptr = 0;
|
||||
else if (xor && !and)
|
||||
*ptr = 0xffffffff;
|
||||
else
|
||||
/* we can't draw "invert" pixels, so render them as black instead */
|
||||
*ptr = 0xff000000;
|
||||
}
|
||||
|
||||
*width = bm.bmWidth;
|
||||
*height = bm.bmHeight;
|
||||
|
||||
done:
|
||||
HeapFree( GetProcessHeap(), 0, mask );
|
||||
return bits;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* get_bitmap_argb
|
||||
*
|
||||
* Return the bitmap bits in ARGB format. Helper for setting icons and cursors.
|
||||
*/
|
||||
static unsigned int *get_bitmap_argb( HDC hdc, HBITMAP color, HBITMAP mask, unsigned int *width,
|
||||
unsigned int *height )
|
||||
{
|
||||
char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
|
||||
BITMAPINFO *info = (BITMAPINFO *)buffer;
|
||||
BITMAP bm;
|
||||
unsigned int *ptr, *bits = NULL;
|
||||
unsigned char *mask_bits = NULL;
|
||||
int i, j;
|
||||
BOOL has_alpha = FALSE;
|
||||
|
||||
if (!color) return get_mono_icon_argb( hdc, mask, width, height );
|
||||
|
||||
if (!GetObjectW( color, sizeof(bm), &bm )) return NULL;
|
||||
info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
info->bmiHeader.biWidth = bm.bmWidth;
|
||||
info->bmiHeader.biHeight = -bm.bmHeight;
|
||||
info->bmiHeader.biPlanes = 1;
|
||||
info->bmiHeader.biBitCount = 32;
|
||||
info->bmiHeader.biCompression = BI_RGB;
|
||||
info->bmiHeader.biSizeImage = bm.bmWidth * bm.bmHeight * 4;
|
||||
info->bmiHeader.biXPelsPerMeter = 0;
|
||||
info->bmiHeader.biYPelsPerMeter = 0;
|
||||
info->bmiHeader.biClrUsed = 0;
|
||||
info->bmiHeader.biClrImportant = 0;
|
||||
if (!(bits = HeapAlloc( GetProcessHeap(), 0, bm.bmWidth * bm.bmHeight * sizeof(unsigned int) )))
|
||||
goto failed;
|
||||
if (!GetDIBits( hdc, color, 0, bm.bmHeight, bits, info, DIB_RGB_COLORS )) goto failed;
|
||||
|
||||
*width = bm.bmWidth;
|
||||
*height = bm.bmHeight;
|
||||
|
||||
for (i = 0; i < bm.bmWidth * bm.bmHeight; i++)
|
||||
if ((has_alpha = (bits[i] & 0xff000000) != 0)) break;
|
||||
|
||||
if (!has_alpha)
|
||||
{
|
||||
unsigned int width_bytes = (bm.bmWidth + 31) / 32 * 4;
|
||||
/* generate alpha channel from the mask */
|
||||
info->bmiHeader.biBitCount = 1;
|
||||
info->bmiHeader.biSizeImage = width_bytes * bm.bmHeight;
|
||||
if (!(mask_bits = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage ))) goto failed;
|
||||
if (!GetDIBits( hdc, mask, 0, bm.bmHeight, mask_bits, info, DIB_RGB_COLORS )) goto failed;
|
||||
ptr = bits;
|
||||
for (i = 0; i < bm.bmHeight; i++)
|
||||
for (j = 0; j < bm.bmWidth; j++, ptr++)
|
||||
if (!((mask_bits[i * width_bytes + j / 8] << (j % 8)) & 0x80)) *ptr |= 0xff000000;
|
||||
HeapFree( GetProcessHeap(), 0, mask_bits );
|
||||
}
|
||||
|
||||
return bits;
|
||||
|
||||
failed:
|
||||
HeapFree( GetProcessHeap(), 0, bits );
|
||||
HeapFree( GetProcessHeap(), 0, mask_bits );
|
||||
*width = *height = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
enum android_system_cursors
|
||||
{
|
||||
TYPE_ARROW = 1000,
|
||||
TYPE_CONTEXT_MENU = 1001,
|
||||
TYPE_HAND = 1002,
|
||||
TYPE_HELP = 1003,
|
||||
TYPE_WAIT = 1004,
|
||||
TYPE_CELL = 1006,
|
||||
TYPE_CROSSHAIR = 1007,
|
||||
TYPE_TEXT = 1008,
|
||||
TYPE_VERTICAL_TEXT = 1009,
|
||||
TYPE_ALIAS = 1010,
|
||||
TYPE_COPY = 1011,
|
||||
TYPE_NO_DROP = 1012,
|
||||
TYPE_ALL_SCROLL = 1013,
|
||||
TYPE_HORIZONTAL_DOUBLE_ARROW = 1014,
|
||||
TYPE_VERTICAL_DOUBLE_ARROW = 1015,
|
||||
TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW = 1016,
|
||||
TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW = 1017,
|
||||
TYPE_ZOOM_IN = 1018,
|
||||
TYPE_ZOOM_OUT = 1019,
|
||||
TYPE_GRAB = 1020,
|
||||
TYPE_GRABBING = 1021,
|
||||
};
|
||||
|
||||
struct system_cursors
|
||||
{
|
||||
WORD id;
|
||||
enum android_system_cursors android_id;
|
||||
};
|
||||
|
||||
static const struct system_cursors user32_cursors[] =
|
||||
{
|
||||
{ OCR_NORMAL, TYPE_ARROW },
|
||||
{ OCR_IBEAM, TYPE_TEXT },
|
||||
{ OCR_WAIT, TYPE_WAIT },
|
||||
{ OCR_CROSS, TYPE_CROSSHAIR },
|
||||
{ OCR_SIZE, TYPE_ALL_SCROLL },
|
||||
{ OCR_SIZEALL, TYPE_ALL_SCROLL },
|
||||
{ OCR_SIZENWSE, TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW },
|
||||
{ OCR_SIZENESW, TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW },
|
||||
{ OCR_SIZEWE, TYPE_HORIZONTAL_DOUBLE_ARROW },
|
||||
{ OCR_SIZENS, TYPE_VERTICAL_DOUBLE_ARROW },
|
||||
{ OCR_NO, TYPE_NO_DROP },
|
||||
{ OCR_HAND, TYPE_HAND },
|
||||
{ OCR_HELP, TYPE_HELP },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct system_cursors comctl32_cursors[] =
|
||||
{
|
||||
/* 102 TYPE_MOVE doesn't exist */
|
||||
{ 104, TYPE_COPY },
|
||||
{ 105, TYPE_ARROW },
|
||||
{ 106, TYPE_HORIZONTAL_DOUBLE_ARROW },
|
||||
{ 107, TYPE_HORIZONTAL_DOUBLE_ARROW },
|
||||
{ 108, TYPE_GRABBING },
|
||||
{ 135, TYPE_VERTICAL_DOUBLE_ARROW },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct system_cursors ole32_cursors[] =
|
||||
{
|
||||
{ 1, TYPE_NO_DROP },
|
||||
/* 2 TYPE_MOVE doesn't exist */
|
||||
{ 3, TYPE_COPY },
|
||||
{ 4, TYPE_ALIAS },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct system_cursors riched20_cursors[] =
|
||||
{
|
||||
{ 105, TYPE_GRABBING },
|
||||
{ 109, TYPE_COPY },
|
||||
/* 110 TYPE_MOVE doesn't exist */
|
||||
{ 111, TYPE_NO_DROP },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct
|
||||
{
|
||||
const struct system_cursors *cursors;
|
||||
WCHAR name[16];
|
||||
} module_cursors[] =
|
||||
{
|
||||
{ user32_cursors, {'u','s','e','r','3','2','.','d','l','l',0} },
|
||||
{ comctl32_cursors, {'c','o','m','c','t','l','3','2','.','d','l','l',0} },
|
||||
{ ole32_cursors, {'o','l','e','3','2','.','d','l','l',0} },
|
||||
{ riched20_cursors, {'r','i','c','h','e','d','2','0','.','d','l','l',0} }
|
||||
};
|
||||
|
||||
static int get_cursor_system_id( const ICONINFOEXW *info )
|
||||
{
|
||||
const struct system_cursors *cursors;
|
||||
unsigned int i;
|
||||
HMODULE module;
|
||||
|
||||
if (info->szResName[0]) return 0; /* only integer resources are supported here */
|
||||
if (!(module = GetModuleHandleW( info->szModName ))) return 0;
|
||||
|
||||
for (i = 0; i < sizeof(module_cursors)/sizeof(module_cursors[0]); i++)
|
||||
if (GetModuleHandleW( module_cursors[i].name ) == module) break;
|
||||
if (i == sizeof(module_cursors)/sizeof(module_cursors[0])) return 0;
|
||||
|
||||
cursors = module_cursors[i].cursors;
|
||||
for (i = 0; cursors[i].id; i++)
|
||||
if (cursors[i].id == info->wResID) return cursors[i].android_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static WNDPROC desktop_orig_wndproc;
|
||||
|
||||
|
@ -1204,6 +1425,51 @@ void CDECL ANDROID_SetCapture( HWND hwnd, UINT flags )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* ANDROID_SetCursor
|
||||
*/
|
||||
void CDECL ANDROID_SetCursor( HCURSOR handle )
|
||||
{
|
||||
static HCURSOR last_cursor;
|
||||
static DWORD last_cursor_change;
|
||||
|
||||
if (InterlockedExchangePointer( (void **)&last_cursor, handle ) != handle ||
|
||||
GetTickCount() - last_cursor_change > 100)
|
||||
{
|
||||
last_cursor_change = GetTickCount();
|
||||
|
||||
if (handle)
|
||||
{
|
||||
unsigned int width = 0, height = 0, *bits = NULL;
|
||||
ICONINFOEXW info;
|
||||
int id;
|
||||
|
||||
info.cbSize = sizeof(info);
|
||||
if (!GetIconInfoExW( handle, &info )) return;
|
||||
|
||||
if (!(id = get_cursor_system_id( &info )))
|
||||
{
|
||||
HDC hdc = CreateCompatibleDC( 0 );
|
||||
bits = get_bitmap_argb( hdc, info.hbmColor, info.hbmMask, &width, &height );
|
||||
DeleteDC( hdc );
|
||||
|
||||
/* make sure hotspot is valid */
|
||||
if (info.xHotspot >= width || info.yHotspot >= height)
|
||||
{
|
||||
info.xHotspot = width / 2;
|
||||
info.yHotspot = height / 2;
|
||||
}
|
||||
}
|
||||
ioctl_set_cursor( id, width, height, info.xHotspot, info.yHotspot, bits );
|
||||
HeapFree( GetProcessHeap(), 0, bits );
|
||||
DeleteObject( info.hbmColor );
|
||||
DeleteObject( info.hbmMask );
|
||||
}
|
||||
else ioctl_set_cursor( 0, 0, 0, 0, 0, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* ANDROID_SetWindowStyle
|
||||
*/
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
@ cdecl MapVirtualKeyEx(long long long) ANDROID_MapVirtualKeyEx
|
||||
@ cdecl ToUnicodeEx(long long ptr ptr long long long) ANDROID_ToUnicodeEx
|
||||
@ cdecl VkKeyScanEx(long long) ANDROID_VkKeyScanEx
|
||||
@ cdecl SetCursor(long) ANDROID_SetCursor
|
||||
@ cdecl ChangeDisplaySettingsEx(ptr ptr long long long) ANDROID_ChangeDisplaySettingsEx
|
||||
@ cdecl EnumDisplayMonitors(long ptr ptr long) ANDROID_EnumDisplayMonitors
|
||||
@ cdecl EnumDisplaySettingsEx(ptr long ptr long) ANDROID_EnumDisplaySettingsEx
|
||||
|
|
Loading…
Reference in New Issue