diff --git a/DBusInterface.md b/DBusInterface.md index de344422..b42cd1e2 100644 --- a/DBusInterface.md +++ b/DBusInterface.md @@ -108,6 +108,15 @@ org.freedesktop.ratbag1.Profile The index of this profile +#### `Enabled` +- type: `b`, read-write, mutable + +True if this is the profile is enabled, false otherwise. + +Note that a disabled profile might not have correct bindings, so it's +a good thing to rebind everything before calling `Commit()` on the +**org.freedesktop.ratbag1.Device**. + #### `Resolutions` - type: `ao`, read-only, mutable diff --git a/ratbagd/ratbagd-profile.c b/ratbagd/ratbagd-profile.c index 1ab3b28c..40cbd137 100644 --- a/ratbagd/ratbagd-profile.c +++ b/ratbagd/ratbagd-profile.c @@ -302,8 +302,57 @@ static int ratbagd_profile_set_active(sd_bus_message *m, ratbag_profile_set_active(profile->lib_profile)); } +static int +ratbagd_profile_set_enabled(sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *m, + void *userdata, + sd_bus_error *error) +{ + struct ratbagd_profile *profile = userdata; + bool enabled; + int r; + + r = sd_bus_message_read(m, "b", &enabled); + if (r < 0) + return r; + + r = ratbag_profile_set_enabled(profile->lib_profile, enabled); + if (r == 0) { + sd_bus *bus = sd_bus_message_get_bus(m); + sd_bus_emit_properties_changed(bus, + profile->path, + RATBAGD_NAME_ROOT ".Profile", + "Enabled", + NULL); + } + + return r; +} + +static int +ratbagd_profile_is_enabled(sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) +{ + struct ratbagd_profile *profile = userdata; + bool enabled = ratbag_profile_is_enabled(profile->lib_profile) != 0; + + return sd_bus_message_append(reply, "b", enabled); +} + const sd_bus_vtable ratbagd_profile_vtable[] = { SD_BUS_VTABLE_START(0), + SD_BUS_WRITABLE_PROPERTY("Enabled", "b", + ratbagd_profile_is_enabled, + ratbagd_profile_set_enabled, 0, + SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Index", "u", NULL, offsetof(struct ratbagd_profile, index), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Resolutions", "ao", ratbagd_profile_get_resolutions, 0, 0), SD_BUS_PROPERTY("Buttons", "ao", ratbagd_profile_get_buttons, 0, 0), diff --git a/ratbagd/ratbagd.c b/ratbagd/ratbagd.c index 2290b56c..a4058513 100644 --- a/ratbagd/ratbagd.c +++ b/ratbagd/ratbagd.c @@ -190,7 +190,7 @@ static int ratbagd_get_themes(sd_bus *bus, * error conditions. */ static const struct ratbag_test_device ratbagd_test_device_descr = { - .num_profiles = 3, + .num_profiles = 4, .num_resolutions = 3, .num_buttons = 4, .num_leds = 3, @@ -282,9 +282,12 @@ static const struct ratbag_test_device ratbagd_test_device_descr = { .hz = 3, .brightness = 40 } + }, + .active = false, + .dflt = false, }, - .active = false, - .dflt = false, + { + .disabled = true, }, }, .destroyed = NULL, diff --git a/src/driver-test.c b/src/driver-test.c index a8fb65c7..90e2faee 100644 --- a/src/driver-test.c +++ b/src/driver-test.c @@ -35,24 +35,41 @@ test_read_profile(struct ratbag_profile *profile, unsigned int index) struct ratbag_test_device *d = ratbag_get_drv_data(profile->device); struct ratbag_test_profile *p; struct ratbag_test_resolution *r; + struct ratbag_resolution *res; unsigned int i; + bool active_set = false; + bool default_set = false; assert(index < d->num_profiles); p = &d->profiles[index]; for (i = 0; i < d->num_resolutions; i++) { - struct ratbag_resolution *res; - r = &p->resolutions[i]; res = ratbag_resolution_init(profile, i, r->xres, r->yres, r->hz); res->is_active = r->active; + if (r->active) + active_set = true; res->is_default = r->dflt; + if (r->dflt) + default_set = true; res->capabilities = r->caps; res->hz = r->hz; assert(res); } + /* special case triggered by the test suite when num_resolutions is 0 */ + if (d->num_resolutions) { + res = ratbag_profile_get_resolution(profile, 0); + assert(res); + if (!active_set) + res->is_active = true; + if (!default_set) + res->is_default = true; + ratbag_resolution_unref(res); + } + profile->is_active = p->active; + profile->is_enabled = !p->disabled; } static int @@ -197,8 +214,10 @@ test_probe(struct ratbag_device *device, const void *data) test_device->num_resolutions, test_device->num_buttons, test_device->num_leds); - if (test_device->num_profiles > 1) + if (test_device->num_profiles > 1) { ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_BUTTON_MACROS); + ratbag_device_set_capability(device, RATBAG_DEVICE_CAP_DISABLE_PROFILE); + } return 0; } diff --git a/src/libratbag-test.h b/src/libratbag-test.h index f9755358..d62276d5 100644 --- a/src/libratbag-test.h +++ b/src/libratbag-test.h @@ -68,6 +68,7 @@ struct ratbag_test_profile { struct ratbag_test_led leds[RATBAG_TEST_MAX_LEDS]; bool active; bool dflt; + bool disabled; }; struct ratbag_test_device { diff --git a/tools/ratbagctl.in b/tools/ratbagctl.in index 1dbceeaa..d0277e94 100755 --- a/tools/ratbagctl.in +++ b/tools/ratbagctl.in @@ -165,13 +165,15 @@ def print_resolution(d, p, r, level): def print_profile(d, p, level): - print(" " * level + "Resolutions:") - for r in p.resolutions: - print_resolution(d, p, r, level + 2) - for b in p.buttons: - print_button(d, p, b, level) - for l in p.leds: - print_led(d, p, l, level) + print(" " * (level - 2) + "Profile {}:{}".format(p.index, " " if not p.enabled else "")) + if p.enabled: + print(" " * level + "Resolutions:") + for r in p.resolutions: + print_resolution(d, p, r, level + 2) + for b in p.buttons: + print_button(d, p, b, level) + for l in p.leds: + print_led(d, p, l, level) def print_device(d, level): @@ -358,6 +360,18 @@ def func_profile_active_set(r, args): d.commit() +def func_profile_enable(r, args): + p, d = find_profile(r, args) + p.enabled = True + d.commit() + + +def func_profile_disable(r, args): + p, d = find_profile(r, args) + p.enabled = False + d.commit() + + def func_dummy(r, args): print("uh, oh, not implemented") pr_debug(args, r, args) @@ -489,36 +503,6 @@ parser_def = [ }, ], }, - { - of_type: command, - name: 'enable', - help_str: 'Enable a profile', - pos_args: [ - { - of_type: argument, - name: 'profile_n', - metavar: 'N', - help_str: 'The profile to enable', - arg_type: int, - }, - ], - func: func_dummy, # FIXME: func_profile_enable, - }, - { - of_type: command, - name: 'disable', - help_str: 'Disable a profile', - pos_args: [ - { - of_type: argument, - name: 'profile_n', - metavar: 'N', - help_str: 'The profile to disable', - arg_type: int, - }, - ], - func: func_dummy, # FIXME: func_profile_disable, - }, ], N_access: { of_type: N_access, @@ -532,6 +516,18 @@ parser_def = [ help_str: 'Show current active profile', func: func_profile_get, }, + { + of_type: command, + name: 'enable', + help_str: 'Enable a profile', + func: func_profile_enable, + }, + { + of_type: command, + name: 'disable', + help_str: 'Disable a profile', + func: func_profile_disable, + }, { of_type: link, dest: 'resolution', diff --git a/tools/ratbagctl.test.in b/tools/ratbagctl.test.in index c396604d..112069fc 100755 --- a/tools/ratbagctl.test.in +++ b/tools/ratbagctl.test.in @@ -174,33 +174,29 @@ class TestRatbgagCtlProfile(TestRatbagCtl): self.launch_fail_test("Profile 0 get test_device X") self.launch_fail_test("Profile 10 get test_device") - @unittest.skip("profile doesn't show enabled/disabled") def test_profile_enable(self): - command = "profile enable" - self.launch_good_test(command + " 1 test_device") r = self.launch_good_test("profile 0 get test_device") - # FIXME: show when the profile is disabled in ratbagctl - self.assertNotIn('enabled', r) - r = self.launch_good_test("profile 1 get test_device") - self.assertIn('enabled', r) - self.launch_fail_test(command) - self.launch_fail_test(command + " X test_device") - self.launch_fail_test(command + " 1 test_device X") - self.launch_fail_test(command + " 10 test_device") + self.assertNotIn('disabled', r) + r = self.launch_good_test("profile 3 get test_device") + self.assertIn('disabled', r) + self.launch_good_test("profile 3 enable test_device") + r = self.launch_good_test("profile 3 get test_device") + self.assertNotIn('Profile 3: ', r) + self.launch_fail_test("profile enable") + self.launch_fail_test("profile X enable test_device") + self.launch_fail_test("profile 1 enable test_device X") + self.launch_fail_test("profile 10 enable test_device") - @unittest.skip("profile doesn't show enabled/disabled") def test_profile_disable(self): - command = "profile disable" - self.launch_good_test(command + " 1 test_device") - r = self.launch_good_test("profile 0 get test_device") - # FIXME: show when the profile is disabled in ratbagctl - self.assertIn('enabled', r) - r = self.launch_good_test("profile 1 get test_device") - self.assertNotIn('enabled', r) - self.launch_fail_test(command) - self.launch_fail_test(command + " X test_device") - self.launch_fail_test(command + " 1 test_device X") - self.launch_fail_test(command + " 10 test_device") + r = self.launch_good_test("profile 2 get test_device") + self.assertNotIn('disabled', r) + self.launch_good_test("profile 2 disable test_device") + r = self.launch_good_test("profile 2 get test_device") + self.assertEqual('Profile 2: ', r) + self.launch_fail_test("profile disable") + self.launch_fail_test("profile X disable test_device") + self.launch_fail_test("profile 1 disable test_device X") + self.launch_fail_test("profile 10 disable test_device") class TestRatbgagCtlResolution(TestRatbagCtl): diff --git a/tools/ratbagd.py b/tools/ratbagd.py index 138f3500..1cb9db3b 100644 --- a/tools/ratbagd.py +++ b/tools/ratbagd.py @@ -299,6 +299,18 @@ class RatbagdProfile(_RatbagdDBus): """The index of this profile.""" return self._get_dbus_property("Index") + @GObject.Property + def enabled(self): + """tells if the profile is enabled.""" + return self._get_dbus_property("Enabled") + + @enabled.setter + def enabled(self, enabled): + """Enable/Disable this profile. + + @param enabled The new state, as boolean""" + return self._set_dbus_property("Enabled", "b", enabled) + @GObject.Property def resolutions(self): """A list of RatbagdResolution objects with this profile's resolutions.