KUtils
xsyncbasedpoller.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2009 Dario Freddi <drf at kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License version 2 as published by the Free Software Foundation. 00007 00008 This library is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 Library General Public License for more details. 00012 00013 You should have received a copy of the GNU Library General Public License 00014 along with this library; see the file COPYING.LIB. If not, write to 00015 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00016 Boston, MA 02110-1301, USA. 00017 */ 00018 00019 #include "xsyncbasedpoller.h" 00020 00021 #include <QX11Info> 00022 00023 #include <klocalizedstring.h> 00024 #include <kglobal.h> 00025 00026 #include <fixx11h.h> 00027 00028 class XSyncBasedPollerHelper 00029 { 00030 public: 00031 XSyncBasedPollerHelper() : q(0) {} 00032 ~XSyncBasedPollerHelper() { 00033 delete q; 00034 } 00035 XSyncBasedPoller *q; 00036 }; 00037 00038 K_GLOBAL_STATIC(XSyncBasedPollerHelper, s_globalXSyncBasedPoller) 00039 00040 XSyncBasedPoller *XSyncBasedPoller::instance() 00041 { 00042 if (!s_globalXSyncBasedPoller->q) { 00043 new XSyncBasedPoller; 00044 } 00045 00046 return s_globalXSyncBasedPoller->q; 00047 } 00048 00049 XSyncBasedPoller::XSyncBasedPoller(QWidget *parent) 00050 : AbstractSystemPoller(parent) 00051 , m_display(QX11Info::display()) 00052 , m_idleCounter(X::None) 00053 , m_resetAlarm(X::None) 00054 , m_available(true) 00055 { 00056 Q_ASSERT(!s_globalXSyncBasedPoller->q); 00057 s_globalXSyncBasedPoller->q = this; 00058 00059 int sync_major, sync_minor; 00060 int ncounters; 00061 XSyncSystemCounter *counters; 00062 00063 if (!XSyncQueryExtension(m_display, &m_sync_event, &m_sync_error)) { 00064 m_available = false; 00065 return; 00066 } 00067 00068 if (!XSyncInitialize(m_display, &sync_major, &sync_minor)) { 00069 m_available = false; 00070 return; 00071 } 00072 00073 kDebug() << sync_major << sync_minor; 00074 00075 counters = XSyncListSystemCounters(m_display, &ncounters); 00076 00077 bool idleFound = false; 00078 00079 for (int i = 0; i < ncounters; ++i) { 00080 if (!strcmp(counters[i].name, "IDLETIME")) { 00081 m_idleCounter = counters[i].counter; 00082 idleFound = true; 00083 break; 00084 } 00085 } 00086 00087 XSyncFreeSystemCounterList(counters); 00088 00089 if (!idleFound) { 00090 m_available = false; 00091 } 00092 00093 if (m_available) { 00094 kDebug() << "XSync seems available and ready"; 00095 } else { 00096 kDebug() << "XSync seems not available"; 00097 } 00098 } 00099 00100 XSyncBasedPoller::~XSyncBasedPoller() 00101 { 00102 } 00103 00104 bool XSyncBasedPoller::isAvailable() 00105 { 00106 return m_available; 00107 } 00108 00109 bool XSyncBasedPoller::setUpPoller() 00110 { 00111 if (!isAvailable()) { 00112 return false; 00113 } 00114 00115 kDebug() << "XSync Inited"; 00116 00117 KApplication::kApplication()->installX11EventFilter(this); 00118 00119 kDebug() << "Supported, init completed"; 00120 00121 return true; 00122 } 00123 00124 void XSyncBasedPoller::unloadPoller() 00125 { 00126 } 00127 00128 void XSyncBasedPoller::addTimeout(int nextTimeout) 00129 { 00130 /* We need to set the counter to the idle time + the value 00131 * requested for next timeout 00132 */ 00133 00134 // If there's already an alarm for the requested timeout, skip 00135 if (m_timeoutAlarm.contains(nextTimeout)) { 00136 return; 00137 } 00138 00139 XSyncValue timeout; 00140 XSyncAlarm newalarm = X::None; 00141 00142 XSyncIntToValue(&timeout, nextTimeout); 00143 00144 setAlarm(m_display, &newalarm, m_idleCounter, 00145 XSyncPositiveComparison, timeout); 00146 00147 m_timeoutAlarm.insert(nextTimeout, newalarm); 00148 } 00149 00150 int XSyncBasedPoller::forcePollRequest() 00151 { 00152 return poll(); 00153 } 00154 00155 int XSyncBasedPoller::poll() 00156 { 00157 XSyncValue idleTime; 00158 XSyncQueryCounter(m_display, m_idleCounter, &idleTime); 00159 00160 return XSyncValueLow32(idleTime); 00161 } 00162 00163 void XSyncBasedPoller::removeTimeout(int timeout) 00164 { 00165 if (m_timeoutAlarm.contains(timeout)) { 00166 XSyncAlarm a = m_timeoutAlarm[timeout]; 00167 XSyncDestroyAlarm(m_display, a); 00168 m_timeoutAlarm.remove(timeout); 00169 } 00170 } 00171 00172 QList<int> XSyncBasedPoller::timeouts() const 00173 { 00174 return m_timeoutAlarm.keys(); 00175 } 00176 00177 void XSyncBasedPoller::stopCatchingIdleEvents() 00178 { 00179 if (m_resetAlarm != X::None) { 00180 XSyncDestroyAlarm(m_display, m_resetAlarm); 00181 m_resetAlarm = X::None; 00182 } 00183 } 00184 00185 void XSyncBasedPoller::catchIdleEvent() 00186 { 00187 XSyncValue idleTime; 00188 00189 XSyncQueryCounter(m_display, m_idleCounter, &idleTime); 00190 00191 /* Set the reset alarm to fire the next time idleCounter < the 00192 * current counter value. XSyncNegativeComparison means <= so 00193 * we have to subtract 1 from the counter value 00194 */ 00195 00196 //NOTE: this must be a int, else compilation might fail 00197 int overflow; 00198 XSyncValue add; 00199 XSyncValue plusone; 00200 XSyncIntToValue(&add, -1); 00201 XSyncValueAdd(&plusone, idleTime, add, &overflow); 00202 setAlarm(m_display, &m_resetAlarm, m_idleCounter, 00203 XSyncNegativeComparison, plusone); 00204 } 00205 00206 void XSyncBasedPoller::reloadAlarms() 00207 { 00208 XSyncValue timeout; 00209 00210 for (QHash<int, XSyncAlarm>::iterator i = m_timeoutAlarm.begin(); i != m_timeoutAlarm.end(); ++i) { 00211 XSyncIntToValue(&timeout, i.key()); 00212 00213 setAlarm(m_display, &(i.value()), m_idleCounter, 00214 XSyncPositiveComparison, timeout); 00215 } 00216 } 00217 00218 bool XSyncBasedPoller::x11Event(XEvent *event) 00219 { 00220 XSyncAlarmNotifyEvent *alarmEvent; 00221 00222 if (event->type != m_sync_event + XSyncAlarmNotify) { 00223 return false; 00224 } 00225 00226 alarmEvent = (XSyncAlarmNotifyEvent *)event; 00227 00228 if (alarmEvent->state == XSyncAlarmDestroyed) { 00229 return false; 00230 } 00231 00232 for (QHash<int, XSyncAlarm>::const_iterator i = m_timeoutAlarm.constBegin(); i != m_timeoutAlarm.constEnd(); ++i) { 00233 if (alarmEvent->alarm == i.value()) { 00234 /* Bling! Caught! */ 00235 emit timeoutReached(i.key()); 00236 // Update the alarm to fire back if the system gets inactive for the same time 00237 catchIdleEvent(); 00238 return false; 00239 } 00240 } 00241 00242 if (alarmEvent->alarm == m_resetAlarm) { 00243 /* Resuming from idle here! */ 00244 stopCatchingIdleEvents(); 00245 reloadAlarms(); 00246 emit resumingFromIdle(); 00247 } 00248 00249 return false; 00250 } 00251 00252 void XSyncBasedPoller::setAlarm(Display *dpy, XSyncAlarm *alarm, XSyncCounter counter, 00253 XSyncTestType test, XSyncValue value) 00254 { 00255 XSyncAlarmAttributes attr; 00256 XSyncValue delta; 00257 unsigned int flags; 00258 00259 XSyncIntToValue(&delta, 0); 00260 00261 attr.trigger.counter = counter; 00262 attr.trigger.value_type = XSyncAbsolute; 00263 attr.trigger.test_type = test; 00264 attr.trigger.wait_value = value; 00265 attr.delta = delta; 00266 00267 flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType | 00268 XSyncCAValue | XSyncCADelta; 00269 00270 if (*alarm) { 00271 XSyncChangeAlarm(dpy, *alarm, flags, &attr); 00272 } else { 00273 *alarm = XSyncCreateAlarm(dpy, flags, &attr); 00274 } 00275 } 00276 00277 void XSyncBasedPoller::simulateUserActivity() 00278 { 00279 XResetScreenSaver(QX11Info::display()); 00280 } 00281 00282 #include "xsyncbasedpoller.moc"
KDE 4.6 API Reference