/*************************************************************************** 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 #include #include KBSwitchApp::KBSwitchApp() { #ifndef HAVE_LIBXKLAVIER //m_twin_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); TQObject::connect(m_intf, SIGNAL(nextGroupSelected()), this, SLOT(slotSelectNextGroup())); TQObject::connect(m_intf, SIGNAL(groupSelected(int)), this, SLOT(slotGroupSelected(int))); TQObject::connect(&m_xkb, SIGNAL(layoutChanged()), this, SLOT(reconfigure())); TQObject::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); TQObject::connect(m_trayicon, SIGNAL(groupSelected(int)), this, SLOT(slotGroupSelected(int))); TQObject::connect(m_trayicon, SIGNAL(clicked()), this, SLOT(slotSelectNextGroup())); TQObject::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 TDEApplication::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); TQObject::connect(&dlg, SIGNAL(okClicked()), m_trayicon, SLOT(slotUpdateIcons())); TQObject::connect(&dlg, SIGNAL(applyClicked()), m_trayicon, SLOT(slotUpdateIcons())); TQObject::connect(&dlg, SIGNAL(okClicked()), this, SLOT(slotPrefChanged())); TQObject::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(tqt_xdisplay(), tqt_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_twin_module && (active_window_id = m_twin_module->activeWindow())) addWindowToMap(active_window_id); else m_active_window = m_window_map.end(); }*/ /** Enable window manager notifications */ /*void KBSwitchApp::enableKWinModule() { if (m_twin_module == NULL) { m_twin_module = new KWinModule(); connect(m_twin_module, SIGNAL(activeWindowChanged(WId)), SLOT(slotWindowChanged(WId))); connect(m_twin_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_twin_module) { m_twin_module->disconnect(); delete m_twin_module; m_twin_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); }