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
|
PerScreenDPI=True
|
||||||
ForceWaylandDPI=0
|
ForceWaylandDPI=0
|
||||||
EnableFractionalScale=True
|
EnableFractionalScale=True
|
||||||
|
UseMonet=True
|
||||||
Animations=True
|
Animations=True
|
||||||
Bounce=True
|
Bounce=True
|
||||||
SpatialStiffness=2000
|
SpatialStiffness=2000
|
||||||
|
|||||||
@@ -29,6 +29,12 @@ if (ENABLE_DBUS)
|
|||||||
set(CLASSICUI_LIBS ${CLASSICUI_LIBS} Fcitx5::Module::DBus)
|
set(CLASSICUI_LIBS ${CLASSICUI_LIBS} Fcitx5::Module::DBus)
|
||||||
endif()
|
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
|
add_fcitx5_addon(m3ui
|
||||||
classicui.cpp window.cpp theme.cpp inputwindow.cpp plasmathemewatchdog.cpp colorhelper.cpp ${CLASSICUI_SRCS}
|
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)
|
target_compile_definitions(m3ui PRIVATE -DFCITX_XCB_EWMH)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
target_include_directories(m3ui PRIVATE "${MONET_INCLUDE_DIR}")
|
||||||
|
|
||||||
target_link_libraries(m3ui
|
target_link_libraries(m3ui
|
||||||
Fcitx5::Core
|
Fcitx5::Core
|
||||||
PkgConfig::Cairo PkgConfig::Pango
|
PkgConfig::Cairo PkgConfig::Pango
|
||||||
|
|||||||
+53
-3
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "classicui.h"
|
#include "classicui.h"
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <cmath>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
@@ -180,6 +181,7 @@ void M3UI::reloadTheme() {
|
|||||||
auto color = variant.dataAs<uint32_t>();
|
auto color = variant.dataAs<uint32_t>();
|
||||||
auto oldIsDark = isDark_;
|
auto oldIsDark = isDark_;
|
||||||
isDark_ = (color == 1);
|
isDark_ = (color == 1);
|
||||||
|
portalSchemeKnown_ = true;
|
||||||
if (oldIsDark != isDark_) {
|
if (oldIsDark != isDark_) {
|
||||||
CLASSICUI_DEBUG() << "XDG Portal AppearanceChanged "
|
CLASSICUI_DEBUG() << "XDG Portal AppearanceChanged "
|
||||||
"isDark"
|
"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 (dbus()) {
|
||||||
if (*config_.useDarkTheme) {
|
if (*config_.useDarkTheme || *config_.useMonet) {
|
||||||
if (!darkModeEntry_ && settingMonitor_) {
|
if (!darkModeEntry_ && settingMonitor_) {
|
||||||
darkModeEntry_ = settingMonitor_->watch(
|
darkModeEntry_ = settingMonitor_->watch(
|
||||||
"org.freedesktop.appearance", "color-scheme", parseMessage);
|
"org.freedesktop.appearance", "color-scheme", parseMessage);
|
||||||
@@ -253,7 +257,7 @@ void M3UI::reloadTheme() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (dbus()) {
|
if (dbus()) {
|
||||||
if (*config_.useAccentColor) {
|
if (*config_.useAccentColor || *config_.useMonet) {
|
||||||
if (!accentColorEntry_ && settingMonitor_) {
|
if (!accentColorEntry_ && settingMonitor_) {
|
||||||
accentColorEntry_ =
|
accentColorEntry_ =
|
||||||
settingMonitor_->watch("org.freedesktop.appearance",
|
settingMonitor_->watch("org.freedesktop.appearance",
|
||||||
@@ -266,7 +270,53 @@ void M3UI::reloadTheme() {
|
|||||||
}
|
}
|
||||||
#endif
|
#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() {
|
void M3UI::suspend() {
|
||||||
|
|||||||
@@ -201,6 +201,11 @@ FCITX_CONFIGURATION(
|
|||||||
"font DPI. If the value is 0, it means this option is "
|
"font DPI. If the value is 0, it means this option is "
|
||||||
"disabled.")}};
|
"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> animations{this, "Animations", _("Enable animations"), true};
|
||||||
Option<bool> bounce{this, "Bounce",
|
Option<bool> bounce{this, "Bounce",
|
||||||
_("Bouncy overshoot (off: critically damped)"), true};
|
_("Bouncy overshoot (off: critically damped)"), true};
|
||||||
@@ -244,6 +249,8 @@ public:
|
|||||||
FCITX_ADDON_DEPENDENCY_LOADER(dbus, instance_->addonManager());
|
FCITX_ADDON_DEPENDENCY_LOADER(dbus, instance_->addonManager());
|
||||||
Instance *instance() const { return instance_; }
|
Instance *instance() const { return instance_; }
|
||||||
const Configuration *getConfig() const override;
|
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 {
|
void setConfig(const RawConfig &config) override {
|
||||||
config_.load(config, true);
|
config_.load(config, true);
|
||||||
safeSaveAsIni(config_, "conf/m3ui.conf");
|
safeSaveAsIni(config_, "conf/m3ui.conf");
|
||||||
@@ -330,6 +337,8 @@ private:
|
|||||||
mutable Theme subconfigTheme_;
|
mutable Theme subconfigTheme_;
|
||||||
bool suspended_ = true;
|
bool suspended_ = true;
|
||||||
bool isDark_ = false;
|
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::optional<Color> accentColor_ = std::nullopt;
|
||||||
|
|
||||||
std::unique_ptr<EventSource> deferedEnableTray_;
|
std::unique_ptr<EventSource> deferedEnableTray_;
|
||||||
|
|||||||
@@ -1180,6 +1180,25 @@ std::vector<Rect> Theme::mask(const BackgroundImageConfig &cfg, int width,
|
|||||||
return result;
|
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) {
|
void Theme::populateColor(std::optional<Color> accent) {
|
||||||
inputPanelBackground_ = *inputPanel->background->color;
|
inputPanelBackground_ = *inputPanel->background->color;
|
||||||
inputPanelBorder_ = *inputPanel->background->borderColor;
|
inputPanelBorder_ = *inputPanel->background->borderColor;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "fcitx-utils/rect.h"
|
#include "fcitx-utils/rect.h"
|
||||||
#include "fcitx/icontheme.h"
|
#include "fcitx/icontheme.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "monettheme.h"
|
||||||
|
|
||||||
namespace fcitx::m3ui {
|
namespace fcitx::m3ui {
|
||||||
enum class Gravity {
|
enum class Gravity {
|
||||||
@@ -364,6 +365,10 @@ public:
|
|||||||
const auto &accentColorFields() const { return accentColorFields_; }
|
const auto &accentColorFields() const { return accentColorFields_; }
|
||||||
|
|
||||||
void populateColor(std::optional<Color> accent);
|
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 &inputPanelBackground() const { return inputPanelBackground_; }
|
||||||
const auto &inputPanelBorder() const { return inputPanelBorder_; }
|
const auto &inputPanelBorder() const { return inputPanelBorder_; }
|
||||||
|
|||||||
Reference in new issue
Block a user