diff options
Diffstat (limited to 'kkbswitch/kbswitchapp.cpp')
-rw-r--r-- | kkbswitch/kbswitchapp.cpp | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/kkbswitch/kbswitchapp.cpp b/kkbswitch/kbswitchapp.cpp new file mode 100644 index 0000000..9dab46a --- /dev/null +++ b/kkbswitch/kbswitchapp.cpp @@ -0,0 +1,379 @@ +/*************************************************************************** + kbswitchapp.cpp - description + ------------------- + begin : Sun Jul 1 2001 + copyright : (C) 2001 by Leonid Zeitlin + email : lz@europe.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "config.h" +#include "kbswitchapp.h" +#include "kbconfigdlg.h" +#include "singlewindowwatcher.h" +#include "windowclasswatcher.h" + +#include <kdebug.h> +#include <klocale.h> +#include <kwinmodule.h> + +KBSwitchApp::KBSwitchApp() +{ +#ifndef HAVE_LIBXKLAVIER + //m_kwin_module = NULL; + m_watcher = NULL; +#endif + if (!m_xkb.xkbAvailable()) return; // oops! No XKB in the server + m_kbconf.load(config()); + m_cur_groupno = m_next_groupno = -1; +#ifdef HAVE_LIBXKLAVIER + XklSetGroupPerApp(m_kbconf.group_scope() != KBConfig::SCOPE_GLOBAL); + if (m_kbconf.toggle_mode()) + XklSetSecondaryGroupsMask(12); /* binary 1100 */ +#else + //resetWindowMap(); + //enableKWinModule(); + enableWatcher(); +#endif + + m_intf = new KBSwitchIntf(this, &m_kbconf); + QObject::connect(m_intf, SIGNAL(nextGroupSelected()), this, SLOT(slotSelectNextGroup())); + QObject::connect(m_intf, SIGNAL(groupSelected(int)), this, SLOT(slotGroupSelected(int))); + + QObject::connect(&m_xkb, SIGNAL(layoutChanged()), this, SLOT(reconfigure())); + QObject::connect(&m_xkb, SIGNAL(groupChanged(int)), this, SLOT(slotXkbGroupChanged(int))); + + m_force_group_setting = false; + int start_group = m_kbconf.default_groupno(); + + m_trayicon = new KBSwitchTrayIcon(&m_kbconf); + QObject::connect(m_trayicon, SIGNAL(groupSelected(int)), this, + SLOT(slotGroupSelected(int))); + QObject::connect(m_trayicon, SIGNAL(clicked()), this, SLOT(slotSelectNextGroup())); + QObject::connect(m_trayicon, SIGNAL(preferencesSelected()), this, + SLOT(slotPreferences())); + + if (start_group != m_xkb.getGroupNo()) { + setStartGroup(start_group); + } + else { + adaptToGroup(start_group); + } + + setMainWidget(m_trayicon); + m_trayicon->show(); + +#ifdef HAVE_LIBXKLAVIER + XklStartListen(); +#endif +} + +KBSwitchApp::~KBSwitchApp(){ +#ifndef HAVE_LIBXKLAVIER + //disableKWinModule(); + disableWatcher(); +#endif +} + +/** No descriptions */ +bool KBSwitchApp::x11EventFilter(XEvent *e){ + // let m_xkb process the event and emit signals if necessary + m_xkb.processEvent(e); + return KApplication::x11EventFilter(e); +} + +/** Update the tray icon to show the flag corresponding to the current keyboard group */ +void KBSwitchApp::updateIcon(int groupno){ + if (groupno >= 0 && groupno < m_kbconf.groupCount()) { // check just in case + m_trayicon->updateTrayIcon(groupno); + if (m_kbconf.toggle_mode()) m_trayicon->setToggleGroups(m_cur_groupno, m_next_groupno); + } +} + +/** No descriptions */ +void KBSwitchApp::slotGroupSelected(int groupno) +{ +#ifdef HAVE_LIBXKLAVIER + XklAllowOneSwitchToSecondaryGroup(); + m_xkb.setGroupNo(groupno); +#else + if (m_cur_groupno != groupno) { + setGroups(groupno, m_cur_groupno); + } +#endif +} + +/** No descriptions */ +void KBSwitchApp::internalToggleGroups() +{ + int tmp = m_next_groupno; + m_next_groupno = m_cur_groupno; + m_cur_groupno = tmp; +} + +/** No descriptions */ +void KBSwitchApp::forceSetGroup(int groupno) +{ + m_force_group_setting = true; +#ifndef HAVE_LIBXKLAVIER + //if (m_active_window != m_window_map.end()) + // m_active_window.data().groupno = groupno; +#endif + m_xkb.setGroupNo(groupno); +} + +/** No descriptions */ +void KBSwitchApp::slotSelectNextGroup() +{ +#ifdef HAVE_LIBXKLAVIER + m_xkb.setGroupNo(XklGetNextGroup()); +#else + //forceSetGroup(m_next_groupno); + m_xkb.setGroupNo(m_next_groupno); +#endif +} + +/** No descriptions */ +void KBSwitchApp::slotPreferences(){ + KBConfigDlg dlg(&m_kbconf); + QObject::connect(&dlg, SIGNAL(okClicked()), m_trayicon, SLOT(slotUpdateIcons())); + QObject::connect(&dlg, SIGNAL(applyClicked()), m_trayicon, SLOT(slotUpdateIcons())); + QObject::connect(&dlg, SIGNAL(okClicked()), this, SLOT(slotPrefChanged())); + QObject::connect(&dlg, SIGNAL(applyClicked()), this, SLOT(slotPrefChanged())); + dlg.exec(); +} + +/** Called when XKeyboard configuration changes */ +void KBSwitchApp::reconfigure(){ + m_kbconf.load(config()); + m_trayicon->reconfigure(); + + // make sure default group is still valid + if (m_kbconf.default_groupno() >= m_xkb.getNumKbdGroups()) + m_kbconf.set_default_groupno(0); + + int groupno = m_xkb.getGroupNo(); + if (groupno >= m_xkb.getNumKbdGroups()) { + // current group no longer valid, reset to default group + setStartGroup(m_kbconf.default_groupno()); + } + else if (!m_force_group_setting) { + adaptToGroup(groupno); + } +#ifndef HAVE_LIBXKLAVIER + //resetWindowMap(); + if (m_watcher) m_watcher->reset(); +#endif +} + +/** Respond to XKB changing the current group */ +void KBSwitchApp::slotXkbGroupChanged(int groupno){ +#ifdef HAVE_LIBXKLAVIER + updateIcon(groupno); +/* XWindowAttributes attrs; + XGetWindowAttributes(qt_xdisplay(), qt_xrootwin(), &attrs); + kdDebug() << "root event mask is " << attrs.your_event_mask << endl; + kdDebug() << "SubstructureNotifyMask is " << + ((attrs.your_event_mask & SubstructureNotifyMask) ? "ON" : "OFF") << endl;*/ +#else + bool accept = false; + if (m_force_group_setting) { // the change of group is forced by us + if (groupno == m_cur_groupno) { // the group is what we wanted, fine + m_force_group_setting = false; + accept = true; + } + else { // oops, not the group we expected + forceSetGroup(m_cur_groupno); + } + } + else { // the change is caused by something external, we didn't request it + if (m_kbconf.toggle_mode() && groupno != m_next_groupno) { // toggle mode, and the group is not correct + m_xkb.setGroupNo(m_next_groupno); + } + else { // adjust to this group + if (m_kbconf.toggle_mode()) internalToggleGroups(); + else { + m_cur_groupno = groupno; + m_next_groupno = m_kbconf.getNextGroup(groupno); + } + accept = true; + } + } + if (accept) { + updateIcon(groupno); + if (m_watcher) m_watcher->changeGroup(groupno, m_next_groupno); + } + /*if (m_kbconf.toggle_mode() && !force_group_setting && groupno != m_next_groupno) { + forceSetGroup(m_next_groupno); + } + else { + updateIcon(groupno); + force_group_setting = false; + if (m_kbconf.toggle_mode()) internalToggleGroups(); + else { + kdDebug() << "slotXkbGroupChanged, change group to " << groupno << endl; + m_cur_groupno = groupno; + m_next_groupno = m_kbconf.getNextGroup(groupno); + } + if (m_watcher) m_watcher->changeGroup(groupno, m_next_groupno); + }*/ +#endif +} + +/** Set the keyboard to the given group and set internal variable accordingly */ +void KBSwitchApp::setStartGroup(int start_group){ + /*m_next_groupno = start_group; + if (m_kbconf.toggle_mode()) { + m_cur_groupno = getNextGroup(start_group); + } + else { + m_cur_groupno = start_group; + } + forceSetGroup(m_next_groupno);*/ + setGroups(start_group, m_kbconf.getNextGroup(start_group)); +} + +/** adapt internal state to the given group */ +void KBSwitchApp::adaptToGroup(int groupno) { + if (! m_kbconf.toggle_mode() || // if not in toggle mode + (m_cur_groupno != groupno // or in toggle mode and internal variables are invalid + || m_next_groupno >= m_kbconf.groupCount() + || m_next_groupno == m_cur_groupno)) { + m_cur_groupno = groupno; + m_next_groupno = m_kbconf.getNextGroup(groupno); + } +#ifndef HAVE_LIBXKLAVIER + if (m_watcher) m_watcher->changeGroup(groupno, m_next_groupno); + /*if (m_active_window != m_window_map.end()) { + m_active_window.data().groupno = groupno; + m_active_window.data().next_groupno = m_next_groupno; + }*/ +#endif + updateIcon(groupno); +} + +/*void KBSwitchApp::slotWindowChanged(WId activeWindow) +{ +#ifndef HAVE_LIBXKLAVIER + m_active_window = m_window_map.find(activeWindow); + if (m_active_window == m_window_map.end()) + addWindowToMap(activeWindow); + if (m_active_window.data().groupno != m_cur_groupno) { + setGroups(m_active_window.data().groupno, m_active_window.data().next_groupno); + } + else m_next_groupno = m_active_window.data().next_groupno; +#endif +}*/ + +void KBSwitchApp::slotWindowChanged(int groupno, int next_groupno) +{ + if (groupno != m_cur_groupno) { + setGroups(groupno, next_groupno); + } + else m_next_groupno = next_groupno; +} + +/*void KBSwitchApp::slotWindowRemoved(WId window) +{ +#ifndef HAVE_LIBXKLAVIER + m_window_map.remove(window); +#endif +} + +#ifndef HAVE_LIBXKLAVIER +void KBSwitchApp::resetWindowMap() +{ + WId active_window_id; + + m_window_map.clear(); + + if (m_kwin_module && (active_window_id = m_kwin_module->activeWindow())) + addWindowToMap(active_window_id); + else + m_active_window = m_window_map.end(); +}*/ + +/** Enable window manager notifications */ +/*void KBSwitchApp::enableKWinModule() +{ + if (m_kwin_module == NULL) { + m_kwin_module = new KWinModule(); + connect(m_kwin_module, SIGNAL(activeWindowChanged(WId)), SLOT(slotWindowChanged(WId))); + connect(m_kwin_module, SIGNAL(windowRemoved(WId)), SLOT(slotWindowRemoved(WId))); + resetWindowMap(); + if (m_cur_groupno != -1 && m_cur_groupno != m_kbconf.default_groupno()) + setStartGroup(m_kbconf.default_groupno()); + } +}*/ + +/** Disable window manager notifications */ +/*void KBSwitchApp::disableKWinModule() +{ + if (m_kwin_module) { + m_kwin_module->disconnect(); + delete m_kwin_module; + m_kwin_module = NULL; + resetWindowMap(); + } +}*/ + +/** adds a new window to the internal window map */ +/*void KBSwitchApp::addWindowToMap(WId window_id) +{ + KBWinInfo wininfo = { m_kbconf.default_groupno(), + m_kbconf.getNextGroup(m_kbconf.default_groupno()) }; + + m_active_window = m_window_map.insert(window_id, wininfo); +} +#endif*/ + +void KBSwitchApp::enableWatcher() +{ + if (!m_watcher) { + m_watcher_type = m_kbconf.group_scope(); + if (m_watcher_type == KBConfig::SCOPE_WINDOW) + m_watcher = new SingleWindowWatcher(&m_kbconf, this); + else if (m_watcher_type == KBConfig::SCOPE_CLASS) + m_watcher = new WindowClassWatcher(&m_kbconf, this); + else return; // if scope is global, don't create watcher + connect(m_watcher, SIGNAL(windowChanged(int, int )), + SLOT(slotWindowChanged(int, int))); + } +} + +void KBSwitchApp::disableWatcher() +{ + if (m_watcher) { + m_watcher->disconnect(); + delete m_watcher; + m_watcher = NULL; + } +} + +/** React to a change in KKBSwitch's user preferences, + * made by user in Configure dialog */ +void KBSwitchApp::slotPrefChanged() +{ +#ifndef HAVE_LIBXKLAVIER + if (m_kbconf.group_scope() != m_watcher_type) { + disableWatcher(); + enableWatcher(); + } +#endif +} + +/** Set the current and next groups */ +void KBSwitchApp::setGroups(int group, int next_group) +{ + m_cur_groupno = group; + m_next_groupno = next_group; + forceSetGroup(group); +} |