Skip to content

Commit

Permalink
Fix the high-precision mice on Windows never setting dz/dw to non-zer…
Browse files Browse the repository at this point in the history
…o values.

Also add API to allow the users to set the precision of the mouse wheel, so as
to be able to take advantage of those high precision mice if they choose to.
  • Loading branch information
SiegeLordEx authored and SiegeLord committed Feb 4, 2015
1 parent 11b12b4 commit 2f79ba3
Show file tree
Hide file tree
Showing 13 changed files with 136 additions and 23 deletions.
45 changes: 44 additions & 1 deletion docs/src/refman/mouse.txt
Expand Up @@ -141,6 +141,50 @@ Retrieve the mouse event source.
Returns NULL if the mouse subsystem was not installed.


## API: al_set_mouse_wheel_precision

Sets the precision of the mouse wheel (the z and w coordinates) for the
specified display. This precision manifests itself as a multiplier on the `dz`
and `dw` fields in mouse events. It also affects the `z` and `w` fields of
events and [ALLEGRO_MOUSE_STATE], but not in a simple way if you alter the
precision often, so it is suggested to reset those axes to 0 when you change
precision. Setting this to a high value allows you to detect small changes in
those two axes for some high precision mice. A flexible way of using this
precision is to set it to a high value (120 is likely sufficient for most, if
not all, mice) and use a floating point `dz` and `dw` like so:

~~~~c
al_set_mouse_wheel_precision(display, 120);

ALLEGRO_EVENT event;
al_wait_for_event(event_queue, &event);
if (event.type == ALLEGRO_EVENT_MOUSE_AXES) {
/* This is a real mouse event. */
if (event.mouse.display) {
double dz =
(double)event.mouse.dz / al_get_mouse_wheel_precision(event.mouse.display);
/* Use dz in some way... */
}
}
~~~~

Precision is set to 1 by default. It is impossible to set it to a lower
precision than that.

Since: 5.1.10

See also: [al_get_mouse_wheel_precision]

## API: al_get_mouse_wheel_precision

Gets the precision of the mouse wheel (the z and w coordinates) inside the
specified display.

Since: 5.1.10

See also: [al_set_mouse_wheel_precision]


## Mouse cursors

### API: al_create_mouse_cursor
Expand Down Expand Up @@ -256,4 +300,3 @@ Stop confining the mouse cursor to any display belonging to the program.
> *Note:* not yet implemented on Mac OS X.

See also: [al_grab_mouse]

15 changes: 15 additions & 0 deletions examples/ex_mouse_events.c
Expand Up @@ -44,6 +44,7 @@ int main(int argc, char **argv)
int mmy = 0;
int mmz = 0;
int mmw = 0;
int precision = 1;
bool in = true;
bool buttons[NUM_BUTTONS] = {false};
int i;
Expand Down Expand Up @@ -105,6 +106,7 @@ int main(int argc, char **argv)
al_draw_textf(font, black, 5, 25, 0, "x %i, y %i, z %i, w %i", mx, my, mz, mw);
al_draw_textf(font, black, 5, 45, 0, "p = %g", p);
al_draw_textf(font, black, 5, 65, 0, "%s", in ? "in" : "out");
al_draw_textf(font, black, 5, 85, 0, "wheel precision (PgUp/PgDn) %d", precision);
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
mmx = mmy = mmz = 0;
al_flip_display();
Expand Down Expand Up @@ -152,6 +154,19 @@ int main(int argc, char **argv)
}
break;

case ALLEGRO_EVENT_KEY_CHAR:
if (event.keyboard.keycode == ALLEGRO_KEY_PGUP) {
precision++;
al_set_mouse_wheel_precision(display, precision);
}
else if (event.keyboard.keycode == ALLEGRO_KEY_PGDN) {
precision--;
if (precision < 1)
precision = 1;
al_set_mouse_wheel_precision(display, precision);
}
break;

