Le 17/07/2019 à 23:14, Jean-Marc Lasgouttes a écrit :
commit 049aed8e08ab0da498561e3382e009852cd1d83d
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Wed Jul 17 01:01:49 2019 +0200

     Respect OS-level keyboard language

So basically, when one changes the SO keyboard using the relevant toggle, LyX will chnage the keyboard at cursor position. Note that if you have two documents pen, the current language in documents that do not have focus is _not_ changed. This could be changed of course, I am taker a better behavior. This is the kind of thing that I expect to tweak after the alpha releases.

This is something that has been on my TODO list for a long time, but it took me a long time to understand what Qt expects me to do. As written below,

* Stephan, I would appreciate to know whether it works with macOS

* Anyone, I'd appreciate to be educated on how ibus works and what needs
  to be done to make it work with ubuntu or other distributions. Hebrew
  users, you are one main target for this feature.

JMarc

This bug provides two features: 1/ when a new document is created the language is set to the current
       keyboard language.
2/ when keyboard is switched at OS level, the input language of
        current window is changed. The language is set preferably to one of
        those of the document. Ex. if the keyboard changes to en_GB but one
        is typing a document in US English and Hebrew, then US English will
        be selected rather that adding UK English to the list.
The implementation depends a lot on Qt. The platform status is : * working on Windows 10 * not working with Linux (although 1/ works with Qt4); it seems that
       Qt5 supports switching through ibus, but I do not know what this
       means.
* not yet tested on macOS. This addresses bugs #6450, #6247 and somehow #10514.
---
  src/Buffer.cpp                       |    4 +++
  src/BufferView.cpp                   |   11 ++++++++++
  src/BufferView.h                     |    6 +++++
  src/Language.cpp                     |   33 +++++++++++++++++++++++++++++--
  src/Language.h                       |    4 +++
  src/frontends/Application.h          |    2 +
  src/frontends/qt4/GuiApplication.cpp |   35 ++++++++++++++++++++++++++++++++++
  src/frontends/qt4/GuiApplication.h   |    3 ++
  8 files changed, 95 insertions(+), 3 deletions(-)

diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index 3ab6c61..85e2795 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -83,6 +83,7 @@
  #include "graphics/GraphicsCache.h"
  #include "graphics/PreviewLoader.h"
+#include "frontends/Application.h"
  #include "frontends/alert.h"
  #include "frontends/Delegates.h"
  #include "frontends/WorkAreaManager.h"
@@ -465,6 +466,9 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, 
bool readonly_,
        if (!cloned_buffer_) {
                temppath = createBufferTmpDir();
                lyxvc.setBuffer(owner_);
+               Language const * inplang = 
languages.getFromCode(theApp()->inputLanguageCode());
+               if (inplang)
+                       params.language = inplang;
                if (use_gui)
                        wa_ = new frontend::WorkAreaManager;
                return;
diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index 97adab8..40d8643 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -2739,6 +2739,17 @@ Cursor const & BufferView::cursor() const
  }
