mirror of
https://github.com/hrvach/deskhop.git
synced 2024-11-24 16:54:18 +01:00
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_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) {
|
||||
state->config.screensaver_enabled ^= 1;
|
||||
send_value(state->config.screensaver_enabled, SCREENSAVER_MSG);
|
||||
state->config.screensaver[BOARD_ROLE].enabled ^= 1;
|
||||
send_value(state->config.screensaver[BOARD_ROLE].enabled, SCREENSAVER_MSG);
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
queue_kbd_report((hid_keyboard_report_t *)packet->data, state);
|
||||
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 */
|
||||
@ -98,6 +99,7 @@ void handle_mouse_abs_uart_msg(uart_packet_t *packet, device_t *state) {
|
||||
state->mouse_y = mouse_report->y;
|
||||
|
||||
state->last_activity[BOARD_ROLE] = time_us_64();
|
||||
state->screensaver_max_time_reached[BOARD_ROLE] = false;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
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) {
|
||||
queue_kbd_report(report, state);
|
||||
state->last_activity[BOARD_ROLE] = time_us_64();
|
||||
state->screensaver_max_time_reached[BOARD_ROLE] = false;
|
||||
} else {
|
||||
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 **********/
|
||||
|
||||
#define CURRENT_CONFIG_VERSION 2
|
||||
#define CURRENT_CONFIG_VERSION 3
|
||||
|
||||
typedef struct {
|
||||
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
|
||||
} 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 */
|
||||
typedef struct {
|
||||
uint32_t magic_header;
|
||||
uint32_t version;
|
||||
uint8_t force_mouse_boot_mode;
|
||||
output_t output[NUM_SCREENS];
|
||||
uint8_t screensaver_enabled;
|
||||
screensaver_t screensaver[NUM_SCREENS];
|
||||
// Keep checksum at the end of the struct
|
||||
uint32_t checksum;
|
||||
} config_t;
|
||||
@ -214,6 +222,7 @@ typedef struct {
|
||||
|
||||
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 (-||-)
|
||||
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
|
||||
uint64_t core1_last_loop_pass; // Timestamp of last core1 loop execution
|
||||
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) {
|
||||
queue_mouse_report(report, state);
|
||||
state->last_activity[BOARD_ROLE] = time_us_64();
|
||||
state->screensaver_max_time_reached[BOARD_ROLE] = false;
|
||||
} else {
|
||||
send_packet((uint8_t *)report, MOUSE_REPORT_MSG, MOUSE_REPORT_LENGTH);
|
||||
}
|
||||
|
@ -63,17 +63,77 @@
|
||||
|
||||
/**================================================== *
|
||||
* ============== Screensaver Config ============== *
|
||||
* ==================================================
|
||||
* ================================================== *
|
||||
*
|
||||
* Defines how long does an output need to be idle for screensaver to kick in.
|
||||
* With this function, after being left idle for a certain amount of time (defined below),
|
||||
* mouse cursor starts moving around like a bouncy-ball in pong. No clicking, of course.
|
||||
* Move mouse on that active output to stop.
|
||||
* While this feature is called 'screensaver', it's not actually a
|
||||
* screensaver :) Really it's a way to ensure that some sort of mouse
|
||||
* activity will be sent to one (or both) outputs when the user has
|
||||
* 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.
|
||||
* SCREENSAVER_TIME_SEC: time in seconds
|
||||
* When the mode is active on an output, the pointer will jump around
|
||||
* 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 */
|
||||
void screensaver_task(device_t *state) {
|
||||
const uint64_t idle_timeout_us = SCREENSAVER_TIME_SEC * 1000000;
|
||||
const int mouse_move_delay = 5000;
|
||||
|
||||
static mouse_abs_report_t report = {.x = 0, .y = 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 */
|
||||
static int dx = 20;
|
||||
static int dy = 25;
|
||||
|
||||
/* If we're not enabled, nothing to do here. */
|
||||
if (!state->config.screensaver_enabled)
|
||||
/* If the maximum time has been reached, nothing to do here. */
|
||||
if (state->screensaver_max_time_reached[BOARD_ROLE]) {
|
||||
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. */
|
||||
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;
|
||||
}
|
||||
|
||||
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. */
|
||||
if ((time_us_32()) - last_pointer_move < mouse_move_delay)
|
||||
|
Loading…
Reference in New Issue
Block a user