summaryrefslogtreecommitdiffstats
path: root/kxkb/kxkb.cpp
diff options
context:
space:
mode:
authorMavridis Philippe <mavridisf@gmail.com>2023-01-06 15:30:57 +0200
committerMavridis Philippe <mavridisf@gmail.com>2023-03-24 15:28:11 +0200
commita67db2d4847d798c01d4fd7584c5bb9297e109e3 (patch)
tree6cb5bb70f6201fa62dec021b92e838d32a6036ec /kxkb/kxkb.cpp
parentb50ab13974adf6f16d72f172f0cf768a44c161da (diff)
downloadtdebase-a67db2d4847d798c01d4fd7584c5bb9297e109e3.tar.gz
tdebase-a67db2d4847d798c01d4fd7584c5bb9297e109e3.zip
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>
Diffstat (limited to 'kxkb/kxkb.cpp')
-rw-r--r--kxkb/kxkb.cpp176
1 files changed, 58 insertions, 118 deletions
diff --git a/kxkb/kxkb.cpp b/kxkb/kxkb.cpp
index 6a37dbf3a..532f26b21 100644
--- a/kxkb/kxkb.cpp
+++ b/kxkb/kxkb.cpp
@@ -63,19 +63,14 @@ KXKBApp::KXKBApp(bool allowStyles, bool GUIenabled)
m_prevWinId(X11Helper::UNKNOWN_WINDOW_ID),
m_rules(NULL),
m_tray(NULL),
- kWinModule(NULL),
- m_forceSetXKBMap( false )
+ kWinModule(NULL)
{
m_extension = new XKBExtension();
if( !m_extension->init() ) {
kdDebug() << "xkb initialization failed, exiting..." << endl;
::exit(1);
}
-
- // keep in sync with kcmlayout.cpp
- keys = new TDEGlobalAccel(TQT_TQOBJECT(this));
-#include "kxkbbindings.cpp"
- keys->updateConnections();
+ connect(m_extension, TQT_SIGNAL(groupChanged(uint)), this, TQT_SLOT(slotGroupChanged(uint)));
m_layoutOwnerMap = new LayoutMap(kxkbConfig);
@@ -86,9 +81,6 @@ KXKBApp::KXKBApp(bool allowStyles, bool GUIenabled)
KXKBApp::~KXKBApp()
{
-// deletePrecompiledLayouts();
-
- delete keys;
delete m_tray;
delete m_rules;
delete m_extension;
@@ -98,24 +90,19 @@ KXKBApp::~KXKBApp()
int KXKBApp::newInstance()
{
- m_extension->reset();
-
- if( settingsRead() )
- layoutApply();
-
+ if (settingsRead()) {
+ layoutApply();
+ }
+
return 0;
}
bool KXKBApp::settingsRead()
{
- kxkbConfig.load( KxkbConfig::LOAD_ACTIVE_OPTIONS );
-
- if( kxkbConfig.m_enableXkbOptions ) {
- kdDebug() << "Setting XKB options " << kxkbConfig.m_options << endl;
- if( !m_extension->setXkbOptions(kxkbConfig.m_options, kxkbConfig.m_resetOldOptions) ) {
- kdDebug() << "Setting XKB options failed!" << endl;
- }
- }
+ XkbOptions options = kxkbConfig.getXkbOptions();
+ if( !m_extension->setXkbOptions(options) ) {
+ kdDebug() << "Setting XKB options failed!" << endl;
+ }
if ( kxkbConfig.m_useKxkb == false ) {
kapp->quit();
@@ -151,38 +138,19 @@ bool KXKBApp::settingsRead()
for(int ii=0; ii<(int)kxkbConfig.m_layouts.count(); 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();
-
- 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
- }
+ m_currentLayout = kxkbConfig.m_layouts[0];
+ kdDebug() << "default layout is " << m_currentLayout.toPair() << endl;
- if( kxkbConfig.m_showSingle == false ) {
- kapp->quit();
- return false;
- }
+ if( kxkbConfig.m_layouts.count() == 1 && !kxkbConfig.m_showSingle) {
+ kapp->quit();
+ return false;
}
- else {
-// initPrecompiledLayouts();
- }
initTray();
TDEGlobal::config()->reparseConfiguration(); // kcontrol modified kdeglobals
- keys->readSettings();
- keys->updateConnections();
return true;
}
@@ -197,7 +165,7 @@ void KXKBApp::initTray()
m_tray = new KxkbLabelController(sysTray, popupMenu);
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);
@@ -223,35 +191,45 @@ bool KXKBApp::setLayout(const TQString& layoutPair)
return false;
}
-
// Activates the keyboard layout specified by 'layoutUnit'
-bool KXKBApp::setLayout(const LayoutUnit& layoutUnit, int group)
+bool KXKBApp::setLayout(const LayoutUnit& layoutUnit)
{
- bool res = false;
-
- if( group == -1 )
- group = layoutUnit.defaultGroup;
-
- 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;
+ uint group = kxkbConfig.m_layouts.findIndex(layoutUnit);
+ bool res = m_extension->setGroup(group);
+ if (res) {
+ m_currentLayout = layoutUnit;
+ }
if (m_tray) {
- if( res )
+ if (res) {
m_tray->setCurrentLayout(layoutUnit);
- else
+ } else {
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;
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
void KXKBApp::windowChanged(WId winId)
{
@@ -291,15 +274,11 @@ void KXKBApp::windowChanged(WId winId)
return;
}
- int group = m_extension->getGroup();
-
kdDebug() << "old WinId: " << m_prevWinId << ", new WinId: " << winId << endl;
- if( m_prevWinId != X11Helper::UNKNOWN_WINDOW_ID ) { // saving layout/group from previous window
-// kdDebug() << "storing " << m_currentLayout.toPair() << ":" << group << " for " << m_prevWinId << endl;
+ if( m_prevWinId != X11Helper::UNKNOWN_WINDOW_ID ) { // saving layout from previous window
// m_layoutOwnerMap->setCurrentWindow(m_prevWinId);
m_layoutOwnerMap->setCurrentLayout(m_currentLayout);
- m_layoutOwnerMap->setCurrentGroup(group);
}
m_prevWinId = winId;
@@ -309,11 +288,8 @@ void KXKBApp::windowChanged(WId winId)
const LayoutState& layoutState = m_layoutOwnerMap->getCurrentLayout();
if( layoutState.layoutUnit != m_currentLayout ) {
- kdDebug() << "switching to " << layoutState.layoutUnit.toPair() << ":" << group << " for " << winId << endl;
- setLayout( layoutState.layoutUnit, layoutState.group );
- }
- else if( layoutState.group != group ) { // we need to change only the group
- m_extension->setGroup(layoutState.group);
+ kdDebug() << "switching to " << layoutState.layoutUnit.toPair() << " for " << winId << endl;
+ setLayout(layoutState.layoutUnit);
}
}
}
@@ -325,50 +301,14 @@ void KXKBApp::slotSettingsChanged(int category)
return;
TDEGlobal::config()->reparseConfiguration(); // kcontrol modified kdeglobals
- keys->readSettings();
- keys->updateConnections();
}
-/*
- Viki (onscreen keyboard) has problems determining some modifiers states
- when kxkb uses precompiled layouts instead of setxkbmap. Probably a bug
- in the xkb functions used for the precompiled layouts *shrug*.
-*/
-void KXKBApp::forceSetXKBMap( bool set )
-{
- if( m_forceSetXKBMap == set )
- return;
- m_forceSetXKBMap = set;
- layoutApply();
+bool KXKBApp::x11EventFilter(XEvent *e) {
+ // let the extension process the event and emit signals if necessary
+ m_extension->processXEvent(e);
+ return TDEApplication::x11EventFilter(e);
}
-/*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 =
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.exec();
return 0;
-}
+} \ No newline at end of file