/*************************************************************************** kmousetool.cpp - description ------------------- begin : Sun Jan 20 23:27:58 PST 2002 copyright : (C) 2002-2003 by Jeff Roush email : jeff@mousetool.com copyright : (C) 2003 by Olaf Schmidt email : ojschmidt@kde.org copyright : (C) 2003 by Gunnar Schmi Dt email : gunnar@schmi-dt.de ***************************************************************************/ /*************************************************************************** * * * 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 "Xmd_kmousetool.h" #include "kmousetool.h" #include "kmousetool.moc" #include #include /* Intrinsics Definitions*/ #include /* Standard Name-String definitions*/ #include /* Standard Name-String definitions*/ #include /* Standard Name-String definitions*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include "mtstroke.h" //using namespace Arts; int currentXPosition; int currentYPosition; //using namespace std; #undef long /** * Gnarly X functions */ void queryPointer(Window *pidRoot, int *pnRx, int *pnRy, int *pnX, int *pnY, unsigned int *puMask); int CursorHasMoved(int minMovement); void LeftClick(); void RightClick(); void DoubleClick(); void LeftDn(); void LeftUp(); // Declarations Display *display; //SimpleSoundServer sound_server(Reference("global:Arts_SimpleSoundServer")); void KMouseTool::init_vars() { continue_timer = 1; tick_count = 0; max_ticks = dwell_time+1; mouse_is_down = FALSE; loadOptions(); // If the ~/.mousetool directory doesn't exist, create it // mSoundFileName = TQDir::homeDirPath(); mSoundFileName = locate("appdata", "sounds/mousetool_tap.wav"); mplayer = new KAudioPlayer(mSoundFileName); // find application file appfilename = locate("exe", "kmousetool"); // find the user's autostart directory autostartdirname = TDEGlobalSettings::autostartPath(); // SimpleSoundServer server(Reference("global:Arts_SimpleSoundServer")); // sound_server(Reference("global:Arts_SimpleSoundServer")); TQDesktopWidget *d = TQApplication::desktop(); int w = d->width(); int h = d->height(); MTStroke::setUpperLeft(0,0); MTStroke::setUpperRight(w-1,0); MTStroke::setLowerLeft(0,h-1); MTStroke::setLowerRight(w-1,h-1); } void KMouseTool::resetSettings() { cbDrag ->setChecked(smart_drag_on); cbStart->setChecked(isAutostart()); cbClick->setChecked(playSound); cbStroke->setChecked(strokesEnabled); movementEdit->setValue(min_movement); dwellTimeEdit->setValue(dwell_time); dragTimeEdit->setValue(drag_time); settingsChanged(); } void KMouseTool::setDefaultSettings() { cbDrag ->setChecked(false); cbStart->setChecked(false); cbClick->setChecked(false); cbStroke->setChecked(false); movementEdit->setValue(5); dwellTimeEdit->setValue(5); dragTimeEdit->setValue(3); settingsChanged(); } void KMouseTool::timerEvent( TQTimerEvent * ) { if (!mousetool_is_running) return; if (!continue_timer) { TQT_TQOBJECT(this)->killTimers(); return; } max_ticks = dwell_time + drag_time; stroke.addPt(currentXPosition, currentYPosition); moving = moving?CursorHasMoved(1):CursorHasMoved(min_movement); if (moving) { if (mousetool_just_started) { mousetool_just_started = false; tick_count = max_ticks; } else tick_count = 0; return; } if (tick_countplay(); // This is a bit slow. // KAudioPlayer::play(mSoundFileName); return; // the solution seems to be to use MCOP, // but SimpleSoundServer is not cooperating // When using the following code, make sure to link with // Put " -lsoundserver_idl" in the linker options in KDevelop. // SimpleSoundServer server = SimpleSoundServer::_fromString("global:Arts_SimpleSoundServer"); // SimpleSoundServer *ss = new SimpleSoundServer(Reference("global:Arts_SimpleSoundServer")); // SimpleSoundServer sound_server2(Reference("global:Arts_SimpleSoundServer")); // if(sound_server.isNull()) // return; // sound_server.play(mSoundFileName.latin1()); // Another approach is to try using TQSound. // TQSound depends on Network Audio Server, which doesn't seem to work on my Debian Woody system. // I haven't spent much time working on it, though. // TQSound::play(mSoundFileName); } KMouseTool::KMouseTool(TQWidget *parent, const char *name) : KMouseToolUI(parent, name) { init_vars(); resetSettings(); connect(movementEdit, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(settingsChanged())); connect(dwellTimeEdit, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(settingsChanged())); connect(dragTimeEdit, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(settingsChanged())); connect(cbDrag, TQT_SIGNAL(stateChanged(int)), this, TQT_SLOT(settingsChanged())); connect(cbStroke, TQT_SIGNAL(stateChanged(int)), this, TQT_SLOT(settingsChanged())); connect(cbClick, TQT_SIGNAL(stateChanged(int)), this, TQT_SLOT(settingsChanged())); connect(cbStart, TQT_SIGNAL(stateChanged(int)), this, TQT_SLOT(settingsChanged())); connect(buttonStartStop, TQT_SIGNAL(clicked()), this, TQT_SLOT(startStopSelected())); buttonDefault->setGuiItem(KStdGuiItem::defaults()); connect(buttonDefault, TQT_SIGNAL(clicked()), this, TQT_SLOT(defaultSelected())); connect(buttonReset, TQT_SIGNAL(clicked()), this, TQT_SLOT(resetSelected())); buttonApply->setGuiItem(KStdGuiItem::apply()); connect(buttonApply, TQT_SIGNAL(clicked()), this, TQT_SLOT(applySelected())); buttonHelp->setGuiItem(KStdGuiItem::help()); connect(buttonHelp, TQT_SIGNAL(clicked()), this, TQT_SLOT(helpSelected())); buttonClose->setGuiItem(KStdGuiItem::close()); connect(buttonClose, TQT_SIGNAL(clicked()), this, TQT_SLOT(closeSelected())); #if TDE_VERSION >= TDE_MAKE_VERSION (3,1,90) buttonQuit->setGuiItem(KStdGuiItem::quit()); #endif // KDE 3.2 connect(buttonQuit, TQT_SIGNAL(clicked()), this, TQT_SLOT(quitSelected())); // When we first start, it's nice to not click immediately. // So, tell MT we're just starting mousetool_just_started = true; startTimer(100); trayIcon = new KMouseToolTray (this, "systemTrayIcon"); updateStartStopText (); connect(trayIcon, TQT_SIGNAL(startStopSelected()), this, TQT_SLOT(startStopSelected())); connect(trayIcon, TQT_SIGNAL(configureSelected()), this, TQT_SLOT(configureSelected())); connect(trayIcon, TQT_SIGNAL(aboutSelected()), this, TQT_SLOT(aboutSelected())); connect(trayIcon, TQT_SIGNAL(helpSelected()), this, TQT_SLOT(helpSelected())); connect(trayIcon, TQT_SIGNAL(quitSelected()), this, TQT_SLOT(quitSelected())); aboutDlg = new KAboutApplication (0, "KMouseToolDlg", false); } KMouseTool::~KMouseTool() { } // ********************************************************* // Raw X functions // Begin mouse monitoring and event generation code. // these should be moved to a separate file. void LeftClick() { XTestFakeButtonEvent(display, 1, TRUE, 0); XTestFakeButtonEvent(display, 1, FALSE, 0); } void DoubleClick() { XTestFakeButtonEvent(display, 1, TRUE, 0); XTestFakeButtonEvent(display, 1, FALSE, 100); XTestFakeButtonEvent(display, 1, TRUE, 200); XTestFakeButtonEvent(display, 1, FALSE, 300); } void RightClick() { XTestFakeButtonEvent(display, 3, TRUE, 0); XTestFakeButtonEvent(display, 3, FALSE, 0); } void LeftDn() { XTestFakeButtonEvent(display, 1, TRUE, 0); } void LeftUp() { XTestFakeButtonEvent(display, 1, FALSE, 0); } void queryPointer(Window *pidRoot, int *pnRx, int *pnRy, int *pnX, int *pnY, unsigned int *puMask) { Window id2, idRoot; int screen_num; screen_num = DefaultScreen(display); idRoot = RootWindow(display,screen_num); XQueryPointer(display, idRoot, &idRoot, &id2, pnRx, pnRy, pnX, pnY, puMask); *pidRoot = idRoot; } // return 1 if cursor has moved, 0 otherwise int CursorHasMoved (int minMovement) { static int nOldRootX = -1; static int nOldRootY = -1; // XEvent evButtonEvent; Window idRootWin; int nRootX, nRootY, nWinX, nWinY; unsigned int uintMask; queryPointer(&idRootWin, &nRootX, &nRootY, &nWinX, &nWinY, &uintMask); int nRes = 0; if ((nRootX>nOldRootX?nRootX-nOldRootX:nOldRootX-nRootX) >= minMovement) nRes = 1; if ((nRootY>nOldRootY?nRootY-nOldRootY:nOldRootY-nRootY) >= minMovement) nRes = 1; currentXPosition = nRootX; currentYPosition = nRootY; if (nRes) { nOldRootX = nRootX; nOldRootY = nRootY; } return nRes; } // End mouse monitoring and event creation code bool KMouseTool::isAutostart() { TQString sym = autostartdirname; sym += "kmousetool"; // sym is now full path to symlink TQFileInfo fi(sym); return fi.exists(); } void KMouseTool::setAutostart (bool start) { TQString sym = autostartdirname; sym += "kmousetool"; // sym is now full path to symlink TQFileInfo fi(sym); TQString cmd; if (start) { if (!fi.exists()) // if it doesn't exist, make it cmd.sprintf("ln -s %s %s", appfilename.latin1(), autostartdirname.latin1()); } else { if (fi.exists()) // if it exists, delete it cmd.sprintf("rm -f %s", sym.latin1()); } system(cmd.ascii()); } bool KMouseTool::applySettings() { int drag, dwell; dwell = dwellTimeEdit->value(); drag = dragTimeEdit->value() ; // The drag time must be less than the dwell time if ( dwell < drag) { KMessageBox::sorry(this, i18n("The drag time must be less than or equal to the dwell time."), i18n("Invalid Value")); return false; } // if we got here, we must be okay. min_movement = movementEdit->value(); smart_drag_on = cbDrag->isChecked(); playSound = cbClick->isChecked(); strokesEnabled = cbStroke->isChecked(); setAutostart (cbStart->isChecked()); dwell_time = dwell; drag_time = drag; tick_count = max_ticks; saveOptions(); settingsChanged(); return true; } // Save options to kmousetoolrc file void KMouseTool::loadOptions() { kapp->config()->setGroup("UserOptions"); playSound = kapp->config()->readBoolEntry("AudibleClick",false); smart_drag_on = kapp->config()->readBoolEntry("SmartDrag",false); dwell_time = kapp->config()->readNumEntry("DwellTime",5); drag_time = kapp->config()->readNumEntry("DragTime",3); min_movement = kapp->config()->readNumEntry("Movement",5); strokesEnabled = kapp->config()->readBoolEntry("strokesEnabled",false); TQPoint p; int x = kapp->config()->readNumEntry("x",0); int y = kapp->config()->readNumEntry("y",0); p.setX(x); p.setY(y); move(p); mousetool_is_running = kapp->config()->readBoolEntry("MouseToolIsRunning",false); display = XOpenDisplay(NULL); } // Save options to kmousetoolrc file void KMouseTool::saveOptions() { TQPoint p = pos(); int x = p.x(); int y = p.y(); kapp->config()->setGroup("ProgramOptions"); kapp->config()->writeEntry("Version", KMOUSETOOL_VERSION); kapp->config()->setGroup("UserOptions"); kapp->config()->writeEntry("x", x); kapp->config()->writeEntry("y", y); kapp->config()->writeEntry("strokesEnabled", strokesEnabled); kapp->config()->writeEntry("IsMinimized", isHidden()); kapp->config()->writeEntry("DwellTime", dwell_time); kapp->config()->writeEntry("DragTime", drag_time); kapp->config()->writeEntry("Movement", min_movement); kapp->config()->writeEntry("SmartDrag", smart_drag_on); kapp->config()->writeEntry("AudibleClick", playSound); kapp->config()->writeEntry("MouseToolIsRunning", mousetool_is_running); kapp->config()->sync(); } void KMouseTool::updateStartStopText() { if (mousetool_is_running) buttonStartStop->setText(i18n("&Stop")); else buttonStartStop->setText(i18n("&Start")); trayIcon->updateStartStopText(mousetool_is_running); } bool KMouseTool::newSettings() { return ((dwell_time != dwellTimeEdit->value()) || (drag_time != dragTimeEdit->value()) || (min_movement != movementEdit->value()) || (smart_drag_on != cbDrag->isChecked()) || (playSound != cbClick->isChecked()) || (strokesEnabled != cbStroke->isChecked()) || (isAutostart() != cbStart->isChecked())); } bool KMouseTool::defaultSettings() { return ((5 == dwellTimeEdit->value()) && (3 == dragTimeEdit->value()) && (5 == movementEdit->value()) && !cbDrag->isChecked() && !cbClick->isChecked() && !cbStroke->isChecked() && !cbStart->isChecked()); } /******** SLOTS **********/ // Value or state changed void KMouseTool::settingsChanged () { buttonReset->setEnabled (newSettings()); buttonApply->setEnabled (newSettings()); buttonDefault->setDisabled (defaultSettings()); } // Buttons within the dialog void KMouseTool::startStopSelected() { mousetool_is_running = !mousetool_is_running; updateStartStopText(); } void KMouseTool::defaultSelected() { setDefaultSettings(); } void KMouseTool::resetSelected() { resetSettings(); } void KMouseTool::applySelected() { applySettings(); } // Buttons at the bottom of the dialog void KMouseTool::helpSelected() { kapp->invokeHelp(); } void KMouseTool::closeSelected() { if (newSettings()) { int answer = KMessageBox::questionYesNoCancel (this, i18n("There are unsaved changes in the active module.\nDo you want to apply the changes before closing the configuration window or discard the changes?"), i18n("Closing Configuration Window"), KStdGuiItem::apply(), KStdGuiItem::discard(), "AutomaticSave"); if (answer == KMessageBox::Yes) applySettings(); else if (answer == KMessageBox::No) resetSettings(); if (answer != KMessageBox::Cancel) hide(); } else hide(); } void KMouseTool::quitSelected() { if (newSettings()) { int answer = KMessageBox::questionYesNoCancel (this, i18n("There are unsaved changes in the active module.\nDo you want to apply the changes before quitting KMousetool or discard the changes?"), i18n("Quitting KMousetool"), KStdGuiItem::apply(), KStdGuiItem::discard(), "AutomaticSave"); if (answer == KMessageBox::Yes) applySettings(); if (answer != KMessageBox::Cancel) { saveOptions(); kapp->quit(); } } else { saveOptions(); kapp->quit(); } } // Menu functions void KMouseTool::configureSelected() { show(); raise(); setActiveWindow(); } void KMouseTool::aboutSelected() { aboutDlg->show(); } KMouseToolTray::KMouseToolTray (TQWidget *parent, const char *name) : KSystemTray (parent, name) { startStopId = contextMenu()->insertItem (i18n("&Start"), this, TQT_SIGNAL(startStopSelected())); contextMenu()->insertSeparator(); contextMenu()->insertItem (TDEGlobal::iconLoader()->loadIcon("configure", KIcon::Small), i18n("&Configure KMouseTool..."), this, TQT_SIGNAL(configureSelected())); contextMenu()->insertSeparator(); contextMenu()->insertItem (TDEGlobal::iconLoader()->loadIcon("contents", KIcon::Small), i18n("KMousetool &Handbook"), this, TQT_SIGNAL(helpSelected())); contextMenu()->insertItem (TDEGlobal::iconLoader()->loadIcon("kmousetool", KIcon::Small), i18n("&About KMouseTool"), this, TQT_SIGNAL(aboutSelected())); } KMouseToolTray::~KMouseToolTray() { } void KMouseToolTray::updateStartStopText(bool mousetool_is_running) { TQPixmap icon; if (mousetool_is_running) { contextMenu()->changeItem (startStopId, i18n("&Stop")); icon = TDEGlobal::iconLoader()->loadIcon("kmousetool_on", KIcon::Small); } else { contextMenu()->changeItem (startStopId, i18n("&Start")); icon = TDEGlobal::iconLoader()->loadIcon("kmousetool_off", KIcon::Small); } setPixmap (icon); show(); }