mouse: Provide a way to read clicks
A mouse click is defined as pressing the mouse and then releasing it over a given spot. Add a function the tracks the mouse state and returns the most recent mouse click, if any. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
@@ -23,7 +23,50 @@ int mouse_get_event(struct udevice *dev, struct mouse_event *evt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mouse_get_click(struct udevice *dev, int *xp, int *yp)
|
||||
{
|
||||
struct mouse_uc_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||
struct mouse_event event;
|
||||
int ret;
|
||||
|
||||
/* Get one mouse event */
|
||||
ret = mouse_get_event(dev, &event);
|
||||
if (ret)
|
||||
return -EAGAIN; /* No event available */
|
||||
|
||||
/* Only process button events for left button */
|
||||
if (event.type == MOUSE_EV_BUTTON &&
|
||||
event.button.button == BUTTON_LEFT) {
|
||||
enum mouse_press_state_t new_state = event.button.press_state;
|
||||
bool pending = false;
|
||||
|
||||
/* Detect press->release transition (click) */
|
||||
if (uc_priv->left_button_state == BUTTON_PRESSED &&
|
||||
new_state == BUTTON_RELEASED) {
|
||||
pending = true;
|
||||
uc_priv->click_x = event.button.x;
|
||||
uc_priv->click_y = event.button.y;
|
||||
}
|
||||
|
||||
/* Update button state */
|
||||
uc_priv->left_button_state = new_state;
|
||||
|
||||
/* If we just detected a click, return it */
|
||||
if (pending) {
|
||||
if (xp)
|
||||
*xp = uc_priv->click_x;
|
||||
if (yp)
|
||||
*yp = uc_priv->click_y;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
UCLASS_DRIVER(mouse) = {
|
||||
.id = UCLASS_MOUSE,
|
||||
.name = "mouse",
|
||||
.per_device_auto = sizeof(struct mouse_uc_priv),
|
||||
};
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#ifndef _MOUSE_H
|
||||
#define _MOUSE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct udevice;
|
||||
|
||||
enum mouse_ev_t {
|
||||
@@ -29,6 +31,19 @@ enum mouse_press_state_t {
|
||||
BUTTON_PRESSED,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mouse_uc_priv - private data for mouse uclass
|
||||
*
|
||||
* @left_button_state: Current state of left button (BUTTON_PRESSED/BUTTON_RELEASED)
|
||||
* @click_x: X coordinate where the click occurred
|
||||
* @click_y: Y coordinate where the click occurred
|
||||
*/
|
||||
struct mouse_uc_priv {
|
||||
enum mouse_press_state_t left_button_state;
|
||||
int click_x;
|
||||
int click_y;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mouse_event - information about a mouse event
|
||||
*
|
||||
@@ -77,4 +92,14 @@ struct mouse_ops {
|
||||
|
||||
int mouse_get_event(struct udevice *dev, struct mouse_event *event);
|
||||
|
||||
/**
|
||||
* mouse_get_click() - Check if a left mouse button click has occurred
|
||||
*
|
||||
* @dev: Mouse device
|
||||
* @xp: Returns X coordinate of click (can be NULL)
|
||||
* @yp: Returns Y coordinate of click (can be NULL)
|
||||
* Returns: 0 if a click has occurred, -EAGAIN if no click pending
|
||||
*/
|
||||
int mouse_get_click(struct udevice *dev, int *xp, int *py);
|
||||
|
||||
#endif
|
||||
|
||||
121
test/dm/mouse.c
121
test/dm/mouse.c
@@ -94,3 +94,124 @@ static int dm_test_mouse_button(struct unit_test_state *uts)
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_mouse_button, UTF_SCAN_PDATA | UTF_SCAN_FDT);
|
||||
|
||||
static int dm_test_mouse_click(struct unit_test_state *uts)
|
||||
{
|
||||
struct udevice *dev;
|
||||
struct mouse_event inject;
|
||||
int x, y;
|
||||
|
||||
ut_assertok(uclass_first_device_err(UCLASS_MOUSE, &dev));
|
||||
|
||||
/* put mouse in test mode */
|
||||
sandbox_mouse_set_test_mode(dev, true);
|
||||
|
||||
/* test that no click is detected initially */
|
||||
ut_asserteq(-EAGAIN, mouse_get_click(dev, &x, &y));
|
||||
|
||||
/* inject a left button press */
|
||||
inject.type = MOUSE_EV_BUTTON;
|
||||
inject.button.button = BUTTON_LEFT;
|
||||
inject.button.press_state = BUTTON_PRESSED;
|
||||
inject.button.clicks = 1;
|
||||
inject.button.x = 300;
|
||||
inject.button.y = 400;
|
||||
|
||||
sandbox_mouse_inject(dev, &inject);
|
||||
|
||||
/*
|
||||
* calling mouse_get_click() should not detect a click yet (press
|
||||
* only)
|
||||
*/
|
||||
ut_asserteq(-EAGAIN, mouse_get_click(dev, &x, &y));
|
||||
|
||||
/* inject a left button release */
|
||||
inject.type = MOUSE_EV_BUTTON;
|
||||
inject.button.button = BUTTON_LEFT;
|
||||
inject.button.press_state = BUTTON_RELEASED;
|
||||
inject.button.clicks = 1;
|
||||
inject.button.x = 300;
|
||||
inject.button.y = 400;
|
||||
|
||||
sandbox_mouse_inject(dev, &inject);
|
||||
|
||||
/* now mouse_get_click() should detect the click */
|
||||
ut_assertok(mouse_get_click(dev, &x, &y));
|
||||
ut_asserteq(300, x);
|
||||
ut_asserteq(400, y);
|
||||
|
||||
/* verify no more clicks are pending */
|
||||
ut_asserteq(-EAGAIN, mouse_get_click(dev, &x, &y));
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_mouse_click, UTF_SCAN_PDATA | UTF_SCAN_FDT);
|
||||
|
||||
static int dm_test_mouse_click_no_coordinates(struct unit_test_state *uts)
|
||||
{
|
||||
struct udevice *dev;
|
||||
struct mouse_event inject;
|
||||
|
||||
ut_assertok(uclass_first_device_err(UCLASS_MOUSE, &dev));
|
||||
|
||||
/* put mouse in test mode */
|
||||
sandbox_mouse_set_test_mode(dev, true);
|
||||
|
||||
/* inject press and release to create a click */
|
||||
inject.type = MOUSE_EV_BUTTON;
|
||||
inject.button.button = BUTTON_LEFT;
|
||||
inject.button.press_state = BUTTON_PRESSED;
|
||||
inject.button.clicks = 1;
|
||||
inject.button.x = 500;
|
||||
inject.button.y = 600;
|
||||
sandbox_mouse_inject(dev, &inject);
|
||||
|
||||
/* process the press event */
|
||||
ut_asserteq(-EAGAIN, mouse_get_click(dev, NULL, NULL));
|
||||
|
||||
inject.button.press_state = BUTTON_RELEASED;
|
||||
sandbox_mouse_inject(dev, &inject);
|
||||
|
||||
/*
|
||||
* now test that click is detected without coordinate return
|
||||
*/
|
||||
ut_assertok(mouse_get_click(dev, NULL, NULL));
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_mouse_click_no_coordinates, UTF_SCAN_PDATA | UTF_SCAN_FDT);
|
||||
|
||||
static int dm_test_mouse_right_button(struct unit_test_state *uts)
|
||||
{
|
||||
struct udevice *dev;
|
||||
struct mouse_event inject;
|
||||
int x, y;
|
||||
|
||||
ut_assertok(uclass_first_device_err(UCLASS_MOUSE, &dev));
|
||||
|
||||
/* put mouse in test mode */
|
||||
sandbox_mouse_set_test_mode(dev, true);
|
||||
|
||||
/*
|
||||
* right button events should not be detected as clicks by
|
||||
* mouse_get_click()
|
||||
*/
|
||||
inject.type = MOUSE_EV_BUTTON;
|
||||
inject.button.button = BUTTON_RIGHT;
|
||||
inject.button.press_state = BUTTON_PRESSED;
|
||||
inject.button.clicks = 1;
|
||||
inject.button.x = 100;
|
||||
inject.button.y = 200;
|
||||
sandbox_mouse_inject(dev, &inject);
|
||||
|
||||
ut_asserteq(-EAGAIN, mouse_get_click(dev, &x, &y));
|
||||
|
||||
inject.button.press_state = BUTTON_RELEASED;
|
||||
sandbox_mouse_inject(dev, &inject);
|
||||
|
||||
/* still no click detected since it was right button */
|
||||
ut_asserteq(-EAGAIN, mouse_get_click(dev, &x, &y));
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_mouse_right_button, UTF_SCAN_PDATA | UTF_SCAN_FDT);
|
||||
|
||||
Reference in New Issue
Block a user