Compare commits

...

10 Commits

Author SHA1 Message Date
Hrvoje Cavrak d78bcd4638 Fix screensaver issue with rapid movement. 2024-12-04 20:00:13 +01:00
Hrvoje Čavrak fa4ccdfeae
Merge pull request #181 from eltariel/relative-jitter
Use relative mouse reports for jitter screensaver mode
2024-12-04 18:31:48 +01:00
Ellie T 85089fee11 Use relative mouse reports for jitter screensaver mode 2024-12-04 20:08:48 +11:00
Hrvoje Čavrak cbb98e4a88
Merge pull request #179 from eltariel/macos-screen-switch
Tweak macos screen switch helper
2024-11-27 20:08:08 +01:00
Hrvoje Čavrak 99399030f2
Update mouse.c
Removing duplicate lines.
2024-11-27 20:07:24 +01:00
Ellie T ff70bdafb5 Tweak macos screen switch helper
- Increase relative mouse movement to over one screen pixel in most
  resolutions
- Extract MacOS desktop switch helper to its own function
- Clean up unused parameters in top-level desktop switch
2024-11-27 21:51:19 +11:00
Hrvoje Cavrak 92baf1a2f2 Fixing usage_max. 2024-11-25 22:30:15 +01:00
Hrvoje Cavrak 79fd4068b6 Tweak Readme 2024-11-25 21:27:05 +01:00
Hrvoje Cavrak d345b11da5 Fix oshw logo #2 2024-11-25 21:17:34 +01:00
Hrvoje Cavrak 7c0fa3e20a Fix oshw logo 2024-11-25 21:16:18 +01:00
8 changed files with 85 additions and 78 deletions

View File

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.6)
## Version Configuration ## Version Configuration
set(VERSION_MAJOR 00) set(VERSION_MAJOR 00)
set(VERSION_MINOR 161) set(VERSION_MINOR 162)
## Release Type Selection ## Release Type Selection
option(DH_DEBUG "Build a debug version" OFF) option(DH_DEBUG "Build a debug version" OFF)

View File

@ -10,7 +10,7 @@ All I wanted was a way to use a keyboard shortcut to quickly switch outputs, pai
## Features ## Features
- Completely **free and open source** - Completely **[free and open source](https://certification.oshwa.org/de000149.html)**
- No noticeable delay when switching - No noticeable delay when switching
- Simply drag the mouse pointer between computers - Simply drag the mouse pointer between computers
- No software installed - No software installed
@ -19,9 +19,9 @@ All I wanted was a way to use a keyboard shortcut to quickly switch outputs, pai
- Full Galvanic isolation between your outputs - Full Galvanic isolation between your outputs
- Works with Linux, macOS and Windows - Works with Linux, macOS and Windows
![Image](img/oshw.svg){width=240} [User Manual](user-manual.pdf) is now available
[Proudly certified](https://certification.oshwa.org/de000149.html) by the Open Source Hardware Association (oshwa.org)
![Image](img/oshw.svg)
------ ------
## How it works ## How it works
@ -53,9 +53,6 @@ It also remembers the LED state for each computer, so you can pick up exactly ho
![Image](img/demo-typing.gif) ![Image](img/demo-typing.gif)
## User Manual
To help you set up, configure and program the board available [read the manual provided here](user-manual.pdf).
## How to build ## How to build
To avoid version mismatch and reported path issues when building, as well as to save you from having to download a large SDK, the project now bundles minimal pico sdk and tinyusb. To avoid version mismatch and reported path issues when building, as well as to save you from having to download a large SDK, the project now bundles minimal pico sdk and tinyusb.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -39,7 +39,7 @@ void _get_border_position(device_t *state, border_size_t *border) {
border->top = state->pointer_y; border->top = state->pointer_y;
} }
void _screensaver_set(device_t *state, bool value) { void _screensaver_set(device_t *state, uint8_t value) {
if (CURRENT_BOARD_IS_ACTIVE_OUTPUT) if (CURRENT_BOARD_IS_ACTIVE_OUTPUT)
state->config.output[BOARD_ROLE].screensaver.mode = value; state->config.output[BOARD_ROLE].screensaver.mode = value;
else else
@ -123,12 +123,18 @@ void mouse_zoom_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
/* When pressed, enables the screensaver on active output */ /* When pressed, enables the screensaver on active output */
void enable_screensaver_hotkey_handler(device_t *state, hid_keyboard_report_t *report) { void enable_screensaver_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
_screensaver_set(state, true); uint8_t desired_mode = state->config.output[BOARD_ROLE].screensaver.mode;
/* If the user explicitly asks for screensaver to be active, ignore config and turn it on */
if (desired_mode == DISABLED)
desired_mode = PONG;
_screensaver_set(state, desired_mode);
} }
/* When pressed, disables the screensaver on active output */ /* When pressed, disables the screensaver on active output */
void disable_screensaver_hotkey_handler(device_t *state, hid_keyboard_report_t *report) { void disable_screensaver_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
_screensaver_set(state, false); _screensaver_set(state, DISABLED);
} }
/* Put the device into a special configuration mode */ /* Put the device into a special configuration mode */

View File

@ -206,9 +206,10 @@ enum screen_pos_e {
}; };
enum screensaver_mode_e { enum screensaver_mode_e {
DISABLED = 0, DISABLED = 0,
PONG = 1, PONG = 1,
JITTER = 2, JITTER = 2,
MAX_SS_VAL = JITTER,
}; };
#define ITF_NUM_HID 0 #define ITF_NUM_HID 0

