Merge pull request #67 from kpfleming/screensaver-features
Screensaver features
This commit is contained in:
commit
f0b36569c9
|
@ -28,5 +28,18 @@ const config_t default_config = {
|
||||||
.screen_count = 1,
|
.screen_count = 1,
|
||||||
.screen_index = 0,
|
.screen_index = 0,
|
||||||
},
|
},
|
||||||
.screensaver_enabled = SCREENSAVER_ENABLED,
|
.screensaver[OUTPUT_A] =
|
||||||
|
{
|
||||||
|
.enabled = SCREENSAVER_A_ENABLED,
|
||||||
|
.only_if_inactive = SCREENSAVER_A_ONLY_IF_INACTIVE,
|
||||||
|
.idle_time_us = SCREENSAVER_A_IDLE_TIME_SEC * 1000000,
|
||||||
|
.max_time_us = SCREENSAVER_A_MAX_TIME_SEC * 1000000,
|
||||||
|
},
|
||||||
|
.screensaver[OUTPUT_B] =
|
||||||
|
{
|
||||||
|
.enabled = SCREENSAVER_B_ENABLED,
|
||||||
|
.only_if_inactive = SCREENSAVER_B_ONLY_IF_INACTIVE,
|
||||||
|
.idle_time_us = SCREENSAVER_B_IDLE_TIME_SEC * 1000000,
|
||||||
|
.max_time_us = SCREENSAVER_B_MAX_TIME_SEC * 1000000,
|
||||||
|
},
|
||||||
};
|
};
|
|
@ -69,8 +69,8 @@ void wipe_config_hotkey_handler(device_t *state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void screensaver_hotkey_handler(device_t *state) {
|
void screensaver_hotkey_handler(device_t *state) {
|
||||||
state->config.screensaver_enabled ^= 1;
|
state->config.screensaver[BOARD_ROLE].enabled ^= 1;
|
||||||
send_value(state->config.screensaver_enabled, SCREENSAVER_MSG);
|
send_value(state->config.screensaver[BOARD_ROLE].enabled, SCREENSAVER_MSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When pressed, toggles the current mouse zoom mode state */
|
/* When pressed, toggles the current mouse zoom mode state */
|
||||||
|
@ -87,6 +87,7 @@ void mouse_zoom_hotkey_handler(device_t *state) {
|
||||||
void handle_keyboard_uart_msg(uart_packet_t *packet, device_t *state) {
|
void handle_keyboard_uart_msg(uart_packet_t *packet, device_t *state) {
|
||||||
queue_kbd_report((hid_keyboard_report_t *)packet->data, state);
|
queue_kbd_report((hid_keyboard_report_t *)packet->data, state);
|
||||||
state->last_activity[BOARD_ROLE] = time_us_64();
|
state->last_activity[BOARD_ROLE] = time_us_64();
|
||||||
|
state->screensaver_max_time_reached[BOARD_ROLE] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Function handles received mouse moves from the other board */
|
/* Function handles received mouse moves from the other board */
|
||||||
|
@ -98,6 +99,7 @@ void handle_mouse_abs_uart_msg(uart_packet_t *packet, device_t *state) {
|
||||||
state->mouse_y = mouse_report->y;
|
state->mouse_y = mouse_report->y;
|
||||||
|
|
||||||
state->last_activity[BOARD_ROLE] = time_us_64();
|
state->last_activity[BOARD_ROLE] = time_us_64();
|
||||||
|
state->screensaver_max_time_reached[BOARD_ROLE] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Function handles request to switch output */
|
/* Function handles request to switch output */
|
||||||
|
@ -149,7 +151,7 @@ void handle_wipe_config_msg(uart_packet_t *packet, device_t *state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_screensaver_msg(uart_packet_t *packet, device_t *state) {
|
void handle_screensaver_msg(uart_packet_t *packet, device_t *state) {
|
||||||
state->config.screensaver_enabled = packet->data[0];
|
state->config.screensaver[BOARD_ROLE].enabled = packet->data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**==================================================== *
|
/**==================================================== *
|
||||||
|
|
|
@ -162,6 +162,7 @@ void send_key(hid_keyboard_report_t *report, device_t *state) {
|
||||||
if (CURRENT_BOARD_IS_ACTIVE_OUTPUT) {
|
if (CURRENT_BOARD_IS_ACTIVE_OUTPUT) {
|
||||||
queue_kbd_report(report, state);
|
queue_kbd_report(report, state);
|
||||||
state->last_activity[BOARD_ROLE] = time_us_64();
|
state->last_activity[BOARD_ROLE] = time_us_64();
|
||||||
|
state->screensaver_max_time_reached[BOARD_ROLE] = false;
|
||||||
} else {
|
} else {
|
||||||
send_packet((uint8_t *)report, KEYBOARD_REPORT_MSG, KBD_REPORT_LENGTH);
|
send_packet((uint8_t *)report, KEYBOARD_REPORT_MSG, KBD_REPORT_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
13
src/main.h
13
src/main.h
|
@ -146,7 +146,7 @@ typedef struct {
|
||||||
|
|
||||||
/********* Configuration storage definitions **********/
|
/********* Configuration storage definitions **********/
|
||||||
|
|
||||||
#define CURRENT_CONFIG_VERSION 2
|
#define CURRENT_CONFIG_VERSION 3
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int top; // When jumping from a smaller to a bigger screen, go to THIS top height
|
int top; // When jumping from a smaller to a bigger screen, go to THIS top height
|
||||||
|
@ -164,13 +164,21 @@ typedef struct {
|
||||||
border_size_t border; // Screen border size/offset to keep cursor at same height when switching
|
border_size_t border; // Screen border size/offset to keep cursor at same height when switching
|
||||||
} output_t;
|
} output_t;
|
||||||
|
|
||||||
|
/* Define screensaver parameters */
|
||||||
|
typedef struct {
|
||||||
|
uint8_t enabled;
|
||||||
|
uint8_t only_if_inactive;
|
||||||
|
uint64_t idle_time_us;
|
||||||
|
uint64_t max_time_us;
|
||||||
|
} screensaver_t;
|
||||||
|
|
||||||
/* Data structure defining how configuration is stored */
|
/* Data structure defining how configuration is stored */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t magic_header;
|
uint32_t magic_header;
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
uint8_t force_mouse_boot_mode;
|
uint8_t force_mouse_boot_mode;
|
||||||
output_t output[NUM_SCREENS];
|
output_t output[NUM_SCREENS];
|
||||||
uint8_t screensaver_enabled;
|
screensaver_t screensaver[NUM_SCREENS];
|
||||||
// Keep checksum at the end of the struct
|
// Keep checksum at the end of the struct
|
||||||
uint32_t checksum;
|
uint32_t checksum;
|
||||||
} config_t;
|
} config_t;
|
||||||
|
@ -214,6 +222,7 @@ typedef struct {
|
||||||
|
|
||||||
uint8_t keyboard_leds[NUM_SCREENS]; // State of keyboard LEDs (index 0 = A, index 1 = B)
|
uint8_t keyboard_leds[NUM_SCREENS]; // State of keyboard LEDs (index 0 = A, index 1 = B)
|
||||||
uint64_t last_activity[NUM_SCREENS]; // Timestamp of the last input activity (-||-)
|
uint64_t last_activity[NUM_SCREENS]; // Timestamp of the last input activity (-||-)
|
||||||
|
bool screensaver_max_time_reached[NUM_SCREENS]; // Screensaver maximum time has been reached (will be reset at the next input activity)
|
||||||
receiver_state_t receiver_state; // Storing the state for the simple receiver state machine
|
receiver_state_t receiver_state; // Storing the state for the simple receiver state machine
|
||||||
uint64_t core1_last_loop_pass; // Timestamp of last core1 loop execution
|
uint64_t core1_last_loop_pass; // Timestamp of last core1 loop execution
|
||||||
uint8_t active_output; // Currently selected output (0 = A, 1 = B)
|
uint8_t active_output; // Currently selected output (0 = A, 1 = B)
|
||||||
|
|
|
@ -53,6 +53,7 @@ void output_mouse_report(mouse_abs_report_t *report, device_t *state) {
|
||||||
if (CURRENT_BOARD_IS_ACTIVE_OUTPUT) {
|
if (CURRENT_BOARD_IS_ACTIVE_OUTPUT) {
|
||||||
queue_mouse_report(report, state);
|
queue_mouse_report(report, state);
|
||||||
state->last_activity[BOARD_ROLE] = time_us_64();
|
state->last_activity[BOARD_ROLE] = time_us_64();
|
||||||
|
state->screensaver_max_time_reached[BOARD_ROLE] = false;
|
||||||
} else {
|
} else {
|
||||||
send_packet((uint8_t *)report, MOUSE_REPORT_MSG, MOUSE_REPORT_LENGTH);
|
send_packet((uint8_t *)report, MOUSE_REPORT_MSG, MOUSE_REPORT_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,17 +63,77 @@
|
||||||
|
|
||||||
/**================================================== *
|
/**================================================== *
|
||||||
* ============== Screensaver Config ============== *
|
* ============== Screensaver Config ============== *
|
||||||
* ==================================================
|
* ================================================== *
|
||||||
*
|
*
|
||||||
* Defines how long does an output need to be idle for screensaver to kick in.
|
* While this feature is called 'screensaver', it's not actually a
|
||||||
* With this function, after being left idle for a certain amount of time (defined below),
|
* screensaver :) Really it's a way to ensure that some sort of mouse
|
||||||
* mouse cursor starts moving around like a bouncy-ball in pong. No clicking, of course.
|
* activity will be sent to one (or both) outputs when the user has
|
||||||
* Move mouse on that active output to stop.
|
* not interacted with that output. This can be used to stop a
|
||||||
|
* screensaver or screenlock from activating on the attached computer,
|
||||||
|
* or to just watch the mouse pointer bouncing around!
|
||||||
*
|
*
|
||||||
* SCREENSAVER_ENABLED: [0 or 1] 0 means screensaver is disabled, 1 means it is enabled.
|
* When the mode is active on an output, the pointer will jump around
|
||||||
* SCREENSAVER_TIME_SEC: time in seconds
|
* the screen like a bouncing-ball in a Pong game (however no click
|
||||||
|
* events will be generated, of course).
|
||||||
|
*
|
||||||
|
* This mode is activated by 'idle time' on a per-output basis; if the
|
||||||
|
* mode is enabled for output B, and output B doesn't have any
|
||||||
|
* activity for (at least) the specified idle time, then the mode will
|
||||||
|
* be activated and will continue until the inactivity time reaches
|
||||||
|
* the maximum (if one has been specified). This allows you to stop a
|
||||||
|
* screensaver/screenlock from activating while you are still at your
|
||||||
|
* desk (but just interacting with the other computer attached to
|
||||||
|
* Deskhop), but let it activate if you leave your desk for an
|
||||||
|
* extended period of time.
|
||||||
|
*
|
||||||
|
* Additionally, this mode can be automatically disabled if the output
|
||||||
|
* is the currently-active output.
|
||||||
|
*
|
||||||
|
* If you only set the ENABLED options below, and leave the rest of
|
||||||
|
* the defaults in place, then the screensaver mode will activate
|
||||||
|
* after 4 minutes (240 seconds) of inactivity, will continue forever,
|
||||||
|
* but will only activate on an output that is not currently
|
||||||
|
* active.
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#define SCREENSAVER_ENABLED 0
|
/**================================================== *
|
||||||
#define SCREENSAVER_TIME_SEC 240
|
*
|
||||||
|
* SCREENSAVER_{A|B}_ENABLED: [0 or 1] 0 means screensaver is
|
||||||
|
* disabled, 1 means it is enabled.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define SCREENSAVER_A_ENABLED 1
|
||||||
|
#define SCREENSAVER_B_ENABLED 0
|
||||||
|
|
||||||
|
/**================================================== *
|
||||||
|
*
|
||||||
|
* SCREENSAVER_{A|B}_IDLE_TIME_SEC: Number of seconds that an output
|
||||||
|
* must be inactive before the screensaver mode will be activated.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define SCREENSAVER_A_IDLE_TIME_SEC 60
|
||||||
|
#define SCREENSAVER_B_IDLE_TIME_SEC 240
|
||||||
|
|
||||||
|
/**================================================== *
|
||||||
|
*
|
||||||
|
* SCREENSAVER_{A|B}_MAX_TIME_SEC: Number of seconds that an output
|
||||||
|
* can be inactive before the screensaver mode will be deactivated. If
|
||||||
|
* zero, the screensaver will run indefinitely.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define SCREENSAVER_A_MAX_TIME_SEC 120
|
||||||
|
#define SCREENSAVER_B_MAX_TIME_SEC 0
|
||||||
|
|
||||||
|
/**================================================== *
|
||||||
|
*
|
||||||
|
* SCREENSAVER_{A|B}_ONLY_IF_INACTIVE: [0 or 1] 1 means the
|
||||||
|
* screensaver will activate only if the output is inactive.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define SCREENSAVER_A_ONLY_IF_INACTIVE 1
|
||||||
|
#define SCREENSAVER_B_ONLY_IF_INACTIVE 1
|
||||||
|
|
39
src/utils.c
39
src/utils.c
|
@ -106,23 +106,54 @@ void save_config(device_t *state) {
|
||||||
|
|
||||||
/* 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 uint64_t idle_timeout_us = SCREENSAVER_TIME_SEC * 1000000;
|
|
||||||
const int mouse_move_delay = 5000;
|
const int mouse_move_delay = 5000;
|
||||||
|
|
||||||
static mouse_abs_report_t report = {.x = 0, .y = 0};
|
static mouse_abs_report_t report = {.x = 0, .y = 0};
|
||||||
static int last_pointer_move = 0;
|
static int last_pointer_move = 0;
|
||||||
|
|
||||||
|
uint64_t current_time = time_us_64();
|
||||||
|
static uint64_t last_activation_time = 0;
|
||||||
|
|
||||||
/* "Randomly" chosen initial values */
|
/* "Randomly" chosen initial values */
|
||||||
static int dx = 20;
|
static int dx = 20;
|
||||||
static int dy = 25;
|
static int dy = 25;
|
||||||
|
|
||||||
/* If we're not enabled, nothing to do here. */
|
/* If the maximum time has been reached, nothing to do here. */
|
||||||
if (!state->config.screensaver_enabled)
|
if (state->screensaver_max_time_reached[BOARD_ROLE]) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're not enabled, nothing to do here. */
|
||||||
|
if (!state->config.screensaver[BOARD_ROLE].enabled) {
|
||||||
|
last_activation_time = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're not the selected output and that is required, nothing to do here. */
|
||||||
|
if (state->config.screensaver[BOARD_ROLE].only_if_inactive &&
|
||||||
|
CURRENT_BOARD_IS_ACTIVE_OUTPUT) {
|
||||||
|
last_activation_time = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* We are enabled, but idle time still too small to activate. */
|
/* We are enabled, but idle time still too small to activate. */
|
||||||
if (time_us_64() - state->last_activity[BOARD_ROLE] < idle_timeout_us)
|
if ((current_time - state->last_activity[BOARD_ROLE]) <
|
||||||
|
state->config.screensaver[BOARD_ROLE].idle_time_us) {
|
||||||
|
last_activation_time = 0;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_activation_time == 0) {
|
||||||
|
last_activation_time = current_time;
|
||||||
|
} else {
|
||||||
|
/* We are enabled, but max time has been reached. */
|
||||||
|
if ((current_time - last_activation_time) >
|
||||||
|
state->config.screensaver[BOARD_ROLE].max_time_us) {
|
||||||
|
state->screensaver_max_time_reached[BOARD_ROLE] = true;
|
||||||
|
last_activation_time = 0;
|
||||||
|
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 < mouse_move_delay)
|
||||||
|
|
Loading…
Reference in New Issue