case ALLEGRO_EVENT_DISPLAY_RESIZE:
al_acknowledge_resize(event.display.source);
break;
Expand Down
2 changes: 2 additions & 0 deletions include/allegro5/internal/aintern_display.h
Expand Up @@ -122,6 +122,8 @@ struct ALLEGRO_DISPLAY
int w, h;
int min_w, min_h;
int max_w, max_h;

int mouse_wheel_precision;

int backbuffer_format; /* ALLEGRO_PIXELFORMAT */

Expand Down
2 changes: 2 additions & 0 deletions include/allegro5/mouse.h
Expand Up @@ -68,6 +68,8 @@ AL_FUNC(int, al_get_mouse_state_axis, (const ALLEGRO_MOUSE_STATE *sta
AL_FUNC(bool, al_get_mouse_cursor_position, (int *ret_x, int *ret_y));
AL_FUNC(bool, al_grab_mouse, (struct ALLEGRO_DISPLAY *display));
AL_FUNC(bool, al_ungrab_mouse, (void));
AL_FUNC(void, al_set_mouse_wheel_precision, (struct ALLEGRO_DISPLAY *display, int precision));
AL_FUNC(int, al_get_mouse_wheel_precision, (struct ALLEGRO_DISPLAY *display));

AL_FUNC(ALLEGRO_EVENT_SOURCE *, al_get_mouse_event_source, (void));

Expand Down
4 changes: 2 additions & 2 deletions include/allegro5/platform/aintwin.h
Expand Up @@ -116,8 +116,8 @@ void _al_win_fix_modifiers(void);

/* mouse routines */
void _al_win_mouse_handle_move(int x, int y, bool abs, ALLEGRO_DISPLAY_WIN *win_disp);
void _al_win_mouse_handle_wheel(int d, bool abs, ALLEGRO_DISPLAY_WIN *win_disp);
void _al_win_mouse_handle_hwheel(int d, bool abs, ALLEGRO_DISPLAY_WIN *win_disp);
void _al_win_mouse_handle_wheel(int raw_dz, bool abs, ALLEGRO_DISPLAY_WIN *win_disp);
void _al_win_mouse_handle_hwheel(int raw_dw, bool abs, ALLEGRO_DISPLAY_WIN *win_disp);
void _al_win_mouse_handle_button(int button, bool down, int x, int y, bool abs, ALLEGRO_DISPLAY_WIN *win_disp);
void _al_win_mouse_handle_leave(ALLEGRO_DISPLAY_WIN *win_display);
void _al_win_mouse_handle_enter(ALLEGRO_DISPLAY_WIN *win_display);
Expand Down
2 changes: 2 additions & 0 deletions src/display.c
Expand Up @@ -65,6 +65,8 @@ ALLEGRO_DISPLAY *al_create_display(int w, int h)
settings->settings[ALLEGRO_AUTO_CONVERT_BITMAPS] = 1;
}

display->mouse_wheel_precision = 1;

display->min_w = 0;
display->min_h = 0;
display->max_w = 0;
Expand Down
9 changes: 9 additions & 0 deletions src/linux/lmseev.c
Expand Up @@ -480,6 +480,7 @@ static void process_abs(const struct input_event *event)
static void handle_axis_event(int dx, int dy, int dz)
{
if (current_tool != no_tool) {
ALLEGRO_SYSTEM *s = al_get_system_driver();
x_axis.out_abs = _ALLEGRO_CLAMP(x_axis.out_min, x_axis.out_abs, x_axis.out_max);
y_axis.out_abs = _ALLEGRO_CLAMP(y_axis.out_min, y_axis.out_abs, y_axis.out_max);
/* There's no range for z */
Expand All @@ -488,6 +489,14 @@ static void handle_axis_event(int dx, int dy, int dz)
the_mouse.state.y = y_axis.out_abs;
the_mouse.state.z = z_axis.out_abs;

if (s && s->displays._size > 0) {
ALLEGRO_DISPLAY *d = _al_vector_ref(&s->displays, 0);
if (d) {
dz *= d->mouse_wheel_precision;
the_mouse.state.z *= d->mouse_wheel_precision;
}
}

generate_mouse_event(
ALLEGRO_EVENT_MOUSE_AXES,
the_mouse.state.x, the_mouse.state.y, the_mouse.state.z,
Expand Down
4 changes: 2 additions & 2 deletions src/macosx/qzmouse.m
Expand Up @@ -131,8 +131,8 @@ void _al_osx_mouse_generate_event(NSEvent* evt, ALLEGRO_DISPLAY* dpy)
type = ALLEGRO_EVENT_MOUSE_AXES;
dx = 0;
dy = 0;
osx_mouse.w_axis += [evt deltaX];
osx_mouse.z_axis += [evt deltaY];
osx_mouse.w_axis += dpy->mouse_wheel_precision * [evt deltaX];
osx_mouse.z_axis += dpy->mouse_wheel_precision * [evt deltaY];
dw = osx_mouse.w_axis - osx_mouse.state.w;
dz = osx_mouse.z_axis - osx_mouse.state.z;
break;
Expand Down
21 changes: 21 additions & 0 deletions src/mousenu.c
Expand Up @@ -310,4 +310,25 @@ ALLEGRO_EVENT_SOURCE *al_get_mouse_event_source(void)
}



/* Function: al_set_mouse_wheel_precision
*/
void al_set_mouse_wheel_precision(ALLEGRO_DISPLAY *display, int precision)
{
ASSERT(display);
if (precision < 1)
precision = 1;
display->mouse_wheel_precision = precision;
}



/* Function: al_get_mouse_wheel_precision
*/
int al_get_mouse_wheel_precision(ALLEGRO_DISPLAY *display)
{
ASSERT(display);
return display->mouse_wheel_precision;
}

/* vim: set sts=3 sw=3 et: */
10 changes: 5 additions & 5 deletions src/sdl/sdl_mouse.c
Expand Up @@ -54,13 +54,13 @@ void _al_sdl_mouse_event(SDL_Event *e)
}
else if (e->type == SDL_MOUSEWHEEL) {
event.mouse.type = ALLEGRO_EVENT_MOUSE_AXES;
mouse->z += e->wheel.y;
mouse->w += e->wheel.x;
d = _al_sdl_find_display(e->wheel.windowID);
mouse->z += d->mouse_wheel_precision * e->wheel.y;
mouse->w += d->mouse_wheel_precision * e->wheel.x;
event.mouse.z = mouse->z;
event.mouse.w = mouse->w;
event.mouse.dz = e->wheel.y;
event.mouse.dw = e->wheel.x;
d = _al_sdl_find_display(e->wheel.windowID);
event.mouse.dz = d->mouse_wheel_precision * e->wheel.y;
event.mouse.dw = d->mouse_wheel_precision * e->wheel.x;
}
else {
switch (e->button.button) {
Expand Down
36 changes: 26 additions & 10 deletions src/win/wmouse.c
Expand Up @@ -43,6 +43,10 @@ static ALLEGRO_MOUSE_STATE mouse_state;
static ALLEGRO_MOUSE the_mouse;
static bool installed = false;

// The floating point versions of z/w in the mouse_state
static double float_mouse_z = 0.0;
static double float_mouse_w = 0.0;


static bool init_mouse(void)
{
Expand Down Expand Up @@ -185,6 +189,8 @@ static bool set_mouse_axis(int which, int val)
if (which == 2) {
int dz = (val - mouse_state.z);

float_mouse_z = val;

if (dz != 0) {
mouse_state.z = val;

Expand All @@ -202,6 +208,8 @@ static bool set_mouse_axis(int which, int val)
if (which == 3) {
int dw = (val - mouse_state.w);

float_mouse_w = val;

if (dw != 0) {
mouse_state.w = val;

Expand Down Expand Up @@ -322,21 +330,25 @@ void _al_win_mouse_handle_move(int x, int y, bool abs, ALLEGRO_DISPLAY_WIN *win_
}


void _al_win_mouse_handle_wheel(int z, bool abs, ALLEGRO_DISPLAY_WIN *win_disp)
void _al_win_mouse_handle_wheel(int raw_dz, bool abs, ALLEGRO_DISPLAY_WIN *win_disp)
{
ALLEGRO_DISPLAY *display = (ALLEGRO_DISPLAY *)win_disp;
int d;
int new_z;
double float_dz = display->mouse_wheel_precision * (double)raw_dz / WHEEL_DELTA;

if (!installed)
return;

if (!abs) {
mouse_state.z += z;
d = z;
float_mouse_z += float_dz;
}
else {
d = z - mouse_state.z;
mouse_state.z = z;
float_mouse_z = float_dz;
}
new_z = (int)float_mouse_z;
d = new_z - mouse_state.z;
mouse_state.z = new_z;

generate_mouse_event(ALLEGRO_EVENT_MOUSE_AXES,
mouse_state.x, mouse_state.y, mouse_state.z, mouse_state.w, mouse_state.pressure,
Expand All @@ -345,21 +357,25 @@ void _al_win_mouse_handle_wheel(int z, bool abs, ALLEGRO_DISPLAY_WIN *win_disp)
}


void _al_win_mouse_handle_hwheel(int w, bool abs, ALLEGRO_DISPLAY_WIN *win_disp)
void _al_win_mouse_handle_hwheel(int raw_dw, bool abs, ALLEGRO_DISPLAY_WIN *win_disp)
{
ALLEGRO_DISPLAY *display = (ALLEGRO_DISPLAY *)win_disp;
int d;
int new_w;
double float_dw = display->mouse_wheel_precision * (double)raw_dw / WHEEL_DELTA;

if (!installed)
return;

if (!abs) {
mouse_state.w += w;
d = w;
float_mouse_w += float_dw;
}
else {
d = w - mouse_state.w;
mouse_state.w = w;
float_mouse_w = float_dw;
}
new_w = (int)float_mouse_w;
d = new_w - mouse_state.w;
mouse_state.w = new_w;

generate_mouse_event(ALLEGRO_EVENT_MOUSE_AXES,
mouse_state.x, mouse_state.y, mouse_state.z, mouse_state.w, mouse_state.pressure,
Expand Down
6 changes: 3 additions & 3 deletions src/win/wwindow.c
Expand Up @@ -484,7 +484,7 @@ static LRESULT CALLBACK window_callback(HWND hWnd, UINT message,

if (rm->usButtonFlags & RI_MOUSE_WHEEL) {
SHORT z = (SHORT)rm->usButtonData;
_al_win_mouse_handle_wheel(z / WHEEL_DELTA, false, win_display);
_al_win_mouse_handle_wheel(z, false, win_display);
}
}

Expand Down Expand Up @@ -543,15 +543,15 @@ static LRESULT CALLBACK window_callback(HWND hWnd, UINT message,
case WM_MOUSEWHEEL: {
if (accept_mouse_event()) {
int d = GET_WHEEL_DELTA_WPARAM(wParam);
_al_win_mouse_handle_wheel(d / WHEEL_DELTA, false, win_display);
_al_win_mouse_handle_wheel(d, false, win_display);
return TRUE;
}
break;
}
case WM_MOUSEHWHEEL: {
if (accept_mouse_event()) {
int d = GET_WHEEL_DELTA_WPARAM(wParam);
_al_win_mouse_handle_hwheel(d / WHEEL_DELTA, false, win_display);
_al_win_mouse_handle_hwheel(d, false, win_display);
return TRUE;
}
break;
Expand Down
3 changes: 3 additions & 0 deletions src/x/xmousenu.c
Expand Up @@ -380,6 +380,9 @@ static void wheel_motion_handler(int x_button, ALLEGRO_DISPLAY *display)
if (x_button == 7) dw = 1;
if (dz == 0 && dw == 0) return;

dz *= display->mouse_wheel_precision;
dw *= display->mouse_wheel_precision;

_al_event_source_lock(&the_mouse.parent.es);
{
the_mouse.state.z += dz;
Expand Down

0 comments on commit 2f79ba3

Please sign in to comment.