View File

@ -66,7 +66,7 @@
HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\ HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\
HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\
HID_USAGE_MIN ( 1 ) ,\ HID_USAGE_MIN ( 1 ) ,\
HID_USAGE_MAX ( 5 ) ,\ HID_USAGE_MAX ( 8 ) ,\
HID_LOGICAL_MIN ( 0 ) ,\ HID_LOGICAL_MIN ( 0 ) ,\
HID_LOGICAL_MAX ( 1 ) ,\ HID_LOGICAL_MAX ( 1 ) ,\
\ \

View File

@ -17,6 +17,9 @@
#include "main.h" #include "main.h"
#define MACOS_SWITCH_MOVE_X 10
#define MACOS_SWITCH_MOVE_COUNT 5
/* Move mouse coordinate 'position' by 'offset', but don't fall off the screen */ /* Move mouse coordinate 'position' by 'offset', but don't fall off the screen */
int32_t move_and_keep_on_screen(int position, int offset) { int32_t move_and_keep_on_screen(int position, int offset) {
/* Lowest we can go is 0 */ /* Lowest we can go is 0 */
@ -122,7 +125,7 @@ int16_t scale_y_coordinate(int screen_from, int screen_to, device_t *state) {
} }
void switch_screen( void switch_screen(
device_t *state, output_t *output, int new_x, int output_from, int output_to, int direction) { device_t *state, output_t *output, int output_to, int direction) {
uint8_t *mouse_park_pos = &state->config.output[state->active_output].mouse_park_pos; uint8_t *mouse_park_pos = &state->config.output[state->active_output].mouse_park_pos;
int16_t mouse_y = (*mouse_park_pos == 0) ? MIN_SCREEN_COORD : /* Top */ int16_t mouse_y = (*mouse_park_pos == 0) ? MIN_SCREEN_COORD : /* Top */
@ -137,17 +140,21 @@ void switch_screen(
state->pointer_y = scale_y_coordinate(output->number, 1 - output->number, state); state->pointer_y = scale_y_coordinate(output->number, 1 - output->number, state);
} }
void switch_desktop(device_t *state, output_t *output, int new_index, int direction) { void switch_desktop_macos(device_t *state, int direction) {
/* Fix for MACOS: Send relative mouse movement here, one or two pixels in the /* Fix for MACOS: Send relative mouse movement here, one or two pixels in the
direction of movement, BEFORE absolute report sets X to 0 */ direction of movement, BEFORE absolute report sets X to 0 */
mouse_report_t move_relative_one uint16_t move = (direction == LEFT) ? -MACOS_SWITCH_MOVE_X : MACOS_SWITCH_MOVE_X;
= {.x = (direction == LEFT) ? -5 : 5, .mode = RELATIVE}; mouse_report_t move_relative_one = {.x = move, .mode = RELATIVE};
/* Once doesn't seem reliable enough, do it a few times */
for (int i = 0; i < MACOS_SWITCH_MOVE_COUNT; i++)
output_mouse_report(&move_relative_one, state);
}
void switch_desktop(device_t *state, output_t *output, int new_index, int direction) {
switch (output->os) { switch (output->os) {
case MACOS: case MACOS:
/* Once doesn't seem reliable enough, do it a few times */ switch_desktop_macos(state, direction);
for (int i = 0; i < 5; i++)
output_mouse_report(&move_relative_one, state);
break; break;
case WINDOWS: case WINDOWS:
@ -199,7 +206,7 @@ void check_screen_switch(const mouse_values_t *values, device_t *state) {
if (state->mouse_buttons) if (state->mouse_buttons)
return; return;
switch_screen(state, output, new_x, state->active_output, 1 - state->active_output, direction); switch_screen(state, output, 1 - state->active_output, direction);
} }
/* If here, this output has multiple desktops and we are not on the main one */ /* If here, this output has multiple desktops and we are not on the main one */
else else

View File

@ -59,22 +59,51 @@ void usb_host_task(device_t *state) {
tuh_task(); tuh_task();
} }
mouse_report_t *screensaver_pong(device_t *state) {
static mouse_report_t report = {0};
static int dx = 20, dy = 25;
/* Check if we are bouncing off the walls and reverse direction in that case. */
if (report.x + dx < MIN_SCREEN_COORD || report.x + dx > MAX_SCREEN_COORD)
dx = -dx;
if (report.y + dy < MIN_SCREEN_COORD || report.y + dy > MAX_SCREEN_COORD)
dy = -dy;
report.x += dx;
report.y += dy;
return &report;
}
mouse_report_t *screensaver_jitter(device_t *state) {
const int16_t jitter_distance = 2;
static mouse_report_t report = {
.y = jitter_distance,
.mode = RELATIVE,
};
report.y = -report.y;
return &report;
}
/* Have something fun and entertaining when idle. */ /* Have something fun and entertaining when idle. */
void screensaver_task(device_t *state) { void screensaver_task(device_t *state) {
const int mouse_move_delay = 5000; const uint32_t delays[] = {
0, /* DISABLED, unused index 0 */
5000, /* PONG, move mouse every 5 ms for a high framerate */
10000000, /* JITTER, once every 10 sec is more than enough */
};
static int last_pointer_move = 0;
screensaver_t *screensaver = &state->config.output[BOARD_ROLE].screensaver; screensaver_t *screensaver = &state->config.output[BOARD_ROLE].screensaver;
uint64_t inactivity_period = time_us_64() - state->last_activity[BOARD_ROLE]; uint64_t inactivity_period = time_us_64() - state->last_activity[BOARD_ROLE];
static mouse_report_t report = {0};
static int last_pointer_move = 0;
static int dx = 20, dy = 25, jitter = 1;
/* If we're not enabled, nothing to do here. */ /* If we're not enabled, nothing to do here. */
if (screensaver->mode == DISABLED) if (screensaver->mode == DISABLED)
return; return;
/* System is still not idle for long enough to activate or we've been running for too long */ /* System is still not idle for long enough to activate or screensaver mode is not supported */
if (inactivity_period < screensaver->idle_time_us) if (inactivity_period < screensaver->idle_time_us || screensaver->mode > MAX_SS_VAL)
return; return;
/* We exceeded the maximum permitted screensaver runtime */ /* We exceeded the maximum permitted screensaver runtime */
@ -87,32 +116,25 @@ void screensaver_task(device_t *state) {
return; return;
/* We're active! Now check if it's time to move the cursor yet. */ /* We're active! Now check if it's time to move the cursor yet. */
if ((time_us_32()) - last_pointer_move < mouse_move_delay) if (time_us_32() - last_pointer_move < delays[screensaver->mode])
return; return;
mouse_report_t *report;
switch (screensaver->mode) { switch (screensaver->mode) {
case PONG: case PONG:
/* Check if we are bouncing off the walls and reverse direction in that case. */ report = screensaver_pong(state);
if (report.x + dx < MIN_SCREEN_COORD || report.x + dx > MAX_SCREEN_COORD)
dx = -dx;
if (report.y + dy < MIN_SCREEN_COORD || report.y + dy > MAX_SCREEN_COORD)
dy = -dy;
report.x += dx;
report.y += dy;
break; break;
case JITTER: case JITTER:
report.x = state->pointer_x + jitter; report = screensaver_jitter(state);
report.y = state->pointer_y + jitter;
jitter = -jitter;
break; break;
default:
return;
} }
/* Move mouse pointer */ /* Move mouse pointer */
queue_mouse_report(&report, state); queue_mouse_report(report, state);
/* Update timer of the last pointer move */ /* Update timer of the last pointer move */
last_pointer_move = time_us_32(); last_pointer_move = time_us_32();