|
|
|
/***************************************************************************
|
|
|
|
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 <tdelocale.h>
|
|
|
|
#include <twinmodule.h>
|
|
|
|
|
|
|
|
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, TQ_SIGNAL(nextGroupSelected()), this, TQ_SLOT(slotSelectNextGroup()));
|
|
|
|
TQObject::connect(m_intf, TQ_SIGNAL(groupSelected(int)), this, TQ_SLOT(slotGroupSelected(int)));
|
|
|
|
|
|
|
|
TQObject::connect(&m_xkb, TQ_SIGNAL(layoutChanged()), this, TQ_SLOT(reconfigure()));
|
|
|
|
TQObject::connect(&m_xkb, TQ_SIGNAL(groupChanged(int)), this, TQ_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, TQ_SIGNAL(groupSelected(int)), this,
|
|
|
|
TQ_SLOT(slotGroupSelected(int)));
|
|
|
|
TQObject::connect(m_trayicon, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotSelectNextGroup()));
|
|
|
|
TQObject::connect(m_trayicon, TQ_SIGNAL(preferencesSelected()), this,
|
|
|
|
TQ_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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Select the next keyboard layout (wraps around) */
|
|
|
|
void KBSwitchApp::slotSelectNextGroup()
|
|
|
|
{
|
|
|
|
#ifdef HAVE_LIBXKLAVIER
|
|
|
|
m_xkb.setGroupNo(XklGetNextGroup());
|
|
|
|
#else
|
|
|
|
//forceSetGroup(m_next_groupno);
|
|
|
|
m_xkb.setGroupNo(m_next_groupno);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Select the previous keyboard layout (wraps around) */
|
|
|
|
void KBSwitchApp::slotSelectPrevGroup()
|
|
|
|
{
|
|
|
|
#ifdef HAVE_LIBXKLAVIER
|
|
|
|
m_xkb.setGroupNo(XklGetPrevGroup());
|
|
|
|
#else
|
|
|
|
m_xkb.setGroupNo(m_kbconf.getPrevGroup(m_cur_groupno));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/** No descriptions */
|
|
|
|
void KBSwitchApp::slotPreferences(){
|
|
|
|
KBConfigDlg dlg(&m_kbconf);
|
|
|
|
TQObject::connect(&dlg, TQ_SIGNAL(okClicked()), m_trayicon, TQ_SLOT(slotUpdateIcons()));
|
|
|
|
TQObject::connect(&dlg, TQ_SIGNAL(applyClicked()), m_trayicon, TQ_SLOT(slotUpdateIcons()));
|
|
|
|
TQObject::connect(&dlg, TQ_SIGNAL(okClicked()), this, TQ_SLOT(slotPrefChanged()));
|
|
|
|
TQObject::connect(&dlg, TQ_SIGNAL(applyClicked()), this, TQ_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, TQ_SIGNAL(activeWindowChanged(WId)), TQ_SLOT(slotWindowChanged(WId)));
|
|
|
|
connect(m_twin_module, TQ_SIGNAL(windowRemoved(WId)), TQ_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, TQ_SIGNAL(windowChanged(int, int )),
|
|
|
|
TQ_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);
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "kbswitchapp.moc"
|