summaryrefslogtreecommitdiff
path: root/core/launcher/serverapp.cpp
authorzecke <zecke>2003-08-25 15:00:50 (UTC)
committer zecke <zecke>2003-08-25 15:00:50 (UTC)
commitbf3c4abb9dff716e098f05852d9a3d8ac8cbcb44 (patch) (unidiff)
treef74d4765868000d27c45771573032515ac8db8be /core/launcher/serverapp.cpp
parent292b097e7db25dd231381c5b09307a1fbe81a492 (diff)
downloadopie-bf3c4abb9dff716e098f05852d9a3d8ac8cbcb44.zip
opie-bf3c4abb9dff716e098f05852d9a3d8ac8cbcb44.tar.gz
opie-bf3c4abb9dff716e098f05852d9a3d8ac8cbcb44.tar.bz2
Initial revision
Diffstat (limited to 'core/launcher/serverapp.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/serverapp.cpp617
1 files changed, 617 insertions, 0 deletions
diff --git a/core/launcher/serverapp.cpp b/core/launcher/serverapp.cpp
new file mode 100644
index 0000000..6edaa21
--- a/dev/null
+++ b/core/launcher/serverapp.cpp
@@ -0,0 +1,617 @@
1/**********************************************************************
2** Copyright (C) 2000-2003 Trolltech AS. All rights reserved.
3**
4** This file is part of the Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "serverapp.h"
22
23#include <qtopia/password.h>
24#include <qtopia/config.h>
25#include <qtopia/power.h>
26#include <qtopia/devicebuttonmanager.h>
27#include <qtopia/pluginloader.h>
28
29#ifdef Q_WS_QWS
30#include <qtopia/qcopenvelope_qws.h>
31#endif
32#include <qtopia/global.h>
33#include <qtopia/custom.h>
34
35#ifdef Q_WS_QWS
36#include <qgfx_qws.h>
37#endif
38#ifdef Q_OS_WIN32
39#include <io.h>
40#include <process.h>
41#else
42#include <unistd.h>
43#endif
44#include <qmessagebox.h>
45#include <qtimer.h>
46#include <qpainter.h>
47#include <qfile.h>
48#include <qpixmapcache.h>
49
50#include <stdlib.h>
51
52static ServerApplication *serverApp = 0;
53static int loggedin=0;
54
55
56
57/* Apply light/power settings for current power source */
58static void applyLightSettings(PowerStatus *p)
59{
60 int initbright, intervalDim, intervalLightOff, intervalSuspend;
61 bool dim, lightoff, suspend;
62
63 {
64 Config config("qpe");
65 bool defsus;
66 if ( p->acStatus() == PowerStatus::Online ) {
67 config.setGroup("ExternalPower");
68 defsus = FALSE;
69 } else {
70 config.setGroup("BatteryPower");
71 defsus = TRUE;
72 }
73
74 intervalDim = config.readNumEntry( "Interval_Dim", 20 );
75 intervalLightOff = config.readNumEntry("Interval_LightOff", 30);
76 intervalSuspend = config.readNumEntry("Interval", 240);
77 initbright = config.readNumEntry("Brightness", 255);
78 dim = config.readBoolEntry("Dim", TRUE);
79 lightoff = config.readBoolEntry("LightOff", FALSE );
80 suspend = config.readBoolEntry("Suspend", defsus );
81
82 /* For compability*/
83 config.setGroup("Screensaver");
84 config.writeEntry( "Dim", dim );
85 config.writeEntry( "LightOff", lightoff );
86 config.writeEntry( "Suspend", suspend );
87 config.writeEntry( "Interval_Dim", intervalDim );
88 config.writeEntry( "Interval_LightOff", intervalLightOff );
89 config.writeEntry( "Interval", intervalSuspend );
90 config.writeEntry( "Brightness", initbright );
91 }
92
93 int i_dim = (dim ? intervalDim : 0);
94 int i_lightoff = (lightoff ? intervalLightOff : 0);
95 int i_suspend = (suspend ? intervalSuspend : 0);
96
97#ifndef QT_NO_COP
98 QCopEnvelope eB("QPE/System", "setBacklight(int)" );
99 eB << initbright;
100
101 QCopEnvelope e("QPE/System", "setScreenSaverIntervals(int,int,int)" );
102 e << i_dim << i_lightoff << i_suspend;
103#endif
104}
105
106//---------------------------------------------------------------------------
107
108/*
109 Priority is number of alerts that are needed to pop up
110 alert.
111 */
112class DesktopPowerAlerter : public QMessageBox
113{
114 Q_OBJECT
115public:
116 DesktopPowerAlerter( QWidget *parent, const char *name = 0 )
117 : QMessageBox( tr("Battery Status"), tr("Low Battery"),
118 QMessageBox::Critical,
119 QMessageBox::Ok | QMessageBox::Default,
120 QMessageBox::NoButton, QMessageBox::NoButton,
121 parent, name, FALSE )
122 {
123 currentPriority = INT_MAX;
124 alertCount = 0;
125 }
126
127 void alert( const QString &text, int priority );
128 void hideEvent( QHideEvent * );
129private:
130 int currentPriority;
131 int alertCount;
132};
133
134void DesktopPowerAlerter::alert( const QString &text, int priority )
135{
136 alertCount++;
137 if ( alertCount < priority )
138 return;
139 if ( priority > currentPriority )
140 return;
141 currentPriority = priority;
142 setText( text );
143 show();
144}
145
146
147void DesktopPowerAlerter::hideEvent( QHideEvent *e )
148{
149 QMessageBox::hideEvent( e );
150 alertCount = 0;
151 currentPriority = INT_MAX;
152}
153
154//---------------------------------------------------------------------------
155
156KeyFilter::KeyFilter(QObject* parent) : QObject(parent), held_tid(0), heldButton(0)
157{
158 qwsServer->setKeyboardFilter(this);
159}
160
161void KeyFilter::timerEvent(QTimerEvent* e)
162{
163 if ( e->timerId() == held_tid ) {
164 killTimer(held_tid);
165 // button held
166 if ( heldButton ) {
167 emit activate(heldButton, TRUE);
168 heldButton = 0;
169 }
170 held_tid = 0;
171 }
172}
173
174bool KeyFilter::filter(int /*unicode*/, int keycode, int modifiers, bool press,
175 bool autoRepeat)
176{
177 if ( !loggedin
178 // Permitted keys
179 && keycode != Key_F34 // power
180 && keycode != Key_F30 // select
181 && keycode != Key_Enter
182 && keycode != Key_Return
183 && keycode != Key_Space
184 && keycode != Key_Left
185 && keycode != Key_Right
186 && keycode != Key_Up
187 && keycode != Key_Down )
188 return TRUE;
189 if ( !modifiers ) {
190 if ( !((ServerApplication*)qApp)->keyboardGrabbed() ) {
191 // First check to see if DeviceButtonManager knows something about this button:
192 const DeviceButton* button = DeviceButtonManager::instance().buttonForKeycode(keycode);
193 if (button && !autoRepeat) {
194 if ( held_tid ) {
195 killTimer(held_tid);
196 held_tid = 0;
197 }
198 if ( button->heldAction().isNull() ) {
199 if ( press )
200 emit activate(button, FALSE);
201 } else if ( press ) {
202 heldButton = button;
203 held_tid = startTimer(500);
204 } else if ( heldButton ) {
205 heldButton = 0;
206 emit activate(button, FALSE);
207 }
208 QWSServer::screenSaverActivate(FALSE);
209 return TRUE;
210 }
211 }
212 if ( keycode == Key_F34 ) {
213 if ( press ) emit power();
214 return TRUE;
215 }
216 if ( keycode == Key_F35 ) {
217 if ( press ) emit backlight();
218 return TRUE;
219 }
220 if ( keycode == Key_F32 ) {
221#ifndef QT_NO_COP
222 if ( press ) QCopEnvelope e( "QPE/Desktop", "startSync()" );
223#endif
224 return TRUE;
225 }
226 if ( keycode == Key_F31 ) {
227 if ( press ) emit symbol();
228 QWSServer::screenSaverActivate(FALSE);
229 return TRUE;
230 }
231 }
232 if ( keycode == Key_NumLock ) {
233 if ( press ) emit numLockStateToggle();
234 }
235 if ( keycode == Key_CapsLock ) {
236 if ( press ) emit capsLockStateToggle();
237 }
238 if ( serverApp )
239 serverApp->keyClick(keycode,press,autoRepeat);
240 return FALSE;
241}
242
243enum MemState { MemUnknown, MemVeryLow, MemLow, MemNormal } memstate=MemUnknown;
244
245#if defined(QPE_HAVE_MEMALERTER)
246QPE_MEMALERTER_IMPL
247#endif
248
249#if defined(CUSTOM_SOUND_IMPL)
250CUSTOM_SOUND_IMPL
251#endif
252
253//---------------------------------------------------------------------------
254
255bool ServerApplication::doRestart = FALSE;
256bool ServerApplication::allowRestart = TRUE;
257
258ServerApplication::ServerApplication( int& argc, char **argv, Type t )
259 : QPEApplication( argc, argv, t )
260{
261#ifdef CUSTOM_SOUND_INIT
262 CUSTOM_SOUND_INIT;
263#endif
264
265#if defined(QPE_HAVE_MEMALERTER)
266 initMemalerter();
267#endif
268
269 // We know we'll have lots of cached pixmaps due to App/DocLnks
270 QPixmapCache::setCacheLimit(512);
271
272 QTimer *timer = new QTimer( this );
273 connect( timer, SIGNAL(timeout()), this, SLOT(psTimeout()) );
274 timer->start( 10000 );
275 ps = new PowerStatus;
276 pa = new DesktopPowerAlerter( 0 );
277
278 applyLightSettings(ps);
279
280 if ( PluginLoader::inSafeMode() )
281 QTimer::singleShot(500, this, SLOT(showSafeMode()) );
282 QTimer::singleShot(20*1000, this, SLOT(clearSafeMode()) );
283
284 KeyFilter* kf = new KeyFilter(this);
285
286 connect( kf, SIGNAL(launch()), this, SIGNAL(launch()) );
287 connect( kf, SIGNAL(power()), this, SIGNAL(power()) );
288 connect( kf, SIGNAL(backlight()), this, SIGNAL(backlight()) );
289 connect( kf, SIGNAL(symbol()), this, SIGNAL(symbol()));
290 connect( kf, SIGNAL(numLockStateToggle()), this,SIGNAL(numLockStateToggle()));
291 connect( kf, SIGNAL(capsLockStateToggle()), this,SIGNAL(capsLockStateToggle()));
292 connect( kf, SIGNAL(activate(const DeviceButton*,bool)), this,SIGNAL(activate(const DeviceButton*,bool)));
293
294 connect( kf, SIGNAL(power()), this, SLOT(togglePower()) );
295 connect( kf, SIGNAL(backlight()), this, SLOT(toggleLight()) );
296
297 connect( this, SIGNAL(volumeChanged(bool)), this, SLOT(rereadVolumes()) );
298 rereadVolumes();
299
300 serverApp = this;
301}
302
303
304ServerApplication::~ServerApplication()
305{
306 delete ps;
307 delete pa;
308}
309
310bool ServerApplication::screenLocked()
311{
312 return loggedin == 0;
313}
314
315void ServerApplication::login(bool at_poweron)
316{
317 if ( !loggedin ) {
318 Global::terminateBuiltin("calibrate"); // No tr
319 Password::authenticate(at_poweron);
320 loggedin=1;
321#ifndef QT_NO_COP
322 QCopEnvelope e( "QPE/Desktop", "unlocked()" );
323#endif
324 }
325}
326
327#if defined(QPE_HAVE_TOGGLELIGHT)
328#include <qtopia/config.h>
329
330#include <sys/ioctl.h>
331#include <sys/types.h>
332#include <fcntl.h>
333#include <unistd.h>
334#include <errno.h>
335#include <linux/ioctl.h>
336#include <time.h>
337#endif
338
339static bool blanked=FALSE;
340
341static void blankScreen()
342{
343#ifdef QWS
344 QWidget w(0, 0, Qt::WStyle_Customize | Qt::WStyle_NoBorder | Qt::WStyle_Tool | Qt::WStyle_StaysOnTop | Qt::WPaintUnclipped);
345 w.resize( qt_screen->width(), qt_screen->height() );
346 w.move(0, 0);
347
348 QPainter p(&w);
349 p.fillRect(w.rect(), QBrush(QColor(255,255,255)) );
350 p.end();
351 w.repaint();
352
353 blanked = TRUE;
354#endif
355}
356
357static void darkScreen()
358{
359 qpe_setBacklight(0); // force off
360}
361
362
363void ServerApplication::togglePower()
364{
365 static int haveAPM = -1;
366 if ( haveAPM < 0 ) {
367 if ( QFile::exists( "/proc/apm" ) ) {
368 haveAPM = 1;
369 } else {
370 haveAPM = 0;
371 qWarning( "Cannot suspend - no APM support in kernel" );
372 }
373 }
374
375 if ( haveAPM ) {
376 bool wasloggedin = loggedin;
377 loggedin=0;
378 if ( wasloggedin ) {
379 Config cfg( QPEApplication::qpeDir()+"/etc/Security.conf", Config::File);
380 cfg.setGroup("Passcode");
381 QString passcode = cfg.readEntry("passcode");
382 if ( !passcode.isEmpty() && cfg.readNumEntry("passcode_poweron",0) )
383 blankScreen();
384 }
385
386 system("apm --suspend");
387
388#ifndef QT_NO_COP
389 QWSServer::screenSaverActivate( FALSE );
390 {
391 QCopEnvelope("QPE/Card", "mtabChanged()" ); // might have changed while asleep
392 QCopEnvelope e("QPE/System", "setBacklight(int)");
393 e << -3; // Force on
394 }
395#endif
396 if ( wasloggedin )
397 login(TRUE);
398 }
399
400 //qcopBridge->closeOpenConnections();
401 //qDebug("called togglePower()!!!!!!");
402}
403
404void ServerApplication::toggleLight()
405{
406#ifndef QT_NO_COP
407 QCopEnvelope e("QPE/System", "setBacklight(int)");
408 e << -2; // toggle
409#endif
410}
411
412
413#ifdef Q_WS_QWS
414bool ServerApplication::qwsEventFilter( QWSEvent *e )
415{
416 checkMemory();
417
418 if ( e->type == QWSEvent::Mouse ) {
419 QWSMouseEvent *me = (QWSMouseEvent *)e;
420 static bool up = TRUE;
421 if ( me->simpleData.state&LeftButton ) {
422 if ( up ) {
423 up = FALSE;
424 screenClick(TRUE);
425 }
426 } else if ( !up ) {
427 up = TRUE;
428 screenClick(FALSE);
429 }
430 }
431
432 return QPEApplication::qwsEventFilter( e );
433}
434#endif
435
436void ServerApplication::psTimeout()
437{
438 checkMemory(); // in case no events are being generated
439
440 PowerStatus::ACStatus oldStatus = ps->acStatus();
441
442 *ps = PowerStatusManager::readStatus();
443
444 if ( oldStatus != ps->acStatus() ) {
445 // power source changed, read settings applying to current powersource
446 applyLightSettings(ps);
447 }
448
449
450 if ( (ps->batteryStatus() == PowerStatus::VeryLow ) ) {
451 pa->alert( tr( "Battery is running very low." ), 6 );
452 }
453
454 if ( ps->batteryStatus() == PowerStatus::Critical ) {
455 pa->alert( tr( "Battery level is critical!\n"
456 "Please recharge the main battery!" ), 1 );
457 }
458
459 if ( ps->backupBatteryStatus() == PowerStatus::VeryLow ) {
460 pa->alert( tr( "The Back-up battery is very low.\nPlease charge the back-up battery." ), 3 );
461 }
462}
463
464void ServerApplication::showSafeMode()
465{
466 if ( QMessageBox::warning(0, tr("Safe Mode"), tr("<P>A system startup error occurred, "
467 "and the system is now in Safe Mode. "
468 "Plugins are not loaded in Safe Mode. "
469 "You can use the Plugin Manager to "
470 "disable plugins that cause system error."), tr("OK"), tr("Plugin Manager..."), 0) == 1 ) {
471 Global::execute( "pluginmanager" );
472 }
473}
474
475void ServerApplication::clearSafeMode()
476{
477 // If we've been running OK for a while then we won't bother going into
478 // safe mode immediately on the next crash.
479 Config cfg( "PluginLoader" );
480 cfg.setGroup( "Global" );
481 QString mode = cfg.readEntry( "Mode", "Normal" );
482 if ( mode == "MaybeSafe" ) {
483 cfg.writeEntry( "Mode", "Normal" );
484 }
485}
486
487void ServerApplication::shutdown()
488{
489 if ( type() != GuiServer )
490 return;
491 ShutdownImpl *sd = new ShutdownImpl( 0, 0, WDestructiveClose );
492 connect( sd, SIGNAL(shutdown(ShutdownImpl::Type)),
493 this, SLOT(shutdown(ShutdownImpl::Type)) );
494 sd->showMaximized();
495}
496
497void ServerApplication::shutdown( ShutdownImpl::Type t )
498{
499 switch ( t ) {
500 case ShutdownImpl::ShutdownSystem:
501#ifndef Q_OS_WIN32
502 execlp("shutdown", "shutdown", "-h", "now", (void*)0); // No tr
503#else
504 qDebug("ServerApplication::ShutdownSystem");
505 prepareForTermination(FALSE);
506 quit();
507#endif
508 break;
509
510 case ShutdownImpl::RebootSystem:
511#ifndef Q_OS_WIN32
512 execlp("shutdown", "shutdown", "-r", "now", (void*)0); // No tr
513#else
514 qDebug("ServerApplication::RebootSystem");
515 restart();
516#endif
517 break;
518
519 case ShutdownImpl::RestartDesktop:
520 restart();
521 break;
522
523 case ShutdownImpl::TerminateDesktop:
524 prepareForTermination(FALSE);
525 quit();
526 break;
527 }
528}
529
530void ServerApplication::restart()
531{
532 if ( allowRestart ) {
533 prepareForTermination(TRUE);
534 doRestart = TRUE;
535 quit();
536 }
537}
538
539void ServerApplication::rereadVolumes()
540{
541 Config cfg("Sound");
542 cfg.setGroup("System");
543 touchclick = cfg.readBoolEntry("Touch");
544 keyclick = cfg.readBoolEntry("Key");
545}
546
547
548void ServerApplication::checkMemory()
549{
550#if defined(QPE_HAVE_MEMALERTER)
551 static bool ignoreNormal=TRUE;
552 static bool existingMessage=FALSE;
553
554 if(existingMessage)
555 return; // don't show a second message while still on first
556
557 existingMessage = TRUE;
558 switch ( memstate ) {
559 case MemUnknown:
560 break;
561 case MemLow:
562 memstate = MemUnknown;
563 if ( !recoverMemory() ) {
564 QMessageBox::warning( 0 , tr("Memory Status"),
565 tr("Memory Low\nPlease save data.") );
566 ignoreNormal = FALSE;
567 }
568 break;
569 case MemNormal:
570 memstate = MemUnknown;
571 if ( !ignoreNormal ) {
572 ignoreNormal = TRUE;
573 QMessageBox::information ( 0 , tr("Memory Status"),
574 "Memory OK" );
575 }
576 break;
577 case MemVeryLow:
578 memstate = MemUnknown;
579 QMessageBox::critical( 0 , tr("Memory Status"),
580 tr("Critical Memory Shortage\n"
581 "Please end this application\n"
582 "immediately.") );
583 recoverMemory();
584 }
585 existingMessage = FALSE;
586#endif
587}
588
589bool ServerApplication::recoverMemory()
590{
591 return FALSE;
592}
593
594void ServerApplication::keyClick(int keycode, bool press, bool repeat)
595{
596#ifdef CUSTOM_SOUND_KEYCLICK
597 if ( keyclick )
598 CUSTOM_SOUND_KEYCLICK(keycode,press,repeat);
599#else
600 Q_UNUSED( keycode );
601 Q_UNUSED( press );
602 Q_UNUSED( repeat );
603#endif
604}
605
606void ServerApplication::screenClick(bool press)
607{
608#ifdef CUSTOM_SOUND_TOUCH
609 if ( touchclick )
610 CUSTOM_SOUND_TOUCH(press);
611#else
612 Q_UNUSED( press );
613#endif
614}
615
616
617#include "serverapp.moc"