summaryrefslogtreecommitdiff
path: root/core/launcher/desktop.cpp
Unidiff
Diffstat (limited to 'core/launcher/desktop.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/desktop.cpp655
1 files changed, 655 insertions, 0 deletions
diff --git a/core/launcher/desktop.cpp b/core/launcher/desktop.cpp
new file mode 100644
index 0000000..d39af25
--- a/dev/null
+++ b/core/launcher/desktop.cpp
@@ -0,0 +1,655 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of 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 "desktop.h"
22#include "info.h"
23#include "launcher.h"
24#include "mrulist.h"
25#include "qcopbridge.h"
26#include "shutdownimpl.h"
27#include "startmenu.h"
28#include "taskbar.h"
29#include "transferserver.h"
30#include "irserver.h"
31#include "packageslave.h"
32
33#include <qpe/applnk.h>
34#include <qpe/mimetype.h>
35#include <qpe/password.h>
36#include <qpe/config.h>
37#include <qpe/power.h>
38#include <qpe/qcopenvelope_qws.h>
39#include <qpe/global.h>
40#ifdef QT_QWS_CUSTOM
41#include "qpe/custom.h"
42#endif
43
44#include <qgfx_qws.h>
45#include <qmainwindow.h>
46#include <qmessagebox.h>
47#include <qtimer.h>
48#include <qwindowsystem_qws.h>
49
50#include <stdlib.h>
51#include <unistd.h>
52
53static Desktop* qpedesktop = 0;
54static int loggedin=0;
55static void login(bool at_poweron)
56{
57 if ( !loggedin ) {
58 Global::terminateBuiltin("calibrate");
59 Password::authenticate(at_poweron);
60 loggedin=1;
61 QCopEnvelope e( "QPE/Desktop", "unlocked()" );
62 }
63}
64
65bool Desktop::screenLocked()
66{
67 return loggedin == 0;
68}
69
70/*
71 Priority is number of alerts that are needed to pop up
72 alert.
73 */
74class DesktopPowerAlerter : public QMessageBox
75{
76public:
77 DesktopPowerAlerter( QWidget *parent, const char *name = 0 )
78 : QMessageBox( tr("Battery Status"), "Low Battery",
79 QMessageBox::Critical,
80 QMessageBox::Ok | QMessageBox::Default,
81 QMessageBox::NoButton, QMessageBox::NoButton,
82 parent, name, FALSE )
83 {
84 currentPriority = INT_MAX;
85 alertCount = 0;
86 }
87
88 void alert( const QString &text, int priority );
89 void hideEvent( QHideEvent * );
90private:
91 int currentPriority;
92 int alertCount;
93};
94
95void DesktopPowerAlerter::alert( const QString &text, int priority )
96{
97 alertCount++;
98 if ( alertCount < priority )
99 return;
100 if ( priority > currentPriority )
101 return;
102 currentPriority = priority;
103 setText( text );
104 show();
105}
106
107
108void DesktopPowerAlerter::hideEvent( QHideEvent *e )
109{
110 QMessageBox::hideEvent( e );
111 alertCount = 0;
112 currentPriority = INT_MAX;
113}
114
115
116
117DesktopApplication::DesktopApplication( int& argc, char **argv, Type t )
118 : QPEApplication( argc, argv, t )
119{
120
121 QTimer *t = new QTimer( this );
122 connect( t, SIGNAL(timeout()), this, SLOT(psTimeout()) );
123 t->start( 10000 );
124 ps = new PowerStatus;
125 pa = new DesktopPowerAlerter( 0 );
126}
127
128
129DesktopApplication::~DesktopApplication()
130{
131 delete ps;
132 delete pa;
133}
134
135
136enum MemState { Unknown, VeryLow, Low, Normal } memstate=Unknown;
137
138#ifdef Q_WS_QWS
139bool DesktopApplication::qwsEventFilter( QWSEvent *e )
140{
141 qpedesktop->checkMemory();
142
143 if ( e->type == QWSEvent::Key ) {
144 QWSKeyEvent *ke = (QWSKeyEvent *)e;
145 if ( !loggedin && ke->simpleData.keycode != Key_F34 )
146 return TRUE;
147 bool press = ke->simpleData.is_press;
148 if ( !keyboardGrabbed() ) {
149 if ( ke->simpleData.keycode == Key_F9 ) {
150 if ( press ) emit datebook();
151 return TRUE;
152 }
153 if ( ke->simpleData.keycode == Key_F10 ) {
154 if ( !press && cardSendTimer ) {
155 emit contacts();
156 delete cardSendTimer;
157 } else if ( press ) {
158 cardSendTimer = new QTimer();
159 cardSendTimer->start( 2000, TRUE );
160 connect( cardSendTimer, SIGNAL( timeout() ), this, SLOT( sendCard() ) );
161 }
162 return TRUE;
163 }
164 /* menu key now opens application menu/toolbar
165 if ( ke->simpleData.keycode == Key_F11 ) {
166 if ( press ) emit menu();
167 return TRUE;
168 }
169 */
170 if ( ke->simpleData.keycode == Key_F12 ) {
171 while( activePopupWidget() )
172 activePopupWidget()->close();
173 if ( press ) emit launch();
174 return TRUE;
175 }
176 if ( ke->simpleData.keycode == Key_F13 ) {
177 if ( press ) emit email();
178 return TRUE;
179 }
180 }
181 if ( ke->simpleData.keycode == Key_F34 ) {
182 if ( press ) emit power();
183 return TRUE;
184 }
185 if ( ke->simpleData.keycode == Key_F35 ) {
186 if ( press ) emit backlight();
187 return TRUE;
188 }
189 if ( ke->simpleData.keycode == Key_F32 ) {
190 if ( press ) QCopEnvelope e( "QPE/Desktop", "startSync()" );
191 return TRUE;
192 }
193 if ( ke->simpleData.keycode == Key_F31 && !ke->simpleData.modifiers ) {
194 if ( press ) emit symbol();
195 return TRUE;
196 }
197 if ( ke->simpleData.keycode == Key_NumLock ) {
198 if ( press ) emit numLockStateToggle();
199 }
200 if ( ke->simpleData.keycode == Key_CapsLock ) {
201 if ( press ) emit capsLockStateToggle();
202 }
203 if ( press )
204 qpedesktop->keyClick();
205 } else {
206 if ( e->type == QWSEvent::Mouse ) {
207 QWSMouseEvent *me = (QWSMouseEvent *)e;
208 static bool up = TRUE;
209 if ( me->simpleData.state&LeftButton ) {
210 if ( up ) {
211 up = FALSE;
212 qpedesktop->screenClick();
213 }
214 } else {
215 up = TRUE;
216 }
217 }
218 }
219
220 return QPEApplication::qwsEventFilter( e );
221}
222#endif
223
224void DesktopApplication::psTimeout()
225{
226 qpedesktop->checkMemory(); // in case no events are being generated
227
228 *ps = PowerStatusManager::readStatus();
229
230 if ( (ps->batteryStatus() == PowerStatus::VeryLow ) ) {
231 pa->alert( tr( "Battery is running very low." ), 6 );
232 }
233
234 if ( ps->batteryStatus() == PowerStatus::Critical ) {
235 pa->alert( tr( "Battery level is critical!\n"
236 "Keep power off until power restored!" ), 1 );
237 }
238
239 if ( ps->backupBatteryStatus() == PowerStatus::VeryLow ) {
240 pa->alert( tr( "The Back-up battery is very low.\nPlease charge the back-up battery." ), 3 );
241 }
242}
243
244
245void DesktopApplication::sendCard()
246{
247 delete cardSendTimer;
248 cardSendTimer = 0;
249 QString card = getenv("HOME");
250 card += "/Applications/addressbook/businesscard.vcf";
251
252 if ( QFile::exists( card ) ) {
253 QCopEnvelope e("QPE/Obex", "send(QString,QString,QString)");
254 QString mimetype = "text/x-vCard";
255 e << tr("business card") << card << mimetype;
256 }
257}
258
259#if defined(QPE_HAVE_MEMALERTER)
260QPE_MEMALERTER_IMPL
261#endif
262
263#if defined(CUSTOM_SOUND_IMPL)
264CUSTOM_SOUND_IMPL
265#endif
266
267//===========================================================================
268
269Desktop::Desktop() :
270 QWidget( 0, 0, WStyle_Tool | WStyle_Customize ),
271 qcopBridge( 0 ),
272 transferServer( 0 ),
273 packageSlave( 0 )
274{
275#ifdef CUSTOM_SOUND_INIT
276 CUSTOM_SOUND_INIT;
277#endif
278
279 qpedesktop = this;
280
281// bg = new Info( this );
282 tb = new TaskBar;
283
284 launcher = new Launcher( 0, 0, WStyle_Customize | QWidget::WGroupLeader );
285
286 connect(launcher, SIGNAL(busy()), tb, SLOT(startWait()));
287 connect(launcher, SIGNAL(notBusy(const QString&)), tb, SLOT(stopWait(const QString&)));
288
289 int displayw = qApp->desktop()->width();
290 int displayh = qApp->desktop()->height();
291
292
293 QSize sz = tb->sizeHint();
294
295 setGeometry( 0, displayh-sz.height(), displayw, sz.height() );
296 tb->setGeometry( 0, displayh-sz.height(), displayw, sz.height() );
297
298 tb->show();
299 launcher->showMaximized();
300 launcher->show();
301 launcher->raise();
302#if defined(QPE_HAVE_MEMALERTER)
303 initMemalerter();
304#endif
305 // start services
306 startTransferServer();
307 (void) new IrServer( this );
308 rereadVolumes();
309
310 packageSlave = new PackageSlave( this );
311 connect(qApp, SIGNAL(volumeChanged(bool)), this, SLOT(rereadVolumes()));
312
313 qApp->installEventFilter( this );
314}
315
316void Desktop::show()
317{
318 login(TRUE);
319 QWidget::show();
320}
321
322Desktop::~Desktop()
323{
324 delete launcher;
325 delete tb;
326 delete qcopBridge;
327 delete transferServer;
328}
329
330bool Desktop::recoverMemory()
331{
332 return tb->recoverMemory();
333}
334
335void Desktop::checkMemory()
336{
337#if defined(QPE_HAVE_MEMALERTER)
338 static bool ignoreNormal=FALSE;
339 static bool existingMessage=FALSE;
340
341 if(existingMessage)
342 return; // don't show a second message while still on first
343
344 existingMessage = TRUE;
345 switch ( memstate ) {
346 case Unknown:
347 break;
348 case Low:
349 memstate = Unknown;
350 if ( recoverMemory() )
351 ignoreNormal = TRUE;
352 else
353 QMessageBox::warning( 0 , "Memory Status",
354 "The memory smacks of shortage. \n"
355 "Please save data. " );
356 break;
357 case Normal:
358 memstate = Unknown;
359 if ( ignoreNormal )
360 ignoreNormal = FALSE;
361 else
362 QMessageBox::information ( 0 , "Memory Status",
363 "There is enough memory again." );
364 break;
365 case VeryLow:
366 memstate = Unknown;
367 QMessageBox::critical( 0 , "Memory Status",
368 "The memory is very low. \n"
369 "Please end this application \n"
370 "immediately." );
371 recoverMemory();
372 }
373 existingMessage = FALSE;
374#endif
375}
376
377static bool isVisibleWindow(int wid)
378{
379 const QList<QWSWindow> &list = qwsServer->clientWindows();
380 QWSWindow* w;
381 for (QListIterator<QWSWindow> it(list); (w=it.current()); ++it) {
382 if ( w->winId() == wid )
383 return !w->isFullyObscured();
384 }
385 return FALSE;
386}
387
388static bool hasVisibleWindow(const QString& clientname)
389{
390 const QList<QWSWindow> &list = qwsServer->clientWindows();
391 QWSWindow* w;
392 for (QListIterator<QWSWindow> it(list); (w=it.current()); ++it) {
393 if ( w->client()->identity() == clientname && !w->isFullyObscured() )
394 return TRUE;
395 }
396 return FALSE;
397}
398
399void Desktop::raiseLauncher()
400{
401 if ( isVisibleWindow(launcher->winId()) )
402 launcher->nextView();
403 else
404 launcher->raise();
405}
406
407void Desktop::executeOrModify(const QString& appLnkFile)
408{
409 AppLnk lnk(MimeType::appsFolderName() + "/" + appLnkFile);
410 if ( lnk.isValid() ) {
411 QCString app = lnk.exec().utf8();
412 Global::terminateBuiltin("calibrate");
413 if ( QCopChannel::isRegistered("QPE/Application/" + app) ) {
414 MRUList::addTask(&lnk);
415 if ( hasVisibleWindow(app) )
416 QCopChannel::send("QPE/Application/" + app, "nextView()");
417 else
418 QCopChannel::send("QPE/Application/" + app, "raise()");
419 } else {
420 lnk.execute();
421 }
422 }
423}
424
425void Desktop::raiseDatebook()
426{
427 executeOrModify("Applications/datebook.desktop");
428}
429
430void Desktop::raiseContacts()
431{
432 executeOrModify("Applications/addressbook.desktop");
433}
434
435void Desktop::raiseMenu()
436{
437 Global::terminateBuiltin("calibrate");
438 tb->startMenu()->launch();
439}
440
441void Desktop::raiseEmail()
442{
443 executeOrModify("Applications/qtmail.desktop");
444}
445
446#if defined(QPE_HAVE_TOGGLELIGHT)
447#include <qpe/config.h>
448
449#include <sys/ioctl.h>
450#include <sys/types.h>
451#include <fcntl.h>
452#include <unistd.h>
453#include <errno.h>
454#include <linux/ioctl.h>
455#include <time.h>
456#endif
457
458static bool blanked=FALSE;
459
460static void blankScreen()
461{
462 if ( !qt_screen ) return;
463 /* Should use a big black window instead.
464 QGfx* g = qt_screen->screenGfx();
465 g->fillRect(0,0,qt_screen->width(),qt_screen->height());
466 delete g;
467 */
468 blanked = TRUE;
469}
470
471static void darkScreen()
472{
473 extern void qpe_setBacklight(int);
474 qpe_setBacklight(0); // force off
475}
476
477
478void Desktop::togglePower()
479{
480 bool wasloggedin = loggedin;
481 loggedin=0;
482 darkScreen();
483 if ( wasloggedin )
484 blankScreen();
485 system("apm --suspend");
486 QWSServer::screenSaverActivate( FALSE );
487 {
488 QCopEnvelope("QPE/Card", "mtabChanged()" ); // might have changed while asleep
489 QCopEnvelope e("QPE/System", "setBacklight(int)");
490 e << -3; // Force on
491 }
492 if ( wasloggedin )
493 login(TRUE);
494 //qcopBridge->closeOpenConnections();
495 //qDebug("called togglePower()!!!!!!");
496}
497
498void Desktop::toggleLight()
499{
500 QCopEnvelope e("QPE/System", "setBacklight(int)");
501 e << -2; // toggle
502}
503
504void Desktop::toggleSymbolInput()
505{
506 tb->toggleSymbolInput();
507}
508
509void Desktop::toggleNumLockState()
510{
511 tb->toggleNumLockState();
512}
513
514void Desktop::toggleCapsLockState()
515{
516 tb->toggleCapsLockState();
517}
518
519void Desktop::styleChange( QStyle &s )
520{
521 QWidget::styleChange( s );
522 int displayw = qApp->desktop()->width();
523 int displayh = qApp->desktop()->height();
524
525 QSize sz = tb->sizeHint();
526
527 tb->setGeometry( 0, displayh-sz.height(), displayw, sz.height() );
528}
529
530void DesktopApplication::shutdown()
531{
532 if ( type() != GuiServer )
533 return;
534 ShutdownImpl *sd = new ShutdownImpl( 0, 0, WDestructiveClose );
535 connect( sd, SIGNAL(shutdown(ShutdownImpl::Type)),
536 this, SLOT(shutdown(ShutdownImpl::Type)) );
537 sd->showMaximized();
538}
539
540void DesktopApplication::shutdown( ShutdownImpl::Type t )
541{
542 switch ( t ) {
543 case ShutdownImpl::ShutdownSystem:
544 execlp("shutdown", "shutdown", "-h", "now", (void*)0);
545 break;
546 case ShutdownImpl::RebootSystem:
547 execlp("shutdown", "shutdown", "-r", "now", (void*)0);
548 break;
549 case ShutdownImpl::RestartDesktop:
550 restart();
551 break;
552 case ShutdownImpl::TerminateDesktop:
553 prepareForTermination(FALSE);
554 quit();
555 break;
556 }
557}
558
559void DesktopApplication::restart()
560{
561 prepareForTermination(TRUE);
562
563#ifdef Q_WS_QWS
564 for ( int fd = 3; fd < 100; fd++ )
565 close( fd );
566#if defined(QT_DEMO_SINGLE_FLOPPY)
567 execl( "/sbin/init", "qpe", 0 );
568#elif defined(QT_QWS_CASSIOPEIA)
569 execl( "/bin/sh", "sh", 0 );
570#else
571 execl( (qpeDir()+"/bin/qpe").latin1(), "qpe", 0 );
572#endif
573 exit(1);
574#endif
575}
576
577void Desktop::startTransferServer()
578{
579 // start qcop bridge server
580 qcopBridge = new QCopBridge( 4243 );
581 if ( !qcopBridge->ok() ) {
582 delete qcopBridge;
583 qcopBridge = 0;
584 }
585 // start transfer server
586 transferServer = new TransferServer( 4242 );
587 if ( !transferServer->ok() ) {
588 delete transferServer;
589 transferServer = 0;
590 }
591 if ( !transferServer || !qcopBridge )
592 startTimer( 2000 );
593}
594
595void Desktop::timerEvent( QTimerEvent *e )
596{
597 killTimer( e->timerId() );
598 startTransferServer();
599}
600
601void Desktop::terminateServers()
602{
603 delete transferServer;
604 delete qcopBridge;
605 transferServer = 0;
606 qcopBridge = 0;
607}
608
609void Desktop::rereadVolumes()
610{
611 Config cfg("Sound");
612 cfg.setGroup("System");
613 touchclick = cfg.readBoolEntry("Touch");
614 keyclick = cfg.readBoolEntry("Key");
615}
616
617void Desktop::keyClick()
618{
619#ifdef CUSTOM_SOUND_KEYCLICK
620 if ( keyclick )
621 CUSTOM_SOUND_KEYCLICK;
622#endif
623}
624
625void Desktop::screenClick()
626{
627#ifdef CUSTOM_SOUND_TOUCH
628 if ( touchclick )
629 CUSTOM_SOUND_TOUCH;
630#endif
631}
632
633void Desktop::soundAlarm()
634{
635#ifdef CUSTOM_SOUND_ALARM
636 CUSTOM_SOUND_ALARM;
637#endif
638}
639
640bool Desktop::eventFilter( QObject *w, QEvent *ev )
641{
642 if ( ev->type() == QEvent::KeyPress ) {
643 QKeyEvent *ke = (QKeyEvent *)ev;
644 if ( ke->key() == Qt::Key_F11 ) { // menu key
645 QWidget *active = qApp->activeWindow();
646 if ( active && active->isPopup() ) {
647 active->close();
648 }
649 raiseMenu();
650 return TRUE;
651 }
652 }
653 return FALSE;
654}
655