mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-26 22:40:25 +00:00
Add HID mouse auto-clicker. (#2627)
* Add HID mouse auto-clicker. * Add click rate adjustment to HID auto-clicker. * Fix formatting. * HidRemote: modify jiggler/clicker event filter and allow repeat to change click rate --------- Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
parent
c3ececcf96
commit
71e85ac367
6 changed files with 254 additions and 1 deletions
22
applications/external/hid_app/hid.c
vendored
22
applications/external/hid_app/hid.c
vendored
|
@ -11,6 +11,7 @@ enum HidDebugSubmenuIndex {
|
||||||
HidSubmenuIndexMedia,
|
HidSubmenuIndexMedia,
|
||||||
HidSubmenuIndexTikTok,
|
HidSubmenuIndexTikTok,
|
||||||
HidSubmenuIndexMouse,
|
HidSubmenuIndexMouse,
|
||||||
|
HidSubmenuIndexMouseClicker,
|
||||||
HidSubmenuIndexMouseJiggler,
|
HidSubmenuIndexMouseJiggler,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,6 +33,9 @@ static void hid_submenu_callback(void* context, uint32_t index) {
|
||||||
} else if(index == HidSubmenuIndexTikTok) {
|
} else if(index == HidSubmenuIndexTikTok) {
|
||||||
app->view_id = BtHidViewTikTok;
|
app->view_id = BtHidViewTikTok;
|
||||||
view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewTikTok);
|
view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewTikTok);
|
||||||
|
} else if(index == HidSubmenuIndexMouseClicker) {
|
||||||
|
app->view_id = HidViewMouseClicker;
|
||||||
|
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouseClicker);
|
||||||
} else if(index == HidSubmenuIndexMouseJiggler) {
|
} else if(index == HidSubmenuIndexMouseJiggler) {
|
||||||
app->view_id = HidViewMouseJiggler;
|
app->view_id = HidViewMouseJiggler;
|
||||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouseJiggler);
|
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouseJiggler);
|
||||||
|
@ -53,6 +57,7 @@ static void bt_hid_connection_status_changed_callback(BtStatus status, void* con
|
||||||
hid_keyboard_set_connected_status(hid->hid_keyboard, connected);
|
hid_keyboard_set_connected_status(hid->hid_keyboard, connected);
|
||||||
hid_media_set_connected_status(hid->hid_media, connected);
|
hid_media_set_connected_status(hid->hid_media, connected);
|
||||||
hid_mouse_set_connected_status(hid->hid_mouse, connected);
|
hid_mouse_set_connected_status(hid->hid_mouse, connected);
|
||||||
|
hid_mouse_clicker_set_connected_status(hid->hid_mouse_clicker, connected);
|
||||||
hid_mouse_jiggler_set_connected_status(hid->hid_mouse_jiggler, connected);
|
hid_mouse_jiggler_set_connected_status(hid->hid_mouse_jiggler, connected);
|
||||||
hid_tiktok_set_connected_status(hid->hid_tiktok, connected);
|
hid_tiktok_set_connected_status(hid->hid_tiktok, connected);
|
||||||
}
|
}
|
||||||
|
@ -114,6 +119,12 @@ Hid* hid_alloc(HidTransport transport) {
|
||||||
hid_submenu_callback,
|
hid_submenu_callback,
|
||||||
app);
|
app);
|
||||||
}
|
}
|
||||||
|
submenu_add_item(
|
||||||
|
app->device_type_submenu,
|
||||||
|
"Mouse Clicker",
|
||||||
|
HidSubmenuIndexMouseClicker,
|
||||||
|
hid_submenu_callback,
|
||||||
|
app);
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
app->device_type_submenu,
|
app->device_type_submenu,
|
||||||
"Mouse Jiggler",
|
"Mouse Jiggler",
|
||||||
|
@ -172,6 +183,15 @@ Hid* hid_app_alloc_view(void* context) {
|
||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
app->view_dispatcher, HidViewMouse, hid_mouse_get_view(app->hid_mouse));
|
app->view_dispatcher, HidViewMouse, hid_mouse_get_view(app->hid_mouse));
|
||||||
|
|
||||||
|
// Mouse clicker view
|
||||||
|
app->hid_mouse_clicker = hid_mouse_clicker_alloc(app);
|
||||||
|
view_set_previous_callback(
|
||||||
|
hid_mouse_clicker_get_view(app->hid_mouse_clicker), hid_exit_confirm_view);
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher,
|
||||||
|
HidViewMouseClicker,
|
||||||
|
hid_mouse_clicker_get_view(app->hid_mouse_clicker));
|
||||||
|
|
||||||
// Mouse jiggler view
|
// Mouse jiggler view
|
||||||
app->hid_mouse_jiggler = hid_mouse_jiggler_alloc(app);
|
app->hid_mouse_jiggler = hid_mouse_jiggler_alloc(app);
|
||||||
view_set_previous_callback(
|
view_set_previous_callback(
|
||||||
|
@ -205,6 +225,8 @@ void hid_free(Hid* app) {
|
||||||
hid_media_free(app->hid_media);
|
hid_media_free(app->hid_media);
|
||||||
view_dispatcher_remove_view(app->view_dispatcher, HidViewMouse);
|
view_dispatcher_remove_view(app->view_dispatcher, HidViewMouse);
|
||||||
hid_mouse_free(app->hid_mouse);
|
hid_mouse_free(app->hid_mouse);
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, HidViewMouseClicker);
|
||||||
|
hid_mouse_clicker_free(app->hid_mouse_clicker);
|
||||||
view_dispatcher_remove_view(app->view_dispatcher, HidViewMouseJiggler);
|
view_dispatcher_remove_view(app->view_dispatcher, HidViewMouseJiggler);
|
||||||
hid_mouse_jiggler_free(app->hid_mouse_jiggler);
|
hid_mouse_jiggler_free(app->hid_mouse_jiggler);
|
||||||
view_dispatcher_remove_view(app->view_dispatcher, BtHidViewTikTok);
|
view_dispatcher_remove_view(app->view_dispatcher, BtHidViewTikTok);
|
||||||
|
|
2
applications/external/hid_app/hid.h
vendored
2
applications/external/hid_app/hid.h
vendored
|
@ -20,6 +20,7 @@
|
||||||
#include "views/hid_keyboard.h"
|
#include "views/hid_keyboard.h"
|
||||||
#include "views/hid_media.h"
|
#include "views/hid_media.h"
|
||||||
#include "views/hid_mouse.h"
|
#include "views/hid_mouse.h"
|
||||||
|
#include "views/hid_mouse_clicker.h"
|
||||||
#include "views/hid_mouse_jiggler.h"
|
#include "views/hid_mouse_jiggler.h"
|
||||||
#include "views/hid_tiktok.h"
|
#include "views/hid_tiktok.h"
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ struct Hid {
|
||||||
HidKeyboard* hid_keyboard;
|
HidKeyboard* hid_keyboard;
|
||||||
HidMedia* hid_media;
|
HidMedia* hid_media;
|
||||||
HidMouse* hid_mouse;
|
HidMouse* hid_mouse;
|
||||||
|
HidMouseClicker* hid_mouse_clicker;
|
||||||
HidMouseJiggler* hid_mouse_jiggler;
|
HidMouseJiggler* hid_mouse_jiggler;
|
||||||
HidTikTok* hid_tiktok;
|
HidTikTok* hid_tiktok;
|
||||||
|
|
||||||
|
|
1
applications/external/hid_app/views.h
vendored
1
applications/external/hid_app/views.h
vendored
|
@ -4,6 +4,7 @@ typedef enum {
|
||||||
HidViewKeyboard,
|
HidViewKeyboard,
|
||||||
HidViewMedia,
|
HidViewMedia,
|
||||||
HidViewMouse,
|
HidViewMouse,
|
||||||
|
HidViewMouseClicker,
|
||||||
HidViewMouseJiggler,
|
HidViewMouseJiggler,
|
||||||
BtHidViewTikTok,
|
BtHidViewTikTok,
|
||||||
HidViewExitConfirm,
|
HidViewExitConfirm,
|
||||||
|
|
214
applications/external/hid_app/views/hid_mouse_clicker.c
vendored
Normal file
214
applications/external/hid_app/views/hid_mouse_clicker.c
vendored
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
#include "hid_mouse_clicker.h"
|
||||||
|
#include <gui/elements.h>
|
||||||
|
#include "../hid.h"
|
||||||
|
|
||||||
|
#include "hid_icons.h"
|
||||||
|
|
||||||
|
#define TAG "HidMouseClicker"
|
||||||
|
#define DEFAULT_CLICK_RATE 1
|
||||||
|
#define MAXIMUM_CLICK_RATE 60
|
||||||
|
|
||||||
|
struct HidMouseClicker {
|
||||||
|
View* view;
|
||||||
|
Hid* hid;
|
||||||
|
FuriTimer* timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool connected;
|
||||||
|
bool running;
|
||||||
|
int rate;
|
||||||
|
HidTransport transport;
|
||||||
|
} HidMouseClickerModel;
|
||||||
|
|
||||||
|
static void hid_mouse_clicker_start_or_restart_timer(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
HidMouseClicker* hid_mouse_clicker = context;
|
||||||
|
|
||||||
|
if(furi_timer_is_running(hid_mouse_clicker->timer)) {
|
||||||
|
furi_timer_stop(hid_mouse_clicker->timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
with_view_model(
|
||||||
|
hid_mouse_clicker->view,
|
||||||
|
HidMouseClickerModel * model,
|
||||||
|
{
|
||||||
|
furi_timer_start(
|
||||||
|
hid_mouse_clicker->timer, furi_kernel_get_tick_frequency() / model->rate);
|
||||||
|
},
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hid_mouse_clicker_draw_callback(Canvas* canvas, void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
HidMouseClickerModel* model = context;
|
||||||
|
|
||||||
|
// Header
|
||||||
|
if(model->transport == HidTransportBle) {
|
||||||
|
if(model->connected) {
|
||||||
|
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||||
|
} else {
|
||||||
|
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Mouse Clicker");
|
||||||
|
|
||||||
|
// Ok
|
||||||
|
canvas_draw_icon(canvas, 63, 25, &I_Space_65x18);
|
||||||
|
if(model->running) {
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
|
||||||
|
FuriString* rate_label = furi_string_alloc();
|
||||||
|
furi_string_printf(rate_label, "%d clicks/s\n\nUp / Down", model->rate);
|
||||||
|
elements_multiline_text(canvas, AlignLeft, 35, furi_string_get_cstr(rate_label));
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
furi_string_free(rate_label);
|
||||||
|
|
||||||
|
elements_slightly_rounded_box(canvas, 66, 27, 60, 13);
|
||||||
|
canvas_set_color(canvas, ColorWhite);
|
||||||
|
} else {
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
elements_multiline_text(canvas, AlignLeft, 35, "Press Start\nto start\nclicking");
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
}
|
||||||
|
canvas_draw_icon(canvas, 74, 29, &I_Ok_btn_9x9);
|
||||||
|
if(model->running) {
|
||||||
|
elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Stop");
|
||||||
|
} else {
|
||||||
|
elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Start");
|
||||||
|
}
|
||||||
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
|
||||||
|
// Back
|
||||||
|
canvas_draw_icon(canvas, 74, 49, &I_Pin_back_arrow_10x8);
|
||||||
|
elements_multiline_text_aligned(canvas, 91, 57, AlignLeft, AlignBottom, "Quit");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hid_mouse_clicker_timer_callback(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
HidMouseClicker* hid_mouse_clicker = context;
|
||||||
|
with_view_model(
|
||||||
|
hid_mouse_clicker->view,
|
||||||
|
HidMouseClickerModel * model,
|
||||||
|
{
|
||||||
|
if(model->running) {
|
||||||
|
hid_hal_mouse_press(hid_mouse_clicker->hid, HID_MOUSE_BTN_LEFT);
|
||||||
|
hid_hal_mouse_release(hid_mouse_clicker->hid, HID_MOUSE_BTN_LEFT);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hid_mouse_clicker_enter_callback(void* context) {
|
||||||
|
hid_mouse_clicker_start_or_restart_timer(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hid_mouse_clicker_exit_callback(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
HidMouseClicker* hid_mouse_clicker = context;
|
||||||
|
furi_timer_stop(hid_mouse_clicker->timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool hid_mouse_clicker_input_callback(InputEvent* event, void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
HidMouseClicker* hid_mouse_clicker = context;
|
||||||
|
|
||||||
|
bool consumed = false;
|
||||||
|
bool rate_changed = false;
|
||||||
|
|
||||||
|
if(event->type != InputTypeShort && event->type != InputTypeRepeat) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
with_view_model(
|
||||||
|
hid_mouse_clicker->view,
|
||||||
|
HidMouseClickerModel * model,
|
||||||
|
{
|
||||||
|
switch(event->key) {
|
||||||
|
case InputKeyOk:
|
||||||
|
model->running = !model->running;
|
||||||
|
consumed = true;
|
||||||
|
break;
|
||||||
|
case InputKeyUp:
|
||||||
|
if(model->rate < MAXIMUM_CLICK_RATE) {
|
||||||
|
model->rate++;
|
||||||
|
}
|
||||||
|
rate_changed = true;
|
||||||
|
consumed = true;
|
||||||
|
break;
|
||||||
|
case InputKeyDown:
|
||||||
|
if(model->rate > 1) {
|
||||||
|
model->rate--;
|
||||||
|
}
|
||||||
|
rate_changed = true;
|
||||||
|
consumed = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
consumed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
true);
|
||||||
|
|
||||||
|
if(rate_changed) {
|
||||||
|
hid_mouse_clicker_start_or_restart_timer(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
HidMouseClicker* hid_mouse_clicker_alloc(Hid* hid) {
|
||||||
|
HidMouseClicker* hid_mouse_clicker = malloc(sizeof(HidMouseClicker));
|
||||||
|
|
||||||
|
hid_mouse_clicker->view = view_alloc();
|
||||||
|
view_set_context(hid_mouse_clicker->view, hid_mouse_clicker);
|
||||||
|
view_allocate_model(
|
||||||
|
hid_mouse_clicker->view, ViewModelTypeLocking, sizeof(HidMouseClickerModel));
|
||||||
|
view_set_draw_callback(hid_mouse_clicker->view, hid_mouse_clicker_draw_callback);
|
||||||
|
view_set_input_callback(hid_mouse_clicker->view, hid_mouse_clicker_input_callback);
|
||||||
|
view_set_enter_callback(hid_mouse_clicker->view, hid_mouse_clicker_enter_callback);
|
||||||
|
view_set_exit_callback(hid_mouse_clicker->view, hid_mouse_clicker_exit_callback);
|
||||||
|
|
||||||
|
hid_mouse_clicker->hid = hid;
|
||||||
|
|
||||||
|
hid_mouse_clicker->timer = furi_timer_alloc(
|
||||||
|
hid_mouse_clicker_timer_callback, FuriTimerTypePeriodic, hid_mouse_clicker);
|
||||||
|
|
||||||
|
with_view_model(
|
||||||
|
hid_mouse_clicker->view,
|
||||||
|
HidMouseClickerModel * model,
|
||||||
|
{
|
||||||
|
model->transport = hid->transport;
|
||||||
|
model->rate = DEFAULT_CLICK_RATE;
|
||||||
|
},
|
||||||
|
true);
|
||||||
|
|
||||||
|
return hid_mouse_clicker;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hid_mouse_clicker_free(HidMouseClicker* hid_mouse_clicker) {
|
||||||
|
furi_assert(hid_mouse_clicker);
|
||||||
|
|
||||||
|
furi_timer_stop(hid_mouse_clicker->timer);
|
||||||
|
furi_timer_free(hid_mouse_clicker->timer);
|
||||||
|
|
||||||
|
view_free(hid_mouse_clicker->view);
|
||||||
|
|
||||||
|
free(hid_mouse_clicker);
|
||||||
|
}
|
||||||
|
|
||||||
|
View* hid_mouse_clicker_get_view(HidMouseClicker* hid_mouse_clicker) {
|
||||||
|
furi_assert(hid_mouse_clicker);
|
||||||
|
return hid_mouse_clicker->view;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hid_mouse_clicker_set_connected_status(HidMouseClicker* hid_mouse_clicker, bool connected) {
|
||||||
|
furi_assert(hid_mouse_clicker);
|
||||||
|
with_view_model(
|
||||||
|
hid_mouse_clicker->view,
|
||||||
|
HidMouseClickerModel * model,
|
||||||
|
{ model->connected = connected; },
|
||||||
|
true);
|
||||||
|
}
|
14
applications/external/hid_app/views/hid_mouse_clicker.h
vendored
Normal file
14
applications/external/hid_app/views/hid_mouse_clicker.h
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gui/view.h>
|
||||||
|
|
||||||
|
typedef struct Hid Hid;
|
||||||
|
typedef struct HidMouseClicker HidMouseClicker;
|
||||||
|
|
||||||
|
HidMouseClicker* hid_mouse_clicker_alloc(Hid* bt_hid);
|
||||||
|
|
||||||
|
void hid_mouse_clicker_free(HidMouseClicker* hid_mouse_clicker);
|
||||||
|
|
||||||
|
View* hid_mouse_clicker_get_view(HidMouseClicker* hid_mouse_clicker);
|
||||||
|
|
||||||
|
void hid_mouse_clicker_set_connected_status(HidMouseClicker* hid_mouse_clicker, bool connected);
|
|
@ -95,7 +95,7 @@ static bool hid_mouse_jiggler_input_callback(InputEvent* event, void* context) {
|
||||||
|
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event->key == InputKeyOk) {
|
if(event->type == InputTypeShort && event->key == InputKeyOk) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
hid_mouse_jiggler->view,
|
hid_mouse_jiggler->view,
|
||||||
HidMouseJigglerModel * model,
|
HidMouseJigglerModel * model,
|
||||||
|
|
Loading…
Reference in a new issue