summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kxkb/extension.cpp203
-rw-r--r--kxkb/extension.h56
-rw-r--r--kxkb/kcmlayout.cpp30
-rw-r--r--kxkb/kcmlayout.h6
-rw-r--r--kxkb/kxkb.cpp44
-rw-r--r--kxkb/kxkb.h2
-rw-r--r--kxkb/kxkbconfig.cpp88
-rw-r--r--kxkb/kxkbconfig.h3
8 files changed, 344 insertions, 88 deletions
diff --git a/kxkb/extension.cpp b/kxkb/extension.cpp
index a7da41ead..a9efb8226 100644
--- a/kxkb/extension.cpp
+++ b/kxkb/extension.cpp
@@ -1,3 +1,32 @@
+/*******************************************************************************
+
+ Xkb extension for KXkb
+ Copyright © 2009-2025 Trinity Desktop project
+ Copyright © 2001 S.R. Haque <[email protected]>
+
+ Derived from an original by Matthias H�zer-Klpfel released under the QPL.
+
+ Some portions come from kkbswitch released under the GNU GPL v2 (or later).
+ Copyright © 2001 Leonid Zeitlin <[email protected]>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*******************************************************************************/
+
+#include <stdlib.h>
#include <string.h>
#include <errno.h>
@@ -5,10 +34,13 @@
#include <tqmap.h>
#include <tqfile.h>
#include <tqdir.h>
+#include <tqtimer.h>
#include <kdebug.h>
+#include <tdeapplication.h>
#include <kstandarddirs.h>
#include <tdeprocess.h>
+#include <dcopclient.h>
#include <X11/Xatom.h>
#include <X11/Xos.h>
@@ -21,58 +53,80 @@
#include "extension.h"
+extern "C"
+{
+ static int IgnoreXError(Display *, XErrorEvent *) { return 0; }
+}
static TQString getLayoutKey(const TQString& layout, const TQString& variant)
{
return layout + "." + variant;
}
-XKBExtension::XKBExtension(Display *d)
-{
- if ( d == NULL )
- d = tqt_xdisplay();
- m_dpy = d;
+static XKBExtension *xkbExtension = nullptr;
-// TQStringList dirs = TDEGlobal::dirs()->findDirs ( "tmp", "" );
-// m_tempDir = dirs.count() == 0 ? "/tmp/" : dirs[0];
- m_tempDir = locateLocal("tmp", "");
+XKBExtension *XKBExtension::the()
+{
+ if (!xkbExtension)
+ {
+ xkbExtension = new XKBExtension;
+ if (!xkbExtension->init())
+ {
+ kdFatal() << "xkb initialization failed, exiting..." << endl;
+ ::exit(1);
+ }
+ }
+ return xkbExtension;
}
bool XKBExtension::init()
{
- // Verify the Xlib has matching XKB extension.
+ m_configureLock = 0;
+ acquireConfigureLock();
- int major = XkbMajorVersion;
- int minor = XkbMinorVersion;
+ kdDebug() << "[kxkb-extension] Initializing Xkb extension" << endl;
+ m_dpy = tqt_xdisplay();
- if (!XkbLibraryVersion(&major, &minor))
- {
- kdError() << "[kxkb-extension] Xlib XKB extension " << major << '.' << minor <<
- " != " << XkbMajorVersion << '.' << XkbMinorVersion << endl;
- return false;
- }
+ // Verify the Xlib has matching XKB extension.
+ int major = XkbMajorVersion;
+ int minor = XkbMinorVersion;
- // Verify the X server has matching XKB extension.
+ if (!XkbLibraryVersion(&major, &minor))
+ {
+ kdError() << "[kxkb-extension] Xlib XKB extension " << major << '.' << minor <<
+ " != " << XkbMajorVersion << '.' << XkbMinorVersion << endl;
+ return false;
+ }
- int opcode_rtrn;
- int error_rtrn;
- int xkb_opcode;
- if (!XkbQueryExtension(m_dpy, &opcode_rtrn, &xkb_opcode, &error_rtrn,
- &major, &minor))
- {
- kdError() << "[kxkb-extension] X server XKB extension " << major << '.' << minor <<
- " != " << XkbMajorVersion << '.' << XkbMinorVersion << endl;
- return false;
- }
+ // Verify the X server has matching XKB extension.
+ int opcode_rtrn;
+ int error_rtrn;
+ int xkb_opcode;
+ if (!XkbQueryExtension(m_dpy, &opcode_rtrn, &xkb_opcode, &error_rtrn,
+ &major, &minor))
+ {
+ kdError() << "[kxkb-extension] X server XKB extension " << major << '.' << minor <<
+ " != " << XkbMajorVersion << '.' << XkbMinorVersion << endl;
+ return false;
+ }
// Do it, or face horrible memory corrupting bugs
- ::XkbInitAtoms(NULL);
+ ::XkbInitAtoms(nullptr);
+
+ // Watch for interesting events
+ XkbSelectEventDetails(m_dpy, XkbUseCoreKbd, XkbStateNotify,
+ XkbAllStateComponentsMask, XkbGroupStateMask);
+
+ XkbSelectEventDetails(m_dpy, XkbUseCoreKbd, XkbNewKeyboardNotify,
+ XkbAllNewKeyboardEventsMask, XkbAllNewKeyboardEventsMask);
- // watch group change events
- XkbSelectEventDetails(m_dpy, XkbUseCoreKbd, XkbStateNotify,
- XkbAllStateComponentsMask, XkbGroupStateMask);
- return true;
+// TQStringList dirs = TDEGlobal::dirs()->findDirs ( "tmp", "" );
+// m_tempDir = dirs.count() == 0 ? "/tmp/" : dirs[0];
+ m_tempDir = locateLocal("tmp", "");
+
+ releaseConfigureLock();
+ return true;
}
XKBExtension::~XKBExtension()
@@ -81,8 +135,27 @@ XKBExtension::~XKBExtension()
deletePrecompiledLayouts();*/
}
+void XKBExtension::acquireConfigureLock()
+{
+ ++m_configureLock;
+}
+
+void XKBExtension::releaseConfigureLock()
+{
+ // Without this protection in place KXkb would react to configuration
+ // changes caused by itself
+ TQTimer::singleShot(500, this, TQ_SLOT(slotReleaseConfigureLock()));
+}
+
+void XKBExtension::slotReleaseConfigureLock()
+{
+ --m_configureLock;
+}
+
bool XKBExtension::setXkbOptions(const XkbOptions options)
{
+ acquireConfigureLock();
+
TQString exe = TDEGlobal::dirs()->findExe("setxkbmap");
if (exe.isEmpty())
{
@@ -121,7 +194,8 @@ bool XKBExtension::setXkbOptions(const XkbOptions options)
else
{
// Avoid duplication of options in Append mode
- TQStringList srvOptions = TQStringList::split(",", XKBExtension::getServerOptions());
+ XkbOptions _opt = getServerOptions();
+ TQStringList srvOptions = TQStringList::split(",", _opt.options);
TQStringList kxkbOptions = TQStringList::split(",", options.options);
TQStringList newOptions;
for (TQStringList::Iterator it = kxkbOptions.begin(); it != kxkbOptions.end(); ++it)
@@ -144,49 +218,72 @@ bool XKBExtension::setXkbOptions(const XkbOptions options)
// are already set and we are in append mode so we want to avoid
// duplicates
kdWarning() << "[setXkbOptions] No options need to be set" << endl;
+ slotReleaseConfigureLock(); // immediately release the lock
return true;
}
+ p << "-synch";
+
kdDebug() << "[setXkbOptions] Command: " << p.args() << endl;
p.start(TDEProcess::Block);
+ releaseConfigureLock();
+
return p.normalExit() && (p.exitStatus() == 0);
}
-TQString XKBExtension::getServerOptions()
+XkbOptions XKBExtension::getServerOptions()
{
- XkbRF_VarDefsRec vd;
- if (XkbRF_GetNamesProp(tqt_xdisplay(), nullptr, &vd) && vd.options)
- {
- kdDebug() << "[kxkb-extension] Got server options " << vd.options << endl;
- return TQString(vd.options);
- }
- return TQString::null;
+ XkbOptions options;
+ XkbRF_VarDefsRec vd;
+ if (XkbRF_GetNamesProp(tqt_xdisplay(), nullptr, &vd))
+ {
+ options.model = vd.model;
+ options.layouts = vd.layout;
+ options.variants = vd.variant;
+ options.options = vd.options;
+ }
+ return options;
}
bool XKBExtension::setGroup(unsigned int group)
{
kdDebug() << "[kxkb-extension] Setting group " << group << endl;
- return XkbLockGroup( m_dpy, XkbUseCoreKbd, group );
+ return XkbLockGroup(m_dpy, XkbUseCoreKbd, group);
}
uint XKBExtension::getGroup() const
{
XkbStateRec xkbState;
- XkbGetState( m_dpy, XkbUseCoreKbd, &xkbState );
+ XkbGetState(m_dpy, XkbUseCoreKbd, &xkbState);
return xkbState.group;
}
-/** Examines an X Event passed to it and takes actions if the event is of
- * interest to KXkb */
+bool XKBExtension::kcmlayoutRunning()
+{
+ return kapp->dcopClient()->isApplicationRegistered("TDECModuleProxy-keyboard_layout");
+}
+
+// Examines an X Event passed to it and takes actions if the event is of
+// interest to KXkb
void XKBExtension::processXEvent(XEvent *event) {
- XkbEvent* xkb_event = (XkbEvent*)event;
- if (xkb_event->any.xkb_type == XkbStateNotify &&
- xkb_event->state.changed & XkbGroupStateMask)
- {
- emit groupChanged((uint)xkb_event->state.group);
- }
+ XkbEvent* xkb_event = (XkbEvent*)event;
+ if (xkb_event->any.xkb_type == XkbStateNotify && xkb_event->state.changed & XkbGroupStateMask)
+ {
+ emit groupChanged((uint)xkb_event->state.group);
+ }
+
+ else if (xkb_event->any.xkb_type == XkbNewKeyboardNotify)
+ {
+ if (m_configureLock > 0 || kcmlayoutRunning())
+ {
+ return;
+ }
+ acquireConfigureLock();
+ emit optionsChanged();
+ releaseConfigureLock();
+ }
}
-#include "extension.moc"
+#include "extension.moc" \ No newline at end of file
diff --git a/kxkb/extension.h b/kxkb/extension.h
index 091cce582..7bc085dbf 100644
--- a/kxkb/extension.h
+++ b/kxkb/extension.h
@@ -1,7 +1,36 @@
+/*******************************************************************************
+
+ Xkb extension for KXkb
+ Copyright © 2009-2025 Trinity Desktop project
+ Copyright © 2001 S.R. Haque <[email protected]>
+
+ Derived from an original by Matthias H�zer-Klpfel released under the QPL.
+
+ Some portions come from kkbswitch released under the GNU GPL v2 (or later).
+ Copyright © 2001 Leonid Zeitlin <[email protected]>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*******************************************************************************/
+
#ifndef __EXTENSION_H__
#define __EXTENSION_H__
#include <X11/Xlib.h>
+
#include <tqobject.h>
#include "kxkbconfig.h"
@@ -11,24 +40,43 @@ class XKBExtension : public TQObject
TQ_OBJECT
public:
- XKBExtension(Display *display=NULL);
+ static XKBExtension *the();
~XKBExtension();
+
+ XKBExtension(XKBExtension const&) = delete;
+ void operator=(XKBExtension const&) = delete;
+
bool init();
- static bool setXkbOptions(const XkbOptions options);
- static TQString getServerOptions();
+ bool setXkbOptions(const XkbOptions options);
bool setGroup(uint group);
+
uint getGroup() const;
+ XkbOptions getServerOptions();
+
void processXEvent(XEvent *ev);
+ void acquireConfigureLock();
+ void releaseConfigureLock();
+
+ bool kcmlayoutRunning();
+
+private slots:
+ void slotReleaseConfigureLock();
+
+protected:
+ XKBExtension() {}
+
private:
- Display *m_dpy;
+ Display *m_dpy;
TQString m_tempDir;
int m_keycode;
static TQMap<TQString, FILE*> fileCache;
+ int m_configureLock;
signals:
void groupChanged(uint group);
+ void optionsChanged();
};
#endif
diff --git a/kxkb/kcmlayout.cpp b/kxkb/kcmlayout.cpp
index 256247371..b1deda349 100644
--- a/kxkb/kcmlayout.cpp
+++ b/kxkb/kcmlayout.cpp
@@ -14,6 +14,7 @@
#include <tqbuttongroup.h>
#include <tqspinbox.h>
#include <tqvbox.h>
+#include <tqtimer.h>
#include <tdefontrequester.h>
#include <kcolorbutton.h>
@@ -190,8 +191,8 @@ LayoutConfig::LayoutConfig(TQWidget *parent, const char *name)
#include "kxkbbindings.cpp"
makeOptionsTab();
- load();
makeShortcutsTab();
+ TQTimer::singleShot(0, this, TQ_SLOT(load()));
}
@@ -204,12 +205,22 @@ LayoutConfig::~LayoutConfig()
void LayoutConfig::load()
{
+ bool modified = false;
+ m_kxkbConfig.load(KxkbConfig::LOAD_ALL_OPTIONS);
+
+ // Check if the active settings are different from the saved settings
+ if (m_kxkbConfig.m_useKxkb)
+ {
+ XkbOptions options = XKBExtension::the()->getServerOptions();
+ modified = m_kxkbConfig.setFromXkbOptions(options);
+ }
+
m_kxkbConfig.load(KxkbConfig::LOAD_ALL_OPTIONS);
keys->readSettings();
- initUI();
+ initUI(modified);
}
-void LayoutConfig::initUI() {
+void LayoutConfig::initUI(bool modified) {
const char* modelName = m_rules->models()[m_kxkbConfig.m_model];
if( modelName == NULL )
modelName = DEFAULT_MODEL;
@@ -226,7 +237,6 @@ void LayoutConfig::initUI() {
for ( ; src_it.current(); ++src_it ) {
TQListViewItem* srcItem = src_it.current();
-
if ( layoutUnit.layout == src_it.current()->text(LAYOUT_COLUMN_MAP) ) { // check if current config knows about this layout
TQListViewItem* newItem = copyLVI(srcItem, widget->listLayoutsDst);
@@ -354,7 +364,7 @@ void LayoutConfig::initUI() {
updateOptionsCommand();
updateHotkeyCombo(true);
- emit TDECModule::changed( false );
+ emit TDECModule::changed(modified);
}
@@ -433,7 +443,8 @@ void LayoutConfig::save()
if (m_forceGrpOverwrite)
{
// First get all the server's options
- TQStringList srvOptions = TQStringList::split(",", XKBExtension::getServerOptions());
+ XkbOptions _opt = XKBExtension::the()->getServerOptions();
+ TQStringList srvOptions = TQStringList::split(",", _opt.options);
TQStringList newOptions;
// Then remove all grp: options
@@ -450,7 +461,7 @@ void LayoutConfig::save()
xkbOptions.options = newOptions.join(",");
xkbOptions.resetOld = true;
- if (!XKBExtension::setXkbOptions(xkbOptions))
+ if (!XKBExtension::the()->setXkbOptions(xkbOptions))
{
kdWarning() << "[LayoutConfig::save] Could not overwrite previous grp: options!" << endl;
}
@@ -1008,7 +1019,8 @@ void LayoutConfig::updateHotkeyCombo(bool initial) {
// Get server options first
if (initial || widget->xkbOptsMode->selectedId() == 1)
{
- TQStringList opts = TQStringList::split(",", XKBExtension::getServerOptions());
+ XkbOptions _opt = XKBExtension::the()->getServerOptions();
+ TQStringList opts = TQStringList::split(",", _opt.options);
for (TQStringList::Iterator it = opts.begin(); it != opts.end(); ++it)
{
TQString option(*it);
@@ -1268,7 +1280,7 @@ extern "C"
kapp->startServiceByDesktopName("kxkb");
}
else {
- if (!XKBExtension::setXkbOptions(m_kxkbConfig.getKXkbOptions())) {
+ if (!XKBExtension::the()->setXkbOptions(m_kxkbConfig.getKXkbOptions())) {
kdDebug() << "Setting XKB options failed!" << endl;
}
}
diff --git a/kxkb/kcmlayout.h b/kxkb/kcmlayout.h
index 256946ad1..0d2e153b2 100644
--- a/kxkb/kcmlayout.h
+++ b/kxkb/kcmlayout.h
@@ -23,11 +23,13 @@ public:
LayoutConfig(TQWidget *parent = 0L, const char *name = 0L);
virtual ~LayoutConfig();
+ void initUI(bool modified = false);
+ virtual TQString handbookDocPath() const;
+
+public slots:
void load();
void save();
void defaults();
- void initUI();
- virtual TQString handbookDocPath() const;
protected:
TQString createOptionString();
diff --git a/kxkb/kxkb.cpp b/kxkb/kxkb.cpp
index 8bced3fea..f87c066bb 100644
--- a/kxkb/kxkb.cpp
+++ b/kxkb/kxkb.cpp
@@ -24,7 +24,6 @@ DESCRIPTION
*/
#include <unistd.h>
-#include <stdlib.h>
#include <assert.h>
#include <tqregexp.h>
@@ -70,13 +69,10 @@ KXKBApp::KXKBApp(bool allowStyles, bool GUIenabled)
m_tray(NULL),
kWinModule(NULL)
{
- X11Helper::initializeTranslations();
- m_extension = new XKBExtension();
- if( !m_extension->init() ) {
- kdDebug() << "xkb initialization failed, exiting..." << endl;
- ::exit(1);
- }
- connect(m_extension, TQ_SIGNAL(groupChanged(uint)), this, TQ_SLOT(slotGroupChanged(uint)));
+ X11Helper::initializeTranslations();
+ XKBExtension *xkb = XKBExtension::the();
+ connect(xkb, TQ_SIGNAL(groupChanged(uint)), this, TQ_SLOT(slotGroupChanged(uint)));
+ connect(xkb, TQ_SIGNAL(optionsChanged()), this, TQ_SLOT(slotSyncXkbOptions()));
m_layoutOwnerMap = new LayoutMap(kxkbConfig);
@@ -97,7 +93,6 @@ KXKBApp::~KXKBApp()
{
delete m_tray;
delete m_rules;
- delete m_extension;
delete m_layoutOwnerMap;
delete kWinModule;
delete keys;
@@ -203,7 +198,7 @@ void KXKBApp::readSettings()
void KXKBApp::applyXkbOptions()
{
XkbOptions options = kxkbConfig.getKXkbOptions();
- if (!m_extension->setXkbOptions(options)) {
+ if (!XKBExtension::the()->setXkbOptions(options)) {
kdWarning() << "Setting XKB options failed!" << endl;
}
}
@@ -236,14 +231,14 @@ bool KXKBApp::setLayout(const LayoutUnit& layoutUnit)
bool KXKBApp::setLayout(const uint group)
{
// If this group is already set, just show the notification and return
- if (m_extension->getGroup() == group) {
+ if (XKBExtension::the()->getGroup() == group) {
if (kxkbConfig.m_enableNotify) {
showLayoutNotification();
}
return true;
}
- bool ok = m_extension->setGroup(group);
+ bool ok = XKBExtension::the()->setGroup(group);
if (!ok) {
TQString layout = kxkbConfig.m_layouts[group].toPair();
if (m_tray) {
@@ -290,8 +285,8 @@ void KXKBApp::menuActivated(int id)
void KXKBApp::slotGroupChanged(uint group)
{
- kdDebug() << "slotGroupChanged: " << group << ", layout count: " << kxkbConfig.m_layouts.count() << endl;
if (group >= kxkbConfig.m_layouts.count()) {
+ kdError() << "[kxkb] unknown group requested: " << group << endl;
if (m_tray)
{
m_tray->setError(i18n("Unknown"));
@@ -317,7 +312,25 @@ void KXKBApp::slotGroupChanged(uint group)
}
}
-void KXKBApp::showLayoutNotification() {
+void KXKBApp::slotSyncXkbOptions()
+{
+ // Make sure the X11 server has had enough time to apply the change
+ TQTimer::singleShot(100, this, TQ_SLOT(syncXkbOptions()));
+}
+
+void KXKBApp::syncXkbOptions()
+{
+ XkbOptions options = XKBExtension::the()->getServerOptions();
+ if (kxkbConfig.setFromXkbOptions(options))
+ {
+ m_layoutOwnerMap->reset();
+ m_tray->initLayoutList(kxkbConfig.m_layouts, *m_rules);
+ }
+ slotGroupChanged(XKBExtension::the()->getGroup());
+}
+
+void KXKBApp::showLayoutNotification()
+{
bool useKMilo = kxkbConfig.m_notifyUseKMilo && isKMiloAvailable(),
notificationSent = false;
@@ -396,7 +409,6 @@ void KXKBApp::windowChanged(WId winId)
}
}
-
void KXKBApp::slotSettingsChanged(int category)
{
if (category == TDEApplication::SETTINGS_SHORTCUTS) {
@@ -408,7 +420,7 @@ void KXKBApp::slotSettingsChanged(int category)
bool KXKBApp::x11EventFilter(XEvent *e) {
// let the extension process the event and emit signals if necessary
- m_extension->processXEvent(e);
+ XKBExtension::the()->processXEvent(e);
return TDEApplication::x11EventFilter(e);
}
diff --git a/kxkb/kxkb.h b/kxkb/kxkb.h
index b5ac7b7bf..5cbebed5a 100644
--- a/kxkb/kxkb.h
+++ b/kxkb/kxkb.h
@@ -83,6 +83,8 @@ protected slots:
void readSettings();
void applyXkbOptions();
+ void slotSyncXkbOptions();
+ void syncXkbOptions();
private:
void initTray();
diff --git a/kxkb/kxkbconfig.cpp b/kxkb/kxkbconfig.cpp
index 166dab174..5409f8270 100644
--- a/kxkb/kxkbconfig.cpp
+++ b/kxkb/kxkbconfig.cpp
@@ -33,6 +33,7 @@ const char* DEFAULT_MODEL = "pc104";
void KxkbConfig::load(int loadMode)
{
// INITIAL OPTIONS (loaded regardless of whether KXkb is enabled)
+
TDEConfig *config = new TDEConfig("kxkbrc", true, false);
config->setGroup("Layout");
@@ -46,7 +47,8 @@ void KxkbConfig::load(int loadMode)
return;
}
- // ALL OTHER OPTIONS (loaded only when KXkb is enabled)
+ // BASIC OPTIONS (passed to setxkbmap)
+
m_model = config->readEntry("Model", DEFAULT_MODEL);
// Layouts
@@ -93,6 +95,13 @@ void KxkbConfig::load(int loadMode)
}
}
+ if (loadMode == LOAD_BASIC_OPTIONS)
+ {
+ return;
+ }
+
+ // ALL OTHER OPTIONS (of interest only to KXkb itself)
+
// Tray indicator
m_showSingle = config->readBoolEntry("ShowSingle", false);
@@ -267,6 +276,74 @@ void KxkbConfig::setDefaults()
m_stickySwitchingDepth = 2;
}
+bool KxkbConfig::setFromXkbOptions(XkbOptions options)
+{
+ XkbOptions curOptions = getKXkbOptions();
+
+ bool modified = false;
+
+ // We need to fix the variants string if it is empty, otherwise the
+ // comparison below will often wrongly assume that the variants have
+ // changed
+ if (options.variants.isEmpty())
+ {
+ options.variants = ""; // ensure the string is empty but not null
+ for (int i = 0; i < options.layouts.contains(","); ++i)
+ {
+ options.variants += ",";
+ }
+ }
+
+ // Check if keyboard layout options have changed
+ if ((options.model != curOptions.model && !options.model.isNull()))
+ {
+ modified = true;
+ m_model = options.model;
+ }
+
+ if ((options.layouts != curOptions.layouts) || (options.variants != curOptions.variants))
+ {
+ modified = true;
+ m_layouts.clear();
+
+ TQStringList layouts = TQStringList::split(",", options.layouts, true);
+ TQStringList variants = TQStringList::split(",", options.variants, true);
+ TQStringList::Iterator lit = layouts.begin();
+ TQStringList::Iterator vit = variants.begin();
+
+ if (layouts.empty())
+ {
+ layouts << "us";
+ }
+
+ while (lit != layouts.end())
+ {
+ TQString layout = *lit;
+ TQString variant = vit != variants.end() ? *vit : TQString::null;
+ m_layouts.append(LayoutUnit(layout, variant));
+
+ ++lit;
+ if (vit != variants.end())
+ {
+ ++vit;
+ }
+ }
+ }
+
+ TQStringList serverOpts = TQStringList::split(",", options.options);
+ TQStringList kxkbOpts = TQStringList::split(",", curOptions.options);
+ serverOpts.sort();
+ kxkbOpts.sort();
+
+ if (serverOpts != kxkbOpts)
+ {
+ modified = true;
+ m_options = options.options;
+ }
+
+ return modified;
+}
+
TQStringList KxkbConfig::getLayoutStringList(/*bool compact*/)
{
TQStringList layoutList;
@@ -323,10 +400,15 @@ const XkbOptions KxkbConfig::getKXkbOptions() {
}
options.layouts = layouts.join(",");
options.variants = variants.join(",");
- options.model = m_model;
options.options = m_options;
- kdDebug() << "[getKXkbOptions] options: " << m_options << endl;
options.resetOld = m_resetOldOptions;
+ options.model = m_model;
+
+ if (options.model.isEmpty())
+ {
+ options.model = DEFAULT_MODEL;
+ }
+
return options;
}
diff --git a/kxkb/kxkbconfig.h b/kxkb/kxkbconfig.h
index a365ef252..7d02fd3a3 100644
--- a/kxkb/kxkbconfig.h
+++ b/kxkb/kxkbconfig.h
@@ -45,7 +45,7 @@ extern const char* DEFAULT_MODEL;
class KxkbConfig
{
public:
- enum { LOAD_INIT_OPTIONS, LOAD_ALL_OPTIONS };
+ enum { LOAD_INIT_OPTIONS, LOAD_BASIC_OPTIONS, LOAD_ALL_OPTIONS };
bool m_useKxkb;
bool m_showSingle;
@@ -82,6 +82,7 @@ public:
static TQString getDefaultDisplayName(const TQString& code_);
static TQString getDefaultDisplayName(const LayoutUnit& layoutUnit, bool single=false);
+ bool setFromXkbOptions(XkbOptions options);
const XkbOptions getKXkbOptions();
private: