Kxkb: Improve layout switching

1) New layout switching approach

The new approach is based on the "grp" options group of Xkb
and so enables us to use predefined X11 layout (group) switching
hotkeys like "Caps Lock" or "Shift+Alt" (you can see the full list
in the Options tab). The added bonus to this is that we conform
to the Xkb setting.

The code lets Xkb handle the keyboard layout switching hotkey(s)
and is similar to the one that is used in kkbswitch, monitoring
for an Xkb group (layout) change event.

This solution required me to remove some hacky and obsolete code
which was there to support really old pre-XFree-4.2 era systems
and included the "include groups" hack.

This means that the "Enable latin layout" checkbox is now gone
and setxkbmap is only called when the keyboard layouts and/or
options are modified, and not for every layout change.

2) Common layout switching hotkeys combobox

A combobox was added to the first page of the Keyboard Layouts
KCM module. It provides to the users a quick way to set a layout
switching key combination. It also controls the "grp" group in
the Xkb tab.

A special note about this combobox is that, even if Append Mode
was selected in the Xkb Options tab, this hotkey will overwrite
previous hotkey options. This means that all grp: options will
be forced removed before applying the option from the combobox
(in contrast to specifying options via the Xkb Options tab,
which, in Append Mode, will not get overwritten until next login).

Signed-off-by: Mavridis Philippe <mavridisf@gmail.com>
pull/304/head
Mavridis Philippe 1 year ago
parent b50ab13974
commit a67db2d484
No known key found for this signature in database
GPG Key ID: F8D2D7E2F989A494

@ -66,7 +66,6 @@ void KKeyModule::init( bool isGlobal, bool _bSeriesOnly, bool bSeriesNone )
#include "../../kicker/taskbar/taskbarbindings.cpp" #include "../../kicker/taskbar/taskbarbindings.cpp"
#include "../../kdesktop/kdesktopbindings.cpp" #include "../../kdesktop/kdesktopbindings.cpp"
#include "../../klipper/klipperbindings.cpp" #include "../../klipper/klipperbindings.cpp"
#include "../../kxkb/kxkbbindings.cpp"
#undef TDEShortcuts #undef TDEShortcuts
KeyScheme = "Global Key Scheme"; KeyScheme = "Global Key Scheme";
KeySet = "Global Keys"; KeySet = "Global Keys";
@ -489,7 +488,6 @@ void KKeyModule::init()
#include "../../kicker/kicker/core/kickerbindings.cpp" #include "../../kicker/kicker/core/kickerbindings.cpp"
#include "../../kicker/taskbar/taskbarbindings.cpp" #include "../../kicker/taskbar/taskbarbindings.cpp"
#include "../../kdesktop/kdesktopbindings.cpp" #include "../../kdesktop/kdesktopbindings.cpp"
#include "../../kxkb/kxkbbindings.cpp"
#undef TDEShortcuts #undef TDEShortcuts
kdDebug(125) << "KKeyModule::init() - Read Config Bindings\n"; kdDebug(125) << "KKeyModule::init() - Read Config Bindings\n";

@ -190,7 +190,6 @@ extern "C"
#include "../../kicker/kicker/core/kickerbindings.cpp" #include "../../kicker/kicker/core/kickerbindings.cpp"
#include "../../kicker/taskbar/taskbarbindings.cpp" #include "../../kicker/taskbar/taskbarbindings.cpp"
#include "../../kdesktop/kdesktopbindings.cpp" #include "../../kdesktop/kdesktopbindings.cpp"
#include "../../kxkb/kxkbbindings.cpp"
// Write all the global keys to kdeglobals. // Write all the global keys to kdeglobals.
// This is needed to be able to check for conflicts with global keys in app's keyconfig // This is needed to be able to check for conflicts with global keys in app's keyconfig

@ -116,7 +116,6 @@ void ShortcutsModule::initGUI()
#include "../../kicker/taskbar/taskbarbindings.cpp" #include "../../kicker/taskbar/taskbarbindings.cpp"
#include "../../kdesktop/kdesktopbindings.cpp" #include "../../kdesktop/kdesktopbindings.cpp"
#include "../../klipper/klipperbindings.cpp" #include "../../klipper/klipperbindings.cpp"
#include "../../kxkb/kxkbbindings.cpp"
kdDebug(125) << "B-----------" << endl; kdDebug(125) << "B-----------" << endl;
m_actionsSequence.init( m_actionsGeneral ); m_actionsSequence.init( m_actionsGeneral );