+void BufferView::setCursorLanguage(std::string const & code)
+{
+       Language const * lang = languages.getFromCode(code, 
buffer_.getLanguages());
+       if (lang) {
+               d->cursor_.current_font.setLanguage(lang);
+               d->cursor_.real_current_font.setLanguage(lang);
+       } else
+               LYXERR0("setCursorLanguage: unknown language code " << code);
+}
+
+
  bool BufferView::singleParUpdate()
  {
        Text & buftext = buffer_.text();
diff --git a/src/BufferView.h b/src/BufferView.h
index 40dd0d2..bb75c16 100644
--- a/src/BufferView.h
+++ b/src/BufferView.h
@@ -267,6 +267,12 @@ public:
        /// sets cursor.
        /// This is used when handling LFUN_MOUSE_PRESS.
        bool mouseSetCursor(Cursor & cur, bool select = false);
+       /// Set the cursor language from language code.
+       /* Considers first exact math with the codes used in the document,
+        * then approximate match among the same list, and finally exact
+        * or partial match with the whole list of languages.
+        */
+       void setCursorLanguage(std::string const & code);
/// sets the selection.
        /* When \c backwards == false, set anchor
diff --git a/src/Language.cpp b/src/Language.cpp
index 52c1c4f..a1f3562 100644
--- a/src/Language.cpp
+++ b/src/Language.cpp
@@ -367,6 +367,7 @@ bool readTranslations(Lexer & lex, Language::TranslationMap 
& trans)
  enum Match {
        NoMatch,
        ApproximateMatch,
+       VeryApproximateMatch,
        ExactMatch
  };
@@ -389,6 +390,8 @@ Match match(string const & code, Language const & lang)
        if ((code.size() == 2) && (langcode.size() > 2)
                && (code + '_' == langcode.substr(0, 3)))
                return ApproximateMatch;
+       if (code.substr(0,2) == langcode.substr(0,2))
+               return VeryApproximateMatch;
        return NoMatch;
  }
@@ -398,17 +401,41 @@ Match match(string const & code, Language const & lang) Language const * Languages::getFromCode(string const & code) const
  {
-       // Try for exact match first
+       // 1/ exact match with any known language
        for (auto const & l : languagelist_) {
                if (match(code, l.second) == ExactMatch)
                        return &l.second;
        }
-       // If not found, look for lang prefix (without country) instead
+
+       // 2/ approximate with any known language
        for (auto const & l : languagelist_) {
                if (match(code, l.second) == ApproximateMatch)
                        return &l.second;
        }
-       LYXERR0("Unknown language `" + code + "'");
+       return 0;
+}
+
+
+Language const * Languages::getFromCode(string const & code,
+                       set<Language const *> const & tryfirst) const
+{
+       // 1/ exact match with tryfirst list
+       for (auto const * lptr : tryfirst) {
+               if (match(code, *lptr) == ExactMatch)
+                       return lptr;
+       }
+
+       // 2/ approximate match with tryfirst list
+       for (auto const * lptr : tryfirst) {
+               Match const m = match(code, *lptr);
+               if (m == ApproximateMatch || m == VeryApproximateMatch)
+                       return lptr;
+       }
+
+       // 3/ stricter match in all languages
+       return getFromCode(code);
+
+       LYXERR0("Unknown language `" << code << "'");
        return 0;
  }
diff --git a/src/Language.h b/src/Language.h
index 5627dd4..9201b00 100644
--- a/src/Language.h
+++ b/src/Language.h
@@ -21,6 +21,7 @@
  #include "support/trivstring.h"
#include <map>
+#include <set>
  #include <vector>
@@ -168,6 +169,9 @@ public:
        ///
        Language const * getFromCode(std::string const & code) const;
        ///
+       Language const * getFromCode(std::string const & code,
+                       std::set<Language const *> const & tryfirst) const;
+       ///
        void readLayoutTranslations(support::FileName const & filename);
        ///
        Language const * getLanguage(std::string const & language) const;
diff --git a/src/frontends/Application.h b/src/frontends/Application.h
index cf82776..415cea1 100644
--- a/src/frontends/Application.h
+++ b/src/frontends/Application.h
@@ -240,6 +240,8 @@ public:
        /// \return the math icon name for the given command.
        static docstring mathIcon(docstring const & c);
+ /// The language associated to current keyboard
+       virtual std::string inputLanguageCode() const = 0;
        /// Handle a accented char key sequence
        /// FIXME: this is only needed for LFUN_ACCENT_* in Text::dispatch()
        virtual void handleKeyFunc(FuncCode action) = 0;
diff --git a/src/frontends/qt4/GuiApplication.cpp 
b/src/frontends/qt4/GuiApplication.cpp
index 666b961..dd34324 100644
--- a/src/frontends/qt4/GuiApplication.cpp
+++ b/src/frontends/qt4/GuiApplication.cpp
@@ -1089,6 +1089,12 @@ GuiApplication::GuiApplication(int & argc, char ** argv)
        if (lyxrc.typewriter_font_name.empty())
                lyxrc.typewriter_font_name = fromqstr(typewriterFontName());
+#if (QT_VERSION >= 0x050000)
+       // Qt4 does this in event(), see below.
+       // Track change of keyboard
+       connect(inputMethod(), SIGNAL(localeChanged()), this, 
SLOT(onLocaleChanged()));
+#endif
+
        d->general_timer_.setInterval(500);
        connect(&d->general_timer_, SIGNAL(timeout()),
                this, SLOT(handleRegularEvents()));
@@ -2115,6 +2121,26 @@ docstring GuiApplication::viewStatusMessage()
  }
+string GuiApplication::inputLanguageCode() const
+{
+#if (QT_VERSION < 0x050000)
+       QLocale loc = keyboardInputLocale();
+#else
+       QLocale loc = inputMethod()->locale();
+#endif
+       //LYXERR0("input lang = " << fromqstr(loc.name()));
+       return fromqstr(loc.name());
+}
+
+
+void GuiApplication::onLocaleChanged()
+{
+       //LYXERR0("Change language to " << inputLanguage()->lang());
+       if (currentView() && currentView()->currentBufferView())
+               
currentView()->currentBufferView()->setCursorLanguage(inputLanguageCode());
+}
+
+
  void GuiApplication::handleKeyFunc(FuncCode action)
  {
        char_type c = 0;
@@ -2718,6 +2744,15 @@ bool GuiApplication::event(QEvent * e)
                e->accept();
                return true;
        }
+#if (QT_VERSION < 0x050000)
+       // Qt5 uses a signal for that, see above.
+       case QEvent::KeyboardLayoutChange:
+               //LYXERR0("keyboard change");
+               if (currentView() && currentView()->currentBufferView())
+                       
currentView()->currentBufferView()->setCursorLanguage(inputLanguageCode());
+               e->accept();
+               return true;
+#endif
        default:
                return QApplication::event(e);
        }
diff --git a/src/frontends/qt4/GuiApplication.h 
b/src/frontends/qt4/GuiApplication.h
index 22d4365..f5b11c9 100644
--- a/src/frontends/qt4/GuiApplication.h
+++ b/src/frontends/qt4/GuiApplication.h
@@ -77,6 +77,7 @@ public:
        void unregisterSocketCallback(int fd) override;
        bool searchMenu(FuncRequest const & func, docstring_list & names) const 
override;
        bool hasBufferView() const override;
+       std::string inputLanguageCode() const override;
        void handleKeyFunc(FuncCode action) override;
        bool unhide(Buffer * buf) override;
        //@}
@@ -214,6 +215,8 @@ private Q_SLOTS:
        ///
        void onLastWindowClosed();
        ///
+       void onLocaleChanged();
+       ///
        void slotProcessFuncRequestQueue() { processFuncRequestQueue(); }
private:


Reply via email to