• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • kdeutils
  • Sitemap
  • Contact Us
 

klaptopdaemon

laptop_daemon.cpp

Go to the documentation of this file.
00001 g/*
00002  * laptop_daemon.cpp
00003  * Copyright (C) 1999 Paul Campbell <paul@taniwha.com>
00004  *
00005  * this replaces kcmlaptop - there are 2 parts - one is the panels that
00006  *  put the setup configuration in the "kcmlaptop" configm, the other
00007  *  is the laptop_daemon (this guy) who watches the battery state
00008  *  and does stuff as a result
00009  *
00010  * This file contains the implementation of the main laptop battery monitoring daemon
00011  *
00012  * $Id: laptop_daemon.cpp 735151 2007-11-11 01:35:15Z pino $
00013  *
00014  *  This program is free software; you can redistribute it and/or modify
00015  *  it under the terms of the GNU General Public License as published by
00016  *  the Free Software Foundation; either version 2 of the License, or
00017  *  (at your option) any later version.
00018  *
00019  *  This program is distributed in the hope that it will be useful,
00020  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022  *  GNU General Public License for more details.
00023  *
00024  *  You should have received a copy of the GNU General Public License
00025  *  along with this program; if not, write to the Free Software
00026  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00027  */
00028 
00029 #include <stdlib.h>
00030 #include <fcntl.h>
00031 
00032 #include <QTimer>
00033 //Added by qt3to4:
00034 #include <QTimerEvent>
00035 #include <Q3CString>
00036 
00037 #include <kconfig.h>
00038 #include <klocale.h>
00039 #include <kcmdlineargs.h>
00040 #include "laptop_daemon.h"
00041 #include "portable.h"
00042 #include <kaboutdata.h>
00043 #include <kaudioplayer.h>
00044 #include <kapplication.h>
00045 #include <sys/ioctl.h>
00046 #include <kmessagebox.h>
00047 #include <kpassivepopup.h>
00048 #include <qsocketnotifier.h>
00049 #include <qcursor.h>
00050 
00051 #include <unistd.h>
00052 #include <sys/time.h>
00053 #include <libkworkspace/kworkspace.h>
00054 
00055 #include <kpluginfactory.h>
00056 #include <kpluginloader.h>
00057 
00058 K_PLUGIN_FACTORY(LaptopDaemonFactory,
00059                  registerPlugin<laptop_daemon>();
00060     )
00061 K_EXPORT_PLUGIN(LaptopDaemonFactory("klaptopdaemon"))
00062 
00063 class XWidget: public QWidget {
00064 public:
00065     XWidget(laptop_daemon *p):QWidget(0) { pd = p; }
00066 private:
00067     bool x11Event(XEvent *event);
00068     laptop_daemon *pd;
00069 };
00070 bool XWidget::x11Event(XEvent *event) { return pd->x11Event(event); }
00071 
00072 laptop_daemon::laptop_daemon(QObject* parent, const QList<QVariant>&)
00073     : KDEDModule(parent)
00074 {
00075     xwidget = new XWidget(this);
00076     xwidget->hide();
00077     kapp->installX11EventFilter(xwidget);
00078 
00079     backoffTimer = 0;
00080     need_wait = 0;
00081     saved_brightness = 0;
00082         saved_throttle = 0;
00083         saved_performance = 0;
00084     wake_timer = 0;
00085     button_bright_saved=0;
00086     button_bright_val=0;
00087     button_saved_performance = 0;
00088     button_saved_throttle = 0;
00089     power_button_off = 0;
00090 
00091     if (laptop_portable::has_brightness()) {
00092         brightness = laptop_portable::get_brightness();
00093     } else {
00094         brightness = 0;
00095     }
00096     buttonThread.sethandle(this);
00097         triggered[0] = 0;
00098         triggered[1] = 0;
00099     timer = 0;
00100     dock_widget = 0;
00101     oldTimer = 0;
00102     sony_fd = -1;
00103     sony_notifier = 0;
00104     knownFullyCharged = 0;
00105     sony_disp = 0;
00106         connect(this, SIGNAL(signal_checkBattery()), SLOT(checkBatteryNow()));
00107 
00108     //hasAudio = (audioServer.serverStatus() == 0) ? true : false;
00109 
00110         // FIXME: make these configurable.  Some system definitely don't
00111         //        use /var/run/stab
00112     if (!access("/var/run/stab", R_OK|F_OK))
00113             _pcmcia = new KPCMCIA(8, "/var/run/stab");
00114     else if (!access("/var/lib/pcmcia/stab", R_OK|F_OK))
00115         _pcmcia = new KPCMCIA(8, "/var/lib/pcmcia/stab");
00116     else _pcmcia = NULL;
00117 
00118     if (_pcmcia)
00119             connect(_pcmcia, SIGNAL(cardUpdated(int)), this, SLOT(updatePCMCIA(int)));
00120     connect( &autoLock, SIGNAL(timeout()), this, SLOT(timerDone()) );
00121 
00122 }
00123 
00124 laptop_daemon::~laptop_daemon()
00125 {
00126     delete xwidget;
00127     delete _pcmcia;
00128         delete dock_widget;
00129         delete sony_notifier;
00130     if (sony_disp)
00131         XCloseDisplay(sony_disp);
00132 }
00133 
00134 void
00135 laptop_daemon::quit()
00136 {
00137     deleteLater();
00138 }
00139 
00140 void laptop_daemon::restart()
00141 {
00142         if (oldTimer > 0) {
00143                 killTimer(oldTimer);
00144         oldTimer=0;
00145     }
00146     if (timer) {
00147         autoLock.stop();
00148         timer = 0;
00149     }
00150     s.load();
00151     if (s.has_brightness) {
00152         brightness = laptop_portable::get_brightness();
00153     } else {
00154         brightness = 0;
00155     }
00156 
00157     if (!s.need_to_run()) {
00158         quit();
00159         return;
00160     }
00161 
00162     if (sony_fd < 0)
00163         sony_fd = ::open("/dev/sonypi", O_RDONLY|O_NONBLOCK);
00164     if (s.sony_enablescrollbar||s.sony_middleemulation) {
00165         if (sony_disp == 0 && sony_fd >= 0)
00166             sony_disp = XOpenDisplay(NULL);
00167         if (sony_fd < 0 || sony_disp == 0) {
00168             s.sony_enablescrollbar = 0;
00169             s.sony_middleemulation = 0;
00170         }
00171     }
00172 
00173     // change the dock state if necessary
00174 
00175     if (s.enabled) {
00176         if (!dock_widget) {
00177             dock_widget = new laptop_dock(this);
00178             dock_widget->setPCMCIA(_pcmcia);
00179             dock_widget->show();
00180         }
00181         dock_widget->reload_icon();
00182         dock_widget->SetupPopup();
00183     } else {
00184         if (dock_widget) {
00185             delete dock_widget;
00186             dock_widget = 0;
00187         }
00188     }
00189 
00190     if (s.enable_lid_button && (lid_state = laptop_portable::get_button(laptop_portable::LidButton))) {
00191         if (s.button_lid_bright_enabled)
00192             SetBrightness(0, s.button_lid_bright_val);
00193         if (s.button_lid_performance_enabled)
00194             SetPerformance(s.button_lid_performance_val);
00195         if (s.button_lid_throttle_enabled)
00196             SetThrottle(s.button_lid_throttle_val);
00197         switch (s.button_lid) {
00198         case 1: invokeStandby();
00199             break;
00200         case 2: invokeSuspend();
00201             break;
00202         case 3: invokeHibernate();
00203             break;
00204         case 4: invokeLogout();
00205             break;
00206         case 5: invokeShutdown();
00207             break;
00208         }
00209     }
00210     if (s.enable_power_button && (power_state = laptop_portable::get_button(laptop_portable::PowerButton))) {
00211         if (s.button_power_bright_enabled)
00212             SetBrightness(0, s.button_power_bright_val);
00213         if (s.button_power_performance_enabled)
00214             SetPerformance(s.button_power_performance_val);
00215         if (s.button_power_throttle_enabled)
00216             SetThrottle(s.button_power_throttle_val);
00217         switch (s.button_power) {
00218         case 1: invokeStandby();
00219             break;
00220         case 2: invokeSuspend();
00221             break;
00222         case 3: invokeHibernate();
00223             break;
00224         case 4: invokeLogout();
00225             break;
00226         case 5: invokeShutdown();
00227             break;
00228         }
00229     }
00230     if (s.button_power_bright_enabled || s.button_power_performance_enabled || s.button_power_throttle_enabled ||
00231         s.button_lid_bright_enabled || s.button_lid_performance_enabled || s.button_lid_throttle_enabled ||
00232         s.button_lid != 0 || s.button_power != 0) { // need a fast thread to poll every sec
00233         if (!buttonThread.running()) {
00234             buttonThread.start();
00235         }
00236     } else {
00237         if (buttonThread.running()) {
00238             buttonThread.quit();
00239             buttonThread.done();
00240         }
00241     }
00242 
00243 
00244     // Do setup
00245     struct power_result p = laptop_portable::poll_battery_state();
00246     powered = p.powered;
00247 
00248     need_wait = 0;
00249     saved_brightness = 0;
00250         saved_throttle = 0;
00251         saved_performance = 0;
00252     if (s.power_action[0] || s.power_action[1] || s.power_brightness_enabled[0] || s.power_brightness_enabled[0] ||
00253         s.power_performance_enabled[0] || s.power_performance_enabled[1] || s.power_throttle_enabled[0] || s.power_throttle_enabled[1]) {
00254         power_time = s.power_wait[powered?0:1];
00255         timer = 1;
00256         autoLock.setLoadAverage(s.lav_enabled[powered?0:1], s.lav_val[powered?0:1]);
00257         autoLock.setTimeout(power_time);
00258         autoLock.start();
00259     } else {
00260         timer = 0;
00261     }
00262 
00263 
00264     if (s.useBlankSaver) {
00265         setBlankSaver(!p.powered);
00266     }
00267 
00268     start_monitor();
00269 
00270     // brightness control
00271 
00272     if (s.has_brightness) {
00273         if (s.bright_pon && powered) {
00274             SetBrightness(0, s.bright_son);
00275         } else
00276         if (s.bright_poff && !powered) {
00277             SetBrightness(0, s.bright_soff);
00278         }
00279     }
00280     if (s.has_performance) {
00281         if (s.performance_pon && powered) {
00282             SetPerformance(s.performance_val_on);
00283         } else
00284         if (s.performance_poff && !powered) {
00285             SetPerformance(s.performance_val_off);
00286         }
00287     }
00288     if (s.has_throttle) {
00289         if (s.throttle_pon && powered) {
00290             SetThrottle(s.throttle_val_on);
00291         } else
00292         if (s.throttle_poff && !powered) {
00293             SetThrottle(s.throttle_val_off);
00294         }
00295     }
00296 
00297     // sony support
00298 
00299     if (s.sony_enablescrollbar||s.sony_middleemulation) {
00300         if (sony_notifier == 0) {
00301             sony_notifier = new QSocketNotifier( sony_fd, QSocketNotifier::Read, this );
00302             if (sony_notifier)
00303                 QObject::connect( sony_notifier, SIGNAL(activated(int)),
00304                                                   this, SLOT(sonyDataReceived()) );
00305         }
00306     } else {
00307         if (sony_notifier) {
00308             delete sony_notifier;
00309             sony_notifier = 0;
00310         }
00311     }
00312 }
00313 
00314 
00315 void laptop_daemon::setBlankSaver(bool blanked)
00316 {
00317     QByteArray ba;
00318     QDataStream ds(&ba, QIODevice::WriteOnly);
00319 
00320     ds.setVersion(QDataStream::Qt_3_1);
00321     ds << bool(blanked);
00322     // can't use kapp->dcopClient() because it breaks KUniqueApplication
00323     DCOPClient c;
00324     c.attach();
00325     c.send("kdesktop", "KScreensaverIface", "setBlankOnly(bool)", ba);
00326     c.detach();
00327 }
00328 
00329 
00330 void laptop_daemon::timerDone()
00331 {
00332     int action;
00333 
00334     timer = 0;
00335     autoLock.stop();        // stop - see the note below about backoff
00336     if (powered) {
00337         action = s.power_action[0];
00338     } else {
00339         action = s.power_action[1];
00340     }
00341     switch (action) {
00342     case 1: invokeStandby();
00343         break;
00344     case 2: invokeSuspend();
00345         break;
00346     case 3: invokeHibernate();
00347         break;
00348     }
00349     if ((powered?s.power_brightness_enabled[0]:s.power_brightness_enabled[1])) {
00350         need_wait = 1;
00351         if (!saved_brightness) {
00352             saved_brightness = 1;
00353             saved_brightness_val = brightness;
00354         }
00355         SetBrightness(1, powered?s.power_brightness[0]:s.power_brightness[1]);
00356     }
00357     if ((powered?s.power_performance_enabled[0]:s.power_performance_enabled[1])) {
00358         need_wait = 1;
00359         if (!saved_performance) {
00360             QStringList profile_list;
00361                 int current_profile;
00362             bool *active_list;
00363                 if (laptop_portable::get_system_performance(1, current_profile, profile_list, active_list)) {
00364                 saved_performance = 1;
00365                 saved_performance_val = profile_list[current_profile];
00366             }
00367         }
00368         SetPerformance(powered?s.power_performance[0]:s.power_performance[1]);
00369     }
00370     if ((powered?s.power_throttle_enabled[0]:s.power_throttle_enabled[1])) {
00371         need_wait = 1;
00372         if (!saved_throttle) {
00373             QStringList profile_list;
00374                 int current_profile;
00375             bool *active_list;
00376                 if (laptop_portable::get_system_throttling(1, current_profile, profile_list, active_list)) {
00377                 saved_throttle = 1;
00378                 saved_throttle_val = profile_list[current_profile];
00379             }
00380         }
00381         SetPerformance(powered?s.power_throttle[0]:s.power_throttle[1]);
00382     }
00383     //
00384     // we must give ourself enough time to handle any necessary evil before we start looking again
00385     //  (many of the above things cause unexpected time discontinuities)
00386     //
00387     if (need_wait) {
00388         wakepos.setX(QCursor::pos().x());
00389         wakepos.setY(QCursor::pos().y());
00390         if (!wake_timer) {
00391             wake_timer = new QTimer(this);
00392                 connect(wake_timer, SIGNAL(timeout()), this, SLOT(WakeCheck()));
00393             wake_timer->start(1*1000, 1);
00394         }
00395     } else {
00396         if (!backoffTimer) {
00397             backoffTimer = new QTimer(this);
00398                 connect(backoffTimer, SIGNAL(timeout()), this, SLOT(BackoffRestart()));
00399             backoffTimer->start(60*1000, 1);
00400         }
00401     }
00402 }
00403 
00404 void
00405 laptop_daemon::BackoffRestart()
00406 {
00407     delete backoffTimer;
00408     backoffTimer = 0;
00409     if (!timer) {
00410         timer = 1;
00411         autoLock.start();
00412     }
00413 }
00414 
00415 void
00416 laptop_daemon::WakeCheck()
00417 {
00418     if (!wake_timer)
00419         return;
00420     if (!need_wait) {
00421         wake_timer->stop();
00422         delete wake_timer;
00423         wake_timer = 0;
00424         return;
00425     }
00426     if (wakepos.x() != QCursor::pos().x() || wakepos.y() != QCursor::pos().y()) {
00427         wake_timer->stop();
00428         delete wake_timer;
00429         wake_timer = 0;
00430         WakeUpAuto();
00431     }
00432 }
00433 
00434 void
00435 laptop_daemon::WakeUpAuto()
00436 {
00437     if (!need_wait)
00438         return;
00439     need_wait = 0;
00440     if (saved_brightness) {
00441         SetBrightness(0, saved_brightness_val);
00442         saved_brightness = 0;
00443     }
00444     if (saved_throttle) {
00445         SetThrottle(saved_throttle_val);
00446         saved_throttle = 0;
00447     }
00448     if (saved_performance) {
00449         SetPerformance(saved_performance_val);
00450         saved_performance = 0;
00451     }
00452     if (!timer) {
00453         timer = 1;
00454         autoLock.start();
00455     }
00456 }
00457 
00458 bool
00459 laptop_daemon::x11Event(XEvent *event)
00460 {
00461     switch (event->type) {
00462     case KeyPress:
00463     case ButtonPress:
00464         if (need_wait)
00465             WakeUpAuto();
00466             if (!event->xkey.send_event) {
00467             if (need_wait)
00468                 WakeUpAuto();
00469                 autoLock.keyPressed();
00470         }
00471         break;
00472 
00473     case CreateNotify:
00474             autoLock.windowCreated(event->xcreatewindow.window);
00475         break;
00476     }
00477     return(0);
00478 }
00479 
00480 void laptop_daemon::dock_quit()
00481 {
00482     if (dock_widget)
00483         delete dock_widget;
00484     dock_widget = 0;
00485 }
00486 
00487 
00488 void laptop_daemon::updatePCMCIA(int num)
00489 {
00490   Q_UNUSED(num);
00491   //kDebug() << "PCMCIA card " << num << " was updated." ;
00492 
00493   // Two things we do here.  We provide notifications for cards
00494   // being inserted / cards going to sleep / cards waking up
00495   // and cards being safe to eject.
00496   // The second thing we do is provide the desktop icon actions
00497   // via dcop.
00498 }
00499 
00500 
00501 void laptop_daemon::haveBatteryLow(int t, const int num, const int type)
00502 {
00503     displayPixmap();
00504 
00505     // beep if we are allowed to
00506     if (s.systemBeep[t]) {
00507         //KNotifyClient::beep();
00508         (void)kapp->beep();
00509     }
00510 
00511     // run a command if we have to
00512     if (s.runCommand[t]) {
00513         // make sure the command exists
00514         if (!s.runCommandPath[t].isEmpty()) {
00515             KProcess::startDetached(s.runCommandPath[t]);
00516         }
00517     }
00518 
00519     if (s.do_brightness[t])
00520         SetBrightness(0, s.val_brightness[t]);
00521     if (s.do_throttle[t])
00522         SetThrottle(s.val_throttle[t]);
00523     if (s.do_performance[t])
00524         SetPerformance(s.val_performance[t]);
00525 
00526     // play a sound if we have to
00527     if (s.playSound[t]) {
00528          KAudioPlayer::play(s.playSoundPath[t]);
00529     }
00530 
00531 
00532     if (s.do_hibernate[t])
00533         invokeHibernate();
00534     if (s.do_suspend[t])
00535         invokeSuspend();
00536     if (s.do_standby[t])
00537         invokeStandby();
00538     if (s.logout[t])
00539         invokeLogout();
00540     if (s.shutdown[t])
00541         invokeShutdown();
00542     // notify if we must (must be last since it's synchronous)
00543     if (s.notify[t]) {
00544             if (type) {
00545                 if (s.time_based_action_critical) {
00546                     KPassivePopup::message(i18n("Battery power is running out."),
00547                                            i18n("%1 % charge left.", num),
00548                                            BarIcon("battery"), dock_widget,
00549                                            0, 20000);
00550                 } else {
00551                     // Will this ever be reached?
00552                     KPassivePopup::message(i18n("Battery power is running out."),
00553                                            i18n("%1 % charge left.", num),
00554                                            BarIcon("battery"), dock_widget,
00555                                            0, 20000);
00556                 }
00557             }
00558             else {
00559                 if (s.time_based_action_low) {
00560                     KPassivePopup::message(i18n("Battery power is running out."),
00561                                            i18np("1 minute left.","%1 minutes left.", num),
00562                                            BarIcon("battery"), dock_widget,
00563                                            0, 20000);
00564                 } else {
00565                     KPassivePopup::message(i18n("Battery power is running out."),
00566                                            i18np("1% left.", "%1 percent left.", num),
00567                                            BarIcon("battery"), dock_widget,
00568                                            0, 20000);
00569                 }
00570             }
00571     }
00572 }
00573 
00574 int laptop_daemon::calcBatteryTime(int percent, long time, bool restart)
00575 {
00576 #define MAX_SAMPLES_USED 3
00577   static int percents[MAX_SAMPLES_USED];
00578   static long times[MAX_SAMPLES_USED];
00579   static int lastused=-1;
00580   int r=-1;
00581 
00582   if ( (lastused==-1) || restart )
00583   {
00584      percents[0]=percent;
00585      times[0]=time;
00586      lastused=0;
00587   }
00588   else
00589   {
00590      // Add the % and time to the arrays
00591      // (or just update the time if the % hasn't changed)
00592      if (percents[lastused]!=percent)
00593     if (lastused!=MAX_SAMPLES_USED-1)
00594     {
00595        lastused++;
00596        percents[lastused]=percent;
00597        times[lastused]=time;
00598     }
00599     else
00600     {
00601       for (int i=1;i<MAX_SAMPLES_USED;i++)
00602       {  percents[i-1]=percents[i]; times[i-1]=times[i]; };
00603     }
00604      percents[lastused]=percent;
00605      times[lastused]=time;
00606 
00607      //Now let's do the real calculations
00608 
00609      if (lastused==0) return -1;
00610 
00611      // Copy the data to temporary variables
00612      double tp[MAX_SAMPLES_USED];
00613      double tt[MAX_SAMPLES_USED];
00614 
00615      for (int i=0;i<=lastused;i++)
00616      { tp[i]=percents[i]; tt[i]=times[i]; };
00617 
00618      for (int c=lastused; c>1; c--)
00619      {
00620        for (int i=0; i<c-1; i++)
00621        {
00622           tp[i]=(tp[i]+tp[i+1])/2;
00623           tt[i]=(tt[i]+tt[i+1])/2;
00624        }
00625      }
00626 
00627      // Now we've reduced all the samples to an approximation with just a line
00628 
00629      if (tp[1]-tp[0]!=0)
00630         r=static_cast<int>(tt[0]-(tp[0]/(tp[1]-tp[0]))*(tt[1]-tt[0])-time);
00631 
00632 
00633   }
00634 
00635   return r;
00636 }
00637 
00638 void laptop_daemon::checkBatteryNow()
00639 {
00640     struct power_result p;
00641 
00642     p = laptop_portable::poll_battery_state();
00643 
00644     if (s.useBlankSaver && oldpowered != p.powered) {
00645         setBlankSaver(!p.powered);
00646     }
00647 
00648     powered = p.powered;
00649     left = p.time;
00650     val = p.percentage;
00651 
00652     if (oldpowered != powered && s.has_brightness) {
00653         if (s.bright_pon && powered) {
00654             SetBrightness(0, s.bright_son);
00655         } else
00656         if (s.bright_poff && !powered) {
00657             SetBrightness(0, s.bright_soff);
00658         }
00659         if (s.performance_pon && powered) {
00660             SetPerformance(s.performance_val_on);
00661         } else
00662         if (s.performance_poff && !powered) {
00663             SetPerformance(s.performance_val_off);
00664         }
00665         if (s.throttle_pon && powered) {
00666             SetThrottle(s.throttle_val_on);
00667         } else
00668         if (s.throttle_poff && !powered) {
00669             SetThrottle(s.throttle_val_off);
00670         }
00671 
00672     }
00673 
00674         if (left==-1)  // Let's try to calculate the expected battery time left
00675         {
00676        timeval tv;
00677        gettimeofday(&tv, 0);
00678        left=calcBatteryTime(((powered)?100-val:val), tv.tv_sec, oldpowered!=powered );
00679         }
00680 
00681     if (timer && oldpowered != powered) {
00682         need_wait = 0;
00683         saved_brightness = 0;
00684             saved_throttle = 0;
00685             saved_performance = 0;
00686         autoLock.setLoadAverage(s.lav_enabled[powered?0:1], s.lav_val[powered?0:1]);
00687         if (power_time != s.power_wait[powered?0:1]) {
00688             power_time = s.power_wait[powered?0:1];
00689             autoLock.stop();
00690             autoLock.setTimeout(power_time);
00691             autoLock.start();
00692         }
00693     }
00694     if (!knownFullyCharged) {
00695         knownFullyCharged = 1;
00696     } else
00697     if (s.notifyMeWhenFull && oldval != val && val == 100)
00698         KMessageBox::queuedMessageBox(0, KMessageBox::Information, i18n("Your battery is now fully charged."), i18n("Laptop Battery"));
00699     changed =  oldpowered != powered||oldexists != s.exists||oldval != val || oldleft!=left;
00700     oldpowered = powered;
00701     oldexists = s.exists;
00702     oldval = val;
00703     oldleft = left;
00704     if (changed)
00705         displayPixmap();
00706 }
00707 
00708 void laptop_daemon::start_monitor()
00709 {
00710     checkBatteryNow();
00711     displayPixmap();
00712     oldTimer = startTimer(s.poll * 1000);
00713 }
00714 
00715 void laptop_daemon::setPollInterval(const int interval)
00716 {
00717         s.poll = interval;
00718 
00719         // Kill any old timers that may be running
00720         if (oldTimer > 0) {
00721                 killTimer(oldTimer);
00722 
00723                 // Start a new timer will the specified time
00724                 oldTimer = startTimer(interval * 1000);
00725 
00726                 emit(signal_checkBattery());
00727         }
00728 }
00729 
00730 void laptop_daemon::timerEvent(QTimerEvent *)
00731 {
00732         emit(signal_checkBattery());
00733 }
00734 
00735 void laptop_daemon::displayPixmap()
00736 {
00737     if (s.have_time == 2 && s.exists && !powered) {     // in some circumstances
00738         s.have_time = (val < 0 ? 0 : 1);            // the battery is not charging
00739         KConfig *config = new KConfig("kcmlaptoprc");
00740         if (config) {
00741             config->setGroup("BatteryLow");         // we can;t figure this out 'till
00742             config->writeEntry("HaveTime", s.have_time);
00743             config->sync();
00744             delete config;
00745         }
00746     }
00747 
00748     if (dock_widget)
00749         dock_widget->displayPixmap();
00750 
00751     if (left >= 0) {
00752             if (!triggered[0]) {
00753                 if (s.time_based_action_low) {
00754                     if (s.exists && !powered && left <= s.low[0]) {
00755                         triggered[0] = 1;
00756                         haveBatteryLow(0, left, 0);
00757                     }
00758                 } else {
00759                     if (s.exists && !powered && val <= s.low[1]) {
00760                         triggered[0] = 1;
00761                         haveBatteryLow(0, val, 0);
00762                     }
00763                 }
00764             }
00765             if (!triggered[1]) {
00766                 if (s.time_based_action_critical) {
00767                     if (s.exists && !powered && left <= s.low[2]) {
00768                         triggered[1] = 1;
00769                         haveBatteryLow(1, left, 0);
00770                     }
00771                 } else {
00772                     if (s.exists && !powered && val <= s.low[3]) {
00773                         triggered[1] = 1;
00774                         haveBatteryLow(1, val, 0);
00775                     }
00776                 }
00777             }
00778         }
00779 
00780         if (s.time_based_action_low || s.time_based_action_critical) {
00781             if (left > (s.low[2]+1))
00782                 triggered[1] = 0;
00783             if (left > s.low[0])
00784                 triggered[0] = 0;
00785         } else {
00786             if (val > (s.low[3]+1))
00787                 triggered[1] = 0;
00788             if (val > s.low[1])
00789                 triggered[0] = 0;
00790         }
00791 
00792         if (s.have_time != 1) {
00793             if (!triggered[0]) {
00794                 if (s.exists && !powered && val <= s.low[0]) {
00795                     triggered[0] = 1;
00796                     haveBatteryLow(0, val, 1);
00797                 }
00798             } else {
00799                 if (!triggered[1]) {
00800                     if (s.exists && !powered && val <= s.low[1]) {
00801                         triggered[1] = 1;
00802                         haveBatteryLow(1, val, 1);
00803                     }
00804                 }
00805                 if (val > (s.low[1]+1))
00806                     triggered[1] = 0;
00807                 if (val > s.low[0])
00808                     triggered[0] = 0;
00809             }
00810         }
00811 }
00812 
00813 void laptop_daemon::invokeStandby()
00814 {
00815     laptop_portable::invoke_standby();
00816 }
00817 
00818 void laptop_daemon::invokeSuspend()
00819 {
00820     laptop_portable::invoke_suspend();
00821 }
00822 
00823 void laptop_daemon::invokeHibernate()
00824 {
00825     laptop_portable::invoke_hibernation();
00826 }
00827 
00828 void laptop_daemon::invokeLogout()
00829 {
00830     bool rc = KWorkSpace::requestShutDown(KApplication::ShutdownConfirmNo, KWorkSpace::ShutdownTypeNone, KWorkSpace::ShutdownModeForceNow);
00831     if (!rc)
00832         KMessageBox::sorry(0, i18n("Logout failed."));
00833 }
00834 
00835 void laptop_daemon::invokeShutdown()
00836 {
00837     bool rc = KWorkSpace::requestShutDown(KApplication::ShutdownConfirmNo, KWorkSpace::ShutdownTypeHalt, KWorkSpace::ShutdownModeForceNow);
00838     if (!rc)
00839         KMessageBox::sorry(0, i18n("Shutdown failed."));
00840 }
00841 
00842 /*
00843  * Portions of the following code borrowed with thanks from:
00844  *
00845  * Sony Programmable I/O Control Device driver for VAIO.
00846  * Userspace X11 Daemon Utility
00847  *
00848  * Copyright 2001 Stelian Pop, Alcove
00849  *
00850  * This program is free software; you can redistribute it and/or modify
00851  * it under the terms of the GNU General Public License as published by
00852  * the Free Software Foundation; either version 2, or (at your option)
00853  * any later version.
00854  *
00855  * This program is distributed in the hope that it will be useful,
00856  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00857  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00858  * GNU General Public License for more details.
00859  *
00860  * You should have received a copy of the GNU General Public License
00861  * along with this program; if not, write to the Free Software
00862  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00863  *
00864  */
00865 
00866 
00867 static void simulateButton(Display *disp, int button) {
00868        XTestGrabControl(disp, True);
00869        XTestFakeButtonEvent(disp, button, True, 0);
00870        XTestFakeButtonEvent(disp, button, False, 0);
00871        XSync(disp, False);
00872        XTestGrabControl(disp, False);
00873 }
00874 
00875 static void simulateButtonDown(Display *disp, int button) {
00876        XTestGrabControl(disp, True);
00877        XTestFakeButtonEvent(disp, button, True, 0);
00878        XSync(disp, False);
00879        XTestGrabControl(disp, False);
00880 }
00881 
00882 static void simulateButtonUp(Display *disp, int button) {
00883         XTestGrabControl(disp, True);
00884     XTestFakeButtonEvent(disp, button, False, 0);
00885     XSync(disp, False);
00886     XTestGrabControl(disp, False);
00887 }
00888 
00889 #define SONYPI_EVENT_JOGDIAL_DOWN                1
00890 #define SONYPI_EVENT_JOGDIAL_UP                  2
00891 #define SONYPI_EVENT_JOGDIAL_DOWN_PRESSED        3
00892 #define SONYPI_EVENT_JOGDIAL_UP_PRESSED          4
00893 #define SONYPI_EVENT_JOGDIAL_PRESSED             5
00894 #define SONYPI_EVENT_JOGDIAL_RELEASED            6
00895 
00896 void laptop_daemon::sonyDataReceived()
00897 {
00898     unsigned char event;
00899 
00900     if (::read(sony_fd, &event, sizeof(event)) != sizeof(event))
00901             return;
00902     switch(event) {
00903     case SONYPI_EVENT_JOGDIAL_UP:
00904         if (sony_disp && s.sony_enablescrollbar) {
00905             simulateButton(sony_disp, 4);