summaryrefslogtreecommitdiffstats
path: root/kxkb/kxkb.cpp
diff options
context:
space:
mode:
authorMavridis Philippe <mavridisf@gmail.com>2024-10-28 14:40:20 +0200
committerMavridis Philippe <mavridisf@gmail.com>2024-11-12 22:29:51 +0200
commit71068b3b258a340be30a91c3a5af92718da70cdd (patch)
tree6ba4afb1b1b254f21cef141321a51b5605ba54c4 /kxkb/kxkb.cpp
parent1afb78e598cc0d8c320e98c963cb98ab7935435f (diff)
downloadtdebase-71068b3b258a340be30a91c3a5af92718da70cdd.tar.gz
tdebase-71068b3b258a340be30a91c3a5af92718da70cdd.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 <mavridisf@gmail.com>
Diffstat (limited to 'kxkb/kxkb.cpp')
-rw-r--r--kxkb/kxkb.cpp258
1 files changed, 129 insertions, 129 deletions
diff --git a/kxkb/kxkb.cpp b/kxkb/kxkb.cpp
index 1d899299f..bbfa4d87e 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,164 @@ 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();
+ if (group < 0 || 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 +336,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);