@ -5,7 +5,6 @@ tde_l10n_create_template(
SOURCES SOURCES
kcmlayout.cpp kcmlayout.cpp
kcmmisc.cpp kcmmisc.cpp
kxkbbindings.cpp
pixmap.cpp pixmap.cpp
rules.cpp rules.cpp
*.ui *.ui
@ -16,7 +15,6 @@ tde_l10n_create_template(
SOURCES SOURCES
extension.cpp extension.cpp
kxkb.cpp kxkb.cpp
kxkbbindings.cpp
kxkbtraywindow.cpp kxkbtraywindow.cpp
pixmap.cpp pixmap.cpp
rules.cpp rules.cpp

@ -21,20 +21,11 @@
#include "extension.h" #include "extension.h"
TQMap<TQString, FILE*> XKBExtension::fileCache; //TODO: move to class?
static TQString getLayoutKey(const TQString& layout, const TQString& variant) static TQString getLayoutKey(const TQString& layout, const TQString& variant)
{ {
return layout + "." + variant; return layout + "." + variant;
} }
TQString XKBExtension::getPrecompiledLayoutFilename(const TQString& layoutKey)
{
TQString compiledLayoutFileName = m_tempDir + layoutKey + ".xkm";
return compiledLayoutFileName;
}
XKBExtension::XKBExtension(Display *d) XKBExtension::XKBExtension(Display *d)
{ {
if ( d == NULL ) if ( d == NULL )
@ -76,16 +67,11 @@ bool XKBExtension::init()
// Do it, or face horrible memory corrupting bugs // Do it, or face horrible memory corrupting bugs
::XkbInitAtoms(NULL); ::XkbInitAtoms(NULL);
return true; // watch group change events
} XkbSelectEventDetails(m_dpy, XkbUseCoreKbd, XkbStateNotify,
XkbAllStateComponentsMask, XkbGroupStateMask);
void XKBExtension::reset() return true;
{
for(TQMap<TQString, FILE*>::ConstIterator it = fileCache.begin(); it != fileCache.end(); it++) {
fclose(*it);
// remove( TQFile::encodeName(getPrecompiledLayoutFileName(*it)) );
}
fileCache.clear();
} }
XKBExtension::~XKBExtension() XKBExtension::~XKBExtension()
@ -94,106 +80,38 @@ XKBExtension::~XKBExtension()
deletePrecompiledLayouts();*/ deletePrecompiledLayouts();*/
} }
bool XKBExtension::setXkbOptions(const TQString& options, bool resetOld) bool XKBExtension::setXkbOptions(const XkbOptions options)
{ {
if (options.isEmpty()) TQString exe = TDEGlobal::dirs()->findExe("setxkbmap");
return true; if (exe.isEmpty())
return false;
TQString exe = TDEGlobal::dirs()->findExe("setxkbmap");
if (exe.isEmpty())
return false;
TDEProcess p;
p << exe;
if( resetOld )
p << "-option";
p << "-option" << options;
p.start(TDEProcess::Block);
return p.normalExit() && (p.exitStatus() == 0); TDEProcess p;
} p << exe;
bool XKBExtension::setLayout(const TQString& model, p << "-layout";
const TQString& layout, const TQString& variant, p << options.layouts;
const TQString& includeGroup, bool useCompiledLayouts)
{
if( useCompiledLayouts == false ) {
return setLayoutInternal( model, layout, variant, includeGroup );
}
const TQString layoutKey = getLayoutKey(layout, variant); p << "-variant";
p << options.variants;
bool res; if (!options.model.isEmpty()) {
if( fileCache.contains(layoutKey) ) { p << "-model";
res = setCompiledLayout( layoutKey ); p << options.model;
kdDebug() << "[kxkb-extension] setCompiledLayout " << layoutKey << ": " << res << endl;
if( res )
return res;
} }
// else {
res = setLayoutInternal( model, layout, variant, includeGroup );
kdDebug() << "[kxkb-extension] setRawLayout " << layoutKey << ": " << res << endl;
if( res )
compileCurrentLayout( layoutKey );
// }
return res;
}
// private if (options.resetOld) {
bool XKBExtension::setLayoutInternal(const TQString& model, p << "-option";
const TQString& layout, const TQString& variant, }
const TQString& includeGroup) if (!options.options.isEmpty()) {
{ p << "-option" << options.options;
if ( layout.isEmpty() )
return false;
TQString exe = TDEGlobal::dirs()->findExe("setxkbmap");
if( exe.isEmpty() ) {
kdError() << "[kxkb-extension] Can't find setxkbmap" << endl;
return false;
} }
TQString fullLayout = layout; kdDebug() << "[kxkb-extension] Command: " << p.args() << endl;
TQString fullVariant = variant;
if( includeGroup.isEmpty() == false ) {
fullLayout = includeGroup;
fullLayout += ",";
fullLayout += layout;
// fullVariant = baseVar;
fullVariant = ",";
fullVariant += variant;
}
TDEProcess p;
p << exe;
// p << "-rules" << rule;
if( model.isEmpty() == false )
p << "-model" << model;
p << "-layout" << fullLayout;
if( !fullVariant.isNull() && !fullVariant.isEmpty() )
p << "-variant" << fullVariant;
p.start(TDEProcess::Block);
// reload system-wide hotkey-setup keycode -> keysym maps
TQString modmapFileName = TDEGlobal::dirs()->findResource( "data", "kxkb/system.xmodmap" );
if ( TQFile::exists( modmapFileName ) ) {
TDEProcess pXmodmap;
pXmodmap << "xmodmap" << modmapFileName;
pXmodmap.start(TDEProcess::Block);
}
if ( TQFile::exists( TQDir::home().path() + "/.Xmodmap" ) ) { p.start(TDEProcess::Block);
TDEProcess pXmodmapHome;
pXmodmapHome << "xmodmap" << TQDir::home().path() + "/.Xmodmap";
pXmodmapHome.start(TDEProcess::Block);
}
return p.normalExit() && (p.exitStatus() == 0); return p.normalExit() && (p.exitStatus() == 0);
} }
bool XKBExtension::setGroup(unsigned int group) bool XKBExtension::setGroup(unsigned int group)
@ -209,130 +127,13 @@ unsigned int XKBExtension::getGroup() const
return xkbState.group; return xkbState.group;
} }
/** /** Examines an X Event passed to it and takes actions if the event is of
* @brief Gets the current layout in its binary compiled form * interest to KXkb */
* and write it to the file specified by 'fileName' void XKBExtension::processXEvent(XEvent *event) {
* @param[in] fileName file to store compiled layout to XkbEvent* xkb_event = (XkbEvent*)event;
* @return true if no problem, false otherwise if (xkb_event->any.xkb_type == XkbStateNotify) {
*/ emit groupChanged(xkb_event->state.group);
bool XKBExtension::compileCurrentLayout(const TQString &layoutKey)
{
XkbFileInfo result;
memset(&result, 0, sizeof(result));
result.type = XkmKeymapFile;
XkbReadFromServer(m_dpy, XkbAllMapComponentsMask, XkbAllMapComponentsMask, &result);
const TQString fileName = getPrecompiledLayoutFilename(layoutKey);
kdDebug() << "[kxkb-extension] compiling layout " << this << " cache size: " << fileCache.count() << endl;
if( fileCache.contains(layoutKey) ) {
kdDebug() << "[kxkb-extension] trashing old compiled layout for " << fileName << endl;
if( fileCache[ layoutKey ] != NULL )
fclose( fileCache[ layoutKey ] ); // recompiling - trash the old file
fileCache.remove(fileName);
}
FILE *output = fopen(TQFile::encodeName(fileName), "w");
if ( output == NULL )
{
kdWarning() << "[kxkb-extension] Could not open " << fileName << " to precompile: " << strerror(errno) << endl;
XkbFreeKeyboard(result.xkb, XkbAllControlsMask, True);
return false;
} }
if( !XkbWriteXKMFile(output, &result) ) {
kdWarning() << "[kxkb-extension] Could not write compiled layout to " << fileName << endl;
fclose(output);
return false;
}
fclose(output); // TODO: can we change mode w/out reopening?
FILE *input = fopen(TQFile::encodeName(fileName), "r");
fileCache[ layoutKey ] = input;
XkbFreeKeyboard(result.xkb, XkbAllControlsMask, True);
return true;
} }
/** #include "extension.moc"
* @brief takes layout from its compiled binary snapshot in file
* and sets it as current
* TODO: cache layout in memory rather than in file
*/
bool XKBExtension::setCompiledLayout(const TQString &layoutKey)
{
FILE *input = NULL;
if( fileCache.contains(layoutKey) ) {
input = fileCache[ layoutKey ];
}
if( input == NULL ) {
kdWarning() << "[kxkb-extension] setCompiledLayout trying to reopen xkb file" << endl; // should never happen
const TQString fileName = getPrecompiledLayoutFilename(layoutKey);
input = fopen(TQFile::encodeName(fileName), "r");
// FILE *input = fopen(TQFile::encodeName(fileName), "r");
if ( input == NULL ) {
kdDebug() << "[kxkb-extension] Unable to open " << fileName << ": " << strerror(errno) << endl;
fileCache.remove(layoutKey);
return false;
}
}
else {
rewind(input);
}
XkbFileInfo result;
memset(&result, 0, sizeof(result));
if ((result.xkb = XkbAllocKeyboard())==NULL) {
kdWarning() << "[kxkb-extension] Unable to allocate memory for keyboard description" << endl;
// fclose(input);
// fileCache.remove(layoutKey);
return false;
}
unsigned retVal = XkmReadFile(input, 0, XkmKeymapLegal, &result);
if (retVal == XkmKeymapLegal)
{
// this means reading the Xkm didn't manage to read any section
kdWarning() << "[kxkb-extension] Unable to load map from file" << endl;
XkbFreeKeyboard(result.xkb, XkbAllControlsMask, True);
fclose(input);
fileCache.remove(layoutKey);
return false;
}
// fclose(input); // don't close - goes in cache
if (XkbChangeKbdDisplay(m_dpy, &result) == Success)
{
if (!XkbWriteToServer(&result))
{
kdWarning() << "[kxkb-extension] Unable to write the keyboard layout to X display" << endl;
XkbFreeKeyboard(result.xkb, XkbAllControlsMask, True);
return false;
}
}
else
{
kdWarning() << "[kxkb-extension] Unable prepare the keyboard layout for X display" << endl;
}
XkbFreeKeyboard(result.xkb, XkbAllControlsMask, True);
return true;
}
// Deletes the precompiled layouts stored in temporary files
// void XKBExtension::deletePrecompiledLayouts()
// {
// TQMapConstIterator<LayoutUnit, TQString> it, end;
// end = m_compiledLayoutFileNames.end();
// for (it = m_compiledLayoutFileNames.begin(); it != end; ++it)
// {
// unlink(TQFile::encodeName(it.data()));
// }
// m_compiledLayoutFileNames.clear();
// }

@ -2,36 +2,32 @@
#define __EXTENSION_H__ #define __EXTENSION_H__
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <tqobject.h>
#include "kxkbconfig.h"
class XKBExtension class XKBExtension : public TQObject
{ {
TQ_OBJECT
public: public:
XKBExtension(Display *display=NULL); XKBExtension(Display *display=NULL);
~XKBExtension(); ~XKBExtension();
bool init(); bool init();
void reset();
static bool setXkbOptions(const TQString& options, bool resetOldOptions); static bool setXkbOptions(const XkbOptions options);
bool setLayout(const TQString& model,
const TQString& layout, const TQString& variant,
const TQString& includeGroup, bool useCompiledLayouts=true);
bool setGroup(unsigned int group); bool setGroup(unsigned int group);
unsigned int getGroup() const; unsigned int getGroup() const;
void processXEvent(XEvent *ev);
private: private:
Display *m_dpy; Display *m_dpy;
TQString m_tempDir; TQString m_tempDir;
int m_keycode;
static TQMap<TQString, FILE*> fileCache; static TQMap<TQString, FILE*> fileCache;
bool setLayoutInternal(const TQString& model, signals:
const TQString& layout, const TQString& variant, void groupChanged(uint group);
const TQString& includeGroup);
bool compileCurrentLayout(const TQString& layoutKey);
bool setCompiledLayout(const TQString& layoutKey);
TQString getPrecompiledLayoutFilename(const TQString& layoutKey);
// void deletePrecompiledLayouts();
}; };
#endif #endif

