Skip to content

Commit

Permalink
added Mouse.moveAbs() as a new feature for absolute mouse positioning…
Browse files Browse the repository at this point in the history
… as requested in issue arduino#1417.

all parameters have the range of -32768 to 32767 and must be scaled to screen pixels
some examples:
  x=0, y=0 is the middle of the screen
  x=-32768, y=-32768 is the top left corner
  x=32767, y=-32768 is the top right corner
  x=32767, y=32767 is the bottom right corner
  x=-32768, y=32767 is the bottom left corner
  • Loading branch information
nospam2000 committed Jul 21, 2013
1 parent 674ab3b commit 7b77d1e
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 1 deletion.
57 changes: 56 additions & 1 deletion hardware/arduino/cores/arduino/HID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ Keyboard_ Keyboard;
#define HID_REPORTID_KEYBOARD (2)
#define HID_REPORTID_RAWHID (3)
#define HID_REPORTID_SYSTEMCONTROL (4)
#define HID_REPORTID_MOUSE_ABS (5)
extern const u8 _hidReportDescriptor[] PROGMEM;
const u8 _hidReportDescriptor[] = {

// Mouse
// Mouse relative
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
Expand Down Expand Up @@ -82,6 +83,38 @@ const u8 _hidReportDescriptor[] = {
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION

#ifdef MOUSE_ABS_ENABLED
// Mouse absolute
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x85, HID_REPORTID_MOUSE_ABS, // REPORT_ID (5)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x38, // USAGE (Wheel)
0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768)
0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
#endif

// Keyboard
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47
0x09, 0x06, // USAGE (Keyboard)
Expand Down Expand Up @@ -268,6 +301,28 @@ void Mouse_::move(signed char x, signed char y, signed char wheel)
HID_SendReport(HID_REPORTID_MOUSE,m,sizeof(m));
}

#ifdef MOUSE_ABS_ENABLED
// all parameters have the range of -32768 to 32767 and must be scaled to screen pixels
// some examples:
// x=0,y=0 is the middle of the screen
// x=-32768,y=-32768 is the top left corner
// x=32767,y=-32768 is the top right corner
// x=32767,y=32767 is the bottom right corner
// x=-32768,y=32767 is the bottom left corner
void Mouse_::moveAbs(int16_t x, int16_t y, int16_t wheel)
{
u8 m[7];
m[0] = _buttons; // TODO: is it a good idea to take over the _buttons from relative report here or should it be left out?
m[1] = LSB(x);
m[2] = MSB(x);
m[3] = LSB(y);
m[4] = MSB(y);
m[5] = LSB(wheel);
m[6] = MSB(wheel);
HID_SendReport(HID_REPORTID_MOUSE_ABS,m,sizeof(m));
}
#endif

void Mouse_::buttons(uint8_t b)
{
if (b != _buttons)
Expand Down
4 changes: 4 additions & 0 deletions hardware/arduino/cores/arduino/USBAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#define __USBAPI__

#if defined(USBCON)
#define MOUSE_ABS_ENABLED

//================================================================================
//================================================================================
Expand Down Expand Up @@ -65,6 +66,9 @@ class Mouse_
void end(void);
void click(uint8_t b = MOUSE_LEFT);
void move(signed char x, signed char y, signed char wheel = 0);
#ifdef MOUSE_ABS_ENABLED
void moveAbs(int16_t x, int16_t y, int16_t wheel); // all parameters have the range of -32768 to 32767 and must be scaled to screen pixels
#endif
void press(uint8_t b = MOUSE_LEFT); // press LEFT by default
void release(uint8_t b = MOUSE_LEFT); // release LEFT by default
bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default
Expand Down

2 comments on commit 7b77d1e

@jBachalo
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No matter what permutation I use using the native map method, can't quite get this to work.

@nospam2000
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was using the following sketch for testing a year ago (I don't have an Arduino Leonardo right now to test it):

include "Platform.h"

// all of the screen_res constants must be !=0 to avoid division by zero
const int16_t screen_res_x = 1920; // must match the screen x resolution
const int16_t screen_res_y = 1280; // must match the screen y resolution
const int16_t screen_res_wheel = 1000; // is scaled from -1000 to 1000

// when you use it on a Mac, set border to 15%

if 1

// for Windows use a border of 0%
const int32_t borderPercent = 0L;

else

// for Max OSX use a border of 15%
// this is for solving the Max OSX border issue
const int32_t borderPercent = 15L;

endif

const int32_t minVal = -32768L; // must match the value of Logical Minimum in the mouse absolute descriptor in HID.cpp
const int32_t maxVal = 32767L; // must match the value of Logical Maximum in the mouse absolute descriptor in HID.cpp
const int32_t borderVal = ((maxVal - minVal + 1) * borderPercent / 200L);
uint32_t g_prevTime;

void setup()
{
Serial.begin(9600);

// initialize control over the mouse:
Mouse.begin();

g_prevTime = millis();
delay(10000);
}

void loop()
{
u32 m = millis();
u32 tDiff = m - g_prevTime;
if(tDiff >= 10) // one step each 10 ms
{
g_prevTime = m;

static float pos;
pos += TWO_PI / 1000.0f;
if(pos > TWO_PI)
  pos = 0.0f;
uint16_t x_screen = ((sin(pos) + 1.0f) / 2.0f) * screen_res_x;
uint16_t y_screen = ((cos(pos) + 1.0f) / 2.0f) * screen_res_y;

moveMouseAbsScreen(x_screen, y_screen, 0);

}
}

// translate screen coordinates to absolute mouse coordinates and move the mouse to that position
void moveMouseAbsScreen(int16_t x_screen, int16_t y_screen, int16_t wheel_screen)
{
int16_t x = map(x_screen, 0, screen_res_x - 1, minVal + borderVal, maxVal - borderVal);
int16_t y = map(y_screen, 0, screen_res_y - 1, minVal + borderVal, maxVal - borderVal);
int16_t wheel = map(wheel_screen, -screen_res_wheel, screen_res_wheel, minVal, maxVal);
Mouse.moveAbs(x, y, wheel);
}

Please sign in to comment.