mirror of https://github.com/cutefishos/settings
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
4.0 KiB
C++
129 lines
4.0 KiB
C++
// SPDX-FileCopyrightText: 2026 Reion Wong <reionwong@gmail.com>
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
#include "pages/hotcorners/hotcorners.h"
|
|
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
|
|
#include "base/i18n.h"
|
|
|
|
using namespace cutefish::base;
|
|
using cutefish::i18n::trc;
|
|
|
|
namespace settings {
|
|
|
|
static constexpr const char* kService = "org.cutefish.HotCorners1";
|
|
static constexpr const char* kPath = "/org/cutefish/HotCorners1";
|
|
|
|
// The compositor's modifier bits, as in the shortcuts service.
|
|
static constexpr int kShiftDown = 1 << 0;
|
|
static constexpr int kControlDown = 1 << 1;
|
|
static constexpr int kAltDown = 1 << 2;
|
|
static constexpr int kMetaDown = 1 << 3;
|
|
|
|
// topLeft, topLeftModifiers and so on.
|
|
static std::string propertyName(const std::string& corner, const char* suffix = "")
|
|
{
|
|
std::string name;
|
|
bool upper = false;
|
|
for (const char c : corner) {
|
|
if (c == '-') {
|
|
upper = true;
|
|
continue;
|
|
}
|
|
name += upper ? char(c - 'a' + 'A') : c;
|
|
upper = false;
|
|
}
|
|
return name + suffix;
|
|
}
|
|
|
|
HotCorners::HotCorners()
|
|
: m_corners(dbus::Connection::session(), kService, kPath, kService)
|
|
{
|
|
dbus::Connection* bus = m_corners.connection();
|
|
if (!bus)
|
|
return;
|
|
// Read at once, so the page has the values for its first frame.
|
|
if (const dbus::Reply reply = m_corners.getAll(); !reply.isError()) {
|
|
m_properties = reply.value<dbus::VariantMap>().value_or(dbus::VariantMap());
|
|
m_available = true;
|
|
}
|
|
const dbus::Proxy shortcuts(bus, "org.cutefish.Shortcuts1", "/org/cutefish/Shortcuts1", "org.cutefish.Shortcuts1");
|
|
m_commandKeys = shortcuts.property<std::string>("shortcutConvention").value_or(std::string()) == "command";
|
|
m_changedMatch = m_corners.onSignal("changed", [this](const dbus::Message&) { reload(); });
|
|
m_watch = bus->watchName(kService, [this](const std::string& owner) {
|
|
if (!owner.empty()) {
|
|
reload();
|
|
} else if (m_available) {
|
|
m_available = false;
|
|
m_properties.clear();
|
|
changed.emit();
|
|
}
|
|
});
|
|
}
|
|
|
|
void HotCorners::reload()
|
|
{
|
|
m_reload = m_corners.getAllAsync([this](const dbus::Reply& reply) {
|
|
if (reply.isError())
|
|
return;
|
|
m_properties = reply.value<dbus::VariantMap>().value_or(dbus::VariantMap());
|
|
m_available = true;
|
|
changed.emit();
|
|
});
|
|
}
|
|
|
|
std::string HotCorners::action(const std::string& corner) const
|
|
{
|
|
const auto it = m_properties.find(propertyName(corner));
|
|
return it == m_properties.end() ? std::string() : it->second.value<std::string>();
|
|
}
|
|
|
|
int HotCorners::modifiers(const std::string& corner) const
|
|
{
|
|
const auto it = m_properties.find(propertyName(corner, "Modifiers"));
|
|
return it == m_properties.end() ? 0 : it->second.value<int32_t>(0);
|
|
}
|
|
|
|
void HotCorners::setCorner(const std::string& corner, const std::string& action, int modifiers)
|
|
{
|
|
if (!m_available)
|
|
return;
|
|
m_calls[corner] = m_corners.callAsync("setCorner", [this](const dbus::Reply& reply) {
|
|
if (reply.isError()) {
|
|
fprintf(stderr, "Cannot update hot corner: %s\n", reply.error().message.c_str());
|
|
changed.emit();
|
|
}
|
|
}, corner, action, int32_t(modifiers));
|
|
}
|
|
|
|
int HotCorners::heldModifiers() const
|
|
{
|
|
if (!m_available)
|
|
return 0;
|
|
return m_corners.call("heldModifiers").value<int32_t>().value_or(0);
|
|
}
|
|
|
|
std::string HotCorners::modifierText(int modifiers) const
|
|
{
|
|
// Under the Command convention Meta is the Command key, Alt is Option.
|
|
std::string text;
|
|
const auto add = [&text](const char* part) {
|
|
if (!text.empty())
|
|
text += " + ";
|
|
text += part;
|
|
};
|
|
if (modifiers & kControlDown)
|
|
add(m_commandKeys ? trc("key", "Control") : trc("key", "Ctrl"));
|
|
if (modifiers & kAltDown)
|
|
add(m_commandKeys ? trc("key", "Option") : trc("key", "Alt"));
|
|
if (modifiers & kShiftDown)
|
|
add(trc("key", "Shift"));
|
|
if (modifiers & kMetaDown)
|
|
add(m_commandKeys ? trc("key", "Command") : trc("key", "Meta"));
|
|
return text;
|
|
}
|
|
|
|
} // namespace settings
|