summaryrefslogtreecommitdiffstats
path: root/kkbswitch/kbswitchapp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kkbswitch/kbswitchapp.cpp')
-rw-r--r--kkbswitch/kbswitchapp.cpp379
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);
+}