Colour the candidate window from the desktop accent via libmonet
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
064ca6b4d4
commit
5bea01e224
6 files changed
+95
-3
No files matched your search
@@ -10,6 +10,7 @@ UseAccentColor=False
|
||||
PerScreenDPI=True
|
||||
ForceWaylandDPI=0
|
||||
EnableFractionalScale=True
|
||||
UseMonet=True
|
||||
Animations=True
|
||||
Bounce=True
|
||||
SpatialStiffness=2000
|
||||
|
||||
@@ -29,6 +29,12 @@ if (ENABLE_DBUS)
|
||||
set(CLASSICUI_LIBS ${CLASSICUI_LIBS} Fcitx5::Module::DBus)
|
||||
endif()
|
||||
|
||||
# libmonet, the shared colour code, header only. build.sh fetches it at a pinned
|
||||
# commit and passes the directory.
|
||||
if (NOT MONET_INCLUDE_DIR OR NOT EXISTS "${MONET_INCLUDE_DIR}/monet/monet.h")
|
||||
message(FATAL_ERROR "MONET_INCLUDE_DIR must point at the include directory of libmonet")
|
||||
endif()
|
||||
|
||||
add_fcitx5_addon(m3ui
|
||||
classicui.cpp window.cpp theme.cpp inputwindow.cpp plasmathemewatchdog.cpp colorhelper.cpp ${CLASSICUI_SRCS}
|
||||
)
|
||||
@@ -37,6 +43,8 @@ if (ENABLE_X11)
|
||||
target_compile_definitions(m3ui PRIVATE -DFCITX_XCB_EWMH)
|
||||
endif()
|
||||
|
||||
target_include_directories(m3ui PRIVATE "${MONET_INCLUDE_DIR}")
|
||||
|
||||
target_link_libraries(m3ui
|
||||
Fcitx5::Core
|
||||
PkgConfig::Cairo PkgConfig::Pango
|
||||
|
||||
+53
-3
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "classicui.h"
|
||||
#include <fcntl.h>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
@@ -180,6 +181,7 @@ void M3UI::reloadTheme() {
|
||||
auto color = variant.dataAs<uint32_t>();
|
||||
auto oldIsDark = isDark_;
|
||||
isDark_ = (color == 1);
|
||||
portalSchemeKnown_ = true;
|
||||
if (oldIsDark != isDark_) {
|
||||
CLASSICUI_DEBUG() << "XDG Portal AppearanceChanged "
|
||||
"isDark"
|
||||
@@ -189,8 +191,10 @@ void M3UI::reloadTheme() {
|
||||
}
|
||||
};
|
||||
|
||||
// The portal is also how the colours for UseMonet are learned, over the
|
||||
// connection Fcitx5 already has, so nothing has to be started for it.
|
||||
if (dbus()) {
|
||||
if (*config_.useDarkTheme) {
|
||||
if (*config_.useDarkTheme || *config_.useMonet) {
|
||||
if (!darkModeEntry_ && settingMonitor_) {
|
||||
darkModeEntry_ = settingMonitor_->watch(
|
||||
"org.freedesktop.appearance", "color-scheme", parseMessage);
|
||||
@@ -253,7 +257,7 @@ void M3UI::reloadTheme() {
|
||||
};
|
||||
|
||||
if (dbus()) {
|
||||
if (*config_.useAccentColor) {
|
||||
if (*config_.useAccentColor || *config_.useMonet) {
|
||||
if (!accentColorEntry_ && settingMonitor_) {
|
||||
accentColorEntry_ =
|
||||
settingMonitor_->watch("org.freedesktop.appearance",
|
||||
@@ -266,7 +270,53 @@ void M3UI::reloadTheme() {
|
||||
}
|
||||
#endif
|
||||
|
||||
theme_.populateColor(accentColor_);
|
||||
if (*config_.useMonet) {
|
||||
theme_.applyMonet(mapScheme(monetScheme()));
|
||||
}
|
||||
// The accent colour is only watched for UseMonet, it must not recolour the
|
||||
// fields of a classic theme unless the user asked for that.
|
||||
theme_.populateColor(*config_.useAccentColor ? accentColor_
|
||||
: std::nullopt);
|
||||
}
|
||||
|
||||
monet::Scheme M3UI::monetScheme() const {
|
||||
// Nothing is ever started from here: a slow program would stall the input
|
||||
// method. The portal is read through the connection Fcitx5 has, the other
|
||||
// sources only read files.
|
||||
monet::Context ctx = monet::Context::system();
|
||||
ctx.run = [](const std::vector<std::string> &, int) {
|
||||
return std::optional<std::string>();
|
||||
};
|
||||
monet::Source portal{
|
||||
"fcitx-portal", [this](const monet::Context &) {
|
||||
monet::Appearance a;
|
||||
if (accentColor_) {
|
||||
auto q = [](float c) {
|
||||
return static_cast<std::uint8_t>(std::lround(c * 255.0f));
|
||||
};
|
||||
a.accent = monet::Rgb{q(accentColor_->redF()),
|
||||
q(accentColor_->greenF()),
|
||||
q(accentColor_->blueF())};
|
||||
}
|
||||
if (portalSchemeKnown_) {
|
||||
a.mode = isDark_ ? monet::Mode::Dark : monet::Mode::Light;
|
||||
}
|
||||
return a;
|
||||
}};
|
||||
// MONET_SEED and MONET_MODE first, then what the portal said, then the rest.
|
||||
std::vector<monet::Source> sources;
|
||||
for (auto &source : monet::defaultSources(ctx)) {
|
||||
sources.push_back(std::move(source));
|
||||
if (sources.back().name == "override") {
|
||||
sources.push_back(portal);
|
||||
}
|
||||
}
|
||||
const monet::Appearance a = monet::detect(ctx, sources);
|
||||
CLASSICUI_DEBUG() << "Monet seed " << monet::hex(*a.accent) << " from "
|
||||
<< a.accentSource << ", "
|
||||
<< (*a.mode == monet::Mode::Dark ? "dark" : "light")
|
||||
<< " from " << a.modeSource;
|
||||
return monet::generate(*a.accent, *a.mode);
|
||||
}
|
||||
|
||||
void M3UI::suspend() {
|
||||
|
||||
@@ -201,6 +201,11 @@ FCITX_CONFIGURATION(
|
||||
"font DPI. If the value is 0, it means this option is "
|
||||
"disabled.")}};
|
||||
|
||||
Option<bool> useMonet{
|
||||
this, "UseMonet",
|
||||
_("Take the colours from the desktop: its accent colour and its light "
|
||||
"or dark setting"),
|
||||
true};
|
||||
Option<bool> animations{this, "Animations", _("Enable animations"), true};
|
||||
Option<bool> bounce{this, "Bounce",
|
||||
_("Bouncy overshoot (off: critically damped)"), true};
|
||||
@@ -244,6 +249,8 @@ public:
|
||||
FCITX_ADDON_DEPENDENCY_LOADER(dbus, instance_->addonManager());
|
||||
Instance *instance() const { return instance_; }
|
||||
const Configuration *getConfig() const override;
|
||||
// The scheme for the current desktop colours, see classicui.cpp.
|
||||
monet::Scheme monetScheme() const;
|
||||
void setConfig(const RawConfig &config) override {
|
||||
config_.load(config, true);
|
||||
safeSaveAsIni(config_, "conf/m3ui.conf");
|
||||
@@ -330,6 +337,8 @@ private:
|
||||
mutable Theme subconfigTheme_;
|
||||
bool suspended_ = true;
|
||||
bool isDark_ = false;
|
||||
// The portal has answered, so isDark_ is a value and not just the default.
|
||||
bool portalSchemeKnown_ = false;
|
||||
std::optional<Color> accentColor_ = std::nullopt;
|
||||
|
||||
std::unique_ptr<EventSource> deferedEnableTray_;
|
||||
|
||||
@@ -1180,6 +1180,25 @@ std::vector<Rect> Theme::mask(const BackgroundImageConfig &cfg, int width,
|
||||
return result;
|
||||
}
|
||||
|
||||
void Theme::applyMonet(const MonetColors &c) {
|
||||
// A classic theme draws its panel from images, there is nothing to recolour.
|
||||
if (inputPanel->surfaceColor->alpha() == 0) {
|
||||
return;
|
||||
}
|
||||
auto *panel = inputPanel.mutableValue();
|
||||
panel->surfaceColor.setValue(c.surface);
|
||||
panel->outlineColor.setValue(c.outline);
|
||||
panel->highlightFillColor.setValue(c.highlightFill);
|
||||
panel->normalColor.setValue(c.normal);
|
||||
panel->highlightColor.setValue(c.highlight);
|
||||
panel->highlightBackgroundColor.setValue(c.highlightBackground);
|
||||
panel->highlightCandidateColor.setValue(c.highlightCandidate);
|
||||
panel->candidateLabelColor.setValue(c.candidateLabel);
|
||||
panel->highlightCandidateLabelColor.setValue(c.highlightCandidateLabel);
|
||||
panel->candidateCommentColor.setValue(c.candidateComment);
|
||||
panel->highlightCandidateCommentColor.setValue(c.highlightCandidateComment);
|
||||
}
|
||||
|
||||
void Theme::populateColor(std::optional<Color> accent) {
|
||||
inputPanelBackground_ = *inputPanel->background->color;
|
||||
inputPanelBorder_ = *inputPanel->background->borderColor;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "fcitx-utils/rect.h"
|
||||
#include "fcitx/icontheme.h"
|
||||
#include "common.h"
|
||||
#include "monettheme.h"
|
||||
|
||||
namespace fcitx::m3ui {
|
||||
enum class Gravity {
|
||||
@@ -364,6 +365,10 @@ public:
|
||||
const auto &accentColorFields() const { return accentColorFields_; }
|
||||
|
||||
void populateColor(std::optional<Color> accent);
|
||||
// Replaces the colours of a Material style theme (one with a SurfaceColor)
|
||||
// with colours that follow the desktop. Other themes are left as they are.
|
||||
// Call it after load() and before populateColor().
|
||||
void applyMonet(const MonetColors &colors);
|
||||
|
||||
const auto &inputPanelBackground() const { return inputPanelBackground_; }
|
||||
const auto &inputPanelBorder() const { return inputPanelBorder_; }
|
||||
|
||||
Reference in new issue
Block a user