mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-26 14:15:32 +00:00
Respect OS-level keyboard language
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.
This commit is contained in:
parent
2890b99a76
commit
049aed8e08
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user