Skip to content

Added Features#11

Open
pjobson wants to merge 2 commits into
S0raWasTaken:masterfrom
pjobson:newfeatures
Open

Added Features#11
pjobson wants to merge 2 commits into
S0raWasTaken:masterfrom
pjobson:newfeatures

Conversation

@pjobson

@pjobson pjobson commented Jun 6, 2026

Copy link
Copy Markdown

Added: Start Delay, Repeat Count, Manual Start (for use with Start Delay), multiple key presses, also inactive/active button.

image

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown

Ready to act? Review this PR in Change Stack to turn feedback into patch suggestions you can inspect and refine.

Review Change Stack

Walkthrough

This PR refactors XKeyClicker from a single-key repeat mode to a multi-key automation system. A new KeyBehavior enum and KeyAction struct enable per-key click/hold selection. The XKeyClicker struct gains fields for start delay, repeat count, key actions list, and tracking state. The GTK UI is expanded with start delay, repeat count, and manual start controls, plus a list-based key manager using TreeView. The core automation loop is refactored into explicit start/stop helpers and repeat-count sequencing logic.

Changes

Multi-key automation refactor

Layer / File(s) Summary
Data model and key-behavior abstractions
src/primitives.rs
KeyBehavior enum and KeyAction struct pair keys with click/hold selection. KeyType updated (removes Repeated, adds AddKey). XKeyClicker struct expanded with start_delay, repeat_count, current_count, key_actions, click_index, held_keys, and prev_state fields; new public methods manage and query key actions.
Core automation loop and key sequencing
src/main.rs
Introduces on_start, on_stop, and click_next_key helpers to manage activation, start delays, held-key press/release, and click sequencing. Rewrites auto_clicker loop with state-transition detection. Updates refresh_list_store to display key actions with index and behavior.
UI layout and widget structure
src/xkeyclicker.ui
Window resized to 400x450. Status indicator row added (label + GtkDrawingArea). Options section restructured: removes repeated-key selector, adds start/stop keybind button, start delay and repeat count entries, and manual start button. New "Keys to Repeat" frame with GtkTreeView (in scrolled window) and buttons to add, remove, move keys.
UI event handlers and status management
src/main.rs
GTK/glib imports and MainContext channel added. Key capture uses KeyMessage::KeyCaptured. Start-delay and repeat-count entry handlers parse input and toggle UI state. Manual-start button toggles activation. Key-list UI uses ListStore+TreeView with togglable hold behavior and add/remove/move controls. Status indicator draw callback colors based on active state; periodic timeout keeps list and status in sync.

Sequence Diagram

sequenceDiagram
  participant User
  participant GTK as GTK UI
  participant AutoClicker as auto_clicker loop
  participant OnStart
  participant ClickNextKey
  participant OnStop
  participant XKeyClicker
  User->>GTK: click manual start button
  GTK->>XKeyClicker: set active = true
  AutoClicker->>AutoClicker: detect state change
  AutoClicker->>OnStart: call on_start()
  OnStart->>XKeyClicker: apply start_delay sleep
  OnStart->>XKeyClicker: simulate press for held keys
  loop for each repeat cycle
    AutoClicker->>ClickNextKey: should click next key?
    ClickNextKey->>XKeyClicker: check current_count vs repeat_count
    alt repeat not exhausted
      ClickNextKey-->>AutoClicker: return true
      AutoClicker->>XKeyClicker: simulate press/release for click key
      AutoClicker->>XKeyClicker: increment click_index
    else repeat done
      ClickNextKey-->>AutoClicker: return false
    end
  end
  User->>GTK: click manual start button to deactivate
  GTK->>XKeyClicker: set active = false
  AutoClicker->>OnStop: call on_stop()
  OnStop->>XKeyClicker: release held keys
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