@ -43,8 +43,7 @@ enum {
LAYOUT_COLUMN_NAME = 1, LAYOUT_COLUMN_NAME = 1,
LAYOUT_COLUMN_MAP = 2, LAYOUT_COLUMN_MAP = 2,
LAYOUT_COLUMN_VARIANT = 3, LAYOUT_COLUMN_VARIANT = 3,
LAYOUT_COLUMN_INCLUDE = 4, LAYOUT_COLUMN_DISPLAY_NAME = 4,
LAYOUT_COLUMN_DISPLAY_NAME = 5,
SRC_LAYOUT_COLUMN_COUNT = 3, SRC_LAYOUT_COLUMN_COUNT = 3,
DST_LAYOUT_COLUMN_COUNT = 6 DST_LAYOUT_COLUMN_COUNT = 6
}; };
@ -110,6 +109,9 @@ LayoutConfig::LayoutConfig(TQWidget *parent, const char *name)
connect( TQT_TQOBJECT(widget->chkEnable), TQT_SIGNAL( toggled( bool )), TQT_TQOBJECT(this), TQT_SLOT(changed())); connect( TQT_TQOBJECT(widget->chkEnable), TQT_SIGNAL( toggled( bool )), TQT_TQOBJECT(this), TQT_SLOT(changed()));
connect( TQT_TQOBJECT(widget->chkShowSingle), TQT_SIGNAL( toggled( bool )), TQT_TQOBJECT(this), TQT_SLOT(changed())); connect( TQT_TQOBJECT(widget->chkShowSingle), TQT_SIGNAL( toggled( bool )), TQT_TQOBJECT(this), TQT_SLOT(changed()));
connect( TQT_TQOBJECT(widget->comboHotkey), TQT_SIGNAL(activated(int)), TQT_TQOBJECT(this), TQT_SLOT(hotkeyComboChanged()));
connect( TQT_TQOBJECT(widget->comboHotkey), TQT_SIGNAL(activated(int)), TQT_TQOBJECT(this), TQT_SLOT(updateOptionsCommand()));
connect( TQT_TQOBJECT(widget->comboHotkey), TQT_SIGNAL(activated(int)), TQT_TQOBJECT(this), TQT_SLOT(changed()));
connect( TQT_TQOBJECT(widget->comboModel), TQT_SIGNAL(activated(int)), TQT_TQOBJECT(this), TQT_SLOT(changed())); connect( TQT_TQOBJECT(widget->comboModel), TQT_SIGNAL(activated(int)), TQT_TQOBJECT(this), TQT_SLOT(changed()));
connect( TQT_TQOBJECT(widget->listLayoutsSrc), TQT_SIGNAL(doubleClicked(TQListViewItem*,const TQPoint&, int)), connect( TQT_TQOBJECT(widget->listLayoutsSrc), TQT_SIGNAL(doubleClicked(TQListViewItem*,const TQPoint&, int)),
@ -124,9 +126,6 @@ LayoutConfig::LayoutConfig(TQWidget *parent, const char *name)
connect( widget->editDisplayName, TQT_SIGNAL(textChanged(const TQString&)), TQT_TQOBJECT(this), TQT_SLOT(displayNameChanged(const TQString&))); connect( widget->editDisplayName, TQT_SIGNAL(textChanged(const TQString&)), TQT_TQOBJECT(this), TQT_SLOT(displayNameChanged(const TQString&)));
connect( widget->chkLatin, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(changed()));
connect( widget->chkLatin, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(latinChanged()));
widget->btnUp->setIconSet(SmallIconSet("1uparrow")); widget->btnUp->setIconSet(SmallIconSet("1uparrow"));
connect( widget->btnUp, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(changed())); connect( widget->btnUp, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(changed()));
connect( widget->btnUp, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(moveUp())); connect( widget->btnUp, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(moveUp()));
@ -149,16 +148,12 @@ LayoutConfig::LayoutConfig(TQWidget *parent, const char *name)
widget->listLayoutsSrc->setColumnText(LAYOUT_COLUMN_FLAG, ""); widget->listLayoutsSrc->setColumnText(LAYOUT_COLUMN_FLAG, "");
widget->listLayoutsDst->setColumnText(LAYOUT_COLUMN_FLAG, ""); widget->listLayoutsDst->setColumnText(LAYOUT_COLUMN_FLAG, "");
widget->listLayoutsDst->setColumnText(LAYOUT_COLUMN_INCLUDE, "");
// widget->listLayoutsDst->setColumnText(LAYOUT_COLUMN_DISPLAY_NAME, ""); // widget->listLayoutsDst->setColumnText(LAYOUT_COLUMN_DISPLAY_NAME, "");
widget->listLayoutsSrc->setColumnWidth(LAYOUT_COLUMN_FLAG, 28); widget->listLayoutsSrc->setColumnWidth(LAYOUT_COLUMN_FLAG, 28);
widget->listLayoutsDst->setColumnWidth(LAYOUT_COLUMN_FLAG, 28); widget->listLayoutsDst->setColumnWidth(LAYOUT_COLUMN_FLAG, 28);
widget->listLayoutsDst->header()->setResizeEnabled(FALSE, LAYOUT_COLUMN_INCLUDE);
widget->listLayoutsDst->header()->setResizeEnabled(FALSE, LAYOUT_COLUMN_DISPLAY_NAME); widget->listLayoutsDst->header()->setResizeEnabled(FALSE, LAYOUT_COLUMN_DISPLAY_NAME);
widget->listLayoutsDst->setColumnWidthMode(LAYOUT_COLUMN_INCLUDE, TQListView::Manual);
widget->listLayoutsDst->setColumnWidth(LAYOUT_COLUMN_INCLUDE, 0);
// widget->listLayoutsDst->setColumnWidth(LAYOUT_COLUMN_DISPLAY_NAME, 0); // widget->listLayoutsDst->setColumnWidth(LAYOUT_COLUMN_DISPLAY_NAME, 0);
widget->listLayoutsDst->setSorting(-1); widget->listLayoutsDst->setSorting(-1);
@ -212,7 +207,6 @@ void LayoutConfig::initUI() {
TQListViewItem* newItem = copyLVI(srcItem, widget->listLayoutsDst); TQListViewItem* newItem = copyLVI(srcItem, widget->listLayoutsDst);
newItem->setText(LAYOUT_COLUMN_VARIANT, layoutUnit.variant); newItem->setText(LAYOUT_COLUMN_VARIANT, layoutUnit.variant);
newItem->setText(LAYOUT_COLUMN_INCLUDE, layoutUnit.includeGroup);
newItem->setText(LAYOUT_COLUMN_DISPLAY_NAME, layoutUnit.displayName); newItem->setText(LAYOUT_COLUMN_DISPLAY_NAME, layoutUnit.displayName);
widget->listLayoutsDst->insertItem(newItem); widget->listLayoutsDst->insertItem(newItem);
newItem->moveItem(widget->listLayoutsDst->lastItem()); newItem->moveItem(widget->listLayoutsDst->lastItem());
@ -222,6 +216,24 @@ void LayoutConfig::initUI() {
} }
} }
// initialize hotkey combo
TQDict<char> allOptions = m_rules->options();
TQStringList commonHotkeys;
commonHotkeys << "alt_shift_toggle" << "ctrl_shift_toggle"
<< "win_space_toggle" << "alt_space_toggle"
<< "caps_toggle" << "menu_toggle"
<< "lwin_toggle" << "rwin_toggle";
for (TQStringList::ConstIterator hk = commonHotkeys.begin(); hk != commonHotkeys.end(); ++hk ) {
const char *hkOpt = tqstrdup(TQString("grp:" + (*hk)).ascii());
const char *hkDesc = allOptions[hkOpt];
if (hkDesc != 0) { // the option exists
widget->comboHotkey->insertItem(i18n(hkDesc));
}
}
widget->comboHotkey->insertItem(i18n("Other..."));
// display KXKB switching options // display KXKB switching options
widget->chkShowSingle->setChecked(m_kxkbConfig.m_showSingle); widget->chkShowSingle->setChecked(m_kxkbConfig.m_showSingle);
@ -231,7 +243,6 @@ void LayoutConfig::initUI() {
widget->radFlagOnly->setChecked( showFlag && !showLabel ); widget->radFlagOnly->setChecked( showFlag && !showLabel );
widget->radLabelOnly->setChecked( !showFlag && showLabel ); widget->radLabelOnly->setChecked( !showFlag && showLabel );
widget->chkEnableOptions->setChecked( m_kxkbConfig.m_enableXkbOptions );
widget->checkResetOld->setChecked(m_kxkbConfig.m_resetOldOptions); widget->checkResetOld->setChecked(m_kxkbConfig.m_resetOldOptions);
widget->grpLabel->setButton( ( m_kxkbConfig.m_useThemeColors ? 0 : 1 ) ); widget->grpLabel->setButton( ( m_kxkbConfig.m_useThemeColors ? 0 : 1 ) );
@ -272,8 +283,8 @@ void LayoutConfig::initUI() {
widget->optionsFrame->setEnabled( m_kxkbConfig.m_useKxkb ); widget->optionsFrame->setEnabled( m_kxkbConfig.m_useKxkb );
// display xkb options // display xkb options
TQStringList options = TQStringList::split(',', m_kxkbConfig.m_options); TQStringList activeOptions = TQStringList::split(',', m_kxkbConfig.m_options);
for (TQStringList::ConstIterator it = options.begin(); it != options.end(); ++it) for (TQStringList::ConstIterator it = activeOptions.begin(); it != activeOptions.end(); ++it)
{ {
TQString option = *it; TQString option = *it;
TQString optionKey = option.mid(0, option.find(':')); TQString optionKey = option.mid(0, option.find(':'));
@ -294,6 +305,7 @@ void LayoutConfig::initUI() {
} }
updateOptionsCommand(); updateOptionsCommand();
updateHotkeyCombo();
emit TDECModule::changed( false ); emit TDECModule::changed( false );
} }
@ -303,7 +315,6 @@ void LayoutConfig::save()
TQString model = lookupLocalized(m_rules->models(), widget->comboModel->currentText()); TQString model = lookupLocalized(m_rules->models(), widget->comboModel->currentText());
m_kxkbConfig.m_model = model; m_kxkbConfig.m_model = model;
m_kxkbConfig.m_enableXkbOptions = widget->chkEnableOptions->isChecked();
m_kxkbConfig.m_resetOldOptions = widget->checkResetOld->isChecked(); m_kxkbConfig.m_resetOldOptions = widget->checkResetOld->isChecked();
m_kxkbConfig.m_options = createOptionString(); m_kxkbConfig.m_options = createOptionString();
@ -320,17 +331,14 @@ void LayoutConfig::save()
while (item) { while (item) {
TQString layout = item->text(LAYOUT_COLUMN_MAP); TQString layout = item->text(LAYOUT_COLUMN_MAP);
TQString variant = item->text(LAYOUT_COLUMN_VARIANT); TQString variant = item->text(LAYOUT_COLUMN_VARIANT);
TQString includes = item->text(LAYOUT_COLUMN_INCLUDE);
TQString displayName = item->text(LAYOUT_COLUMN_DISPLAY_NAME); TQString displayName = item->text(LAYOUT_COLUMN_DISPLAY_NAME);
LayoutUnit layoutUnit(layout, variant); LayoutUnit layoutUnit(layout, variant);
layoutUnit.includeGroup = includes;
layoutUnit.displayName = displayName; layoutUnit.displayName = displayName;
layouts.append( layoutUnit ); layouts.append( layoutUnit );
item = item->nextSibling(); item = item->nextSibling();
kdDebug() << "To save: layout " << layoutUnit.toPair() kdDebug() << "To save: layout " << layoutUnit.toPair()
<< ", inc: " << layoutUnit.includeGroup
<< ", disp: " << layoutUnit.displayName << endl; << ", disp: " << layoutUnit.displayName << endl;
} }
m_kxkbConfig.m_layouts = layouts; m_kxkbConfig.m_layouts = layouts;
@ -439,9 +447,6 @@ void LayoutConfig::add()
// than one time, with different variants. // than one time, with different variants.
TQListViewItem* toadd = copyLVI(sel, widget->listLayoutsDst); TQListViewItem* toadd = copyLVI(sel, widget->listLayoutsDst);
// Turn on "Include Latin layout" for new language by default (bnc:204402)
toadd->setText(LAYOUT_COLUMN_INCLUDE, "us");
widget->listLayoutsDst->insertItem(toadd); widget->listLayoutsDst->insertItem(toadd);
if( widget->listLayoutsDst->childCount() > 1 ) if( widget->listLayoutsDst->childCount() > 1 )
toadd->moveItem(widget->listLayoutsDst->lastItem()); toadd->moveItem(widget->listLayoutsDst->lastItem());
@ -551,33 +556,10 @@ void LayoutConfig::updateIndicator(TQListViewItem* selLayout)
{ {
} }
void LayoutConfig::latinChanged()
{
TQListViewItem* selLayout = widget->listLayoutsDst->selectedItem();
if ( !selLayout ) {
widget->chkLatin->setChecked( false );
widget->chkLatin->setEnabled( false );
return;
}
TQString include;
if( widget->chkLatin->isChecked() )
include = "us";
else
include = "";
selLayout->setText(LAYOUT_COLUMN_INCLUDE, include);
LayoutUnit layoutUnitKey = getLayoutUnitKey(selLayout);
kdDebug() << "layout " << layoutUnitKey.toPair() << ", inc: " << include << endl;
}
void LayoutConfig::layoutSelChanged(TQListViewItem *sel) void LayoutConfig::layoutSelChanged(TQListViewItem *sel)
{ {
widget->comboVariant->clear(); widget->comboVariant->clear();
widget->comboVariant->setEnabled( sel != NULL ); widget->comboVariant->setEnabled( sel != NULL );
widget->chkLatin->setChecked( false );
widget->chkLatin->setEnabled( sel != NULL );
if( sel == NULL ) { if( sel == NULL ) {
updateLayoutCommand(); updateLayoutCommand();
@ -588,21 +570,6 @@ void LayoutConfig::layoutSelChanged(TQListViewItem *sel)
LayoutUnit layoutUnitKey = getLayoutUnitKey(sel); LayoutUnit layoutUnitKey = getLayoutUnitKey(sel);
TQString kbdLayout = layoutUnitKey.layout; TQString kbdLayout = layoutUnitKey.layout;
// TODO: need better algorithm here for determining if needs us group
if ( ! m_rules->isSingleGroup(kbdLayout)
|| kbdLayout.startsWith("us") || kbdLayout.startsWith("en") ) {
widget->chkLatin->setEnabled( false );
}
else {
TQString inc = sel->text(LAYOUT_COLUMN_INCLUDE);
if ( inc.startsWith("us") || inc.startsWith("en") ) {
widget->chkLatin->setChecked(true);
}
else {
widget->chkLatin->setChecked(false);
}
}
TQStringList vars = m_rules->getAvailableVariants(kbdLayout); TQStringList vars = m_rules->getAvailableVariants(kbdLayout);
kdDebug() << "layout " << kbdLayout << " has " << vars.count() << " variants" << endl; kdDebug() << "layout " << kbdLayout << " has " << vars.count() << " variants" << endl;
@ -632,11 +599,11 @@ TQWidget* LayoutConfig::makeOptionsTab()
connect(listView, TQT_SIGNAL(clicked(TQListViewItem *)), TQT_SLOT(changed())); connect(listView, TQT_SIGNAL(clicked(TQListViewItem *)), TQT_SLOT(changed()));
connect(listView, TQT_SIGNAL(clicked(TQListViewItem *)), TQT_SLOT(updateOptionsCommand())); connect(listView, TQT_SIGNAL(clicked(TQListViewItem *)), TQT_SLOT(updateOptionsCommand()));
connect(listView, TQT_SIGNAL(clicked(TQListViewItem *)), TQT_SLOT(updateHotkeyCombo()));
connect(widget->chkEnableOptions, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed()));
connect(widget->checkResetOld, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed())); connect(widget->checkResetOld, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed()));
connect(widget->checkResetOld, TQT_SIGNAL(toggled(bool)), TQT_SLOT(updateOptionsCommand())); connect(widget->checkResetOld, TQT_SIGNAL(toggled(bool)), TQT_SLOT(updateOptionsCommand()));
connect(widget->checkResetOld, TQT_SIGNAL(toggled(bool)), TQT_SLOT(updateHotkeyCombo()));
//Create controllers for all options //Create controllers for all options
TQDictIterator<char> it(m_rules->options()); TQDictIterator<char> it(m_rules->options());
@ -646,7 +613,7 @@ TQWidget* LayoutConfig::makeOptionsTab()
if (!it.currentKey().contains(':')) if (!it.currentKey().contains(':'))
{ {
if( it.currentKey() == "ctrl" || it.currentKey() == "caps" if( it.currentKey() == "ctrl" || it.currentKey() == "caps"
|| it.currentKey() == "altwin" ) { || it.currentKey() == "altwin" || it.currentKey() == "grp") {
parent = new OptionListItem(listView, i18n( it.current() ), parent = new OptionListItem(listView, i18n( it.current() ),
TQCheckListItem::RadioButtonController, it.currentKey()); TQCheckListItem::RadioButtonController, it.currentKey());
OptionListItem *item = new OptionListItem(parent, i18n( "None" ), OptionListItem *item = new OptionListItem(parent, i18n( "None" ),
@ -707,52 +674,114 @@ void LayoutConfig::updateOptionsCommand()
void LayoutConfig::updateLayoutCommand() void LayoutConfig::updateLayoutCommand()
{ {
TQString setxkbmap; TQString setxkbmap = "setxkbmap";
TQString layoutDisplayName; setxkbmap += " -model " + lookupLocalized(m_rules->models(),
TQListViewItem* sel = widget->listLayoutsDst->selectedItem(); widget->comboModel->currentText());
TQStringList layoutCodes;
if( sel != NULL ) { TQStringList layoutVariants;
TQString kbdLayout = sel->text(LAYOUT_COLUMN_MAP); TQListViewItem *item = widget->listLayoutsDst->firstChild();
TQString variant = widget->comboVariant->currentText(); while (item) {
if( variant == DEFAULT_VARIANT_NAME ) layoutCodes << item->text(LAYOUT_COLUMN_MAP);
variant = "";
TQString layoutVariant = item->text(LAYOUT_COLUMN_VARIANT);
setxkbmap = "setxkbmap"; //-rules " + m_rule if (layoutVariant == DEFAULT_VARIANT_NAME) {
setxkbmap += " -model " + lookupLocalized(m_rules->models(), widget->comboModel->currentText()) layoutVariant = "";
+ " -layout ";
setxkbmap += kbdLayout;
if( widget->chkLatin->isChecked() )
setxkbmap += ",us";
/* LayoutUnit layoutUnitKey = getLayoutUnitKey(sel);
layoutDisplayName = m_kxkbConfig.getLayoutDisplayName( *m_kxkbConfig.m_layouts.find(layoutUnitKey) );*/
layoutDisplayName = sel->text(LAYOUT_COLUMN_DISPLAY_NAME);
if( layoutDisplayName.isEmpty() ) {
int count = 0;
TQListViewItem *item = widget->listLayoutsDst->firstChild();
while (item) {
TQString layout_ = item->text(LAYOUT_COLUMN_MAP);
if( layout_ == kbdLayout )
++count;
item = item->nextSibling();
}
bool single = count < 2;
layoutDisplayName = m_kxkbConfig.getDefaultDisplayName(LayoutUnit(kbdLayout, variant), single);
}
kdDebug() << "disp: '" << layoutDisplayName << "'" << endl;
if( !variant.isEmpty() ) {
setxkbmap += " -variant ";
if( widget->chkLatin->isChecked() )
setxkbmap += ",";
setxkbmap += variant;
} }
layoutVariants << layoutVariant;
item = item->nextSibling();
}
setxkbmap += " -layout " + layoutCodes.join(",");
if( !layoutVariants.isEmpty() ) {
setxkbmap += " -variant " + layoutVariants.join(",");
} }
widget->editCmdLine->setText(setxkbmap); widget->editCmdLine->setText(setxkbmap);
/* update display name field */
TQListViewItem *sel = widget->listLayoutsDst->selectedItem();
if (!sel) {
return;
}
TQString selLayoutCode = sel->text(LAYOUT_COLUMN_MAP);
TQString selLayoutVariant = widget->comboVariant->currentText();
TQString selDisplayName = sel->text(LAYOUT_COLUMN_DISPLAY_NAME);
if (selDisplayName.isEmpty()) {
int count = 0;
TQListViewItem *item = widget->listLayoutsDst->firstChild();
while (item) {
TQString layoutCode_ = item->text(LAYOUT_COLUMN_MAP);
if (layoutCode_ == selLayoutCode) {
++count;
}
item = item->nextSibling();
}
bool single = count < 2;
selDisplayName = m_kxkbConfig.getDefaultDisplayName(LayoutUnit(selLayoutCode, selLayoutVariant), single);
}
widget->editDisplayName->setEnabled( sel != NULL ); widget->editDisplayName->setEnabled( sel != NULL );
widget->editDisplayName->setText(layoutDisplayName); widget->editDisplayName->setText(selDisplayName);
}
// Synchronizes Xkb grp options --> hotkeys combobox
void LayoutConfig::updateHotkeyCombo() {
OptionListItem *grpItem = m_optionGroups[i18n("grp")];
if (grpItem == NULL) {
kdWarning() << "LayoutConfig: cannot find grp item group" << endl;
return;
}
OptionListItem *child = (OptionListItem*)grpItem->firstChild();
while (child) {
if (child->isOn()) {
bool found = false;
for (int i = 0; i < widget->comboHotkey->count(); ++i) {
if (child->text() == widget->comboHotkey->text(i)) {
widget->comboHotkey->setCurrentItem(i);
found = true;
}
}
if (!found) {
int other = widget->comboHotkey->count() - 1;
widget->comboHotkey->changeItem(i18n("Other (%1)...").arg(child->text()),
other);
widget->comboHotkey->setCurrentItem(other);
}
}
child = (OptionListItem*)child->nextSibling();
}
}
// Synchronizes hotkeys combobox --> Xkb grp options
void LayoutConfig::hotkeyComboChanged() {
TQString hkDesc = widget->comboHotkey->currentText();
OptionListItem *grpItem = m_optionGroups[i18n("grp")];
if (grpItem == NULL) {
kdWarning() << "LayoutConfig: cannot find grp item group" << endl;
return;
}
OptionListItem *child = (OptionListItem*)grpItem->firstChild();
while (child) {
child->setOn(child->text() == hkDesc);
child = (OptionListItem*)child->nextSibling();
}
// Other...
if (widget->comboHotkey->count() - 1 == widget->comboHotkey->currentItem()) {
OptionListItem *none = grpItem->findChildItem("none");
if (none) {
none->setOn(true);
}
widget->tabWidget->setCurrentPage(2);
widget->listOptions->setCurrentItem(none);
widget->listOptions->ensureItemVisible(none);
widget->listOptions->setFocus();
}
} }
void LayoutConfig::changed() void LayoutConfig::changed()
@ -902,12 +931,8 @@ extern "C"
kapp->startServiceByDesktopName("kxkb"); kapp->startServiceByDesktopName("kxkb");
} }
else { else {
// Even if the layouts have been disabled we still want to set Xkb options if (!XKBExtension::setXkbOptions(m_kxkbConfig.getXkbOptions())) {
// user can always switch them off now in the "Options" tab kdDebug() << "Setting XKB options failed!" << endl;
if( m_kxkbConfig.m_enableXkbOptions ) {
if( !XKBExtension::setXkbOptions(m_kxkbConfig.m_options, m_kxkbConfig.m_resetOldOptions) ) {
kdDebug() << "Setting XKB options failed!" << endl;
}
} }
} }
} }

@ -27,7 +27,7 @@ public:
void defaults(); void defaults();
void initUI(); void initUI();
virtual TQString handbookDocPath() const; virtual TQString handbookDocPath() const;
protected: protected:
TQString createOptionString(); TQString createOptionString();
void updateIndicator(TQListViewItem* selLayout); void updateIndicator(TQListViewItem* selLayout);
@ -35,13 +35,14 @@ protected:
protected slots: protected slots:
void moveUp(); void moveUp();
void moveDown(); void moveDown();
void hotkeyComboChanged();
void variantChanged(); void variantChanged();
void displayNameChanged(const TQString& name); void displayNameChanged(const TQString& name);
void latinChanged();
void layoutSelChanged(TQListViewItem *); void layoutSelChanged(TQListViewItem *);
void loadRules(); void loadRules();
void updateLayoutCommand(); void updateLayoutCommand();
void updateOptionsCommand(); void updateOptionsCommand();
void updateHotkeyCombo();
void add(); void add();
void remove(); void remove();

@ -86,15 +86,42 @@
</widget> </widget>
<widget class="TQLabel" row="2" column="2" rowspan="1" colspan="3"> <widget class="TQLabel" row="2" column="2" rowspan="1" colspan="3">
<property name="name"> <property name="name">
<cstring>textLabel1_4_2</cstring> <cstring>labelLayouts</cstring>
</property> </property>
<property name="text"> <property name="text">
<string>Active layouts:</string> <string>Active layouts:</string>
</property> </property>
</widget> </widget>
<widget class="TQLabel" row="0" column="0" rowspan="1" colspan="2">
<property name="name">
<cstring>labelHotkey</cstring>
</property>
<property name="text">
<string>Key combination to &amp;switch layout:</string>
</property>
<property name="buddy" stdset="0">
<cstring>comboHotkey</cstring>
</property>
</widget>
<widget class="TQComboBox" row="1" column="0" rowspan="1" colspan="2">
<property name="name">
<cstring>comboHotkey</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="whatsThis" stdset="0">
<string>Here you can choose the key combination you want to use to switch to the next layout. This list includes only the most common variants. If you choose "Other...", then you will be redirected to the "Options" tab where you can pick from all the available variants.</string>
</property>
</widget>
<widget class="TQLabel" row="0" column="2" rowspan="1" colspan="3"> <widget class="TQLabel" row="0" column="2" rowspan="1" colspan="3">
<property name="name"> <property name="name">
<cstring>textLabel1_2</cstring> <cstring>labelModel</cstring>
</property> </property>
<property name="text"> <property name="text">
<string>Keyboard &amp;model:</string> <string>Keyboard &amp;model:</string>
@ -165,17 +192,6 @@
<bool>true</bool> <bool>true</bool>
</property> </property>
</column> </column>
<column>
<property name="text">
<string>5</string>
</property>
<property name="clickable">
<bool>false</bool>
</property>
<property name="resizable">
<bool>false</bool>
</property>
</column>
<column> <column>
<property name="text"> <property name="text">
<string>Label</string> <string>Label</string>
@ -327,20 +343,6 @@
<string>This is the command which is executed when switching to the selected layout. It may help you if you want to debug layout switching, or if you want to switch layouts without the help of TDE.</string> <string>This is the command which is executed when switching to the selected layout. It may help you if you want to debug layout switching, or if you want to switch layouts without the help of TDE.</string>
</property> </property>
</widget> </widget>
<widget class="TQCheckBox" row="7" column="2" rowspan="1" colspan="3">
<property name="name">
<cstring>chkLatin</cstring>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Include latin layout</string>
</property>
<property name="whatsThis" stdset="0">
<string>If after you switch to this layout some keyboard shortcuts based on latin keys do not work try to enable this option.</string>
</property>
</widget>
<widget class="TQLabel" row="6" column="2"> <widget class="TQLabel" row="6" column="2">
<property name="name"> <property name="name">
<cstring>textLabel1_6</cstring> <cstring>textLabel1_6</cstring>
@ -832,17 +834,6 @@
<property name="name"> <property name="name">
<cstring>unnamed</cstring> <cstring>unnamed</cstring>
</property> </property>
<widget class="TQCheckBox">
<property name="name">
<cstring>chkEnableOptions</cstring>
</property>
<property name="text">
<string>&amp;Enable xkb options</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<widget class="TQGroupBox"> <widget class="TQGroupBox">
<property name="name"> <property name="name">
<cstring>groupBox3_2</cstring> <cstring>groupBox3_2</cstring>
@ -911,12 +902,6 @@
<receiver>grpLayouts</receiver> <receiver>grpLayouts</receiver>
<slot>setEnabled(bool)</slot> <slot>setEnabled(bool)</slot>
</connection> </connection>
<connection>
<sender>chkEnableOptions</sender>
<signal>toggled(bool)</signal>
<receiver>groupBox3_2</receiver>
<slot>setEnabled(bool)</slot>
</connection>
<connection> <connection>
<sender>chkEnableSticky</sender> <sender>chkEnableSticky</sender>
<signal>toggled(bool)</signal> <signal>toggled(bool)</signal>

@ -63,19 +63,14 @@ KXKBApp::KXKBApp(bool allowStyles, bool GUIenabled)
m_prevWinId(X11Helper::UNKNOWN_WINDOW_ID), m_prevWinId(X11Helper::UNKNOWN_WINDOW_ID),
m_rules(NULL), m_rules(NULL),
m_tray(NULL), m_tray(NULL),
kWinModule(NULL), kWinModule(NULL)
m_forceSetXKBMap( false )
{ {
m_extension = new XKBExtension(); m_extension = new XKBExtension();
if( !m_extension->init() ) { if( !m_extension->init() ) {
kdDebug() << "xkb initialization failed, exiting..." << endl; kdDebug() << "xkb initialization failed, exiting..." << endl;
::exit(1); ::exit(1);
} }
connect(m_extension, TQT_SIGNAL(groupChanged(uint)), this, TQT_SLOT(slotGroupChanged(uint)));
// keep in sync with kcmlayout.cpp
keys = new TDEGlobalAccel(TQT_TQOBJECT(this));
#include "kxkbbindings.cpp"
keys->updateConnections();
m_layoutOwnerMap = new LayoutMap(kxkbConfig); m_layoutOwnerMap = new LayoutMap(kxkbConfig);
@ -86,9 +81,6 @@ KXKBApp::KXKBApp(bool allowStyles, bool GUIenabled)
KXKBApp::~KXKBApp() KXKBApp::~KXKBApp()
{ {
// deletePrecompiledLayouts();
delete keys;
delete m_tray; delete m_tray;
delete m_rules; delete m_rules;
delete m_extension; delete m_extension;
@ -98,24 +90,19 @@ KXKBApp::~KXKBApp()
int KXKBApp::newInstance() int KXKBApp::newInstance()
{ {
m_extension->reset(); if (settingsRead()) {
layoutApply();
if( settingsRead() ) }
layoutApply();
return 0; return 0;
} }
bool KXKBApp::settingsRead() bool KXKBApp::settingsRead()
{ {
kxkbConfig.load( KxkbConfig::LOAD_ACTIVE_OPTIONS ); XkbOptions options = kxkbConfig.getXkbOptions();
if( !m_extension->setXkbOptions(options) ) {
if( kxkbConfig.m_enableXkbOptions ) { kdDebug() << "Setting XKB options failed!" << endl;
kdDebug() << "Setting XKB options " << kxkbConfig.m_options << endl; }
if( !m_extension->setXkbOptions(kxkbConfig.m_options, kxkbConfig.m_resetOldOptions) ) {
kdDebug() << "Setting XKB options failed!" << endl;
}
}
if ( kxkbConfig.m_useKxkb == false ) { if ( kxkbConfig.m_useKxkb == false ) {
kapp->quit(); kapp->quit();
@ -151,38 +138,19 @@ bool KXKBApp::settingsRead()
for(int ii=0; ii<(int)kxkbConfig.m_layouts.count(); ii++) { for(int ii=0; ii<(int)kxkbConfig.m_layouts.count(); ii++) {
LayoutUnit& layoutUnit = kxkbConfig.m_layouts[ii]; LayoutUnit& layoutUnit = kxkbConfig.m_layouts[ii];
layoutUnit.defaultGroup = m_rules->getDefaultGroup(layoutUnit.layout, layoutUnit.includeGroup);
kdDebug() << "default group for " << layoutUnit.toPair() << " is " << layoutUnit.defaultGroup << endl;
} }
m_currentLayout = kxkbConfig.getDefaultLayout(); m_currentLayout = kxkbConfig.m_layouts[0];
kdDebug() << "default layout is " << m_currentLayout.toPair() << endl;
if( kxkbConfig.m_layouts.count() == 1 ) {
TQString layoutName = m_currentLayout.layout;
TQString variantName = m_currentLayout.variant;
TQString includeName = m_currentLayout.includeGroup;
int group = m_currentLayout.defaultGroup;
if( !m_extension->setLayout(kxkbConfig.m_model, layoutName, variantName, includeName, false)
|| !m_extension->setGroup( group ) ) {
kdDebug() << "Error switching to single layout " << m_currentLayout.toPair() << endl;
// TODO: alert user
}
if( kxkbConfig.m_showSingle == false ) { if( kxkbConfig.m_layouts.count() == 1 && !kxkbConfig.m_showSingle) {
kapp->quit(); kapp->quit();
return false; return false;
}
} }
else {
// initPrecompiledLayouts();
}
initTray(); initTray();
TDEGlobal::config()->reparseConfiguration(); // kcontrol modified kdeglobals TDEGlobal::config()->reparseConfiguration(); // kcontrol modified kdeglobals
keys->readSettings();
keys->updateConnections();
return true; return true;
} }
@ -197,7 +165,7 @@ void KXKBApp::initTray()
m_tray = new KxkbLabelController(sysTray, popupMenu); m_tray = new KxkbLabelController(sysTray, popupMenu);
connect(popupMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(menuActivated(int))); connect(popupMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(menuActivated(int)));
connect(sysTray, TQT_SIGNAL(toggled()), this, TQT_SLOT(toggled())); connect(sysTray, TQT_SIGNAL(toggled()), this, TQT_SLOT(nextLayout()));
} }
m_tray->setShowFlag(kxkbConfig.m_showFlag); m_tray->setShowFlag(kxkbConfig.m_showFlag);
@ -223,35 +191,45 @@ bool KXKBApp::setLayout(const TQString& layoutPair)
return false; return false;
} }
// Activates the keyboard layout specified by 'layoutUnit' // Activates the keyboard layout specified by 'layoutUnit'
bool KXKBApp::setLayout(const LayoutUnit& layoutUnit, int group) bool KXKBApp::setLayout(const LayoutUnit& layoutUnit)
{ {
bool res = false; uint group = kxkbConfig.m_layouts.findIndex(layoutUnit);
bool res = m_extension->setGroup(group);
if( group == -1 ) if (res) {
group = layoutUnit.defaultGroup; m_currentLayout = layoutUnit;
}
res = m_extension->setLayout(kxkbConfig.m_model,
layoutUnit.layout, layoutUnit.variant,
layoutUnit.includeGroup);
if( res )
m_extension->setGroup(group); // not checking for ret - not important
if( res )
m_currentLayout = layoutUnit;
if (m_tray) { if (m_tray) {
if( res ) if (res) {
m_tray->setCurrentLayout(layoutUnit); m_tray->setCurrentLayout(layoutUnit);
else } else {
m_tray->setError(layoutUnit.toPair()); m_tray->setError(layoutUnit.toPair());
}
}
return res;
}
// Activates the keyboard layout specified by group number
bool KXKBApp::setLayout(const uint group)
{
bool res = m_extension->setGroup(group);
if (res) {
m_currentLayout = kxkbConfig.m_layouts[group];
} }
return res; if (m_tray) {
if (res)
m_tray->setCurrentLayout(m_currentLayout);
else
m_tray->setError(m_currentLayout.toPair());
}
return res;
} }
void KXKBApp::toggled()
void KXKBApp::nextLayout()
{ {
const LayoutUnit& layout = m_layoutOwnerMap->getNextLayout().layoutUnit; const LayoutUnit& layout = m_layoutOwnerMap->getNextLayout().layoutUnit;
setLayout(layout); setLayout(layout);
@ -282,6 +260,11 @@ void KXKBApp::menuActivated(int id)
// } // }
} }
void KXKBApp::slotGroupChanged(uint group) {
m_currentLayout = kxkbConfig.m_layouts[group];
m_tray->setCurrentLayout(m_currentLayout);
}
// TODO: we also have to handle deleted windows // TODO: we also have to handle deleted windows
void KXKBApp::windowChanged(WId winId) void KXKBApp::windowChanged(WId winId)
{ {
@ -291,15 +274,11 @@ void KXKBApp::windowChanged(WId winId)
return; return;
} }
int group = m_extension->getGroup();
kdDebug() << "old WinId: " << m_prevWinId << ", new WinId: " << winId << endl; kdDebug() << "old WinId: " << m_prevWinId << ", new WinId: " << winId << endl;
if( m_prevWinId != X11Helper::UNKNOWN_WINDOW_ID ) { // saving layout/group from previous window if( m_prevWinId != X11Helper::UNKNOWN_WINDOW_ID ) { // saving layout from previous window
// kdDebug() << "storing " << m_currentLayout.toPair() << ":" << group << " for " << m_prevWinId << endl;
// m_layoutOwnerMap->setCurrentWindow(m_prevWinId); // m_layoutOwnerMap->setCurrentWindow(m_prevWinId);
m_layoutOwnerMap->setCurrentLayout(m_currentLayout); m_layoutOwnerMap->setCurrentLayout(m_currentLayout);
m_layoutOwnerMap->setCurrentGroup(group);
} }
m_prevWinId = winId; m_prevWinId = winId;
@ -309,11 +288,8 @@ void KXKBApp::windowChanged(WId winId)
const LayoutState& layoutState = m_layoutOwnerMap->getCurrentLayout(); const LayoutState& layoutState = m_layoutOwnerMap->getCurrentLayout();
if( layoutState.layoutUnit != m_currentLayout ) { if( layoutState.layoutUnit != m_currentLayout ) {
kdDebug() << "switching to " << layoutState.layoutUnit.toPair() << ":" << group << " for " << winId << endl; kdDebug() << "switching to " << layoutState.layoutUnit.toPair() << " for " << winId << endl;
setLayout( layoutState.layoutUnit, layoutState.group ); setLayout(layoutState.layoutUnit);
}
else if( layoutState.group != group ) { // we need to change only the group
m_extension->setGroup(layoutState.group);
} }
} }
} }
@ -325,50 +301,14 @@ void KXKBApp::slotSettingsChanged(int category)
return; return;
TDEGlobal::config()->reparseConfiguration(); // kcontrol modified kdeglobals TDEGlobal::config()->reparseConfiguration(); // kcontrol modified kdeglobals
keys->readSettings();
keys->updateConnections();
} }
/* bool KXKBApp::x11EventFilter(XEvent *e) {
Viki (onscreen keyboard) has problems determining some modifiers states // let the extension process the event and emit signals if necessary
when kxkb uses precompiled layouts instead of setxkbmap. Probably a bug m_extension->processXEvent(e);
in the xkb functions used for the precompiled layouts *shrug*. return TDEApplication::x11EventFilter(e);
*/
void KXKBApp::forceSetXKBMap( bool set )
{
if( m_forceSetXKBMap == set )
return;
m_forceSetXKBMap = set;
layoutApply();
} }
/*Precompiles the keyboard layouts for faster activation later.
This is done by loading each one of them and then dumping the compiled
map from the X server into our local buffer.*/
// void KXKBApp::initPrecompiledLayouts()
// {
// TQStringList dirs = TDEGlobal::dirs()->findDirs ( "tmp", "" );
// TQString tempDir = dirs.count() == 0 ? "/tmp/" : dirs[0];
//
// TQValueList<LayoutUnit>::ConstIterator end = kxkbConfig.m_layouts.end();
//
// for (TQValueList<LayoutUnit>::ConstIterator it = kxkbConfig.m_layouts.begin(); it != end; ++it)
// {
// LayoutUnit layoutUnit(*it);
// // const char* baseGr = m_includes[layout];
// // int group = m_rules->getGroup(layout, baseGr);
// // if( m_extension->setLayout(m_model, layout, m_variants[layout], group, baseGr) ) {
// TQString compiledLayoutFileName = tempDir + layoutUnit.layout + "." + layoutUnit.variant + ".xkm";
// // if( m_extension->getCompiledLayout(compiledLayoutFileName) )
// m_compiledLayoutFileNames[layoutUnit.toPair()] = compiledLayoutFileName;
// // }
// // else {
// // kdDebug() << "Error precompiling layout " << layout << endl;
// // }
// }
// }
const char * DESCRIPTION = const char * DESCRIPTION =
I18N_NOOP("A utility to switch keyboard maps"); I18N_NOOP("A utility to switch keyboard maps");
@ -387,4 +327,4 @@ extern "C" KDE_EXPORT int kdemain(int argc, char *argv[])
app.disableSessionManagement(); app.disableSessionManagement();
app.exec(); app.exec();
return 0; return 0;
} }

