Skip to content

Conversation

@vrnvorona
Copy link

Added two things

  1. Ability to reisntall driver from GUI
  2. Point save config to config file for bit of UX improvement

To do this I've added LocateProjectRoot and storing it for reuse. It searches down 6 levels to find scripts.

Maybe it's not ideal solution, done with Codex, but if it's good or close to it - happy to help

Testing - tried it a couple of times, save works and reinstall also works (change something - apply - save config to config.h - reinstall - restart GUI and it's using new config).

@vrnvorona
Copy link
Author

@AndyFilter FYI, took a bit of time to maybe improve UX with persistent config and export based on idea that came to me from thread #26

@AndyFilter
Copy link
Owner

Hey, the commit looks great I've wanted to improve the export functionality for some time now.
I didn't even know it's possible to open the file dialogue in a specific directory, so that's awesome. It's non intrusive and simplifies the process in some scenarios.

When it comes to the reinstall button there are a couple of things I'd like to point out.

  1. Having a separate menu item just for one button is not very... pleasant (for the lack of better words).
    What I was thinking in this regard is to put it as special option for the "Apply" button (Small UX annoyances #57 (comment)).
  2. The reinstallation (uninstall + install) can be wildly varied for different distros. Ubuntu may use the install.sh + uninstall.sh, but Arch has it's own install script, and I'm not even going to pretend like I know what's going on with Nix, haha. Also I plan to move to packages (at least for debian (You can check out the PR for it)), and I'm currently facing the same issue but without the install scripts, or a nice way to reinstall the driver there. So I'll either have to think of some way around it, or perhaps move the driver API to something different, which is way too much work for now.
    The proposed change would only work for users that installed the driver with the install/uninstall scripts.
  3. The code is quite complex for such a simple task, but I also like the approach and flexibility it provides, nonetheless it would require some refactoring, as I'd rather not have all these functions on top of the main file.

I'll test the changes and think about the possible options this week.

@vrnvorona
Copy link
Author

Valid points for distros. Maybe it's doable to put distro detection into scripts so that them become more universal? I myself have even less knowledge with different distros and used only Ubuntu. Or even reversely, put all installation logic in GUI with OS detection (/etc/os-release and parsing ID/ID_LIKE) and make install path of "build gui -> press button ; for reinstall reuse logic"

For button - I assumed that would be least impactful version, and File submenu didn't sound like good place, though it's not hard to move there.

For saving/reinstalling on apply we'd need some UX to have checkbox or something or third button like "Apply and make default" or something so that save+reinstall is controlled by user and transparent. When trying out settings constant building doesn't make sense.
I can make a change for third button with tooltip on hover right next to apply instead of More submenu, but it still would call scripts instead of more robust way.

And finally for complexity - I agree, just a repeated note that I have negative experience with C++ and that was coded with Codex GPT in 30 mins with a bit of review, there could be better ways to handle this code, or maybe even better way to detect CWD instead of search.

@AndyFilter
Copy link
Owner

Valid points for distros. Maybe it's doable to put distro detection into scripts so that them become more universal?

It perhaps is doable, but unfortunately there are as many distros as there are linux users because of how flexible Linux is. Trying to account for every possible way someone could install this program, and maybe even have their package manager configured is a task for Sisyphus. Supporting such a feature is playing with fire, as I'm sure sooner or later someone with pacman on Ubuntu will open an issue saying that "Ubunu support doesn't work", and because technically the program supports distro-independant features I'll need to resolve that issue.
I may sound overly pessimistic, but I really think this is very difficult to support on Linux. It would simply require a different case for every user.

For saving/reinstalling on apply we'd need some UX to have checkbox or something or third button like "Apply and make default" or something so that save+reinstall is controlled by user and transparent.

What I had in mind was to simply inform the user about additional functionalities of the Apply button on hover:
image
(This might be suboptimal when someone right-clicks this button by a mistake)

or add a whole new context menu (on right click):
image
(but this looks kinda junk)

I didn't want to add additional UI elements to not contribute to the clutter that is already present.

And finally for complexity - I agree, just a repeated note that I have negative experience with C++ and that was coded with Codex GPT in 30 mins with a bit of review, there could be better ways to handle this code, or maybe even better way to detect CWD instead of search.

I get it, maybe it'd be best to move the stuff from this PR and some other functions from the main to a new file, like ..._helper or something along those lines, but I'll need a good idea about how it should be done.

@vrnvorona
Copy link
Author

Ctrl+click may be better then to avoid accidental reinstalls.

@vrnvorona
Copy link
Author

vrnvorona commented Oct 19, 2025

Btw, I tinkered a bit with AI about codebase, maybe we could persist changes with modprobe/depmod? Saving with Apply into conf file and presumably dkms will pick up on reboot?

I did this so far, will test in a bit with reboot

1 - created /etc/modprobe.d/yeetmouse.conf file with exported params like so:

options yeetmouse Sensitivity=0.176 SensitivityY=1.2 OutputCap=0 InputCap=0 Offset=0 Acceleration=0.025 Exponent=2.6 Midpoint=3 Motivity=1.5 PreScale=0.25 AccelerationMode=8 UseSmoothing=1 RotationAngle=-0.1309 AngleSnap_Threshold=0 AngleSnap_Angle=0 LutSize=96 LutDataBuf="17.000000;1.000000;17.810062;1.000426;18.579948;1.001668;19.347439;1.003795;20.073143;1.006700;20.756680;1.010308;21.398670;1.014540;21.998503;1.019301;22.592049;1.024852;23.141388;1.030803;23.646927;1.037034;24.109240;1.043420;24.529097;1.049838;24.907425;1.056165;25.279005;1.062918;25.610624;1.069429;25.936281;1.076298;26.254938;1.083509;26.566345;1.091054;26.870258;1.098926;27.166473;1.107117;27.454855;1.115617;27.735313;1.124416;28.007530;1.133494;28.271479;1.142837;28.527187;1.152431;28.774708;1.162261;29.014166;1.172312;29.245687;1.182570;29.469364;1.193015;29.685465;1.203636;29.894228;1.214419;30.095915;1.225351;30.290829;1.236421;30.479244;1.247618;30.661451;1.258928;30.837652;1.270336;31.008295;1.281839;31.173685;1.293429;31.334152;1.305097;31.490011;1.316838;31.641548;1.328641;31.788984;1.340494;31.932747;1.352398;32.073132;1.364350;32.223999;1.377544;32.397987;1.393189;32.606628;1.412513;32.860554;1.436750;33.194878;1.469565;33.621815;1.512177;33.928097;1.542598;34.177109;1.566888;34.393368;1.587486;34.575626;1.604399;34.735462;1.618851;34.885361;1.632056;35.024754;1.644017;35.167465;1.655936;35.313854;1.667812;35.464142;1.679632;35.618633;1.691389;35.777641;1.703077;35.941486;1.714688;36.110531;1.726219;36.302879;1.738800;36.502289;1.751258;36.709175;1.763579;36.923935;1.775748;37.146957;1.787751;37.378613;1.799570;37.619236;1.811187;37.869125;1.822585;38.128540;1.833744;38.397690;1.844643;38.676723;1.855263;38.965714;1.865584;39.264683;1.875584;39.573563;1.885245;39.892223;1.894549;40.220398;1.903477;40.557632;1.912012;40.903671;1.920142;41.258106;1.927860;41.653866;1.935802;42.092575;1.943835;42.575691;1.951821;43.139542;1.960102;43.749702;1.967918;44.445019;1.975520;45.188072;1.982267;46.015026;1.988284;46.926853;1.993300;47.883366;1.996943;48.919655;1.999235;50.000000;2.000000;"

2 - ran 3 commands:

sudo depmod -a ; sudo modprobe -r yeetmouse && sudo modprobe yeetmouse

and on GUI restart it's updated, and, presumably, will work on reboot. So if it does, we can change reinstall to calling these and maybe add option to persistently update conf on apply. Afaik depmod and modprobe is very well supported on all distros, but I may be wrong as maybe not all isntallation methods even use DKMS

UPD: Yep, it works. Changing .conf and running 3 commands, then log-off and log-in works. I will alter double-check full reboot in case log off is not enough

@AndyFilter
Copy link
Owner

This looks interesting, I think it should work across reboots. And it does provide more flexibility across multiple distros, because I know for sure that Arch and Ubuntu use DKMS, unsure about Nix tho.

Ctrl+click may be better then to avoid accidental reinstalls.

I don't know, that might be unintuitive for some. To prevent miss-clicks both approaches I presented can be combined, so that when hovered a note is presented and then after right clicking a menu is presented with an option to reinstall.

@vrnvorona
Copy link
Author

vrnvorona commented Oct 19, 2025

This looks interesting, I think it should work across reboots. And it does provide more flexibility across multiple distros, because I know for sure that Arch and Ubuntu use DKMS, unsure about Nix tho.

I failed to edit, but on reboot my installation broke - i had to install yeetmouse again for some reason (with message that driver is not installed) and it took defaults from config.h as expected. I will try to research why it had happened.

UPD: tried a bit more and seems to be working. No idea what happened that time, but I placed config in modprobe.d folder and edited it a bunch of times and used those three commands and it works fine on restarts and applies new values. I guess next step would be to create functionality to create/edit this file with sudo and apply with those three commands, and later use your idea for elevated apply to do it with better UX. Since this file uses params from driver I guess there is already mapping present (as current apply does similar call to driver). I didn't yet test fully, but so far the only concern is that file needs to be without new lines with \ etc.

@AndyFilter
Copy link
Owner

AndyFilter commented Oct 19, 2025

Alright, this change looks promising. I've wrote some code to export the config to that .conf format and it works well. The only issue I have is that the AccelerationMode parameter can't be expressed as an enum entry, rather it has to be converted to a numerical value, which is not very clean. So, this:
AccelerationMode=7
instead of this:
AccelerationMode=AccelMode_Jump.

The code I referenced earlier (but I'm sure a clanker could write it in a safer manner):

    std::string ExportModprobeConfig(Parameters params, bool save_to_file) {
        std::stringstream res_ss;

        res_ss << "options yeetmouse";

        try {
            res_ss << " Sensitivity=" << params.sens;
            res_ss << " SensitivityY=" << (params.use_anisotropy ? params.sensY : params.sens);
            res_ss << " OutputCap=" << params.outCap;
            res_ss << " InputCap=" << params.inCap;
            res_ss << " Offset=" << params.offset;
            res_ss << " Acceleration=" << params.accel;
            res_ss << " Exponent=" << params.exponent;
            res_ss << " Midpoint=" << params.midpoint;
            res_ss << " Motivity=" << params.motivity;
            res_ss << " PreScale=" << params.preScale;
            res_ss << " AccelerationMode=" << params.accelMode;
            res_ss << " UseSmoothing=" << params.useSmoothing;
            res_ss << " RotationAngle=" << params.rotation;
            res_ss << " AngleSnap_Threshold=" << params.as_threshold;
            res_ss << " AngleSnap_Angle=" << params.as_angle;
            res_ss << " LutSize=" << params.LUT_size;
            res_ss << " LutDataBuf=" << (params.LUT_size > 1
                                             ? DriverHelper::EncodeLutData(
                                                 params.LUT_data_x, params.LUT_data_y, params.LUT_size)
                                             : "\"\"");

            if (save_to_file) {
                std::ofstream out_file("/etc/modprobe.d/yeetmouse.conf");

                if (!out_file.good())
                    return "";

                out_file << res_ss.str();

                out_file.close();
            }
            return res_ss.str();
        } catch (std::exception &ex) {
            printf("Failed Export: %s\n", ex.what());
        }

        return "";
    }

(it's the same as the other export functions, just with changed param names and constant out file name)

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.

2 participants