commit ac81d8173fde58254c7ed1ce02bcb2d7bbee6927
Author: Koji Yokota <[email protected]>
Date:   Thu Jun 11 18:59:14 2026 +0900

    Make system IM focus color shown when IM focus color is set transparent
    
    and other small fixes
---
 src/frontends/qt/ColorCache.cpp     | 19 ++++++++-
 src/frontends/qt/ColorCache.h       |  2 +
 src/frontends/qt/GuiInputMethod.cpp | 80 +++++++++++++++++++++----------------
 3 files changed, 64 insertions(+), 37 deletions(-)

diff --git a/src/frontends/qt/ColorCache.cpp b/src/frontends/qt/ColorCache.cpp
index a666c529bd..0949c2f3da 100644
--- a/src/frontends/qt/ColorCache.cpp
+++ b/src/frontends/qt/ColorCache.cpp
@@ -35,6 +35,7 @@ QPalette::ColorRole role(ColorCode col)
        case Color_mathmacrobg:
        case Color_mathcorners:
        case Color_preeditbg:
+       case Color_preeditfocus:
                return QPalette::Base;
                break;
 
@@ -44,16 +45,15 @@ QPalette::ColorRole role(ColorCode col)
        case Color_tabularline:
        case Color_previewframe:
        case Color_preedittext:
+       case lyx::Color_preeditfocustext:
                return QPalette::Text;
                break;
 
        case Color_selection:
-       case Color_preeditfocus:
                return QPalette::Highlight;
                break;
        case Color_selectionmath:
        case Color_selectiontext:
-       case lyx::Color_preeditfocustext:
                return QPalette::HighlightedText;
                break;
        case Color_urllabel:
@@ -233,5 +233,20 @@ QColor const argb2qcolor(ARGBColor const & argb)
        return QColor(argb.r, argb.g, argb.b, argb.a);
 }
 
+const QColor qcolorOverlay(const QColor &fg, const QColor &bg)
+{
+       int red, green, blue, alpha;
+
+       float fg_weight = fg.alphaF();
+       float bg_weight = (1 - fg.alphaF()) * bg.alphaF();
+
+       red   = std::round((fg_weight*fg.redF()   + bg_weight*bg.redF()  ) * 
255);
+       green = std::round((fg_weight*fg.greenF() + bg_weight*bg.greenF()) * 
255);
+       blue  = std::round((fg_weight*fg.blueF()  + bg_weight*bg.blueF() ) * 
255);
+       alpha = std::round((1 - (1 - fg.alphaF()) * (1 - bg.alphaF())) * 255);
+
+       return QColor(red, green, blue, alpha);
+}
+
 
 } // namespace lyx
diff --git a/src/frontends/qt/ColorCache.h b/src/frontends/qt/ColorCache.h
index b0d140e147..617bae8e56 100644
--- a/src/frontends/qt/ColorCache.h
+++ b/src/frontends/qt/ColorCache.h
@@ -78,6 +78,8 @@ private:
 QColor const rgb2qcolor(RGBColor const &);
 ///
 QColor const argb2qcolor(ARGBColor const &);
+///
+QColor const qcolorOverlay(QColor const & fg, QColor const & bg);
 
 } // namespace lyx
 
diff --git a/src/frontends/qt/GuiInputMethod.cpp 
b/src/frontends/qt/GuiInputMethod.cpp
index 43059024ac..e36fa31475 100644
--- a/src/frontends/qt/GuiInputMethod.cpp
+++ b/src/frontends/qt/GuiInputMethod.cpp
@@ -205,7 +205,7 @@ void GuiInputMethod::inputMethodEvent(QInputMethodEvent* ev)
        d->font_color_ = d->color_cache_.get(fg);
        d->font_brush_.setColor(d->font_color_);
        LYXERR(Debug::KEY,
-              "Preedit font color is set to " << d->font_color_.name());
+              "Preedit font color is set to " << 
d->font_color_.name(QColor::HexArgb));
 
        d->locale_ = d->sys_im_->locale();
        d->style_.lang_ = d->locale_;