@ -53,40 +53,44 @@ class KXKBApp : public KUniqueApplication
K_DCOP K_DCOP
public: public:
KXKBApp(bool allowStyles=true, bool GUIenabled=true); KXKBApp(bool allowStyles=true, bool GUIenabled=true);
~KXKBApp(); ~KXKBApp();
virtual int newInstance(); virtual int newInstance();
bool setLayout(const LayoutUnit& layoutUnit, int group=-1); bool setLayout(const LayoutUnit& layoutUnit);
bool setLayout(const uint group);
k_dcop: k_dcop:
bool setLayout(const TQString& layoutPair); bool setLayout(const TQString& layoutPair);
TQString getCurrentLayout() { return m_currentLayout.toPair(); } TQString getCurrentLayout() { return m_currentLayout.toPair(); }
TQStringList getLayoutsList() { return kxkbConfig.getLayoutStringList(); } TQStringList getLayoutsList() { return kxkbConfig.getLayoutStringList(); }
void forceSetXKBMap( bool set );
public slots:
void nextLayout();
protected slots: protected slots:
void menuActivated(int id); void menuActivated(int id);
void toggled();
void windowChanged(WId winId); void windowChanged(WId winId);
void layoutApply();
void slotGroupChanged(uint group);
void slotSettingsChanged(int category); void slotSettingsChanged(int category);
protected: protected:
// Read settings, and apply them. // Read settings, and apply them.
bool settingsRead(); bool settingsRead();
void layoutApply();
private: private:
void initTray(); void initTray();
bool x11EventFilter(XEvent *e);
private: private:
KxkbConfig kxkbConfig; KxkbConfig kxkbConfig;
WId m_prevWinId; // for tricky part of saving xkb group WId m_prevWinId; // for tricky part of saving xkb group
LayoutMap* m_layoutOwnerMap; LayoutMap* m_layoutOwnerMap;
LayoutUnit m_currentLayout; LayoutUnit m_currentLayout;
XKBExtension *m_extension; XKBExtension *m_extension;
XkbRules *m_rules; XkbRules *m_rules;