A rabbit once clicked all alone,
But now with a list fully grown—
Hold, click, or delay,
Repeating all day,
A multi-key clicker, full-blown! 🐰⌨️

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Added Features' is vague and generic, failing to convey the specific nature of the changes such as start delay, repeat count, multiple key presses, or the architectural refactoring. Use a more descriptive title that captures the main feature additions, such as 'Add start delay, repeat count, and multiple key management features' or similar.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description is related to the changeset, listing specific features added (start delay, repeat count, manual start, multiple key presses, inactive/active button) with supporting UI screenshot.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
src/xkeyclicker.ui (2)

296-301: ⚡ Quick win

Use numeric widgets for the numeric-only option fields.

src/main.rs:182-213 immediately parses both values as u64 and rewrites invalid edits back to "0". Keeping these as plain GtkEntrys makes the UI accept states the backend immediately rejects. GtkSpinButton would keep the widget contract aligned with the handler logic and avoid the reset-on-parse-failure UX.

Also applies to: 340-345


54-57: ⚡ Quick win

Normalize the top-level packing positions.

This row is assigned position=0, but the existing sibling frames still occupy positions 0, 1, and 2. That makes the final ordering depend on GTK's duplicate-position reordering behavior instead of the XML order. Please renumber or remove the explicit positions so the status row placement stays deterministic across future UI edits.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1bd69a90-9240-499b-b1d1-575e71d630df

📥 Commits

Reviewing files that changed from the base of the PR and between 00dae3b and e0cfd7a.

📒 Files selected for processing (3)
  • src/main.rs
  • src/primitives.rs
  • src/xkeyclicker.ui

Comment thread src/main.rs Outdated
Comment thread src/main.rs
Comment thread src/main.rs Outdated
Comment thread src/main.rs Outdated
1. Fixed blocking sleeps (src/main.rs:48-66)

Added interruptible_sleep() function that checks state every 100ms during delays. This ensures the user can stop during:

- Start delay (on_start)
- Click cooldown intervals (auto_clicker)

2. Empty numeric fields treated as zero (src/main.rs:230-244, 258-269)

Added handling for empty strings in start_delay_entry and repeat_count_entry to explicitly set values to 0 when the field is
cleared.

3. Fixed Entry channel/should_recv race condition (src/main.rs:274-337, 465-476)

- Replaced the mpsc channel approach with a single shared PendingEntry (Rc<RefCell<Option<Entry>>>)
- Both the KeyType and Entry reference are now stored atomically, preventing mismatch when user clicks multiple buttons quickly

4. Dispatch Entry::set_text to GTK main thread (src/main.rs:187-197, 381-414, 478-502)

- Replaced direct Entry updates from the rdev listener thread with a glib channel (glib::MainContext::channel)
- The listener thread now sends KeyMessage::KeyCaptured to the GTK main thread
- The main thread handler processes these messages and safely updates the Entry widgets

Other cleanups

- Removed unused SendBox type from primitives.rs
- Added PartialEq derive to KeyType for comparison
- Removed Debug derive from XKeyClicker (Entry doesn't implement Debug)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main.rs (1)

206-213: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Treat cleared interval fields as zero.

Clearing a cooldown field leaves the previous component in cooldown, so deleting the default 100 ms value still runs with a hidden extra 100ms until the user types another number. That makes the new interval controls report one value in the UI and use another in the worker thread.

💡 Suggested fix
             $time_type.connect_changed(move |entry| {
-                if let Ok(cooldown) = entry.buffer().text().parse::<u64>() {
+                let text = entry.buffer().text();
+                if text.is_empty() {
+                    xkc_handle_clone.cooldown.lock().unwrap().$time_type = 0;
+                } else if let Ok(cooldown) = text.parse::<u64>() {
                     xkc_handle_clone.cooldown.lock().unwrap().$time_type = cooldown;
-                } else if !entry.buffer().text().is_empty() {
+                } else {
                     entry.set_text("0");
                     xkc_handle_clone.cooldown.lock().unwrap().$time_type = 0;
                 }
             });

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4f25d03d-a1d6-457a-867d-91e731ea9ee2

📥 Commits

Reviewing files that changed from the base of the PR and between e0cfd7a and 4275c11.

📒 Files selected for processing (2)
  • src/main.rs
  • src/primitives.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/primitives.rs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant