mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-23 04:53:08 +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,
|
||||
HidSubmenuIndexTikTok,
|
||||
HidSubmenuIndexMouse,
|
||||
HidSubmenuIndexMouseClicker,
|
||||
HidSubmenuIndexMouseJiggler,
|
||||
};
|
||||
|
||||
|
@ -32,6 +33,9 @@ static void hid_submenu_callback(void* context, uint32_t index) {
|
|||
} else if(index == HidSubmenuIndexTikTok) {
|
||||
app->view_id = 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) {
|
||||
app->view_id = 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_media_set_connected_status(hid->hid_media, 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_tiktok_set_connected_status(hid->hid_tiktok, connected);
|
||||
}
|
||||
|
@ -114,6 +119,12 @@ Hid* hid_alloc(HidTransport transport) {
|
|||
hid_submenu_callback,
|
||||
app);
|
||||
}
|
||||
submenu_add_item(
|
||||
app->device_type_submenu,
|
||||
"Mouse Clicker",
|
||||
HidSubmenuIndexMouseClicker,
|
||||
hid_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
app->device_type_submenu,
|
||||
"Mouse Jiggler",
|
||||
|
@ -172,6 +183,15 @@ Hid* hid_app_alloc_view(void* context) {
|
|||
view_dispatcher_add_view(
|
||||
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
|
||||
app->hid_mouse_jiggler = hid_mouse_jiggler_alloc(app);
|
||||
view_set_previous_callback(
|
||||
|
@ -205,6 +225,8 @@ void hid_free(Hid* app) {
|
|||
hid_media_free(app->hid_media);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, HidViewMouse);
|
||||
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);
|
||||
hid_mouse_jiggler_free(app->hid_mouse_jiggler);
|
||||
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_media.h"
|
||||
#include "views/hid_mouse.h"
|
||||
#include "views/hid_mouse_clicker.h"
|
||||
#include "views/hid_mouse_jiggler.h"
|
||||
#include "views/hid_tiktok.h"
|
||||
|
||||
|
@ -43,6 +44,7 @@ struct Hid {
|
|||
HidKeyboard* hid_keyboard;
|
||||
HidMedia* hid_media;
|
||||
HidMouse* hid_mouse;
|
||||
HidMouseClicker* hid_mouse_clicker;
|
||||
HidMouseJiggler* hid_mouse_jiggler;
|
||||
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,
|
||||
HidViewMedia,
|
||||
HidViewMouse,
|
||||
HidViewMouseClicker,
|
||||
HidViewMouseJiggler,
|
||||
BtHidViewTikTok,
|
||||
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;
|
||||
|
||||
if(event->key == InputKeyOk) {
|
||||
if(event->type == InputTypeShort && event->key == InputKeyOk) {
|
||||
with_view_model(
|
||||
hid_mouse_jiggler->view,
|
||||
HidMouseJigglerModel * model,
|
||||
|
|
Loading…
Reference in a new issue