@ -1,12 +0,0 @@
#ifndef NOSLOTS
# define DEF( name, key3, key4, fnSlot ) \
keys->insert( name, i18n(name), TQString(), key3, key4, TQT_TQOBJECT(this), TQT_SLOT(fnSlot) )
#else
# define DEF( name, key3, key4, fnSlot ) \
keys->insert( name, i18n(name), TQString(), key3, key4 )
#endif
keys->insert( "Program:kxkb", i18n("Keyboard") );
DEF( I18N_NOOP("Switch to Next Keyboard Layout"), ALT+CTRL+Qt::Key_K, KKey::QtWIN+CTRL+Qt::Key_K, toggled() );
#undef DEF

@ -30,27 +30,14 @@ static const char* switchModes[SWITCH_POLICY_COUNT] = {
const LayoutUnit DEFAULT_LAYOUT_UNIT = LayoutUnit("us", ""); const LayoutUnit DEFAULT_LAYOUT_UNIT = LayoutUnit("us", "");
const char* DEFAULT_MODEL = "pc104"; const char* DEFAULT_MODEL = "pc104";
LayoutUnit KxkbConfig::getDefaultLayout()
{
if( m_layouts.size() == 0 )
return DEFAULT_LAYOUT_UNIT;
return m_layouts[0];
}
bool KxkbConfig::load(int loadMode) bool KxkbConfig::load(int loadMode)
{ {
TDEConfig *config = new TDEConfig("kxkbrc", true, false); TDEConfig *config = new TDEConfig("kxkbrc", true, false);
config->setGroup("Layout"); config->setGroup("Layout");
// Even if the layouts have been disabled we still want to set Xkb options if( loadMode == LOAD_ALL ) {
// user can always switch them off now in the "Options" tab
m_enableXkbOptions = config->readBoolEntry("EnableXkbOptions", false);
if( m_enableXkbOptions == true || loadMode == LOAD_ALL ) {
m_resetOldOptions = config->readBoolEntry("ResetOldOptions", false); m_resetOldOptions = config->readBoolEntry("ResetOldOptions", false);
m_options = config->readEntry("Options", ""); m_options = config->readEntry("Options", "");
kdDebug() << "Xkb options (enabled=" << m_enableXkbOptions << "): " << m_options << endl;
} }
m_useKxkb = config->readBoolEntry("Use", false); m_useKxkb = config->readBoolEntry("Use", false);
@ -81,7 +68,7 @@ bool KxkbConfig::load(int loadMode)
kdDebug() << " layout " << LayoutUnit(*it).toPair() << " in list: " << m_layouts.contains( LayoutUnit(*it) ) << endl; kdDebug() << " layout " << LayoutUnit(*it).toPair() << " in list: " << m_layouts.contains( LayoutUnit(*it) ) << endl;
} }
kdDebug() << "Found " << m_layouts.count() << " layouts, default is " << getDefaultLayout().toPair() << endl; kdDebug() << "Found " << m_layouts.count() << " layouts" << endl;
TQStringList displayNamesList = config->readListEntry("DisplayNames", ','); TQStringList displayNamesList = config->readListEntry("DisplayNames", ',');
for(TQStringList::ConstIterator it = displayNamesList.begin(); it != displayNamesList.end() ; ++it) { for(TQStringList::ConstIterator it = displayNamesList.begin(); it != displayNamesList.end() ; ++it) {
@ -94,37 +81,6 @@ bool KxkbConfig::load(int loadMode)
} }
} }
// m_includes.clear();
if( X11Helper::areSingleGroupsSupported() ) {
if( config->hasKey("IncludeGroups") ) {
TQStringList includeList = config->readListEntry("IncludeGroups", ',');
for(TQStringList::ConstIterator it = includeList.begin(); it != includeList.end() ; ++it) {
TQStringList includePair = TQStringList::split(':', *it );
if( includePair.count() == 2 ) {
LayoutUnit layoutUnit( includePair[0] );
if( m_layouts.contains( layoutUnit ) ) {
m_layouts[m_layouts.findIndex(layoutUnit)].includeGroup = includePair[1];
kdDebug() << "Got inc group: " << includePair[0] << ": " << includePair[1] << endl;
}
}
}
}
else { //old includes format
kdDebug() << "Old includes..." << endl;
TQStringList includeList = config->readListEntry("Includes");
for(TQStringList::ConstIterator it = includeList.begin(); it != includeList.end() ; ++it) {
TQString layoutName = LayoutUnit::parseLayout( *it );
LayoutUnit layoutUnit( layoutName, "" );
kdDebug() << "old layout for inc: " << layoutUnit.toPair() << " included " << m_layouts.contains( layoutUnit ) << endl;
if( m_layouts.contains( layoutUnit ) ) {
TQString variantName = LayoutUnit::parseVariant(*it);
m_layouts[m_layouts.findIndex(layoutUnit)].includeGroup = variantName;
kdDebug() << "Got inc group: " << layoutUnit.toPair() << ": " << variantName << endl;
}
}
}
}
m_showSingle = config->readBoolEntry("ShowSingle", false); m_showSingle = config->readBoolEntry("ShowSingle", false);
m_showFlag = config->readBoolEntry("ShowFlag", true); m_showFlag = config->readBoolEntry("ShowFlag", true);
m_showLabel = config->readBoolEntry("ShowLabel", true); m_showLabel = config->readBoolEntry("ShowLabel", true);
@ -185,12 +141,10 @@ void KxkbConfig::save()
config->writeEntry("Model", m_model); config->writeEntry("Model", m_model);
config->writeEntry("EnableXkbOptions", m_enableXkbOptions );
config->writeEntry("ResetOldOptions", m_resetOldOptions); config->writeEntry("ResetOldOptions", m_resetOldOptions);
config->writeEntry("Options", m_options ); config->writeEntry("Options", m_options );
TQStringList layoutList; TQStringList layoutList;
TQStringList includeList;
TQStringList displayNamesList; TQStringList displayNamesList;
TQValueList<LayoutUnit>::ConstIterator it; TQValueList<LayoutUnit>::ConstIterator it;
@ -199,11 +153,6 @@ void KxkbConfig::save()
layoutList.append( layoutUnit.toPair() ); layoutList.append( layoutUnit.toPair() );
if( layoutUnit.includeGroup.isEmpty() == false ) {
TQString incGroupUnit = TQString("%1:%2").arg(layoutUnit.toPair(), layoutUnit.includeGroup);
includeList.append( incGroupUnit );
}
TQString displayName( layoutUnit.displayName ); TQString displayName( layoutUnit.displayName );
kdDebug() << " displayName " << layoutUnit.toPair() << " : " << displayName << endl; kdDebug() << " displayName " << layoutUnit.toPair() << " : " << displayName << endl;
if( displayName.isEmpty() == false && displayName != layoutUnit.layout ) { if( displayName.isEmpty() == false && displayName != layoutUnit.layout ) {
@ -215,9 +164,6 @@ void KxkbConfig::save()
config->writeEntry("LayoutList", layoutList); config->writeEntry("LayoutList", layoutList);
kdDebug() << "Saving Layouts: " << layoutList << endl; kdDebug() << "Saving Layouts: " << layoutList << endl;
config->writeEntry("IncludeGroups", includeList);
kdDebug() << "Saving includeGroups: " << includeList << endl;
// if( displayNamesList.empty() == false ) // if( displayNamesList.empty() == false )
config->writeEntry("DisplayNames", displayNamesList); config->writeEntry("DisplayNames", displayNamesList);
// else // else
@ -259,7 +205,6 @@ void KxkbConfig::setDefaults()
{ {
m_model = DEFAULT_MODEL; m_model = DEFAULT_MODEL;
m_enableXkbOptions = false;
m_resetOldOptions = false; m_resetOldOptions = false;
m_options = ""; m_options = "";
@ -321,6 +266,26 @@ TQString KxkbConfig::getDefaultDisplayName(const LayoutUnit& layoutUnit, bool si
return displayName; return displayName;
} }
const XkbOptions KxkbConfig::getXkbOptions() {
load(LOAD_ALL);
XkbOptions options;
TQStringList layouts;
TQStringList variants;
for(TQValueList<LayoutUnit>::ConstIterator it = m_layouts.begin(); it != m_layouts.end(); ++it) {
const LayoutUnit& layoutUnit = *it;
layouts << layoutUnit.layout;
variants << layoutUnit.variant;
}
options.layouts = layouts.join(",");
options.variants = variants.join(",");
options.model = m_model;
options.options = m_options;
kdDebug() << "[getXkbOptions] options: " << m_options << endl;
options.resetOld = m_resetOldOptions;
return options;
}
/** /**
* @brief Gets the single layout part of a layout(variant) string * @brief Gets the single layout part of a layout(variant) string
* @param[in] layvar String in form layout(variant) to parse * @param[in] layvar String in form layout(variant) to parse
@ -356,4 +321,4 @@ const TQString LayoutUnit::parseVariant(const TQString &layvar)
if( pos < 2 || len < 2 ) if( pos < 2 || len < 2 )
return ""; return "";
return varLine.mid(pos+1, len-2); return varLine.mid(pos+1, len-2);
} }

@ -19,6 +19,13 @@
#include <tqptrqueue.h> #include <tqptrqueue.h>
#include <tqmap.h> #include <tqmap.h>
struct XkbOptions {
TQString layouts;
TQString variants;
TQString model;
TQString options;
bool resetOld;
};
/* Utility classes for per-window/per-application layout implementation /* Utility classes for per-window/per-application layout implementation
*/ */
@ -41,9 +48,7 @@ inline TQString createPair(TQString key, TQString value)
struct LayoutUnit { struct LayoutUnit {
TQString layout; TQString layout;
TQString variant; TQString variant;
TQString includeGroup;
TQString displayName; TQString displayName;
int defaultGroup;
LayoutUnit() {} LayoutUnit() {}
@ -115,8 +120,6 @@ public:
TQString m_options; TQString m_options;
TQValueList<LayoutUnit> m_layouts; TQValueList<LayoutUnit> m_layouts;
LayoutUnit getDefaultLayout();
bool load(int loadMode); bool load(int loadMode);
void save(); void save();
void setDefaults(); void setDefaults();
@ -125,6 +128,8 @@ public:
static TQString getDefaultDisplayName(const TQString& code_); static TQString getDefaultDisplayName(const TQString& code_);
static TQString getDefaultDisplayName(const LayoutUnit& layoutUnit, bool single=false); static TQString getDefaultDisplayName(const LayoutUnit& layoutUnit, bool single=false);
const XkbOptions getXkbOptions();
private: private:
static const TQMap<TQString, TQString> parseIncludesMap(const TQStringList& pairList); static const TQMap<TQString, TQString> parseIncludesMap(const TQStringList& pairList);
}; };

@ -88,19 +88,15 @@ LayoutState& LayoutMap::getNextLayout() {
layoutQueue.enqueue(layoutState); layoutQueue.enqueue(layoutState);
kdDebug() << "map: Next layout: " << layoutQueue.head()->layoutUnit.toPair() kdDebug() << "map: Next layout: " << layoutQueue.head()->layoutUnit.toPair()
<< " group: " << layoutQueue.head()->layoutUnit.defaultGroup << " for " << m_currentWinId << endl; << " for " << m_currentWinId << endl;
return *layoutQueue.head(); return *layoutQueue.head();
} }
void LayoutMap::setCurrentGroup(int group) {
getCurrentLayout().group = group;
}
void LayoutMap::setCurrentLayout(const LayoutUnit& layoutUnit) { void LayoutMap::setCurrentLayout(const LayoutUnit& layoutUnit) {
LayoutQueue& layoutQueue = getCurrentLayoutQueue(m_currentWinId); LayoutQueue& layoutQueue = getCurrentLayoutQueue(m_currentWinId);
kdDebug() << "map: Storing layout: " << layoutUnit.toPair() kdDebug() << "map: Storing layout: " << layoutUnit.toPair()
<< " group: " << layoutUnit.defaultGroup << " for " << m_currentWinId << endl; << " for " << m_currentWinId << endl;
int queueSize = (int)layoutQueue.count(); int queueSize = (int)layoutQueue.count();
for(int ii=0; ii<queueSize; ii++) { for(int ii=0; ii<queueSize; ii++) {

@ -27,13 +27,11 @@
// LayoutInfo is used for sticky switching and per-window/application switching policy // LayoutInfo is used for sticky switching and per-window/application switching policy
struct LayoutState { struct LayoutState {
const LayoutUnit& layoutUnit; const LayoutUnit& layoutUnit;
int group;
LayoutState(const LayoutUnit& layoutUnit_): LayoutState(const LayoutUnit& layoutUnit_):
layoutUnit(layoutUnit_), layoutUnit(layoutUnit_)
group(layoutUnit_.defaultGroup)
{ {
// kdDebug() << "new LayoutState " << layoutUnit.toPair() << " group: " << group << endl; // kdDebug() << "new LayoutState " << layoutUnit.toPair() << endl;
} }
}; };
@ -49,7 +47,6 @@ public:
// void setConfig(const KxkbConfig& kxkbConfig); // void setConfig(const KxkbConfig& kxkbConfig);
void setCurrentLayout(const LayoutUnit& layoutUnit); void setCurrentLayout(const LayoutUnit& layoutUnit);
void setCurrentGroup(int group);
LayoutState& getNextLayout(); LayoutState& getNextLayout();
LayoutState& getCurrentLayout(); LayoutState& getCurrentLayout();

@ -35,8 +35,6 @@ XkbRules::XkbRules(bool layoutsOnly):
} }
loadRules(rulesFile, layoutsOnly); loadRules(rulesFile, layoutsOnly);
loadOldLayouts(rulesFile);
loadGroups(::locate("config", "kxkb_groups"));
} }
@ -58,84 +56,6 @@ void XkbRules::loadRules(TQString file, bool layoutsOnly)
// fixLayouts(); // fixLayouts();
} }
// void XkbRules::fixLayouts() {
// // THIS IS TEMPORARY!!!
// // This should be fixed in XFree86 (and actually is fixed in XFree 4.2)
// // some handcoded ones, because the X11 rule file doesn't get them correctly, or in case
// // the rule file wasn't found
// static struct {
// const char * locale;
// const char * layout;
// } fixedLayouts[] = {
// { "ben", "Bengali" },
// { "ar", "Arabic" },
// { "ir", "Farsi" },
// { 0, 0 }
// };
//
// for(int i=0; fixedLayouts[i].layout != 0; i++ ) {
// if( m_layouts.find(fixedLayouts[i].locale) == 0 )
// m_layouts.insert(fixedLayouts[i].locale, fixedLayouts[i].layout);
// }
// }
bool XkbRules::isSingleGroup(const TQString& layout)
{
return X11Helper::areSingleGroupsSupported()
&& !m_oldLayouts.contains(layout)
&& !m_nonLatinLayouts.contains(layout);
}
// check $oldlayouts and $nonlatin groups for XFree 4.3 and later
void XkbRules::loadOldLayouts(TQString rulesFile)
{
OldLayouts* oldLayoutsStruct = X11Helper::loadOldLayouts( rulesFile );
m_oldLayouts = oldLayoutsStruct->oldLayouts;
m_nonLatinLayouts = oldLayoutsStruct->nonLatinLayouts;
}
// for multi-group layouts in XFree 4.2 and older
// or if layout is present in $oldlayout or $nonlatin groups
void XkbRules::loadGroups(TQString file)
{
TQFile f(file);
if (f.open(IO_ReadOnly))
{
TQTextStream ts(&f);
TQString locale;
unsigned int grp;
while (!ts.eof()) {
ts >> locale >> grp;
locale.simplifyWhiteSpace();
if (locale[0] == '#' || locale.left(2) == "//" || locale.isEmpty())
continue;
m_initialGroups.insert(locale, grp);
}
f.close();
}
}
unsigned int
XkbRules::getDefaultGroup(const TQString& layout, const TQString& includeGroup)
{
// check for new one-group layouts in XFree 4.3 and older
if( isSingleGroup(layout) ) {
if( includeGroup.isEmpty() == false )
return 1;
else
return 0;
}
TQMap<TQString, unsigned int>::iterator it = m_initialGroups.find(layout);
return it == m_initialGroups.end() ? 0 : it.data();
}
TQStringList TQStringList
XkbRules::getAvailableVariants(const TQString& layout) XkbRules::getAvailableVariants(const TQString& layout)
{ {
@ -146,8 +66,7 @@ XkbRules::getAvailableVariants(const TQString& layout)
if( result1 ) if( result1 )
return *result1; return *result1;
bool oldLayouts = m_oldLayouts.contains(layout); TQStringList* result = X11Helper::getVariants(layout, X11_DIR);
TQStringList* result = X11Helper::getVariants(layout, X11_DIR, oldLayouts);
m_varLists.insert(layout, result); m_varLists.insert(layout, result);

@ -15,30 +15,21 @@ public:
const TQDict<char> &models() const { return m_models; }; const TQDict<char> &models() const { return m_models; };
const TQDict<char> &layouts() const { return m_layouts; }; const TQDict<char> &layouts() const { return m_layouts; };
const TQDict<char> &options() const { return m_options; }; const TQDict<char> &options() const { return m_options; };
TQStringList getAvailableVariants(const TQString& layout);
unsigned int getDefaultGroup(const TQString& layout, const TQString& includeGroup);
bool isSingleGroup(const TQString& layout); TQStringList getAvailableVariants(const TQString& layout);
protected: protected:
void loadRules(TQString filename, bool layoutsOnly=false); void loadRules(TQString filename, bool layoutsOnly=false);
void loadGroups(TQString filename);
void loadOldLayouts(TQString filename);
private: private:
TQDict<char> m_models; TQDict<char> m_models;
TQDict<char> m_layouts; TQDict<char> m_layouts;
TQDict<char> m_options; TQDict<char> m_options;
TQMap<TQString, unsigned int> m_initialGroups;
TQDict<TQStringList> m_varLists; TQDict<TQStringList> m_varLists;
TQStringList m_oldLayouts;
TQStringList m_nonLatinLayouts;
TQString X11_DIR; // pseudo-constant TQString X11_DIR; // pseudo-constant
// void fixLayouts(); // void fixLayouts();
}; };

Loading…
Cancel
Save