@@ -524,11 +524,11 @@ pos_type GuiInputMethod::setTextFormat(const 
QInputMethodEvent::Attribute & it,
 
        LYXERR(Debug::KEY,
               "QInputMethodEvent::TextFormat start: " << it.start <<
-              " end: " << it.start + it.length - 1 <<
+              " length: " << it.length <<
               " underline? " << char_format.font().underline() <<
               " UnderlineStyle: " << char_format.underlineStyle() <<
-              " fg: " << char_format.foreground().color().name() <<
-              " bg: " << char_format.background().color().name());
+              " fg: " << 
char_format.foreground().color().name(QColor::HexArgb) <<
+              " bg: " << 
char_format.background().color().name(QColor::HexArgb));
 
        //
        // Fit and adjust arrived text formats
@@ -541,18 +541,28 @@ pos_type GuiInputMethod::setTextFormat(const 
QInputMethodEvent::Attribute & it,
 #endif
 
 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
-       // set the style of a focused sector as specified by color themes
-       // it uses a system color if "Use system colors" is checked
+       QColor fg, bg;
+       QColor im_fg = char_format.foreground().color();
+       QColor im_bg = char_format.background().color();
+       // if incoming char_format doesn't specify the color (#000000)
+       // just use the text background as a base color
+       if (im_bg == QColorConstants::Black)
+               im_bg = guiApp->colorCache().get(Color_background);
+
+       // overlay theme's color on char_format's base color
+       // theme's color is the system color if "Use system colors" is checked
        // NOTE: brush size is assumed to be four
        //       if it is to be changed, change the declaration of array in
        //       setPreeditStyle()
        if (it.start == d->caret_rel_pos_) {
-               char_format.setForeground(brush[0]);
-               char_format.setBackground(brush[1]);
+               fg = qcolorOverlay(brush[0].color(), im_fg);
+               bg = qcolorOverlay(brush[1].color(), im_bg);
        } else {
-               char_format.setForeground(brush[2]);
-               char_format.setBackground(brush[3]);
+               fg = qcolorOverlay(brush[2].color(), im_fg);
+               bg = qcolorOverlay(brush[3].color(), im_bg);
        }
+       char_format.setForeground(fg);
+       char_format.setBackground(bg);
 #else
        // avoid unused-parameter warning.
        (void) brush;
@@ -567,9 +577,9 @@ pos_type GuiInputMethod::setTextFormat(const 
QInputMethodEvent::Attribute & it,
                                pickNextSegFromTurnout(next_seg_pos, 
&char_format);
                        if (updated_pos == next_seg_pos) {
                                // no matching segment in the turnout
-                               LYXERR(Debug::KEY, "Pushing to preedit 
register: (" << it.start
-                                      << ", " << it.start + it.length - 1 << 
") bg color: "
-                                      << 
char_format.background().color().name());
+                               LYXERR(Debug::KEY, "Pushing to preedit 
register: [" << it.start
+                                      << ", " << it.start + it.length << ") bg 
color: "
+                                      << 
char_format.background().color().name(QColor::HexArgb));
                                next_seg_pos = registerSegment(it.start, 
(size_type)it.length,
                                                               char_format);
                        } else
@@ -577,19 +587,19 @@ pos_type GuiInputMethod::setTextFormat(const 
QInputMethodEvent::Attribute & it,
                } else {
                        // push the constructed char format together with start 
and length
                        // to the list
-                       LYXERR(Debug::KEY, "Pushing to preedit register: (" << 
it.start
-                              << ", " << it.start + it.length - 1
+                       LYXERR(Debug::KEY, "Pushing to preedit register: [" << 
it.start
+                              << ", " << it.start + it.length
                               << ") fg: "
-                              << char_format.foreground().color().name()
+                              << 
char_format.foreground().color().name(QColor::HexArgb)
                               << " bg: "
-                              << char_format.background().color().name());
+                              << 
char_format.background().color().name(QColor::HexArgb));
                        next_seg_pos =
                                registerSegment(it.start, (size_type)it.length, 
char_format);
                }
                next_seg_pos = pickNextSegFromTurnout(next_seg_pos);
        } else if ((it.start > next_seg_pos || d->initial_tf_entry_) && 
it.length > 0) {
-               LYXERR(Debug::KEY, "Pushing to preedit turnout:  (" << it.start 
<< ", "
-                               << it.start + it.length - 1 << ")");
+               LYXERR(Debug::KEY, "Pushing to preedit turnout: [" << it.start 
<< ", "
+                               << it.start + it.length << ")");
                PreeditSegment turnout = {it.start, (size_type)it.length, 
char_format};
                d->seg_turnout_.push_back(turnout);
                d->initial_tf_entry_ = false;
@@ -608,25 +618,25 @@ pos_type GuiInputMethod::pickNextSegFromTurnout(pos_type 
next_seg_pos,
        // but typically only one is used
        for (auto past_attr = d->seg_turnout_.begin();
             past_attr != d->seg_turnout_.end(); past_attr++) {
-               if ((*past_attr).start_ == next_seg_pos) {
+               if (past_attr->start_ == next_seg_pos) {
                        PreeditSegment seg;
                        if (cf != nullptr) {
-                               cf->merge((*past_attr).char_format_);
-                               seg = {(*past_attr).start_,
-                                                                 
(size_type)(*past_attr).length_, *cf};
+                               cf->merge(past_attr->char_format_);
+                               seg = {past_attr->start_,
+                                                                 
(size_type)past_attr->length_, *cf};
                        } else
-                               seg = {(*past_attr).start_,
-                                                                 
(size_type)(*past_attr).length_,
-                                                                 
(*past_attr).char_format_};
+                               seg = {past_attr->start_,
+                                                                 
(size_type)past_attr->length_,
+                                                                 
past_attr->char_format_};
                        LYXERR(Debug::KEY,
-                              "Pushing to preedit register: (" << 
(*past_attr).start_
-                               << ", " << (*past_attr).start_ + 
(*past_attr).length_ - 1
+                              "Pushing to preedit register: [" << 
past_attr->start_
+                               << ", " << past_attr->start_ + 
past_attr->length_
                                << ") fg: "
-                               << 
(*past_attr).char_format_.foreground().color().name()
+                               << 
past_attr->char_format_.foreground().color().name(QColor::HexArgb)
                                << " bg: "
-                               << 
(*past_attr).char_format_.background().color().name());
+                               << 
past_attr->char_format_.background().color().name(QColor::HexArgb));
                        d->style_.segments_.push_back(seg);
-                       next_seg_pos += (*past_attr).length_;
+                       next_seg_pos += past_attr->length_;
                        if (d->seg_turnout_.size() > 1)
                                to_erase = past_attr;
                        is_matched = true;
@@ -636,15 +646,15 @@ pos_type GuiInputMethod::pickNextSegFromTurnout(pos_type 
next_seg_pos,
        // Clear d->seg_turnout_
        if (is_matched) {
                if (d->seg_turnout_.size() == 1) {
-                       LYXERR(Debug::KEY, "Preedit turnout clearing:    ("
+                       LYXERR(Debug::KEY, "Preedit turnout clearing:    ["
                                << d->seg_turnout_.back().start_ << ", "
                                << d->seg_turnout_.back().start_
-                                      + d->seg_turnout_.back().length_ - 1 << 
")");
+                                      + d->seg_turnout_.back().length_ << ")");
                        d->seg_turnout_.pop_back();
                } else if (d->seg_turnout_.size() > 1) {
-                       LYXERR(Debug::KEY, "Preedit turnout clearing: ("
+                       LYXERR(Debug::KEY, "Preedit turnout clearing: ["
                                << (*to_erase).start_ << ", "
-                               << (*to_erase).start_ + (*to_erase).length_ - 1 
<< ")");
+                               << (*to_erase).start_ + (*to_erase).length_ << 
")");
                        d->seg_turnout_.erase(to_erase);
                }
        }
-- 
lyx-cvs mailing list
[email protected]
https://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to