summaryrefslogtreecommitdiffstats
path: root/kxkb/kxkb.cpp
diff options
context:
space:
mode:
authorMavridis Philippe <[email protected]>2024-10-28 14:40:20 +0200
committerMavridis Philippe <[email protected]>2025-01-15 13:39:05 +0200
commit84ca90dc9369c01c778be01ee26f69b1ee1a422a (patch)
tree0485f1bd9ce79884ca2ef4e2e52f8811baed067a /kxkb/kxkb.cpp
parentb8f5a7414bd00abef13ef3ef6557f742849b9191 (diff)
downloadtdebase-84ca90dc9369c01c778be01ee26f69b1ee1a422a.tar.gz
tdebase-84ca90dc9369c01c778be01ee26f69b1ee1a422a.zip
Kxkb: improve system tray code and fix various switching-related bugs
- Improved layout change logic (indicator is now always updated when the actual switch occurs). This fixes layout switching triggered by the X11 shortcut not being synchronized with layout switching from the tray icon click and the TDE shortcut. - Kxkb will ignore XkbStateNotify events not related to XkbGroupState which caused strange behaviour with the system tray context menu. - Merged KxkbLabelController into KxkbSystemTray This resolves #547. Signed-off-by: Mavridis Philippe <[email protected]>
Diffstat (limited to 'kxkb/kxkb.cpp')
-rw-r--r--kxkb/kxkb.cpp259
1 files changed, 130 insertions, 129 deletions
diff --git a/kxkb/kxkb.cpp b/kxkb/kxkb.cpp
index fd8db27d5..daca1905b 100644
--- a/kxkb/kxkb.cpp
+++ b/kxkb/kxkb.cpp
@@ -86,7 +86,6 @@ KXKBApp::KXKBApp(bool allowStyles, bool GUIenabled)
addKipcEventMask( KIPC::SettingsChanged );
}
-
KXKBApp::~KXKBApp()
{
delete m_tray;
@@ -100,9 +99,8 @@ KXKBApp::~KXKBApp()
int KXKBApp::newInstance()
{
if (settingsRead()) {
- layoutApply();
+ setLayout(m_currentLayout);
}
-
return 0;
}
@@ -117,9 +115,9 @@ bool KXKBApp::settingsRead()
kapp->quit();
return false;
}
-
+
m_prevWinId = X11Helper::UNKNOWN_WINDOW_ID;
-
+
if( kxkbConfig.m_switchingPolicy == SWITCH_POLICY_GLOBAL ) {
delete kWinModule;
kWinModule = NULL;
@@ -130,7 +128,7 @@ bool KXKBApp::settingsRead()
kdWarning() << "With non-virtual desktop only global switching policy supported on non-primary screens" << endl;
//TODO: find out how to handle that
}
-
+
if( kWinModule == NULL ) {
kWinModule = new KWinModule(0, KWinModule::INFO_DESKTOP);
connect(kWinModule, TQ_SIGNAL(activeWindowChanged(WId)), TQ_SLOT(windowChanged(WId)));
@@ -138,27 +136,27 @@ bool KXKBApp::settingsRead()
m_prevWinId = kWinModule->activeWindow();
kdDebug() << "Active window " << m_prevWinId << endl;
}
-
+
m_layoutOwnerMap->reset();
m_layoutOwnerMap->setCurrentWindow( m_prevWinId );
if( m_rules == NULL )
m_rules = new XkbRules(false);
-
+
for(int ii=0; ii<(int)kxkbConfig.m_layouts.count(); ii++) {
LayoutUnit& layoutUnit = kxkbConfig.m_layouts[ii];
}
-
+
m_currentLayout = kxkbConfig.m_layouts[0];
kdDebug() << "default layout is " << m_currentLayout.toPair() << endl;
-
+
if( kxkbConfig.m_layouts.count() == 1 && !kxkbConfig.m_showSingle) {
kapp->quit();
return false;
}
initTray();
-
+
TDEGlobal::config()->reparseConfiguration(); // kcontrol modified kdeglobals
keys->readSettings();
keys->updateConnections();
@@ -168,162 +166,165 @@ bool KXKBApp::settingsRead()
void KXKBApp::initTray()
{
- if( !m_tray )
- {
- KSystemTray* sysTray = new KxkbSystemTray();
- TDEPopupMenu* popupMenu = sysTray->contextMenu();
- // popupMenu->insertTitle( kapp->miniIcon(), kapp->caption() );
-
- m_tray = new KxkbLabelController(sysTray, popupMenu);
- connect(popupMenu, TQ_SIGNAL(activated(int)), this, TQ_SLOT(menuActivated(int)));
- connect(sysTray, TQ_SIGNAL(toggled()), this, TQ_SLOT(nextLayout()));
- }
-
- m_tray->setShowFlag(kxkbConfig.m_showFlag);
- m_tray->initLayoutList(kxkbConfig.m_layouts, *m_rules);
- m_tray->setCurrentLayout(m_currentLayout);
- m_tray->show();
-}
+ if (!m_tray)
+ {
+ m_tray = new KxkbSystemTray();
+ connect(m_tray, TQ_SIGNAL(menuActivated(int)), this, TQ_SLOT(menuActivated(int)));
+ connect(m_tray, TQ_SIGNAL(toggled()), this, TQ_SLOT(nextLayout()));
+ }
-// This function activates the keyboard layout specified by the
-// configuration members (m_currentLayout)
-void KXKBApp::layoutApply()
-{
- setLayout(m_currentLayout);
+ m_tray->initLayoutList(kxkbConfig.m_layouts, *m_rules);
+ m_tray->setCurrentLayout(m_currentLayout);
+ m_tray->show();
}
// kdcop
bool KXKBApp::setLayout(const TQString& layoutPair)
{
- const LayoutUnit layoutUnitKey(layoutPair);
- if( kxkbConfig.m_layouts.contains(layoutUnitKey) ) {
- return setLayout( *kxkbConfig.m_layouts.find(layoutUnitKey) );
- }
- return false;
+ return setLayout((LayoutUnit)layoutPair);
}
// Activates the keyboard layout specified by 'layoutUnit'
bool KXKBApp::setLayout(const LayoutUnit& layoutUnit)
{
- uint group = kxkbConfig.m_layouts.findIndex(layoutUnit);
- bool res = m_extension->setGroup(group);
- if (res) {
- m_currentLayout = layoutUnit;
- maybeShowLayoutNotification();
- }
-
- if (m_tray) {
- if (res) {
- m_tray->setCurrentLayout(layoutUnit);
- } else {
- m_tray->setError(layoutUnit.toPair());
- }
- }
-
- return res;
+ const int group = kxkbConfig.m_layouts.findIndex(layoutUnit);
+ if (group >= 0) {
+ return setLayout(group);
+ }
+ return false;
}
+
// 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];
- }
+ // If this group is already set, just show the notification and return
+ if (m_extension->getGroup() == group) {
+ if (kxkbConfig.m_enableNotify) {
+ showLayoutNotification();
+ }
+ return true;
+ }
- if (m_tray) {
- if (res)
- m_tray->setCurrentLayout(m_currentLayout);
- else
- m_tray->setError(m_currentLayout.toPair());
- }
+ bool ok = m_extension->setGroup(group);
+ if (!ok) {
+ TQString layout = kxkbConfig.m_layouts[group].toPair();
+ if (m_tray) {
+ m_tray->setError(layout);
+ }
- return res;
+ if (kxkbConfig.m_enableNotify) {
+ showErrorNotification(layout);
+ }
+ }
+ return ok;
}
-
void KXKBApp::nextLayout()
{
- const LayoutUnit& layout = m_layoutOwnerMap->getNextLayout().layoutUnit;
- setLayout(layout);
+ const LayoutUnit& layout = m_layoutOwnerMap->getNextLayout().layoutUnit;
+ setLayout(layout);
}
void KXKBApp::prevLayout()
{
- const LayoutUnit& layout = m_layoutOwnerMap->getPrevLayout().layoutUnit;
- setLayout(layout);
+ const LayoutUnit& layout = m_layoutOwnerMap->getPrevLayout().layoutUnit;
+ setLayout(layout);
}
void KXKBApp::menuActivated(int id)
{
- if( KxkbLabelController::START_MENU_ID <= id
- && id < KxkbLabelController::START_MENU_ID + (int)kxkbConfig.m_layouts.count() )
- {
- const LayoutUnit& layout = kxkbConfig.m_layouts[id - KxkbLabelController::START_MENU_ID];
- m_layoutOwnerMap->setCurrentLayout( layout );
- setLayout( layout );
- }
- else if (id == KxkbLabelController::CONFIG_MENU_ID)
+ if (id >= KxkbSystemTray::START_MENU_ID &&
+ id < KxkbSystemTray::START_MENU_ID + kxkbConfig.m_layouts.count())
+ {
+ setLayout(id - KxkbSystemTray::START_MENU_ID);
+ }
+ else if (id == KxkbSystemTray::CONFIG_MENU_ID)
{
TDEProcess p;
p << "tdecmshell" << "keyboard_layout";
p.start(TDEProcess::DontCare);
- }
- else if (id == KxkbLabelController::HELP_MENU_ID)
- {
- TDEApplication::kApplication()->invokeHelp(0, "kxkb");
- }
-// else
-// {
-// quit();
-// }
+ }
+ else if (id == KxkbSystemTray::HELP_MENU_ID)
+ {
+ TDEApplication::kApplication()->invokeHelp(0, "kxkb");
+ }
}
void KXKBApp::slotGroupChanged(uint group)
{
- if (group >= kxkbConfig.m_layouts.count())
- {
- group = 0;
- }
- m_currentLayout = kxkbConfig.m_layouts[group];
- m_tray->setCurrentLayout(m_currentLayout);
- maybeShowLayoutNotification();
+ kdDebug() << "slotGroupChanged: " << group << ", layout count: " << kxkbConfig.m_layouts.count() << endl;
+ if (group >= kxkbConfig.m_layouts.count()) {
+ if (m_tray) {
+ m_tray->setError(i18n("Unknown"));
+ }
+
+ if (kxkbConfig.m_enableNotify) {
+ showErrorNotification(i18n("Unknown"));
+ }
+
+ return;
+ }
+
+ m_currentLayout = kxkbConfig.m_layouts[group];
+ m_layoutOwnerMap->setCurrentLayout(m_currentLayout);
+
+ if (m_tray) {
+ m_tray->setCurrentLayout(m_currentLayout);
+ }
+
+ if (kxkbConfig.m_enableNotify) {
+ showLayoutNotification();
+ }
}
-void KXKBApp::maybeShowLayoutNotification() {
- if (!kxkbConfig.m_enableNotify) return;
-
- TQString layoutName(m_rules->getLayoutName(m_currentLayout));
- bool useKMilo = kxkbConfig.m_notifyUseKMilo;
- bool notificationSent = false;
-
- // Query KDED whether KMiloD is loaded
- if (useKMilo) {
- QCStringList modules;
- TQCString replyType;
- TQByteArray replyData;
- if (kapp->dcopClient()->call("kded", "kded", "loadedModules()",
- TQByteArray(), replyType, replyData))
- {
- if (replyType == "QCStringList") {
- TQDataStream reply(replyData, IO_ReadOnly);
- reply >> modules;
-
- if (!modules.contains("kmilod")) {
- useKMilo = false;
- }
- }
- }
- }
+void KXKBApp::showLayoutNotification() {
+ bool useKMilo = kxkbConfig.m_notifyUseKMilo && isKMiloAvailable(),
+ notificationSent = false;
- if (useKMilo) {
- DCOPRef kmilo("kded", "kmilod");
- if (kmilo.send("displayText(TQString,TQPixmap)", layoutName, kapp->miniIcon()))
- notificationSent = true;
- }
+ TQString layoutName(m_rules->getLayoutName(m_currentLayout));
- if (!notificationSent) {
- KNotifyClient::event(m_tray->winId(), "LayoutChange", layoutName);
- }
+ if (useKMilo) {
+ DCOPRef kmilo("kded", "kmilod");
+ if (kmilo.send("displayText(TQString,TQPixmap)", layoutName, kapp->miniIcon())) {
+ notificationSent = true;
+ }
+ }
+
+ if (!notificationSent) {
+ KNotifyClient::event(m_tray->winId(), "LayoutChange", layoutName);
+ }
+}
+
+void KXKBApp::showErrorNotification(TQString layout) {
+ bool useKMilo = kxkbConfig.m_notifyUseKMilo && isKMiloAvailable(),
+ notificationSent = false;
+
+ if (useKMilo) {
+ DCOPRef kmilo("kded", "kmilod");
+ if (kmilo.send("displayText(TQString,TQPixmap)", i18n("Error changing keyboard layout to '%1'").arg(layout), kapp->miniIcon())) {
+ notificationSent = true;
+ }
+ }
+
+ if (!notificationSent) {
+ KNotifyClient::event(m_tray->winId(), "Error");
+ }
+}
+
+bool KXKBApp::isKMiloAvailable() {
+ QCStringList modules;
+ TQCString replyType;
+ TQByteArray replyData;
+ if (kapp->dcopClient()->call("kded", "kded", "loadedModules()",
+ TQByteArray(), replyType, replyData))
+ {
+ if (replyType == "QCStringList") {
+ TQDataStream reply(replyData, IO_ReadOnly);
+ reply >> modules;
+ return modules.contains("kmilod");
+ }
+ }
+ return false;
}
// TODO: we also have to handle deleted windows
@@ -336,18 +337,18 @@ void KXKBApp::windowChanged(WId winId)
}
kdDebug() << "old WinId: " << m_prevWinId << ", new WinId: " << winId << endl;
-
+
if( m_prevWinId != X11Helper::UNKNOWN_WINDOW_ID ) { // saving layout from previous window
// m_layoutOwnerMap->setCurrentWindow(m_prevWinId);
m_layoutOwnerMap->setCurrentLayout(m_currentLayout);
}
-
+
m_prevWinId = winId;
if( winId != X11Helper::UNKNOWN_WINDOW_ID ) {
m_layoutOwnerMap->setCurrentWindow(winId);
const LayoutState& layoutState = m_layoutOwnerMap->getCurrentLayout();
-
+
if( layoutState.layoutUnit != m_currentLayout ) {
kdDebug() << "switching to " << layoutState.layoutUnit.toPair() << " for " << winId << endl;
setLayout(layoutState.layoutUnit);