author | schurig <schurig> | 2004-09-10 12:18:17 (UTC) |
---|---|---|
committer | schurig <schurig> | 2004-09-10 12:18:17 (UTC) |
commit | 9d0ccc1c5ca687bc017b2b515a9d3a47e98ce521 (patch) (side-by-side diff) | |
tree | 53927c6a19c69d54bb3d0e092ac57180bcb60222 | |
parent | ed70ec4945c7816ec6e899207ec8b99e20e10da5 (diff) | |
download | opie-9d0ccc1c5ca687bc017b2b515a9d3a47e98ce521.zip opie-9d0ccc1c5ca687bc017b2b515a9d3a47e98ce521.tar.gz opie-9d0ccc1c5ca687bc017b2b515a9d3a47e98ce521.tar.bz2 |
added support for DEVFS
-rw-r--r-- | core/applets/vmemo/vmemo.cpp | 10 | ||||
-rw-r--r-- | core/applets/vtapplet/vt.cpp | 8 | ||||
-rw-r--r-- | libopie/odevice.cpp | 4 | ||||
-rw-r--r-- | libopie2/opiemm/osoundsystem.cpp | 5 | ||||
-rw-r--r-- | library/qpeapplication.cpp | 16 |
5 files changed, 40 insertions, 3 deletions
diff --git a/core/applets/vmemo/vmemo.cpp b/core/applets/vmemo/vmemo.cpp index e747a19..07ef15c 100644 --- a/core/applets/vmemo/vmemo.cpp +++ b/core/applets/vmemo/vmemo.cpp @@ -1,665 +1,669 @@ /************************************************************************************ ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ************************************************************************************/ // copyright 2002 Jeremy Cowgar <jc@cowgar.com> // copyright 2002 and 2003 L.J.Potter <ljp@llornkcor.com> /* OPIE */ #include <opie2/odebug.h> using namespace Opie::Core; extern "C" { #include "adpcm.h" } #include <unistd.h> #include <stdio.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/soundcard.h> #include <errno.h> typedef struct _waveheader { u_long main_chunk; /* 'RIFF' */ u_long length; /* filelen */ u_long chunk_type; /* 'WAVE' */ u_long sub_chunk; /* 'fmt ' */ u_long sc_len; /* length of sub_chunk, =16 (chunckSize) format len */ u_short format; /* should be 1 for PCM-code (formatTag) */ u_short modus; /* 1 Mono, 2 Stereo (channels) */ u_long sample_fq; /* samples per second (samplesPerSecond) */ u_long byte_p_sec; /* avg bytes per second (avgBytePerSecond) */ u_short byte_p_spl; /* samplesize; 1 or 2 bytes (blockAlign) */ u_short bit_p_spl; /* 8, 12 or 16 bit (bitsPerSample) */ u_long data_chunk; /* 'data' */ u_long data_length;/* samplecount */ } WaveHeader; #define RIFF 0x46464952 #define WAVE 0x45564157 #define FMT 0x20746D66 #define DATA 0x61746164 #define PCM_CODE 1 #define WAVE_MONO 1 #define WAVE_STEREO 2 struct adpcm_state encoder_state; //struct adpcm_state decoder_state; #define WAVE_FORMAT_DVI_ADPCM (0x0011) #define WAVE_FORMAT_PCM (0x0001) #include "vmemo.h" #include <opie2/otaskbarapplet.h> #include <qpe/qpeapplication.h> #include <qpe/config.h> #include <qpainter.h> #include <qmessagebox.h> int seq = 0; /* XPM */ static char * vmemo_xpm[] = { "16 16 102 2", " c None", ". c #60636A", "+ c #6E6E72", "@ c #68696E", "# c #4D525C", "$ c #6B6C70", "% c #E3E3E8", "& c #EEEEF2", "* c #EAEAEF", "= c #CACAD0", "- c #474A51", "; c #171819", "> c #9B9B9F", ", c #EBEBF0", "' c #F4F4F7", ") c #F1F1F5", "! c #DEDEE4", "~ c #57575C", "{ c #010101", "] c #A2A2A6", "^ c #747477", "/ c #B5B5B8", "( c #AEAEB2", "_ c #69696D", ": c #525256", "< c #181C24", "[ c #97979B", "} c #A7A7AC", "| c #B0B0B4", "1 c #C8C8D1", "2 c #75757B", "3 c #46464A", "4 c #494A4F", "5 c #323234", "6 c #909095", "7 c #39393B", "8 c #757578", "9 c #87878E", "0 c #222224", "a c #414144", "b c #6A6A6E", "c c #020C16", "d c #6B6B6F", "e c #68686D", "f c #5B5B60", "g c #8A8A8F", "h c #6B6B6E", "i c #ADADB2", "j c #828289", "k c #3E3E41", "l c #CFCFD7", "m c #4C4C50", "n c #000000", "o c #66666A", "p c #505054", "q c #838388", "r c #A1A1A7", "s c #A9A9AE", "t c #A8A8B0", "u c #5E5E63", "v c #3A3A3E", "w c #BDBDC6", "x c #59595E", "y c #76767C", "z c #373738", "A c #717174", "B c #727278", "C c #1C1C1E", "D c #3C3C3F", "E c #ADADB6", "F c #54555A", "G c #8B8C94", "H c #5A5A5F", "I c #BBBBC3", "J c #C4C4CB", "K c #909098", "L c #737379", "M c #343437", "N c #8F8F98", "O c #000407", "P c #2D3137", "Q c #B0B1BC", "R c #3B3C40", "S c #6E6E74", "T c #95959C", "U c #74747A", "V c #1D1D1E", "W c #91929A", "X c #42444A", "Y c #22282E", "Z c #B0B2BC", "` c #898A90", " . c #65656A", ".. c #999AA2", "+. c #52535A", "@. c #151B21", "#. c #515257", "$. c #B5B5BE", "%. c #616167", "&. c #1A1D22", "*. c #000713", "=. c #1F1F21", " ", " . + @ # ", " $ % & * = - ", " ; > , ' ) ! ~ ", " { ] ^ / ( _ : ", " < [ } | 1 2 3 ", " 4 5 6 7 8 9 0 a b c ", " d e f g h i j 3 k l m n ", " o p q r s t u v w n ", " o x y z A B C D E n ", " F G H I J K L M N O ", " P Q R S T U V W X ", " Y Z ` b ...+. ", " @.#.$.%.&. ", " *.B =. ", " n n n n n n n n n "}; using namespace Opie::Ui; VMemo::VMemo( QWidget *parent, const char *_name ) : QWidget( parent, _name ) { setFixedHeight( 18 ); setFixedWidth( 14 ); t_timer = new QTimer( this ); connect( t_timer, SIGNAL( timeout() ), SLOT( timerBreak() ) ); Config vmCfg("Vmemo"); vmCfg.setGroup("Defaults"); int toggleKey = setToggleButton(vmCfg.readNumEntry("toggleKey", -1)); useADPCM = vmCfg.readBoolEntry("use_ADPCM", 0); odebug << "toggleKey " << toggleKey << "" << oendl; // if ( QFile::exists ( "/dev/sharp_buz" ) || QFile::exists ( "/dev/sharp_led" )) // systemZaurus=TRUE; // else systemZaurus = FALSE; myChannel = new QCopChannel( "QPE/VMemo", this ); connect( myChannel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(receive(const QCString&,const QByteArray&)) ); if( toggleKey != -1 ) { odebug << "Register key " << toggleKey << "" << oendl; QCopEnvelope e("QPE/Launcher", "keyRegister(int,QCString,QCString)"); // e << 4096; // Key_Escape // e << Key_F5; //4148 e << toggleKey; e << QString("QPE/VMemo"); e << QString("toggleRecord()"); } if(toggleKey == 1) usingIcon = TRUE; else usingIcon = FALSE; // if( vmCfg.readNumEntry("hideIcon",0) == 1) if (!usingIcon) hide(); recording = FALSE; // } } VMemo::~VMemo() { } int VMemo::position() { return 6; } void VMemo::receive( const QCString &msg, const QByteArray &data ) { odebug << "Vmemo receive" << oendl; QDataStream stream( data, IO_ReadOnly ); if (msg == "toggleRecord()") { if (recording) { fromToggle = TRUE; stopRecording(); } else { fromToggle = TRUE; startRecording(); } } } void VMemo::paintEvent( QPaintEvent* ) { QPainter p(this); p.drawPixmap( 0, 1,( const char** ) vmemo_xpm ); } void VMemo::mousePressEvent( QMouseEvent * /*me*/) { /* No mousePress/mouseRelease recording on the iPAQ. The REC button on the iPAQ calls these functions mousePressEvent and mouseReleaseEvent with a NULL parameter. */ // if (!systemZaurus && me != NULL) // return; // } if(!recording) startRecording(); else stopRecording(); } void VMemo::mouseReleaseEvent( QMouseEvent * ) { } bool VMemo::startRecording() { Config config( "Vmemo" ); config.setGroup( "System" ); useAlerts = config.readBoolEntry("Alert",1); if(useAlerts) { msgLabel = new QLabel( 0, "alertLabel" ); msgLabel->setText("<B><P><font size=+2>VMemo-Recording</font></B>"); msgLabel->show(); } odebug << "Start recording engines" << oendl; recording = TRUE; if (openDSP() == -1) { recording = FALSE; return FALSE; } config.setGroup("Defaults"); date = TimeString::dateString( QDateTime::currentDateTime(),false,true); date.replace(QRegExp("'"),""); date.replace(QRegExp(" "),"_"); date.replace(QRegExp(":"),"-"); date.replace(QRegExp(","),""); QString fName; config.setGroup( "System" ); fName = QPEApplication::documentDir() ; fileName = config.readEntry("RecLocation", fName); int s; s=fileName.find(':'); if(s) fileName=fileName.right(fileName.length()-s-2); odebug << "pathname will be "+fileName << oendl; if( fileName.left(1).find('/') == -1) fileName="/"+fileName; if( fileName.right(1).find('/') == -1) fileName+="/"; fName = "vm_"+ date + ".wav"; fileName+=fName; odebug << "filename is " + fileName << oendl; // open tmp file here char *pointer; pointer=tmpnam(NULL); odebug << "Opening tmp file " << pointer << "" << oendl; if(openWAV(pointer ) == -1) { QString err("Could not open the temp file\n"); err += fileName; QMessageBox::critical(0, "vmemo", err, "Abort"); ::close(dsp); return FALSE; } if( record() ) { QString cmd; if( fileName.find(".wav",0,TRUE) == -1) fileName += ".wav"; cmd.sprintf("mv %s "+fileName, pointer); // move tmp file to regular file here system(cmd.latin1()); QArray<int> cats(1); cats[0] = config.readNumEntry("Category", 0); QString dlName("vm_"); dlName += date; DocLnk l; l.setFile(fileName); l.setName(dlName); l.setType("audio/x-wav"); l.setCategories(cats); l.writeLink(); return TRUE; } else return FALSE; } void VMemo::stopRecording() { // show(); odebug << "Stopped recording" << oendl; recording = FALSE; if(useAlerts) { msgLabel->close(); msgLabel=0; delete msgLabel; } t_timer->stop(); Config cfg("Vmemo"); cfg.setGroup("Defaults"); // if( cfg.readNumEntry("hideIcon",0) == 1 ) // hide(); } int VMemo::openDSP() { Config cfg("Vmemo"); cfg.setGroup("Record"); speed = cfg.readNumEntry("SampleRate", 22050); channels = cfg.readNumEntry("Stereo", 1) ? 2 : 1; // 1 = stereo(2), 0 = mono(1) if (cfg.readNumEntry("SixteenBit", 1)==1) { format = AFMT_S16_LE; resolution = 16; } else { format = AFMT_U8; resolution = 8; } odebug << "samplerate: " << speed << ", channels " << channels << ", resolution " << resolution << "" << oendl; if(systemZaurus) { dsp = open("/dev/dsp1", O_RDONLY); //Zaurus needs /dev/dsp1 channels=1; //zaurus has one input channel } else { +#ifdef QT_QWS_DEVFS + dsp = open("/dev/sound/dsp", O_RDONLY); +#else dsp = open("/dev/dsp", O_RDONLY); +#endif } - if(dsp == -1) { + if (dsp == -1) { msgLabel->close(); msgLabel=0; delete msgLabel; perror("open(\"/dev/dsp\")"); errorMsg="open(\"/dev/dsp\")\n "+(QString)strerror(errno); - QMessageBox::critical(0, "vmemo", errorMsg, "Abort"); - return -1; + QMessageBox::critical(0, "vmemo", errorMsg, "Abort"); + return -1; } if(ioctl(dsp, SNDCTL_DSP_SETFMT , &format)==-1) { perror("ioctl(\"SNDCTL_DSP_SETFMT\")"); return -1; } if(ioctl(dsp, SNDCTL_DSP_CHANNELS , &channels)==-1) { perror("ioctl(\"SNDCTL_DSP_CHANNELS\")"); return -1; } if(ioctl(dsp, SNDCTL_DSP_SPEED , &speed)==-1) { perror("ioctl(\"SNDCTL_DSP_SPEED\")"); return -1; } if(ioctl(dsp, SOUND_PCM_READ_RATE , &rate)==-1) { perror("ioctl(\"SOUND_PCM_READ_RATE\")"); return -1; } QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << FALSE; //mute return 1; } int VMemo::openWAV(const char *filename) { track.setName(filename); if(!track.open(IO_WriteOnly|IO_Truncate|IO_Raw)) { errorMsg=filename; return -1; } wav=track.handle(); Config vmCfg("Vmemo"); vmCfg.setGroup("Defaults"); useADPCM = vmCfg.readBoolEntry("use_ADPCM", 0); WaveHeader wh; wh.main_chunk = RIFF; wh.length=0; wh.chunk_type = WAVE; wh.sub_chunk = FMT; wh.sc_len = 16; if(useADPCM) wh.format = WAVE_FORMAT_DVI_ADPCM;//PCM_CODE; else wh.format = PCM_CODE; wh.modus = channels; wh.sample_fq = speed; wh.byte_p_sec = speed * channels * resolution/8; wh.byte_p_spl = channels * (resolution / 8); wh.bit_p_spl = resolution; wh.data_chunk = DATA; wh.data_length= 0; // odebug << "Write header channels " << wh.modus << ", speed " << wh.sample_fq << ", b/s " // << wh.byte_p_sec << ", blockalign " << wh.byte_p_spl << ", bitrate " << wh.bit_p_spl << oendl; write (wav, &wh, sizeof(WaveHeader)); return 1; } bool VMemo::record() { length = 0; int bytesWritten = 0; int result = 0; int value = 0; QString msg; msg.sprintf("Recording format %d", format); odebug << msg << oendl; Config config("Vmemo"); config.setGroup("Record"); int sRate = config.readNumEntry("SizeLimit", 30); odebug << "VMEMO rate" << sRate << oendl; if(sRate > 0) { t_timer->start( sRate * 1000+1000, TRUE); } msg.sprintf("Recording format other"); odebug << msg << oendl; config.setGroup("Defaults"); useADPCM = config.readBoolEntry("use_ADPCM", 0); int bufsize = config.readNumEntry("BufferSize",1024); unsigned short sound[bufsize]; //, monoBuffer[bufsize]; char abuf[bufsize / 2]; short sbuf[bufsize]; odebug << "ready to record"<< oendl; if(useADPCM) { odebug << "usr ADPCM" << oendl; while(recording) { result = ::read(dsp, sbuf, bufsize); // adpcm read if( result <= 0) { perror("recording error "); QMessageBox::message(tr("Note"),tr("error recording")); recording = FALSE; break; return FALSE; } adpcm_coder( sbuf, abuf, result/2, &encoder_state); bytesWritten = ::write(wav, abuf, result/4); // adpcm write length += bytesWritten; if(length < 0) { recording = false; perror("dev/dsp's is a lookin' messy"); QMessageBox::message("Vmemo","Error writing to file\n"+ fileName); break; return FALSE; } printf("%d\r", length); fflush(stdout); qApp->processEvents(); } } else { odebug << "use regular wav" << oendl; while(recording) { result = ::read(dsp, sound, bufsize); // read if( result <= 0) { perror("recording error "); QMessageBox::message(tr("Note"),tr("error recording")); recording = FALSE; break; return FALSE; } bytesWritten = ::write(wav, sound, result); // write length += bytesWritten; if(length < 0) { recording = false; perror("dev/dsp's is a lookin' messy"); QMessageBox::message("Vmemo","Error writing to file\n"+ fileName); break; return FALSE; } // printf("%d\r", length); // fflush(stdout); qApp->processEvents(); } // odebug << "result is " << result << oendl; } odebug << "file has length of " << length << " lasting " << (( length / speed) / channels) / 2 << " seconds" << oendl; value = length + 36; lseek(wav, 4, SEEK_SET); write(wav, &value, 4); lseek(wav, 40, SEEK_SET); write(wav, &length, 4); track.close(); odebug << "Track closed" << oendl; if( ioctl( dsp, SNDCTL_DSP_RESET,0) == -1) perror("ioctl(\"SNDCTL_DSP_RESET\")"); ::close(dsp); Config cfgO("OpieRec"); cfgO.setGroup("Sounds"); int nFiles = cfgO.readNumEntry( "NumberofFiles",0); QString currentFileName = fileName; QString currentFile = "vm_"+ date; float numberOfRecordedSeconds = (float) length / (float)speed * (float)2; cfgO.writeEntry( "NumberofFiles", nFiles + 1); cfgO.writeEntry( QString::number( nFiles + 1), currentFile); cfgO.writeEntry( currentFile, currentFileName); QString time; time.sprintf("%.2f", numberOfRecordedSeconds); cfgO.writeEntry( currentFileName, time ); // odebug << "writing config numberOfRecordedSeconds "+time << oendl; cfgO.write(); odebug << "done recording "+fileName << oendl; Config cfg("qpe"); cfg.setGroup("Volume"); QString foo = cfg.readEntry("Mute","TRUE"); if(foo.find("TRUE",0,TRUE) != -1) QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << TRUE; //mute return TRUE; } int VMemo::setToggleButton(int tog) { for( int i=0; i < 10;i++) { switch (tog) { case 0: return -1; break; case 1: return 0; break; case 2: return Key_F24; //was Escape break; case 3: return Key_Space; break; case 4: return Key_F12; break; case 5: return Key_F9; break; case 6: return Key_F10; break; case 7: return Key_F11; break; case 8: return Key_F13; break; }; } return -1; } void VMemo::timerBreak() { //stop stopRecording(); QMessageBox::message("Vmemo","Vmemo recording has ended"); } EXPORT_OPIE_APPLET_v1( VMemo ) diff --git a/core/applets/vtapplet/vt.cpp b/core/applets/vtapplet/vt.cpp index aec63c3..7832ee0 100644 --- a/core/applets/vtapplet/vt.cpp +++ b/core/applets/vtapplet/vt.cpp @@ -1,164 +1,172 @@ /********************************************************************** ** Copyright (C) 2003-2004 Michael 'Mickey' Lauer <mickey@Vanille.de> ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** **********************************************************************/ #include "vt.h" /* OPIE */ #include <opie2/odebug.h> #include <qpe/resource.h> using namespace Opie::Core; /* QT */ #include <qpopupmenu.h> /* STD */ #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <linux/vt.h> VTApplet::VTApplet ( ) : QObject ( 0, "VTApplet" ) { } VTApplet::~VTApplet ( ) { } int VTApplet::position ( ) const { return 2; } QString VTApplet::name ( ) const { return tr( "VT shortcut" ); } QString VTApplet::text ( ) const { return tr( "Terminal" ); } /* QString VTApplet::tr( const char* s ) const { return qApp->translate( "VTApplet", s, 0 ); } QString VTApplet::tr( const char* s, const char* p ) const { return qApp->translate( "VTApplet", s, p ); } */ QIconSet VTApplet::icon ( ) const { QPixmap pix; QImage img = Resource::loadImage ( "terminal" ); if ( !img. isNull ( )) pix. convertFromImage ( img. smoothScale ( 14, 14 )); return pix; } QPopupMenu *VTApplet::popup ( QWidget* parent ) const { odebug << "VTApplet::popup" << oendl; struct vt_stat vtstat; +#ifdef QT_QWS_DEVFS + int fd = ::open( "/dev/vc/0", O_RDWR ); +#else int fd = ::open( "/dev/tty0", O_RDWR ); +#endif if ( fd == -1 ) return 0; if ( ioctl( fd, VT_GETSTATE, &vtstat ) == -1 ) return 0; m_subMenu = new QPopupMenu( parent ); m_subMenu->setCheckable( true ); for ( int i = 1; i < 10; ++i ) { int id = m_subMenu->insertItem( QString::number( i ), 500+i ); m_subMenu->setItemChecked( id, id-500 == vtstat.v_active ); } ::close( fd ); connect( m_subMenu, SIGNAL( activated(int) ), this, SLOT( changeVT(int) ) ); connect( m_subMenu, SIGNAL( aboutToShow() ), this, SLOT( updateMenu() ) ); return m_subMenu; } void VTApplet::changeVT( int index ) { //odebug << "VTApplet::changeVT( " << index-500 << " )" << oendl; +#ifdef QT_QWS_DEVFS + int fd = ::open("/dev/vc/0", O_RDWR); +#else int fd = ::open("/dev/tty0", O_RDWR); +#endif if ( fd == -1 ) return; ioctl( fd, VT_ACTIVATE, index-500 ); } void VTApplet::updateMenu() { //odebug << "VTApplet::updateMenu()" << oendl; int fd = ::open( "/dev/console", O_RDONLY ); if ( fd == -1 ) return; for ( int i = 1; i < 10; ++i ) { int result = ioctl( fd, VT_DISALLOCATE, i ); /* if ( result == -1 ) odebug << "VT " << i << " disallocated == free" << oendl; else odebug << "VT " << i << " _not_ disallocated == busy" << oendl; */ m_subMenu->setItemEnabled( 500+i, result == -1 ); } ::close( fd ); } void VTApplet::activated() { odebug << "VTApplet::activated()" << oendl; } QRESULT VTApplet::queryInterface ( const QUuid &uuid, QUnknownInterface **iface ) { *iface = 0; if ( uuid == IID_QUnknown ) *iface = this; else if ( uuid == IID_MenuApplet ) *iface = this; else return QS_FALSE; if ( *iface ) (*iface)-> addRef ( ); return QS_OK; } Q_EXPORT_INTERFACE( ) { Q_CREATE_INSTANCE( VTApplet ) } diff --git a/libopie/odevice.cpp b/libopie/odevice.cpp index 21070bf..9d0bbbf 100644 --- a/libopie/odevice.cpp +++ b/libopie/odevice.cpp @@ -1,2134 +1,2138 @@ /* This file is part of the OPIE libraries Copyright (C) 2002 Robert Griebl (sandman@handhelds.org) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <signal.h> #include <sys/time.h> #ifndef QT_NO_SOUND #include <linux/soundcard.h> #endif #include <math.h> #include <qfile.h> #include <qtextstream.h> #include <qpe/sound.h> #include <qpe/resource.h> #include <qpe/config.h> #include <qpe/qcopenvelope_qws.h> #include "odevice.h" #include <qwindowsystem_qws.h> #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif // _IO and friends are only defined in kernel headers ... #define OD_IOC(dir,type,number,size) (( dir << 30 ) | ( type << 8 ) | ( number ) | ( size << 16 )) #define OD_IO(type,number) OD_IOC(0,type,number,0) #define OD_IOW(type,number,size) OD_IOC(1,type,number,sizeof(size)) #define OD_IOR(type,number,size) OD_IOC(2,type,number,sizeof(size)) #define OD_IORW(type,number,size) OD_IOC(3,type,number,sizeof(size)) using namespace Opie; class ODeviceData { public: QString m_vendorstr; OVendor m_vendor; QString m_modelstr; OModel m_model; QString m_systemstr; OSystem m_system; QString m_sysverstr; Transformation m_rotation; ODirection m_direction; QValueList <ODeviceButton> *m_buttons; uint m_holdtime; QStrList *m_cpu_frequencies; }; class iPAQ : public ODevice, public QWSServer::KeyboardFilter { protected: virtual void init ( ); virtual void initButtons ( ); public: virtual bool setSoftSuspend ( bool soft ); virtual bool setDisplayBrightness ( int b ); virtual int displayBrightnessResolution ( ) const; virtual void alarmSound ( ); virtual QValueList <OLed> ledList ( ) const; virtual QValueList <OLedState> ledStateList ( OLed led ) const; virtual OLedState ledState ( OLed led ) const; virtual bool setLedState ( OLed led, OLedState st ); virtual bool hasLightSensor ( ) const; virtual int readLightSensor ( ); virtual int lightSensorResolution ( ) const; protected: virtual bool filter ( int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat ); virtual void timerEvent ( QTimerEvent *te ); int m_power_timer; OLedState m_leds [2]; }; class Jornada : public ODevice { protected: virtual void init ( ); //virtual void initButtons ( ); public: virtual bool setSoftSuspend ( bool soft ); virtual bool setDisplayBrightness ( int b ); virtual int displayBrightnessResolution ( ) const; static bool isJornada(); }; class Zaurus : public ODevice { protected: virtual void init ( ); virtual void initButtons ( ); public: virtual bool setSoftSuspend ( bool soft ); virtual bool setDisplayBrightness ( int b ); virtual int displayBrightnessResolution ( ) const; virtual void alarmSound ( ); virtual void keySound ( ); virtual void touchSound ( ); virtual QValueList <OLed> ledList ( ) const; virtual QValueList <OLedState> ledStateList ( OLed led ) const; virtual OLedState ledState ( OLed led ) const; virtual bool setLedState ( OLed led, OLedState st ); bool hasHingeSensor() const; OHingeStatus readHingeSensor(); static bool isZaurus(); // Does this break BC? virtual bool suspend ( ); Transformation rotation ( ) const; ODirection direction ( ) const; protected: virtual void buzzer ( int snd ); OLedState m_leds [1]; bool m_embedix; void virtual_hook( int id, void *data ); }; class SIMpad : public ODevice, public QWSServer::KeyboardFilter { protected: virtual void init ( ); virtual void initButtons ( ); public: virtual bool setSoftSuspend ( bool soft ); virtual bool suspend(); virtual bool setDisplayStatus( bool on ); virtual bool setDisplayBrightness ( int b ); virtual int displayBrightnessResolution ( ) const; virtual void alarmSound ( ); virtual QValueList <OLed> ledList ( ) const; virtual QValueList <OLedState> ledStateList ( OLed led ) const; virtual OLedState ledState ( OLed led ) const; virtual bool setLedState ( OLed led, OLedState st ); protected: virtual bool filter ( int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat ); virtual void timerEvent ( QTimerEvent *te ); int m_power_timer; OLedState m_leds [1]; //FIXME check if really only one }; class Ramses : public ODevice, public QWSServer::KeyboardFilter { protected: virtual void init ( ); public: virtual bool setSoftSuspend ( bool soft ); virtual bool suspend ( ); virtual bool setDisplayStatus( bool on ); virtual bool setDisplayBrightness ( int b ); virtual int displayBrightnessResolution ( ) const; virtual bool setDisplayContrast ( int b ); virtual int displayContrastResolution ( ) const; protected: virtual bool filter ( int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat ); virtual void timerEvent ( QTimerEvent *te ); int m_power_timer; }; struct i_button { uint model; Qt::Key code; char *utext; char *pix; char *fpressedservice; char *fpressedaction; char *fheldservice; char *fheldaction; } ipaq_buttons [] = { { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx, Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"), "devicebuttons/ipaq_calendar", "datebook", "nextView()", "today", "raise()" }, { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx, Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"), "devicebuttons/ipaq_contact", "addressbook", "raise()", "addressbook", "beamBusinessCard()" }, { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx, Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"), "devicebuttons/ipaq_menu", "QPE/TaskBar", "toggleMenu()", "QPE/TaskBar", "toggleStartMenu()" }, { Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx, Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Mail Button"), "devicebuttons/ipaq_mail", "mail", "raise()", "mail", "newMail()" }, { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx, Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"), "devicebuttons/ipaq_home", "QPE/Launcher", "home()", "buttonsettings", "raise()" }, { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx, Qt::Key_F24, QT_TRANSLATE_NOOP("Button", "Record Button"), "devicebuttons/ipaq_record", "QPE/VMemo", "toggleRecord()", "sound", "raise()" }, }; struct z_button { Qt::Key code; char *utext; char *pix; char *fpressedservice; char *fpressedaction; char *fheldservice; char *fheldaction; } z_buttons [] = { { Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"), "devicebuttons/z_calendar", "datebook", "nextView()", "today", "raise()" }, { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"), "devicebuttons/z_contact", "addressbook", "raise()", "addressbook", "beamBusinessCard()" }, { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"), "devicebuttons/z_home", "QPE/Launcher", "home()", "buttonsettings", "raise()" }, { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"), "devicebuttons/z_menu", "QPE/TaskBar", "toggleMenu()", "QPE/TaskBar", "toggleStartMenu()" }, { Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Mail Button"), "devicebuttons/z_mail", "mail", "raise()", "mail", "newMail()" }, }; struct z_button z_buttons_c700 [] = { { Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Calendar Button"), "devicebuttons/z_calendar", "datebook", "nextView()", "today", "raise()" }, { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Contacts Button"), "devicebuttons/z_contact", "addressbook", "raise()", "addressbook", "beamBusinessCard()" }, { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Home Button"), "devicebuttons/z_home", "QPE/Launcher", "home()", "buttonsettings", "raise()" }, { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Menu Button"), "devicebuttons/z_menu", "QPE/TaskBar", "toggleMenu()", "QPE/TaskBar", "toggleStartMenu()" }, { Qt::Key_F14, QT_TRANSLATE_NOOP("Button", "Display Rotate"), "devicebuttons/z_hinge", "QPE/Rotation", "rotateDefault()", "QPE/Dummy", "doNothing()" }, }; struct s_button { uint model; Qt::Key code; char *utext; char *pix; char *fpressedservice; char *fpressedaction; char *fheldservice; char *fheldaction; } simpad_buttons [] = { { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, Qt::Key_F9, QT_TRANSLATE_NOOP("Button", "Lower+Up"), "devicebuttons/simpad_lower_up", "datebook", "nextView()", "today", "raise()" }, { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Lower+Down"), "devicebuttons/simpad_lower_down", "addressbook", "raise()", "addressbook", "beamBusinessCard()" }, { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "Lower+Right"), "devicebuttons/simpad_lower_right", "QPE/TaskBar", "toggleMenu()", "QPE/TaskBar", "toggleStartMenu()" }, { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Lower+Left"), "devicebuttons/simpad_lower_left", "mail", "raise()", "mail", "newMail()" }, { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, Qt::Key_F5, QT_TRANSLATE_NOOP("Button", "Upper+Up"), "devicebuttons/simpad_upper_up", "QPE/Launcher", "home()", "buttonsettings", "raise()" }, { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, Qt::Key_F6, QT_TRANSLATE_NOOP("Button", "Upper+Down"), "devicebuttons/simpad_upper_down", "addressbook", "raise()", "addressbook", "beamBusinessCard()" }, { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, Qt::Key_F7, QT_TRANSLATE_NOOP("Button", "Upper+Right"), "devicebuttons/simpad_upper_right", "QPE/TaskBar", "toggleMenu()", "QPE/TaskBar", "toggleStartMenu()" }, { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, Qt::Key_F13, QT_TRANSLATE_NOOP("Button", "Upper+Left"), "devicebuttons/simpad_upper_left", "QPE/Rotation", "flip()", "QPE/Rotation", "flip()" }, /* { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Lower+Upper"), "devicebuttons/simpad_lower_upper", "QPE/Launcher", "home()", "buttonsettings", "raise()" }, { Model_SIMpad_CL4 | Model_SIMpad_SL4 | Model_SIMpad_SLC | Model_SIMpad_TSinus, Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "Lower+Upper"), "devicebuttons/simpad_upper_lower", "QPE/Launcher", "home()", "buttonsettings", "raise()" }, */ }; class Yopy : public ODevice { protected: virtual void init ( ); virtual void initButtons ( ); public: virtual bool suspend ( ); virtual bool setDisplayBrightness ( int b ); virtual int displayBrightnessResolution ( ) const; static bool isYopy ( ); }; struct yopy_button { Qt::Key code; char *utext; char *pix; char *fpressedservice; char *fpressedaction; char *fheldservice; char *fheldaction; } yopy_buttons [] = { { Qt::Key_F10, QT_TRANSLATE_NOOP("Button", "Action Button"), "devicebuttons/yopy_action", "datebook", "nextView()", "today", "raise()" }, { Qt::Key_F11, QT_TRANSLATE_NOOP("Button", "OK Button"), "devicebuttons/yopy_ok", "addressbook", "raise()", "addressbook", "beamBusinessCard()" }, { Qt::Key_F12, QT_TRANSLATE_NOOP("Button", "End Button"), "devicebuttons/yopy_end", "QPE/Launcher", "home()", "buttonsettings", "raise()" }, }; static QCString makeChannel ( const char *str ) { if ( str && !::strchr ( str, '/' )) return QCString ( "QPE/Application/" ) + str; else return str; } static inline bool isQWS() { return qApp ? ( qApp-> type ( ) == QApplication::GuiServer ) : false; } ODevice *ODevice::inst ( ) { static ODevice *dev = 0; if ( !dev ) { if ( QFile::exists ( "/proc/hal/model" )) dev = new iPAQ ( ); else if ( Zaurus::isZaurus() ) dev = new Zaurus ( ); else if ( QFile::exists ( "/proc/ucb1x00" ) && QFile::exists ( "/proc/cs3" )) dev = new SIMpad ( ); else if ( Yopy::isYopy() ) dev = new Yopy ( ); else if ( Jornada::isJornada() ) dev = new Jornada ( ); else if ( QFile::exists ( "/proc/sys/board/sys_name" )) dev = new Ramses ( ); else dev = new ODevice ( ); dev-> init ( ); } return dev; } /************************************************** * * common * **************************************************/ ODevice::ODevice ( ) { d = new ODeviceData; d-> m_modelstr = "Unknown"; d-> m_model = Model_Unknown; d-> m_vendorstr = "Unknown"; d-> m_vendor = Vendor_Unknown; d-> m_systemstr = "Unknown"; d-> m_system = System_Unknown; d-> m_sysverstr = "0.0"; d-> m_rotation = Rot0; d-> m_direction = CW; d-> m_holdtime = 1000; // 1000ms d-> m_buttons = 0; d-> m_cpu_frequencies = new QStrList; } void ODevice::systemMessage ( const QCString &msg, const QByteArray & ) { if ( msg == "deviceButtonMappingChanged()" ) { reloadButtonMapping ( ); } } void ODevice::init ( ) { } /** * This method initialises the button mapping */ void ODevice::initButtons ( ) { if ( d-> m_buttons ) return; // Simulation uses iPAQ 3660 device buttons qDebug ( "init Buttons" ); d-> m_buttons = new QValueList <ODeviceButton>; for ( uint i = 0; i < ( sizeof( ipaq_buttons ) / sizeof( i_button )); i++ ) { i_button *ib = ipaq_buttons + i; ODeviceButton b; if (( ib-> model & Model_iPAQ_H36xx ) == Model_iPAQ_H36xx ) { b. setKeycode ( ib-> code ); b. setUserText ( QObject::tr ( "Button", ib-> utext )); b. setPixmap ( Resource::loadPixmap ( ib-> pix )); b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( ib-> fpressedservice ), ib-> fpressedaction )); b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( ib-> fheldservice ), ib-> fheldaction )); d-> m_buttons-> append ( b ); } } reloadButtonMapping ( ); QCopChannel *sysch = new QCopChannel ( "QPE/System", this ); connect ( sysch, SIGNAL( received(const QCString&,const QByteArray&)), this, SLOT( systemMessage(const QCString&,const QByteArray&))); } ODevice::~ODevice ( ) { // we leak m_devicebuttons and m_cpu_frequency // but it's a singleton and it is not so importantant // -zecke delete d; } bool ODevice::setSoftSuspend ( bool /*soft*/ ) { return false; } //#include <linux/apm_bios.h> #define APM_IOC_SUSPEND OD_IO( 'A', 2 ) /** * This method will try to suspend the device * It only works if the user is the QWS Server and the apm application * is installed. * It tries to suspend and then waits some time cause some distributions * do have asynchronus apm implementations. * This method will either fail and return false or it'll suspend the * device and return once the device got woken up * * @return if the device got suspended */ bool ODevice::suspend ( ) { qDebug("ODevice::suspend"); if ( !isQWS( ) ) // only qwsserver is allowed to suspend return false; if ( d-> m_model == Model_Unknown ) // better don't suspend in qvfb / on unkown devices return false; bool res = false; struct timeval tvs, tvn; ::gettimeofday ( &tvs, 0 ); ::sync ( ); // flush fs caches res = ( ::system ( "apm --suspend" ) == 0 ); // This is needed because the iPAQ apm implementation is asynchronous and we // can not be sure when exactly the device is really suspended // This can be deleted as soon as a stable familiar with a synchronous apm implementation exists. if ( res ) { do { // wait at most 1.5 sec: either suspend didn't work or the device resumed ::usleep ( 200 * 1000 ); ::gettimeofday ( &tvn, 0 ); } while ((( tvn. tv_sec - tvs. tv_sec ) * 1000 + ( tvn. tv_usec - tvs. tv_usec ) / 1000 ) < 1500 ); } return res; } //#include <linux/fb.h> better not rely on kernel headers in userspace ... #define FBIOBLANK OD_IO( 'F', 0x11 ) // 0x4611 /* VESA Blanking Levels */ #define VESA_NO_BLANKING 0 #define VESA_VSYNC_SUSPEND 1 #define VESA_HSYNC_SUSPEND 2 #define VESA_POWERDOWN 3 /** * This sets the display on or off */ bool ODevice::setDisplayStatus ( bool on ) { qDebug("ODevice::setDisplayStatus(%d)", on); if ( d-> m_model == Model_Unknown ) return false; bool res = false; int fd; +#ifdef QT_QWS_DEVFS + if (( fd = ::open ( "/dev/fb/0", O_RDWR )) >= 0 ) { +#else if (( fd = ::open ( "/dev/fb0", O_RDWR )) >= 0 ) { +#endif res = ( ::ioctl ( fd, FBIOBLANK, on ? VESA_NO_BLANKING : VESA_POWERDOWN ) == 0 ); ::close ( fd ); } return res; } /** * This sets the display brightness * * @param p The brightness to be set on a scale from 0 to 255 * @return success or failure */ bool ODevice::setDisplayBrightness ( int p) { Q_UNUSED( p ) return false; } /** * @return returns the number of steppings on the brightness slider * in the Light-'n-Power settings. */ int ODevice::displayBrightnessResolution ( ) const { return 16; } /** * This sets the display contrast * @param p The contrast to be set on a scale from 0 to 255 * @return success or failure */ bool ODevice::setDisplayContrast ( int p) { Q_UNUSED( p ) return false; } /** * @return return the max value for the brightness settings slider * or 0 if the device doesn't support setting of a contrast */ int ODevice::displayContrastResolution ( ) const { return 0; } /** * This returns the vendor as string * @return Vendor as QString */ QString ODevice::vendorString ( ) const { return d-> m_vendorstr; } /** * This returns the vendor as one of the values of OVendor * @return OVendor */ OVendor ODevice::vendor ( ) const { return d-> m_vendor; } /** * This returns the model as a string * @return A string representing the model */ QString ODevice::modelString ( ) const { return d-> m_modelstr; } /** * This does return the OModel used */ OModel ODevice::model ( ) const { return d-> m_model; } /** * This does return the systen name */ QString ODevice::systemString ( ) const { return d-> m_systemstr; } /** * Return System as OSystem value */ OSystem ODevice::system ( ) const { return d-> m_system; } /** * @return the version string of the base system */ QString ODevice::systemVersionString ( ) const { return d-> m_sysverstr; } /** * @return the current Transformation */ Transformation ODevice::rotation ( ) const { VirtRotation rot; ODevice* that =(ODevice* )this; that->virtual_hook( VIRTUAL_ROTATION, &rot ); return rot.trans; } /** * @return the current rotation direction */ ODirection ODevice::direction ( ) const { VirtDirection dir; ODevice* that =(ODevice* )this; that->virtual_hook( VIRTUAL_DIRECTION, &dir ); return dir.direct; } /** * This plays an alarmSound */ void ODevice::alarmSound ( ) { #ifndef QT_NO_SOUND static Sound snd ( "alarm" ); if ( snd. isFinished ( )) snd. play ( ); #endif } /** * This plays a key sound */ void ODevice::keySound ( ) { #ifndef QT_NO_SOUND static Sound snd ( "keysound" ); if ( snd. isFinished ( )) snd. play ( ); #endif } /** * This plays a touch sound */ void ODevice::touchSound ( ) { #ifndef QT_NO_SOUND static Sound snd ( "touchsound" ); if ( snd. isFinished ( )) snd. play ( ); #endif } /** * This method will return a list of leds * available on this device * @return a list of LEDs. */ QValueList <OLed> ODevice::ledList ( ) const { return QValueList <OLed> ( ); } /** * This does return the state of the LEDs */ QValueList <OLedState> ODevice::ledStateList ( OLed /*which*/ ) const { return QValueList <OLedState> ( ); } /** * @return the state for a given OLed */ OLedState ODevice::ledState ( OLed /*which*/ ) const { return Led_Off; } /** * Set the state for a LED * @param which Which OLed to use * @param st The state to set * @return success or failure */ bool ODevice::setLedState ( OLed which, OLedState st ) { Q_UNUSED( which ) Q_UNUSED( st ) return false; } /** * @return if the device has a light sensor */ bool ODevice::hasLightSensor ( ) const { return false; } /** * @return a value from the light sensor */ int ODevice::readLightSensor ( ) { return -1; } /** * @return the light sensor resolution */ int ODevice::lightSensorResolution ( ) const { return 0; } /** * @return if the device has a hinge sensor */ bool ODevice::hasHingeSensor ( ) const { VirtHasHinge hing; ODevice* that =(ODevice* )this; that->virtual_hook( VIRTUAL_HAS_HINGE, &hing ); return hing.hasHinge; } /** * @return a value from the hinge sensor */ OHingeStatus ODevice::readHingeSensor ( ) { VirtHingeStatus hing; virtual_hook( VIRTUAL_HINGE, &hing ); return hing.hingeStat; } /** * @return a list with CPU frequencies supported by the hardware */ const QStrList &ODevice::allowedCpuFrequencies ( ) const { return *d->m_cpu_frequencies; } /** * Set desired CPU frequency * * @param index index into d->m_cpu_frequencies of the frequency to be set */ bool ODevice::setCurrentCpuFrequency(uint index) { if (index >= d->m_cpu_frequencies->count()) return false; char *freq = d->m_cpu_frequencies->at(index); qWarning("set freq to %s", freq); int fd; if ((fd = ::open("/proc/sys/cpu/0/speed", O_WRONLY)) >= 0) { char writeCommand[50]; const int count = sprintf(writeCommand, "%s\n", freq); int res = (::write(fd, writeCommand, count) != -1); ::close(fd); return res; } return false; } /** * @return a list of hardware buttons */ const QValueList <ODeviceButton> &ODevice::buttons ( ) { initButtons ( ); return *d-> m_buttons; } /** * @return The amount of time that would count as a hold */ uint ODevice::buttonHoldTime ( ) const { return d-> m_holdtime; } /** * This method return a ODeviceButton for a key code * or 0 if no special hardware button is available for the device * * @return The devicebutton or 0l * @see ODeviceButton */ const ODeviceButton *ODevice::buttonForKeycode ( ushort code ) { initButtons ( ); for ( QValueListConstIterator<ODeviceButton> it = d-> m_buttons-> begin ( ); it != d-> m_buttons-> end ( ); ++it ) { if ( (*it). keycode ( ) == code ) return &(*it); } return 0; } void ODevice::reloadButtonMapping ( ) { initButtons ( ); Config cfg ( "ButtonSettings" ); for ( uint i = 0; i < d-> m_buttons-> count ( ); i++ ) { ODeviceButton &b = ( *d-> m_buttons ) [i]; QString group = "Button" + QString::number ( i ); QCString pch, hch; QCString pm, hm; QByteArray pdata, hdata; if ( cfg. hasGroup ( group )) { cfg. setGroup ( group ); pch = cfg. readEntry ( "PressedActionChannel" ). latin1 ( ); pm = cfg. readEntry ( "PressedActionMessage" ). latin1 ( ); // pdata = decodeBase64 ( buttonFile. readEntry ( "PressedActionArgs" )); hch = cfg. readEntry ( "HeldActionChannel" ). latin1 ( ); hm = cfg. readEntry ( "HeldActionMessage" ). latin1 ( ); // hdata = decodeBase64 ( buttonFile. readEntry ( "HeldActionArgs" )); } b. setPressedAction ( OQCopMessage ( pch, pm, pdata )); b. setHeldAction ( OQCopMessage ( hch, hm, hdata )); } } void ODevice::remapPressedAction ( int button, const OQCopMessage &action ) { initButtons ( ); QString mb_chan; if ( button >= (int) d-> m_buttons-> count ( )) return; ODeviceButton &b = ( *d-> m_buttons ) [button]; b. setPressedAction ( action ); mb_chan=b. pressedAction ( ). channel ( ); Config buttonFile ( "ButtonSettings" ); buttonFile. setGroup ( "Button" + QString::number ( button )); buttonFile. writeEntry ( "PressedActionChannel", (const char*) mb_chan); buttonFile. writeEntry ( "PressedActionMessage", (const char*) b. pressedAction ( ). message ( )); // buttonFile. writeEntry ( "PressedActionArgs", encodeBase64 ( b. pressedAction ( ). data ( ))); QCopEnvelope ( "QPE/System", "deviceButtonMappingChanged()" ); } void ODevice::remapHeldAction ( int button, const OQCopMessage &action ) { initButtons ( ); if ( button >= (int) d-> m_buttons-> count ( )) return; ODeviceButton &b = ( *d-> m_buttons ) [button]; b. setHeldAction ( action ); Config buttonFile ( "ButtonSettings" ); buttonFile. setGroup ( "Button" + QString::number ( button )); buttonFile. writeEntry ( "HeldActionChannel", (const char *) b. heldAction ( ). channel ( )); buttonFile. writeEntry ( "HeldActionMessage", (const char *) b. heldAction ( ). message ( )); // buttonFile. writeEntry ( "HeldActionArgs", decodeBase64 ( b. heldAction ( ). data ( ))); QCopEnvelope ( "QPE/System", "deviceButtonMappingChanged()" ); } void ODevice::virtual_hook(int id, void* data){ switch( id ) { case VIRTUAL_ROTATION:{ VirtRotation* rot = reinterpret_cast<VirtRotation*>( data ); rot->trans = d->m_rotation; break; } case VIRTUAL_DIRECTION:{ VirtDirection *dir = reinterpret_cast<VirtDirection*>( data ); dir->direct = d->m_direction; break; } case VIRTUAL_HAS_HINGE:{ VirtHasHinge *hin = reinterpret_cast<VirtHasHinge*>( data ); hin->hasHinge = false; break; } case VIRTUAL_HINGE:{ VirtHingeStatus *hin = reinterpret_cast<VirtHingeStatus*>( data ); hin->hingeStat = CASE_UNKNOWN; break; } } } /************************************************** * * Yopy 3500/3700 * **************************************************/ bool Yopy::isYopy ( ) { QFile f( "/proc/cpuinfo" ); if ( f. open ( IO_ReadOnly ) ) { QTextStream ts ( &f ); QString line; while( line = ts. readLine ( ) ) { if ( line. left ( 8 ) == "Hardware" ) { int loc = line. find ( ":" ); if ( loc != -1 ) { QString model = line. mid ( loc + 2 ). simplifyWhiteSpace( ); return ( model == "Yopy" ); } } } } return false; } void Yopy::init ( ) { d-> m_vendorstr = "G.Mate"; d-> m_vendor = Vendor_GMate; d-> m_modelstr = "Yopy3700"; d-> m_model = Model_Yopy_3700; d-> m_rotation = Rot0; d-> m_systemstr = "Linupy"; d-> m_system = System_Linupy; QFile f ( "/etc/issue" ); if ( f. open ( IO_ReadOnly )) { QTextStream ts ( &f ); ts.readLine(); d-> m_sysverstr = ts. readLine ( ); f. close ( ); } } void Yopy::initButtons ( ) { if ( d-> m_buttons ) return; d-> m_buttons = new QValueList <ODeviceButton>; for (uint i = 0; i < ( sizeof( yopy_buttons ) / sizeof(yopy_button)); i++) { yopy_button *ib = yopy_buttons + i; ODeviceButton b; b. setKeycode ( ib-> code ); b. setUserText ( QObject::tr ( "Button", ib-> utext )); b. setPixmap ( Resource::loadPixmap ( ib-> pix )); b. setFactoryPresetPressedAction (OQCopMessage(makeChannel(ib->fpressedservice), ib->fpressedaction)); b. setFactoryPresetHeldAction (OQCopMessage(makeChannel(ib->fheldservice), ib->fheldaction)); d-> m_buttons-> append ( b ); } reloadButtonMapping ( ); QCopChannel *sysch = new QCopChannel("QPE/System", this); connect(sysch, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(systemMessage(const QCString&,const QByteArray&))); } bool Yopy::suspend() { /* Opie for Yopy does not implement its own power management at the moment. The public version runs parallel to X, and relies on the existing power management features. */ return false; } bool Yopy::setDisplayBrightness(int /*bright*/) { /* The code here works, but is disabled as the current version runs parallel to X, and relies on the existing backlight demon. */ #if 0 if ( QFile::exists("/proc/sys/pm/light") ) { int fd = ::open("/proc/sys/pm/light", O_WRONLY); if (fd >= 0 ) { if (bright) ::write(fd, "1\n", 2); else ::write(fd, "0\n", 2); ::close(fd); return true; } } #endif return false; } int Yopy::displayBrightnessResolution() const { return 2; } /************************************************** * * iPAQ * **************************************************/ void iPAQ::init ( ) { d-> m_vendorstr = "HP"; d-> m_vendor = Vendor_HP; QFile f ( "/proc/hal/model" ); if ( f. open ( IO_ReadOnly )) { QTextStream ts ( &f ); d-> m_modelstr = "H" + ts. readLine ( ); if ( d-> m_modelstr == "H3100" ) d-> m_model = Model_iPAQ_H31xx; else if ( d-> m_modelstr == "H3600" ) d-> m_model = Model_iPAQ_H36xx; else if ( d-> m_modelstr == "H3700" ) d-> m_model = Model_iPAQ_H37xx; else if ( d-> m_modelstr == "H3800" ) d-> m_model = Model_iPAQ_H38xx; else if ( d-> m_modelstr == "H3900" ) d-> m_model = Model_iPAQ_H39xx; else if ( d-> m_modelstr == "H5400" ) d-> m_model = Model_iPAQ_H5xxx; else d-> m_model = Model_Unknown; f. close ( ); } switch ( d-> m_model ) { case Model_iPAQ_H31xx: case Model_iPAQ_H38xx: d-> m_rotation = Rot90; break; case Model_iPAQ_H36xx: case Model_iPAQ_H37xx: case Model_iPAQ_H39xx: default: d-> m_rotation = Rot270; break; case Model_iPAQ_H5xxx: d-> m_rotation = Rot0; } f. setName ( "/etc/familiar-version" ); if ( f. open ( IO_ReadOnly )) { d-> m_systemstr = "Familiar"; d-> m_system = System_Familiar; QTextStream ts ( &f ); d-> m_sysverstr = ts. readLine ( ). mid ( 10 ); f. close ( ); } else { f. setName ( "/etc/oz_version" ); if ( f. open ( IO_ReadOnly )) { d-> m_systemstr = "OpenEmbedded/iPaq"; d-> m_system = System_Familiar; QTextStream ts ( &f ); ts.setDevice ( &f ); d-> m_sysverstr = ts. readLine ( ); f. close ( ); } } m_leds [0] = m_leds [1] = Led_Off; m_power_timer = 0; } void iPAQ::initButtons ( ) { if ( d-> m_buttons ) return; if ( isQWS( ) ) QWSServer::setKeyboardFilter ( this ); d-> m_buttons = new QValueList <ODeviceButton>; for ( uint i = 0; i < ( sizeof( ipaq_buttons ) / sizeof( i_button )); i++ ) { i_button *ib = ipaq_buttons + i; ODeviceButton b; if (( ib-> model & d-> m_model ) == d-> m_model ) { b. setKeycode ( ib-> code ); b. setUserText ( QObject::tr ( "Button", ib-> utext )); b. setPixmap ( Resource::loadPixmap ( ib-> pix )); b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( ib-> fpressedservice ), ib-> fpressedaction )); b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( ib-> fheldservice ), ib-> fheldaction )); d-> m_buttons-> append ( b ); } } reloadButtonMapping ( ); QCopChannel *sysch = new QCopChannel ( "QPE/System", this ); connect ( sysch, SIGNAL( received(const QCString&,const QByteArray&)), this, SLOT( systemMessage(const QCString&,const QByteArray&))); } //#include <linux/h3600_ts.h> // including kernel headers is evil ... typedef struct { unsigned char OffOnBlink; /* 0=off 1=on 2=Blink */ unsigned char TotalTime; /* Units of 5 seconds */ unsigned char OnTime; /* units of 100m/s */ unsigned char OffTime; /* units of 100m/s */ } LED_IN; typedef struct { unsigned char mode; unsigned char pwr; unsigned char brightness; } FLITE_IN; #define LED_ON OD_IOW( 'f', 5, LED_IN ) #define FLITE_ON OD_IOW( 'f', 7, FLITE_IN ) QValueList <OLed> iPAQ::ledList ( ) const { QValueList <OLed> vl; vl << Led_Power; if ( d-> m_model == Model_iPAQ_H38xx ) vl << Led_BlueTooth; return vl; } QValueList <OLedState> iPAQ::ledStateList ( OLed l ) const { QValueList <OLedState> vl; if ( l == Led_Power ) vl << Led_Off << Led_On << Led_BlinkSlow << Led_BlinkFast; else if ( l == Led_BlueTooth && d-> m_model == Model_iPAQ_H38xx ) vl << Led_Off; // << Led_On << ??? return vl; } OLedState iPAQ::ledState ( OLed l ) const { switch ( l ) { case Led_Power: return m_leds [0]; case Led_BlueTooth: return m_leds [1]; default: return Led_Off; } } bool iPAQ::setLedState ( OLed l, OLedState st ) { static int fd = ::open ( "/dev/touchscreen/0", O_RDWR | O_NONBLOCK ); if ( l == Led_Power ) { if ( fd >= 0 ) { LED_IN leds; ::memset ( &leds, 0, sizeof( leds )); leds. TotalTime = 0; leds. OnTime = 0; leds. OffTime = 1; leds. OffOnBlink = 2; switch ( st ) { case Led_Off : leds. OffOnBlink = 0; break; case Led_On : leds. OffOnBlink = 1; break; case Led_BlinkSlow: leds. OnTime = 10; leds. OffTime = 10; break; case Led_BlinkFast: leds. OnTime = 5; leds. OffTime = 5; break; } if ( ::ioctl ( fd, LED_ON, &leds ) >= 0 ) { m_leds [0] = st; return true; } } } return false; } bool iPAQ::filter ( int /*unicode*/, int keycode, int modifiers, bool isPress, bool autoRepeat ) { int newkeycode = keycode; switch ( keycode ) { // H38xx/H39xx have no "Q" key anymore - this is now the Mail key case HardKey_Menu: { if (( d-> m_model == Model_iPAQ_H38xx ) || ( d-> m_model == Model_iPAQ_H39xx ) || ( d-> m_model == Model_iPAQ_H5xxx)) { newkeycode = HardKey_Mail; } break; } // Rotate cursor keys 180° or 270° case Key_Left : case Key_Right: case Key_Up : case Key_Down : { if (( d-> m_model == Model_iPAQ_H31xx ) || ( d-> m_model == Model_iPAQ_H38xx )) { newkeycode = Key_Left + ( keycode - Key_Left + 2 ) % 4; } // Rotate the cursor keys by 270° // keycode - Key_Left = position of the button starting from left clockwise // add the rotation to it and modolo. No we've the original offset // add the offset to the Key_Left key if ( d-> m_model == Model_iPAQ_H5xxx ) newkeycode = Key_Left + ( keycode - Key_Left + 3 ) % 4; break; } // map Power Button short/long press to F34/F35 case Key_SysReq: { if ( isPress ) { if ( m_power_timer ) killTimer ( m_power_timer ); m_power_timer = startTimer ( 500 ); } else if ( m_power_timer ) { killTimer ( m_power_timer ); m_power_timer = 0; QWSServer::sendKeyEvent ( -1, HardKey_Suspend, 0, true, false ); QWSServer::sendKeyEvent ( -1, HardKey_Suspend, 0, false, false ); } newkeycode = Key_unknown; break; } } if ( newkeycode != keycode ) { if ( newkeycode != Key_unknown ) QWSServer::sendKeyEvent ( -1, newkeycode, modifiers, isPress, autoRepeat ); return true; } else return false; } void iPAQ::timerEvent ( QTimerEvent * ) { killTimer ( m_power_timer ); m_power_timer = 0; QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, true, false ); QWSServer::sendKeyEvent ( -1, HardKey_Backlight, 0, false, false ); } void iPAQ::alarmSound ( ) { #ifndef QT_NO_SOUND static Sound snd ( "alarm" ); int fd; int vol; bool vol_reset = false; if (( fd = ::open ( "/dev/sound/mixer", O_RDWR )) >= 0 ) { if ( ::ioctl ( fd, MIXER_READ( 0 ), &vol ) >= 0 ) { Config cfg ( "qpe" ); cfg. setGroup ( "Volume" ); int volalarm = cfg. readNumEntry ( "AlarmPercent", 50 ); if ( volalarm < 0 ) volalarm = 0; else if ( volalarm > 100 ) volalarm = 100; volalarm |= ( volalarm << 8 ); if ( ::ioctl ( fd, MIXER_WRITE( 0 ), &volalarm ) >= 0 ) vol_reset = true; } } snd. play ( ); while ( !snd. isFinished ( )) qApp-> processEvents ( ); if ( fd >= 0 ) { if ( vol_reset ) ::ioctl ( fd, MIXER_WRITE( 0 ), &vol ); ::close ( fd ); } #endif } bool iPAQ::setSoftSuspend ( bool soft ) { bool res = false; int fd; if (( fd = ::open ( "/proc/sys/ts/suspend_button_mode", O_WRONLY )) >= 0 ) { if ( ::write ( fd, soft ? "1" : "0", 1 ) == 1 ) res = true; else ::perror ( "write to /proc/sys/ts/suspend_button_mode" ); ::close ( fd ); } else ::perror ( "/proc/sys/ts/suspend_button_mode" ); return res; } bool iPAQ::setDisplayBrightness ( int bright ) { bool res = false; int fd; if ( bright > 255 ) bright = 255; if ( bright < 0 ) bright = 0; if (( fd = ::open ( "/dev/touchscreen/0", O_WRONLY )) >= 0 ) { FLITE_IN bl; bl. mode = 1; bl. pwr = bright ? 1 : 0; bl. brightness = ( bright * ( displayBrightnessResolution ( ) - 1 ) + 127 ) / 255; res = ( ::ioctl ( fd, FLITE_ON, &bl ) == 0 ); ::close ( fd ); } return res; } int iPAQ::displayBrightnessResolution ( ) const { switch ( model ( )) { case Model_iPAQ_H31xx: case Model_iPAQ_H36xx: case Model_iPAQ_H37xx: return 128; // really 256, but >128 could damage the LCD case Model_iPAQ_H38xx: case Model_iPAQ_H39xx: return 64; case Model_iPAQ_H5xxx: return 255; default: return 2; } } bool iPAQ::hasLightSensor ( ) const { return true; } int iPAQ::readLightSensor ( ) { int fd; int val = -1; if (( fd = ::open ( "/proc/hal/light_sensor", O_RDONLY )) >= 0 ) { char buffer [8]; if ( ::read ( fd, buffer, 5 ) == 5 ) { char *endptr; buffer [4] = 0; val = ::strtol ( buffer + 2, &endptr, 16 ); if ( *endptr != 0 ) val = -1; } ::close ( fd ); } return val; } int iPAQ::lightSensorResolution ( ) const { return 256; } /************************************************** * * Zaurus * **************************************************/ // Check whether this device is the sharp zaurus.. // FIXME This gets unnecessary complicated. We should think about splitting the Zaurus // class up into individual classes. We need three classes // // Zaurus-Collie (SA-model w/ 320x240 lcd, for SL5500 and SL5000) // Zaurus-Poodle (PXA-model w/ 320x240 lcd, for SL5600) // Zaurus-Corgi (PXA-model w/ 640x480 lcd, for C700, C750, C760, and C860) // // Only question right now is: Do we really need to do it? Because as soon // as the OpenZaurus kernel is ready, there will be a unified interface for all // Zaurus models (concerning apm, backlight, buttons, etc.) // // Comments? - mickeyl. bool Zaurus::isZaurus() { // If the special devices by embedix exist, it is quite simple: it is a Zaurus ! if ( QFile::exists ( "/dev/sharp_buz" ) || QFile::exists ( "/dev/sharp_led" ) ){ return true; } // On non-embedix kernels, we have to look closer. bool is_zaurus = false; QFile f ( "/proc/cpuinfo" ); if ( f. open ( IO_ReadOnly ) ) { QString model; QFile f ( "/proc/cpuinfo" ); QTextStream ts ( &f ); QString line; while( line = ts. readLine ( ) ) { if ( line. left ( 8 ) == "Hardware" ) break; } int loc = line. find ( ":" ); if ( loc != -1 ) model = line. mid ( loc + 2 ). simplifyWhiteSpace( ); if ( model == "Sharp-Collie" || model == "Collie" || model == "SHARP Corgi" || model == "SHARP Shepherd" || model == "SHARP Poodle" || model == "SHARP Husky" ) is_zaurus = true; } return is_zaurus; } void Zaurus::init ( ) { d-> m_vendorstr = "Sharp"; d-> m_vendor = Vendor_Sharp; m_embedix = true; // Not openzaurus means: It has an embedix kernel ! // QFile f ( "/proc/filesystems" ); QString model; // It isn't a good idea to check the system configuration to // detect the distribution ! // Otherwise it may happen that any other distribution is detected as openzaurus, just // because it uses a jffs2 filesystem.. // (eilers) // if ( f. open ( IO_ReadOnly ) && ( QTextStream ( &f ). read ( ). find ( "\tjffs2\n" ) >= 0 )) { QFile f ("/etc/oz_version"); if ( f.exists() ){ d-> m_vendorstr = "OpenZaurus Team"; d-> m_systemstr = "OpenZaurus"; d-> m_system = System_OpenZaurus; if ( f. open ( IO_ReadOnly )) { QTextStream ts ( &f ); d-> m_sysverstr = ts. readLine ( );//. mid ( 10 ); f. close ( ); } // Openzaurus sometimes uses the embedix kernel! // => Check whether this is an embedix kernel FILE *uname = popen("uname -r", "r"); QString line; if ( f.open(IO_ReadOnly, uname) ) { QTextStream ts ( &f ); line = ts. readLine ( ); int loc = line. find ( "embedix" ); if ( loc != -1 ) m_embedix = true; else m_embedix = false; f. close ( ); } pclose(uname); } else { d-> m_systemstr = "Zaurus"; d-> m_system = System_Zaurus; } f. setName ( "/proc/cpuinfo" ); if ( f. open ( IO_ReadOnly ) ) { QTextStream ts ( &f ); QString line; while( line = ts. readLine ( ) ) { if ( line. left ( 8 ) == "Hardware" ) break; } int loc = line. find ( ":" ); if ( loc != -1 ) model = line. mid ( loc + 2 ). simplifyWhiteSpace( ); } if ( model == "SHARP Corgi" ) { d-> m_model = Model_Zaurus_SLC7x0; d-> m_modelstr = "Zaurus SL-C700"; } else if ( model == "SHARP Shepherd" ) { d-> m_model = Model_Zaurus_SLC7x0; d-> m_modelstr = "Zaurus SL-C750"; } else if ( model == "SHARP Husky" ) { d-> m_model = Model_Zaurus_SLC7x0; d-> m_modelstr = "Zaurus SL-C760"; } else if ( model == "SHARP Poodle" ) { d-> m_model = Model_Zaurus_SLB600; d-> m_modelstr = "Zaurus SL-B500 or SL-5600"; } else if ( model == "Sharp-Collie" || model == "Collie" ) { d-> m_model = Model_Zaurus_SL5500; d-> m_modelstr = "Zaurus SL-5500 or SL-5000d"; } else { d-> m_model = Model_Zaurus_SL5500; d-> m_modelstr = "Zaurus (Model unknown)"; } switch ( d-> m_model ) { case Model_Zaurus_SLA300: d-> m_rotation = Rot0; break; case Model_Zaurus_SLC7x0: d-> m_rotation = rotation(); d-> m_direction = direction(); break; case Model_Zaurus_SLB600: case Model_Zaurus_SL5500: case Model_Zaurus_SL5000: default: d-> m_rotation = Rot270; break; } m_leds [0] = Led_Off; } void Zaurus::initButtons ( ) { if ( d-> m_buttons ) return; d-> m_buttons = new QValueList <ODeviceButton>; struct z_button * pz_buttons; int buttoncount; switch ( d-> m_model ) { case Model_Zaurus_SLC7x0: pz_buttons = z_buttons_c700; buttoncount = ARRAY_SIZE(z_buttons_c700); break; default: pz_buttons = z_buttons; buttoncount = ARRAY_SIZE(z_buttons); break; } for ( int i = 0; i < buttoncount; i++ ) { struct z_button *zb = pz_buttons + i; ODeviceButton b; b. setKeycode ( zb-> code ); b. setUserText ( QObject::tr ( "Button", zb-> utext )); b. setPixmap ( Resource::loadPixmap ( zb-> pix )); b. setFactoryPresetPressedAction ( OQCopMessage ( makeChannel ( zb-> fpressedservice ), zb-> fpressedaction )); b. setFactoryPresetHeldAction ( OQCopMessage ( makeChannel ( zb-> fheldservice ), zb-> fheldaction )); d-> m_buttons-> append ( b ); } reloadButtonMapping ( ); QCopChannel *sysch = new QCopChannel ( "QPE/System", this ); connect ( sysch, SIGNAL( received(const QCString&,const QByteArray&)), this, SLOT( systemMessage(const QCString&,const QByteArray&))); } #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> //#include <asm/sharp_char.h> // including kernel headers is evil ... #define SHARP_DEV_IOCTL_COMMAND_START 0x5680 #define SHARP_BUZZER_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START) #define SHARP_BUZZER_MAKESOUND (SHARP_BUZZER_IOCTL_START) #define SHARP_BUZ_TOUCHSOUND 1 /* touch panel sound */ #define SHARP_BUZ_KEYSOUND 2 /* key sound */ #define SHARP_BUZ_SCHEDULE_ALARM 11 /* schedule alarm */ /* --- for SHARP_BUZZER device --- */ //#define SHARP_BUZZER_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START) //#define SHARP_BUZZER_MAKESOUND (SHARP_BUZZER_IOCTL_START) #define SHARP_BUZZER_SETVOLUME (SHARP_BUZZER_IOCTL_START+1) #define SHARP_BUZZER_GETVOLUME (SHARP_BUZZER_IOCTL_START+2) #define SHARP_BUZZER_ISSUPPORTED (SHARP_BUZZER_IOCTL_START+3) #define SHARP_BUZZER_SETMUTE (SHARP_BUZZER_IOCTL_START+4) #define SHARP_BUZZER_STOPSOUND (SHARP_BUZZER_IOCTL_START+5) //#define SHARP_BUZ_TOUCHSOUND 1 /* touch panel sound */ //#define SHARP_BUZ_KEYSOUND 2 /* key sound */ //#define SHARP_PDA_ILLCLICKSOUND 3 /* illegal click */ //#define SHARP_PDA_WARNSOUND 4 /* warning occurred */ //#define SHARP_PDA_ERRORSOUND 5 /* error occurred */ //#define SHARP_PDA_CRITICALSOUND 6 /* critical error occurred */ //#define SHARP_PDA_SYSSTARTSOUND 7 /* system start */ //#define SHARP_PDA_SYSTEMENDSOUND 8 /* system shutdown */ //#define SHARP_PDA_APPSTART 9 /* application start */ //#define SHARP_PDA_APPQUIT 10 /* application ends */ //#define SHARP_BUZ_SCHEDULE_ALARM 11 /* schedule alarm */ //#define SHARP_BUZ_DAILY_ALARM 12 /* daily alarm */ //#define SHARP_BUZ_GOT_PHONE_CALL 13 /* phone call sound */ //#define SHARP_BUZ_GOT_MAIL 14 /* mail sound */ // #define SHARP_LED_IOCTL_START (SHARP_DEV_IOCTL_COMMAND_START) #define SHARP_LED_SETSTATUS (SHARP_LED_IOCTL_START+1) #define SHARP_IOCTL_GET_ROTATION 0x413c typedef struct sharp_led_status { int which; /* select which LED status is wanted. */ int status; /* set new led status if you call SHARP_LED_SETSTATUS */ } sharp_led_status; #define SHARP_LED_MAIL_EXISTS 9 /* mail status (exists or not) */ #define LED_MAIL_NO_UNREAD_MAIL 0 /* for SHARP_LED_MAIL_EXISTS */ #define LED_MAIL_NEWMAIL_EXISTS 1 /* for SHARP_LED_MAIL_EXISTS */ #define LED_MAIL_UNREAD_MAIL_EX 2 /* for SHARP_LED_MAIL_EXISTS */ // #include <asm/sharp_apm.h> // including kernel headers is evil ... #define APM_IOCGEVTSRC OD_IOR( 'A', 203, int ) #define APM_IOCSEVTSRC OD_IORW( 'A', 204, int ) #define APM_EVT_POWER_BUTTON (1 << 0) #define FL_IOCTL_STEP_CONTRAST 100 void Zaurus::buzzer ( int sound ) { #ifndef QT_NO_SOUND QString soundname; // Not all devices have real sound if ( d->m_model == Model_Zaurus_SLC7x0 || d->m_model == Model_Zaurus_SLB600 ){ switch ( sound ){ case SHARP_BUZ_SCHEDULE_ALARM: soundname = "alarm"; break; case SHARP_BUZ_TOUCHSOUND: soundname = "touchsound"; break; case SHARP_BUZ_KEYSOUND: soundname = "keysound"; break; default: soundname = "alarm"; } } // If a soundname is defined, we expect that this device has // sound capabilities.. Otherwise we expect to have the buzzer // device.. if ( !soundname.isEmpty() ){ int fd; int vol; bool vol_reset = false; Sound snd ( soundname ); if (( fd = ::open ( "/dev/sound/mixer", O_RDWR )) >= 0 ) { if ( ::ioctl ( fd, MIXER_READ( 0 ), &vol ) >= 0 ) { Config cfg ( "qpe" ); cfg. setGroup ( "Volume" ); int volalarm = cfg. readNumEntry ( "AlarmPercent", 50 ); if ( volalarm < 0 ) volalarm = 0; else if ( volalarm > 100 ) volalarm = 100; volalarm |= ( volalarm << 8 ); if ( ::ioctl ( fd, MIXER_WRITE( 0 ), &volalarm ) >= 0 ) vol_reset = true; } } snd. play ( ); while ( !snd. isFinished ( )) qApp-> processEvents ( ); if ( fd >= 0 ) { if ( vol_reset ) ::ioctl ( fd, MIXER_WRITE( 0 ), &vol ); ::close ( fd ); } } else { int fd = ::open ( "/dev/sharp_buz", O_WRONLY|O_NONBLOCK ); if ( fd >= 0 ) { ::ioctl ( fd, SHARP_BUZZER_MAKESOUND, sound ); ::close ( fd ); } } #endif } void Zaurus::alarmSound ( ) { buzzer ( SHARP_BUZ_SCHEDULE_ALARM ); } void Zaurus::touchSound ( ) { buzzer ( SHARP_BUZ_TOUCHSOUND ); } void Zaurus::keySound ( ) { buzzer ( SHARP_BUZ_KEYSOUND ); } QValueList <OLed> Zaurus::ledList ( ) const { QValueList <OLed> vl; vl << Led_Mail; return vl; } QValueList <OLedState> Zaurus::ledStateList ( OLed l ) const { QValueList <OLedState> vl; if ( l == Led_Mail ) vl << Led_Off << Led_On << Led_BlinkSlow; return vl; } OLedState Zaurus::ledState ( OLed which ) const { if ( which == Led_Mail ) return m_leds [0]; else return Led_Off; } bool Zaurus::setLedState ( OLed which, OLedState st ) { if (!m_embedix) // Currently not supported on non_embedix kernels return false; static int fd = ::open ( "/dev/sharp_led", O_RDWR|O_NONBLOCK ); if ( which == Led_Mail ) { if ( fd >= 0 ) { struct sharp_led_status leds; ::memset ( &leds, 0, sizeof( leds )); leds. which = SHARP_LED_MAIL_EXISTS; bool ok = true; switch ( st ) { case Led_Off : leds. status = LED_MAIL_NO_UNREAD_MAIL; break; case Led_On : leds. status = LED_MAIL_NEWMAIL_EXISTS; break; case Led_BlinkSlow: leds. status = LED_MAIL_UNREAD_MAIL_EX; break; default : ok = false; } if ( ok && ( ::ioctl ( fd, SHARP_LED_SETSTATUS, &leds ) >= 0 )) { m_leds [0] = st; return true; } } } return false; } bool Zaurus::setSoftSuspend ( bool soft ) { if (!m_embedix) { /* non-Embedix kernels dont have kernel autosuspend */ return ODevice::setSoftSuspend( soft ); } bool res = false; int fd; if ((( fd = ::open ( "/dev/apm_bios", O_RDWR )) >= 0 ) || (( fd = ::open ( "/dev/misc/apm_bios",O_RDWR )) >= 0 )) { int sources = ::ioctl ( fd, APM_IOCGEVTSRC, 0 ); // get current event sources if ( sources >= 0 ) { if ( soft ) sources &= ~APM_EVT_POWER_BUTTON; else sources |= APM_EVT_POWER_BUTTON; if ( ::ioctl ( fd, APM_IOCSEVTSRC, sources ) >= 0 ) // set new event sources res = true; else perror ( "APM_IOCGEVTSRC" ); } else perror ( "APM_IOCGEVTSRC" ); ::close ( fd ); } else perror ( "/dev/apm_bios or /dev/misc/apm_bios" ); return res; } bool Zaurus::setDisplayBrightness ( int bright ) { //qDebug( "Zaurus::setDisplayBrightness( %d )", bright ); bool res = false; int fd; if ( bright > 255 ) bright = 255; if ( bright < 0 ) bright = 0; if ( m_embedix ) { if ( d->m_model == Model_Zaurus_SLC7x0 ) { //qDebug( "using special treatment for devices with the corgi backlight interface" ); // special treatment for devices with the corgi backlight interface if (( fd = ::open ( "/proc/driver/fl/corgi-bl", O_WRONLY )) >= 0 ) { int value = ( bright == 1 ) ? 1 : bright * ( 17.0 / 255.0 ); char writeCommand[100]; const int count = sprintf( writeCommand, "0x%x\n", value ); res = ( ::write ( fd, writeCommand, count ) != -1 ); ::close ( fd ); } return res; } else { // standard treatment for devices with the dumb embedix frontlight interface if (( fd = ::open ( "/dev/fl", O_WRONLY )) >= 0 ) { int bl = ( bright * 4 + 127 ) / 255; // only 4 steps on zaurus if ( bright && !bl ) bl = 1; res = ( ::ioctl ( fd, FL_IOCTL_STEP_CONTRAST, bl ) == 0 ); ::close ( fd ); } } } else { // special treatment for the OpenZaurus unified interface #define FB_BACKLIGHT_SET_BRIGHTNESS _IOW('F', 1, u_int) /* set brightness */ if (( fd = ::open ( "/dev/fb0", O_WRONLY )) >= 0 ) { res = ( ::ioctl ( fd , FB_BACKLIGHT_SET_BRIGHTNESS, bright ) == 0 ); ::close ( fd ); } } return res; } bool Zaurus::suspend ( ) { qDebug("ODevice::suspend"); if ( !isQWS( ) ) // only qwsserver is allowed to suspend return false; if ( d-> m_model == Model_Unknown ) // better don't suspend in qvfb / on unkown devices return false; bool res = false; struct timeval tvs, tvn; ::gettimeofday ( &tvs, 0 ); ::sync ( ); // flush fs caches res = ( ::system ( "apm --suspend" ) == 0 ); // This is needed because the iPAQ apm implementation is asynchronous and we // can not be sure when exactly the device is really suspended // This can be deleted as soon as a stable familiar with a synchronous apm implementation exists. if ( res ) { do { // Yes, wait 15 seconds. This APM bug sucks big time. ::usleep ( 200 * 1000 ); ::gettimeofday ( &tvn, 0 ); } while ((( tvn. tv_sec - tvs. tv_sec ) * 1000 + ( tvn. tv_usec - tvs. tv_usec ) / 1000 ) < 15000 ); } QCopEnvelope ( "QPE/Rotation", "rotateDefault()" ); return res; } Transformation Zaurus::rotation ( ) const { Transformation rot; int handle = 0; int retval = 0; switch ( d-> m_model ) { case Model_Zaurus_SLC7x0: handle = ::open("/dev/apm_bios", O_RDWR|O_NONBLOCK); if (handle == -1) { return Rot270; } else { retval = ::ioctl(handle, SHARP_IOCTL_GET_ROTATION); ::close (handle); if (retval == 2 ) rot = Rot0; else rot = Rot270; } break; case Model_Zaurus_SLA300: case Model_Zaurus_SLB600: case Model_Zaurus_SL5500: case Model_Zaurus_SL5000: default: rot = d-> m_rotation; break; } return rot; } ODirection Zaurus::direction ( ) const { ODirection dir; int handle = 0; int retval = 0; switch ( d-> m_model ) { case Model_Zaurus_SLC7x0: handle = ::open("/dev/apm_bios", O_RDWR|O_NONBLOCK); if (handle == -1) { dir = CW; } else { retval = ::ioctl(handle, SHARP_IOCTL_GET_ROTATION); ::close (handle); if (retval == 2 ) dir = CCW; else dir = CW; } break; case Model_Zaurus_SLA300: case Model_Zaurus_SLB600: case Model_Zaurus_SL5500: case Model_Zaurus_SL5000: default: dir = d-> m_direction; break; } return dir; } int Zaurus::displayBrightnessResolution ( ) const { if (m_embedix) return d->m_model == Model_Zaurus_SLC7x0 ? 18 : 5; else return 256; } diff --git a/libopie2/opiemm/osoundsystem.cpp b/libopie2/opiemm/osoundsystem.cpp index 763ff65..17e5cb0 100644 --- a/libopie2/opiemm/osoundsystem.cpp +++ b/libopie2/opiemm/osoundsystem.cpp @@ -1,317 +1,322 @@ /* This file is part of the Opie Project (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de> =. .=l. .>+-= _;:, .> :=|. This program is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU Library General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; either version 2 of the License, ._= =} : or (at your option) any later version. .%`+i> _;_. .i_,=:_. -<s. This program is distributed in the hope that + . -:. = it will be useful, but WITHOUT ANY WARRANTY; : .. .:, . . . without even the implied warranty of =_ + =;=|` MERCHANTABILITY or FITNESS FOR A _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <opie2/osoundsystem.h> #include <opie2/odebug.h> #include <errno.h> #include <fcntl.h> #include <string.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/soundcard.h> #include <sys/stat.h> using namespace Opie::Core; using namespace Opie::MM; /*====================================================================================== * OSoundSystem *======================================================================================*/ OSoundSystem* OSoundSystem::_instance = 0; OSoundSystem::OSoundSystem() { odebug << "OSoundSystem::OSoundSystem()" << oendl; synchronize(); } void OSoundSystem::synchronize() { // gather available interfaces by inspecting /dev //FIXME: we could use SIOCGIFCONF here, but we aren't interested in virtual (e.g. eth0:0) devices //FIXME: Use SIOCGIFCONF anway, because we can disable listing of aliased devices _interfaces.clear(); _interfaces.insert( "soundcard", new OSoundCard( this, "soundcard" ) ); /* QString str; QFile f( "/dev/sound" ); bool hasFile = f.open( IO_ReadOnly ); if ( !hasFile ) { odebug << "OSoundSystem: /dev/sound not existing. No sound devices available" << oendl; return; } QTextStream s( &f ); s.readLine(); s.readLine(); while ( !s.atEnd() ) { s >> str; str.truncate( str.find( ':' ) ); odebug << "OSoundSystem: found interface '" << str << "'" << oendl; OAudioInterface* iface; iface = new OAudioInterface( this, (const char*) str ); _interfaces.insert( str, iface ); s.readLine(); } */ } int OSoundSystem::count() const { return _interfaces.count(); } OSoundCard* OSoundSystem::card( const QString& iface ) const { return _interfaces[iface]; } OSoundSystem* OSoundSystem::instance() { if ( !_instance ) _instance = new OSoundSystem(); return _instance; } OSoundSystem::CardIterator OSoundSystem::iterator() const { return OSoundSystem::CardIterator( _interfaces ); } /*====================================================================================== * OSoundCard *======================================================================================*/ OSoundCard::OSoundCard( QObject* parent, const char* name ) :QObject( parent, name ), _audio( 0 ), _mixer( 0 ) { odebug << "OSoundCard::OSoundCard()" << oendl; init(); } OSoundCard::~OSoundCard() { } void OSoundCard::init() { +#ifdef QT_QWS_DEVFS + _audio = new OAudioInterface( this, "/dev/sound/dsp" ); + _mixer = new OMixerInterface( this, "/dev/sound/mixer" ); +#else _audio = new OAudioInterface( this, "/dev/dsp" ); _mixer = new OMixerInterface( this, "/dev/mixer" ); +#endif } /*====================================================================================== * OAudioInterface *======================================================================================*/ OAudioInterface::OAudioInterface( QObject* parent, const char* name ) :QObject( parent, name ), _sfd(0) { odebug << "OAudioInterface::OAudioInterface()" << oendl; init(); } OAudioInterface::~OAudioInterface() { } void OAudioInterface::init() { } /*====================================================================================== * OMixerInterface *======================================================================================*/ OMixerInterface::OMixerInterface( QObject* parent, const char* name ) :QObject( parent, name ) { odebug << "OMixerInterface::OMixerInterface()" << oendl; init(); } OMixerInterface::~OMixerInterface() { } void OMixerInterface::init() { // open the device _fd = ::open( name(), O_RDWR ); if ( _fd == -1 ) { owarn << "OMixerInterface::init(): Can't open mixer." << oendl; return; } // construct the device capabilities int devmask = 0; if ( ioctl( _fd, SOUND_MIXER_READ_DEVMASK, &devmask ) != -1 ) { if ( devmask & ( 1 << SOUND_MIXER_VOLUME ) ) _channels.insert( "PlayVolume", SOUND_MIXER_VOLUME ); if ( devmask & ( 1 << SOUND_MIXER_BASS ) ) _channels.insert( "PlayBass", SOUND_MIXER_BASS ); if ( devmask & ( 1 << SOUND_MIXER_TREBLE ) ) _channels.insert( "PlayTreble", SOUND_MIXER_TREBLE ); if ( devmask & ( 1 << SOUND_MIXER_SYNTH ) ) _channels.insert( "PlaySynth", SOUND_MIXER_SYNTH ); if ( devmask & ( 1 << SOUND_MIXER_PCM ) ) _channels.insert( "PlayPCM", SOUND_MIXER_PCM ); if ( devmask & ( 1 << SOUND_MIXER_SPEAKER ) ) _channels.insert( "PlaySpeaker", SOUND_MIXER_SPEAKER ); if ( devmask & ( 1 << SOUND_MIXER_LINE ) ) _channels.insert( "PlayLine", SOUND_MIXER_LINE ); if ( devmask & ( 1 << SOUND_MIXER_MIC ) ) _channels.insert( "PlayMic", SOUND_MIXER_MIC ); if ( devmask & ( 1 << SOUND_MIXER_CD ) ) _channels.insert( "PlayCD", SOUND_MIXER_CD ); if ( devmask & ( 1 << SOUND_MIXER_IMIX ) ) _channels.insert( "PlayInputMix", SOUND_MIXER_IMIX ); if ( devmask & ( 1 << SOUND_MIXER_ALTPCM ) ) _channels.insert( "PlayAltPCM", SOUND_MIXER_ALTPCM ); if ( devmask & ( 1 << SOUND_MIXER_RECLEV ) ) _channels.insert( "PlayRecord", SOUND_MIXER_RECLEV ); if ( devmask & ( 1 << SOUND_MIXER_IGAIN ) ) _channels.insert( "PlayInputGain", SOUND_MIXER_IGAIN ); if ( devmask & ( 1 << SOUND_MIXER_OGAIN ) ) _channels.insert( "PlayOutputGain", SOUND_MIXER_OGAIN ); //odebug << "devmask available and constructed." << oendl; } devmask = 0; if ( ioctl( _fd, SOUND_MIXER_READ_RECMASK, &devmask ) != -1 ) { if ( devmask & ( 1 << SOUND_MIXER_VOLUME ) ) _channels.insert( "RecVolume", SOUND_MIXER_VOLUME ); if ( devmask & ( 1 << SOUND_MIXER_BASS ) ) _channels.insert( "RecBass", SOUND_MIXER_BASS ); if ( devmask & ( 1 << SOUND_MIXER_TREBLE ) ) _channels.insert( "RecTreble", SOUND_MIXER_TREBLE ); if ( devmask & ( 1 << SOUND_MIXER_SYNTH ) ) _channels.insert( "RecSynth", SOUND_MIXER_SYNTH ); if ( devmask & ( 1 << SOUND_MIXER_PCM ) ) _channels.insert( "RecPCM", SOUND_MIXER_PCM ); if ( devmask & ( 1 << SOUND_MIXER_SPEAKER ) ) _channels.insert( "RecSpeaker", SOUND_MIXER_SPEAKER ); if ( devmask & ( 1 << SOUND_MIXER_LINE ) ) _channels.insert( "RecLine", SOUND_MIXER_LINE ); if ( devmask & ( 1 << SOUND_MIXER_MIC ) ) _channels.insert( "RecMic", SOUND_MIXER_MIC ); if ( devmask & ( 1 << SOUND_MIXER_CD ) ) _channels.insert( "RecCD", SOUND_MIXER_CD ); if ( devmask & ( 1 << SOUND_MIXER_IMIX ) ) _channels.insert( "RecInputMix", SOUND_MIXER_IMIX ); if ( devmask & ( 1 << SOUND_MIXER_ALTPCM ) ) _channels.insert( "RecAltPCM", SOUND_MIXER_ALTPCM ); if ( devmask & ( 1 << SOUND_MIXER_RECLEV ) ) _channels.insert( "RecRecord", SOUND_MIXER_RECLEV ); if ( devmask & ( 1 << SOUND_MIXER_IGAIN ) ) _channels.insert( "RecInputGain", SOUND_MIXER_IGAIN ); if ( devmask & ( 1 << SOUND_MIXER_OGAIN ) ) _channels.insert( "RecOutputGain", SOUND_MIXER_OGAIN ); //odebug << "recmask available and constructed." << oendl; } /* ChannelIterator it; for ( it = _channels.begin(); it != _channels.end(); ++it ) { odebug << "Channel " << it.key() << " available (bit " << it.data() << ")" << oendl; odebug << " +--- Volume: " << volume( it.key() ) & 0xff << " | " << volume( it.key() ) >> 8 << "" << oendl; } */ } QStringList OMixerInterface::allChannels() const { ChannelIterator it = _channels.begin(); QStringList channels; while ( it != _channels.end() ) { channels += it.key(); it++; } return channels; } QStringList OMixerInterface::recChannels() const { owarn << "NYI" << oendl; return QStringList(); } QStringList OMixerInterface::playChannels() const { owarn << "NYI" << oendl; return QStringList(); } bool OMixerInterface::hasChannel( const QString& channel ) { return _channels.contains( channel ); } void OMixerInterface::setVolume( const QString& channel, int left, int right ) { int volume = left; volume |= ( right == -1 ) ? left << 8 : right << 8; if ( _channels.contains( channel ) ) { int result = ioctl( _fd, MIXER_WRITE( _channels[channel] ), &volume ); if ( result == -1 ) { owarn << "Can't set volume: " << strerror( errno ) << oendl; } else { if ( result & 0xff != left ) { owarn << "Device adjusted volume from " << left << " to " << (result & 0xff) << oendl; } } } } int OMixerInterface::volume( const QString& channel ) const { int volume; if ( _channels.contains( channel ) ) { if ( ioctl( _fd, MIXER_READ( _channels[channel] ), &volume ) == -1 ) { owarn << "Can't get volume: " << strerror( errno ) << oendl; } else return volume; } return -1; } diff --git a/library/qpeapplication.cpp b/library/qpeapplication.cpp index c6d9cfd..ca90427 100644 --- a/library/qpeapplication.cpp +++ b/library/qpeapplication.cpp @@ -1,2175 +1,2191 @@ /********************************************************************** ** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. ** ** This file is part of the Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** */ #define QTOPIA_INTERNAL_LANGLIST #include <stdlib.h> #include <unistd.h> #ifndef Q_OS_MACX #include <linux/limits.h> // needed for some toolchains (PATH_MAX) #endif #include <qfile.h> #include <qqueue.h> #ifdef Q_WS_QWS #ifndef QT_NO_COP #if QT_VERSION <= 231 #define private public #define sendLocally processEvent #include "qcopenvelope_qws.h" #undef private #else #include "qcopenvelope_qws.h" #endif #endif #include <qwindowsystem_qws.h> #endif #include <qtextstream.h> #include <qpalette.h> #include <qbuffer.h> #include <qptrdict.h> #include <qregexp.h> #include <qdir.h> #include <qlabel.h> #include <qdialog.h> #include <qdragobject.h> #include <qtextcodec.h> #include <qevent.h> #include <qtooltip.h> #include <qsignal.h> #include <qmainwindow.h> #include <qwidgetlist.h> #include <qpixmapcache.h> #if defined(Q_WS_QWS) && !defined(QT_NO_COP) #define QTOPIA_INTERNAL_INITAPP #include "qpeapplication.h" #include "qpestyle.h" #include "styleinterface.h" #if QT_VERSION >= 300 #include <qstylefactory.h> #else #include <qplatinumstyle.h> #include <qwindowsstyle.h> #include <qmotifstyle.h> #include <qmotifplusstyle.h> #include "lightstyle.h" #include <qpe/qlibrary.h> #endif #include "global.h" #include "resource.h" #if QT_VERSION <= 230 && defined(QT_NO_CODECS) #include "qutfcodec.h" #endif #include "config.h" #include "network.h" #ifdef QWS #include "fontmanager.h" #include "fontdatabase.h" #endif #include "alarmserver.h" #include "applnk.h" #include "qpemenubar.h" #include "textcodecinterface.h" #include "imagecodecinterface.h" #include <unistd.h> #include <sys/file.h> #include <sys/ioctl.h> #ifndef QT_NO_SOUND #include <sys/soundcard.h> #endif #include "qt_override_p.h" #include <backend/rohfeedback.h> static bool useBigPixmaps = 0; class HackWidget : public QWidget { public: bool needsOk() { return (getWState() & WState_Reserved1 ); } QRect normalGeometry() { return topData()->normalGeometry; }; }; class QPEApplicationData { public: QPEApplicationData ( ) : presstimer( 0 ), presswidget( 0 ), rightpressed( false ), kbgrabbed( false ), notbusysent( false ), preloaded( false ), forceshow( false ), nomaximize( false ), keep_running( true ), qcopQok( false ), fontFamily( "Vera" ), fontSize( 10 ), smallIconSize( 14 ), bigIconSize( 32 ), qpe_main_widget( 0 ) { Config cfg( "qpe" ); cfg.setGroup( "Appearance" ); useBigPixmaps = cfg.readBoolEntry( "useBigPixmaps", false ); fontFamily = cfg.readEntry( "FontFamily", "Vera" ); fontSize = cfg.readNumEntry( "FontSize", 10 ); smallIconSize = cfg.readNumEntry( "SmallIconSize", 14 ); bigIconSize = cfg.readNumEntry( "BigIconSize", 32 ); #ifdef OPIE_WITHROHFEEDBACK RoH = 0; #endif } int presstimer; QWidget* presswidget; QPoint presspos; #ifdef OPIE_WITHROHFEEDBACK Opie::Internal::RoHFeedback *RoH; #endif bool rightpressed : 1; bool kbgrabbed : 1; bool notbusysent : 1; bool preloaded : 1; bool forceshow : 1; bool nomaximize : 1; bool keep_running : 1; bool qcopQok : 1; QCString fontFamily; int fontSize; int smallIconSize; int bigIconSize; QStringList langs; QString appName; struct QCopRec { QCopRec( const QCString &ch, const QCString &msg, const QByteArray &d ) : channel( ch ), message( msg ), data( d ) { } QCString channel; QCString message; QByteArray data; }; QWidget* qpe_main_widget; QGuardedPtr<QWidget> lastraised; QQueue<QCopRec> qcopq; QString styleName; QString decorationName; void enqueueQCop( const QCString &ch, const QCString &msg, const QByteArray &data ) { qcopq.enqueue( new QCopRec( ch, msg, data ) ); } void sendQCopQ() { if (!qcopQok ) return; QCopRec * r; while((r=qcopq.dequeue())) { // remove from queue before sending... // event loop can come around again before getting // back from sendLocally #ifndef QT_NO_COP QCopChannel::sendLocally( r->channel, r->message, r->data ); #endif delete r; } } static void show_mx(QWidget* mw, bool nomaximize, QString &strName) { if ( mw->inherits("QMainWindow") || mw->isA("QMainWindow") ) { ( ( QMainWindow* ) mw )->setUsesBigPixmaps( useBigPixmaps ); } QPoint p; QSize s; bool max; if ( mw->isVisible() ) { if ( read_widget_rect(strName, max, p, s) && validate_widget_size(mw, p, s) ) { mw->resize(s); mw->move(p); } mw->raise(); } else { if ( mw->layout() && mw->inherits("QDialog") ) { if ( read_widget_rect(strName, max, p, s) && validate_widget_size(mw, p, s) ) { mw->resize(s); mw->move(p); if ( max && !nomaximize ) { mw->showMaximized(); } else { mw->show(); } } else { qpe_show_dialog((QDialog*)mw,nomaximize); } } else { if ( read_widget_rect(strName, max, p, s) && validate_widget_size(mw, p, s) ) { mw->resize(s); mw->move(p); } else { //no stored rectangle, make an estimation int x = (qApp->desktop()->width()-mw->frameGeometry().width())/2; int y = (qApp->desktop()->height()-mw->frameGeometry().height())/2; mw->move( QMAX(x,0), QMAX(y,0) ); #ifdef Q_WS_QWS if ( !nomaximize ) mw->showMaximized(); #endif } if ( max && !nomaximize ) mw->showMaximized(); else mw->show(); } } } static void qpe_show_dialog( QDialog* d, bool nomax ) { QSize sh = d->sizeHint(); int w = QMAX(sh.width(),d->width()); int h = QMAX(sh.height(),d->height()); if ( d->parentWidget() && !d->parentWidget()->topLevelWidget()->isMaximized() ) nomax = TRUE; #ifndef Q_WS_QWS QSize s(qApp->desktop()->width(), qApp->desktop()->height() ); #else QSize s(qt_maxWindowRect.width(), qt_maxWindowRect.height() ); #endif int maxX = s.width() - (d->frameGeometry().width() - d->geometry().width()); int maxY = s.height() - (d->frameGeometry().height() - d->geometry().height()); if ( (w >= maxX && h >= maxY) || ( (!nomax) && ( w > s.width()*3/4 || h > s.height()*3/4 ) ) ) { d->showMaximized(); } else { // try centering the dialog around its parent QPoint p(0,0); if ( d->parentWidget() ) { QPoint pp = d->parentWidget()->mapToGlobal( QPoint(0,0) ); p = QPoint( pp.x() + d->parentWidget()->width()/2, pp.y() + d->parentWidget()->height()/ 2 ); } else { p = QPoint( maxX/2, maxY/2 ); } p = QPoint( p.x() - w/2, p.y() - h/2 ); // qDebug("p(x,y) is %d %d", p.x(), p.y() ); if ( w >= maxX ) { if ( p.y() < 0 ) p.setY(0); if ( p.y() + h > maxY ) p.setY( maxY - h); d->resize(maxX, h); d->move(0, p.y() ); } else if ( h >= maxY ) { if ( p.x() < 0 ) p.setX(0); if ( p.x() + w > maxX ) p.setX( maxX - w); d->resize(w, maxY); d->move(p.x(),0); } else { d->resize(w, h); } d->show(); } } static bool read_widget_rect(const QString &app, bool &maximized, QPoint &p, QSize &s) { maximized = TRUE; // 350 is the trigger in qwsdefaultdecoration for providing a resize button if ( qApp->desktop()->width() <= 350 ) return FALSE; Config cfg( "qpe" ); cfg.setGroup("ApplicationPositions"); QString str = cfg.readEntry( app, QString::null ); QStringList l = QStringList::split(",", str); if ( l.count() == 5) { p.setX( l[0].toInt() ); p.setY( l[1].toInt() ); s.setWidth( l[2].toInt() ); s.setHeight( l[3].toInt() ); maximized = l[4].toInt(); return TRUE; } return FALSE; } static bool validate_widget_size(const QWidget *w, QPoint &p, QSize &s) { #ifndef Q_WS_QWS QRect qt_maxWindowRect = qApp->desktop()->geometry(); #endif int maxX = qt_maxWindowRect.width(); int maxY = qt_maxWindowRect.height(); int wWidth = s.width() + ( w->frameGeometry().width() - w->geometry().width() ); int wHeight = s.height() + ( w->frameGeometry().height() - w->geometry().height() ); // total window size is not allowed to be larger than desktop window size if ( ( wWidth >= maxX ) && ( wHeight >= maxY ) ) return FALSE; if ( wWidth > maxX ) { s.setWidth( maxX - (w->frameGeometry().width() - w->geometry().width() ) ); wWidth = maxX; } if ( wHeight > maxY ) { s.setHeight( maxY - (w->frameGeometry().height() - w->geometry().height() ) ); wHeight = maxY; } // any smaller than this and the maximize/close/help buttons will be overlapping if ( wWidth < 80 || wHeight < 60 ) return FALSE; if ( p.x() < 0 ) p.setX(0); if ( p.y() < 0 ) p.setY(0); if ( p.x() + wWidth > maxX ) p.setX( maxX - wWidth ); if ( p.y() + wHeight > maxY ) p.setY( maxY - wHeight ); return TRUE; } static void store_widget_rect(QWidget *w, QString &app) { // 350 is the trigger in qwsdefaultdecoration for providing a resize button if ( qApp->desktop()->width() <= 350 ) return; // we use these to map the offset of geometry and pos. ( we can only use normalGeometry to // get the non-maximized version, so we have to do it the hard way ) int offsetX = w->x() - w->geometry().left(); int offsetY = w->y() - w->geometry().top(); QRect r; if ( w->isMaximized() ) r = ( (HackWidget *) w)->normalGeometry(); else r = w->geometry(); // Stores the window placement as pos(), size() (due to the offset mapping) Config cfg( "qpe" ); cfg.setGroup("ApplicationPositions"); QString s; s.sprintf("%d,%d,%d,%d,%d", r.left() + offsetX, r.top() + offsetY, r.width(), r.height(), w->isMaximized() ); cfg.writeEntry( app, s ); } static bool setWidgetCaptionFromAppName( QWidget* /*mw*/, const QString& /*appName*/, const QString& /*appsPath*/ ) { /* // This works but disable it for now until it is safe to apply // What is does is scan the .desktop files of all the apps for // the applnk that has the corresponding argv[0] as this program // then it uses the name stored in the .desktop file as the caption // for the main widget. This saves duplicating translations for // the app name in the program and in the .desktop files. AppLnkSet apps( appsPath ); QList<AppLnk> appsList = apps.children(); for ( QListIterator<AppLnk> it(appsList); it.current(); ++it ) { if ( (*it)->exec() == appName ) { mw->setCaption( (*it)->name() ); return TRUE; } } */ return FALSE; } void show(QWidget* mw, bool nomax) { setWidgetCaptionFromAppName( mw, appName, QPEApplication::qpeDir() + "apps" ); nomaximize = nomax; qpe_main_widget = mw; qcopQok = TRUE; #ifndef QT_NO_COP sendQCopQ(); #endif if ( preloaded ) { if (forceshow) show_mx(mw, nomax, appName); } else if ( keep_running ) { show_mx(mw, nomax, appName); } } void loadTextCodecs() { QString path = QPEApplication::qpeDir() + "/plugins/textcodecs"; #ifdef Q_OS_MACX QDir dir( path, "lib*.dylib" ); #else QDir dir( path, "lib*.so" ); #endif QStringList list; if ( dir. exists ( )) list = dir.entryList(); QStringList::Iterator it; for ( it = list.begin(); it != list.end(); ++it ) { TextCodecInterface *iface = 0; QLibrary *lib = new QLibrary( path + "/" + *it ); if ( lib->queryInterface( IID_QtopiaTextCodec, (QUnknownInterface**)&iface ) == QS_OK && iface ) { QValueList<int> mibs = iface->mibEnums(); for (QValueList<int>::ConstIterator i = mibs.begin(); i != mibs.end(); ++i) { (void)iface->createForMib(*i); // ### it exists now; need to remember if we can delete it } } else { lib->unload(); delete lib; } } } void loadImageCodecs() { QString path = QPEApplication::qpeDir() + "/plugins/imagecodecs"; #ifdef Q_OS_MACX QDir dir( path, "lib*.dylib" ); #else QDir dir( path, "lib*.so" ); #endif QStringList list; if ( dir. exists ( )) list = dir.entryList(); QStringList::Iterator it; for ( it = list.begin(); it != list.end(); ++it ) { ImageCodecInterface *iface = 0; QLibrary *lib = new QLibrary( path + "/" + *it ); if ( lib->queryInterface( IID_QtopiaImageCodec, (QUnknownInterface**)&iface ) == QS_OK && iface ) { QStringList formats = iface->keys(); for (QStringList::ConstIterator i = formats.begin(); i != formats.end(); ++i) { (void)iface->installIOHandler(*i); // ### it exists now; need to remember if we can delete it } } else { lib->unload(); delete lib; } } } }; class ResourceMimeFactory : public QMimeSourceFactory { public: ResourceMimeFactory() : resImage( 0 ) { setFilePath( Global::helpPath() ); setExtensionType( "html", "text/html;charset=UTF-8" ); } ~ResourceMimeFactory() { delete resImage; } const QMimeSource* data( const QString& abs_name ) const { const QMimeSource * r = QMimeSourceFactory::data( abs_name ); if ( !r ) { int sl = abs_name.length(); do { sl = abs_name.findRev( '/', sl - 1 ); QString name = sl >= 0 ? abs_name.mid( sl + 1 ) : abs_name; int dot = name.findRev( '.' ); if ( dot >= 0 ) name = name.left( dot ); QImage img = Resource::loadImage( name ); if ( !img.isNull() ) { delete resImage; resImage = new QImageDrag( img ); r = resImage; } } while ( !r && sl > 0 ); } return r; } private: mutable QImageDrag *resImage; }; static int& hack(int& i) { #if QT_VERSION <= 230 && defined(QT_NO_CODECS) // These should be created, but aren't in Qt 2.3.0 (void)new QUtf8Codec; (void)new QUtf16Codec; #endif return i; } static int muted = 0; static int micMuted = 0; static void setVolume( int t = 0, int percent = -1 ) { switch ( t ) { case 0: { Config cfg( "qpe" ); cfg.setGroup( "Volume" ); if ( percent < 0 ) percent = cfg.readNumEntry( "VolumePercent", 50 ); #ifndef QT_NO_SOUND int fd = 0; +#ifdef QT_QWS_DEVFS + if ( ( fd = open( "/dev/sound/mixer", O_RDWR ) ) >= 0 ) { +#else if ( ( fd = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { +#endif int vol = muted ? 0 : percent; // set both channels to same volume vol |= vol << 8; ioctl( fd, MIXER_WRITE( SOUND_MIXER_VOLUME ), &vol ); ::close( fd ); } #endif } break; } } static void setMic( int t = 0, int percent = -1 ) { switch ( t ) { case 0: { Config cfg( "qpe" ); cfg.setGroup( "Volume" ); if ( percent < 0 ) percent = cfg.readNumEntry( "Mic", 50 ); #ifndef QT_NO_SOUND int fd = 0; int mic = micMuted ? 0 : percent; +#ifdef QT_QWS_DEVFS + if ( ( fd = open( "/dev/sound/mixer", O_RDWR ) ) >= 0 ) { +#else if ( ( fd = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { +#endif ioctl( fd, MIXER_WRITE( SOUND_MIXER_MIC ), &mic ); ::close( fd ); } #endif } break; } } static void setBass( int t = 0, int percent = -1 ) { switch ( t ) { case 0: { Config cfg( "qpe" ); cfg.setGroup( "Volume" ); if ( percent < 0 ) percent = cfg.readNumEntry( "BassPercent", 50 ); #ifndef QT_NO_SOUND int fd = 0; int bass = percent; +#ifdef QT_QWS_DEVFS + if ( ( fd = open( "/dev/sound/mixer", O_RDWR ) ) >= 0 ) { +#else if ( ( fd = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { +#endif ioctl( fd, MIXER_WRITE( SOUND_MIXER_BASS ), &bass ); ::close( fd ); } #endif } break; } } static void setTreble( int t = 0, int percent = -1 ) { switch ( t ) { case 0: { Config cfg( "qpe" ); cfg.setGroup( "Volume" ); if ( percent < 0 ) percent = cfg.readNumEntry( "TreblePercent", 50 ); #ifndef QT_NO_SOUND int fd = 0; int treble = percent; +#ifdef QT_QWS_DEVFS + if ( ( fd = open( "/dev/sound/mixer", O_RDWR ) ) >= 0 ) { +#else if ( ( fd = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { +#endif ioctl( fd, MIXER_WRITE( SOUND_MIXER_TREBLE ), &treble ); ::close( fd ); } #endif } break; } } /** \class QPEApplication \brief The QPEApplication class implements various system services that are available to all Qtopia applications. Simply by using QPEApplication instead of QApplication, a standard Qt application becomes a Qtopia application. It automatically follows style changes, quits and raises, and in the case of \link docwidget.html document-oriented\endlink applications, changes the currently displayed document in response to the environment. To create a \link docwidget.html document-oriented\endlink application use showMainDocumentWidget(); to create a non-document-oriented application use showMainWidget(). The keepRunning() function indicates whether the application will continue running after it's processed the last \link qcop.html QCop\endlink message. This can be changed using setKeepRunning(). A variety of signals are emitted when certain events occur, for example, timeChanged(), clockChanged(), weekChanged(), dateFormatChanged() and volumeChanged(). If the application receives a \link qcop.html QCop\endlink message on the application's QPE/Application/\e{appname} channel, the appMessage() signal is emitted. There are also flush() and reload() signals, which are emitted when synching begins and ends respectively - upon these signals, the application should save and reload any data files that are involved in synching. Most of these signals will initially be received and unfiltered through the appMessage() signal. This class also provides a set of useful static functions. The qpeDir() and documentDir() functions return the respective paths. The grabKeyboard() and ungrabKeyboard() functions are used to control whether the application takes control of the device's physical buttons (e.g. application launch keys). The stylus' mode of operation is set with setStylusOperation() and retrieved with stylusOperation(). There are also setInputMethodHint() and inputMethodHint() functions. \ingroup qtopiaemb */ /*! \fn void QPEApplication::clientMoused() \internal */ /*! \fn void QPEApplication::timeChanged(); This signal is emitted when the time changes outside the normal passage of time, i.e. if the time is set backwards or forwards. */ /*! \fn void QPEApplication::clockChanged( bool ampm ); This signal is emitted when the user changes the clock's style. If \a ampm is TRUE, the user wants a 12-hour AM/PM clock, otherwise, they want a 24-hour clock. */ /*! \fn void QPEApplication::volumeChanged( bool muted ) This signal is emitted whenever the mute state is changed. If \a muted is TRUE, then sound output has been muted. */ /*! \fn void QPEApplication::weekChanged( bool startOnMonday ) This signal is emitted if the week start day is changed. If \a startOnMonday is TRUE then the first day of the week is Monday; if \a startOnMonday is FALSE then the first day of the week is Sunday. */ /*! \fn void QPEApplication::dateFormatChanged(DateFormat) This signal is emitted whenever the date format is changed. */ /*! \fn void QPEApplication::flush() ### */ /*! \fn void QPEApplication::reload() */ void QPEApplication::processQCopFile() { QString qcopfn("/tmp/qcop-msg-"); qcopfn += d->appName; // append command name QFile f(qcopfn); if ( f.open(IO_ReadWrite) ) { #ifndef Q_OS_WIN32 flock(f.handle(), LOCK_EX); #endif QDataStream ds(&f); QCString channel, message; QByteArray data; while(!ds.atEnd()) { ds >> channel >> message >> data; d->enqueueQCop(channel,message,data); } ::ftruncate(f.handle(), 0); #ifndef Q_OS_WIN32 f.flush(); flock(f.handle(), LOCK_UN); #endif } #endif } /*! \fn void QPEApplication::appMessage( const QCString& msg, const QByteArray& data ) This signal is emitted when a message is received on this application's QPE/Application/<i>appname</i> \link qcop.html QCop\endlink channel. The slot to which you connect this signal uses \a msg and \a data in the following way: \code void MyWidget::receive( const QCString& msg, const QByteArray& data ) { QDataStream stream( data, IO_ReadOnly ); if ( msg == "someMessage(int,int,int)" ) { int a,b,c; stream >> a >> b >> c; ... } else if ( msg == "otherMessage(QString)" ) { ... } } \endcode \sa qcop.html Note that messages received here may be processed by qpe application and emitted as signals, such as flush() and reload(). */ /*! Constructs a QPEApplication just as you would construct a QApplication, passing \a argc, \a argv, and \a t. For applications, \a t should be the default, GuiClient. Only the Qtopia server passes GuiServer. */ QPEApplication::QPEApplication( int & argc, char **argv, Type t ) : QApplication( hack(argc), argv, t ), pidChannel( 0 ) { QPixmapCache::setCacheLimit(256); // sensible default for smaller devices. d = new QPEApplicationData; d->loadTextCodecs(); d->loadImageCodecs(); setFont( QFont( d->fontFamily, d->fontSize ) ); AppLnk::setSmallIconSize( d->smallIconSize ); AppLnk::setBigIconSize( d->bigIconSize ); QMimeSourceFactory::setDefaultFactory( new ResourceMimeFactory ); connect( this, SIGNAL( lastWindowClosed() ), this, SLOT( hideOrQuit() ) ); sysChannel = new QCopChannel( "QPE/System", this ); connect( sysChannel, SIGNAL( received(const QCString&,const QByteArray&) ), this, SLOT( systemMessage(const QCString&,const QByteArray&) ) ); /* COde now in initapp */ #if 0 #if defined(Q_WS_QWS) && !defined(QT_NO_COP) QString qcopfn( "/tmp/qcop-msg-" ); qcopfn += QString( argv[ 0 ] ); // append command name QFile f( qcopfn ); if ( f.open( IO_ReadOnly ) ) { flock( f.handle(), LOCK_EX ); } QCString channel = QCString( argv[ 0 ] ); channel.replace( QRegExp( ".*/" ), "" ); d->appName = channel; channel = "QPE/Application/" + channel; pidChannel = new QCopChannel( channel, this ); connect( pidChannel, SIGNAL( received(const QCString&,const QByteArray&) ), this, SLOT( pidMessage(const QCString&,const QByteArray&) ) ); if ( f.isOpen() ) { d->keep_running = FALSE; QDataStream ds( &f ); QCString channel, message; QByteArray data; while ( !ds.atEnd() ) { ds >> channel >> message >> data; d->enqueueQCop( channel, message, data ); } flock( f.handle(), LOCK_UN ); f.close(); f.remove(); } for ( int a = 0; a < argc; a++ ) { if ( qstrcmp( argv[ a ], "-preload" ) == 0 ) { argv[ a ] = argv[ a + 1 ]; a++; d->preloaded = TRUE; argc -= 1; } else if ( qstrcmp( argv[ a ], "-preload-show" ) == 0 ) { argv[ a ] = argv[ a + 1 ]; a++; d->preloaded = TRUE; d->forceshow = TRUE; argc -= 1; } } /* overide stored arguments */ setArgs( argc, argv ); #endif #else initApp( argc, argv ); #endif #ifdef Q_WS_QWS /* load the font renderer factories */ FontDatabase::loadRenderers(); #endif #ifndef QT_NO_TRANSLATION d->langs = Global::languageList(); for ( QStringList::ConstIterator it = d->langs.begin(); it != d->langs.end(); ++it ) { QString lang = *it; installTranslation( lang + "/libopie.qm"); installTranslation( lang + "/libqpe.qm" ); installTranslation( lang + "/" + d->appName + ".qm" ); //###language/font hack; should look it up somewhere #ifdef QWS if ( lang == "ja" || lang == "zh_CN" || lang == "zh_TW" || lang == "ko" ) { QFont fn = FontManager::unicodeFont( FontManager::Proportional ); setFont( fn ); } #endif } #endif applyStyle(); if ( type() == GuiServer ) { setVolume(); } installEventFilter( this ); QPEMenuToolFocusManager::initialize(); #ifdef QT_NO_QWS_CURSOR // if we have no cursor, probably don't want tooltips QToolTip::setEnabled( FALSE ); #endif } #ifdef QTOPIA_INTERNAL_INITAPP void QPEApplication::initApp( int argc, char **argv ) { delete pidChannel; d->keep_running = TRUE; d->preloaded = FALSE; d->forceshow = FALSE; QCString channel = QCString(argv[0]); channel.replace(QRegExp(".*/"),""); d->appName = channel; #if QT_VERSION > 235 qt_fbdpy->setIdentity( channel ); // In Qt/E 2.3.6 #endif channel = "QPE/Application/" + channel; pidChannel = new QCopChannel( channel, this); connect( pidChannel, SIGNAL(received(const QCString&,const QByteArray&)), this, SLOT(pidMessage(const QCString&,const QByteArray&))); processQCopFile(); d->keep_running = d->qcopq.isEmpty(); for (int a=0; a<argc; a++) { if ( qstrcmp(argv[a],"-preload")==0 ) { argv[a] = argv[a+1]; a++; d->preloaded = TRUE; argc-=1; } else if ( qstrcmp(argv[a],"-preload-show")==0 ) { argv[a] = argv[a+1]; a++; d->preloaded = TRUE; d->forceshow = TRUE; argc-=1; } } /* overide stored arguments */ setArgs(argc, argv); /* install translation here */ for ( QStringList::ConstIterator it = d->langs.begin(); it != d->langs.end(); ++it ) installTranslation( (*it) + "/" + d->appName + ".qm" ); } #endif static QPtrDict<void>* inputMethodDict = 0; static void createInputMethodDict() { if ( !inputMethodDict ) inputMethodDict = new QPtrDict<void>; } /*! Returns the currently set hint to the system as to whether widget \a w has any use for text input methods. \sa setInputMethodHint() InputMethodHint */ QPEApplication::InputMethodHint QPEApplication::inputMethodHint( QWidget * w ) { if ( inputMethodDict && w ) return ( InputMethodHint ) ( int ) inputMethodDict->find( w ); return Normal; } /*! \enum QPEApplication::InputMethodHint \value Normal the application sometimes needs text input (the default). \value AlwaysOff the application never needs text input. \value AlwaysOn the application always needs text input. */ /*! Hints to the system that widget \a w has use for text input methods as specified by \a mode. \sa inputMethodHint() InputMethodHint */ void QPEApplication::setInputMethodHint( QWidget * w, InputMethodHint mode ) { createInputMethodDict(); if ( mode == Normal ) { inputMethodDict->remove ( w ); } else { inputMethodDict->insert( w, ( void* ) mode ); } } class HackDialog : public QDialog { public: void acceptIt() { accept(); } void rejectIt() { reject(); } }; void QPEApplication::mapToDefaultAction( QWSKeyEvent * ke, int key ) { // specialised actions for certain widgets. May want to // add more stuff here. if ( activePopupWidget() && activePopupWidget() ->inherits( "QListBox" ) && activePopupWidget() ->parentWidget() && activePopupWidget() ->parentWidget() ->inherits( "QComboBox" ) ) key = Qt::Key_Return; if ( activePopupWidget() && activePopupWidget() ->inherits( "QPopupMenu" ) ) key = Qt::Key_Return; #ifdef QWS ke->simpleData.keycode = key; #endif } /*! \internal */ #ifdef QWS bool QPEApplication::qwsEventFilter( QWSEvent * e ) { if ( !d->notbusysent && e->type == QWSEvent::Focus ) { if ( qApp->type() != QApplication::GuiServer ) { QCopEnvelope e( "QPE/System", "notBusy(QString)" ); e << d->appName; } d->notbusysent = TRUE; } if ( type() == GuiServer ) { switch ( e->type ) { case QWSEvent::Mouse: if ( e->asMouse() ->simpleData.state && !QWidget::find( e->window() ) ) emit clientMoused(); break; default: break; } } if ( e->type == QWSEvent::Key ) { QWSKeyEvent *ke = ( QWSKeyEvent * ) e; if ( ke->simpleData.keycode == Qt::Key_F33 ) { // Use special "OK" key to press "OK" on top level widgets QWidget * active = activeWindow(); QWidget *popup = 0; if ( active && active->isPopup() ) { popup = active; active = active->parentWidget(); } if ( active && ( int ) active->winId() == ke->simpleData.window && !active->testWFlags( WStyle_Customize | WType_Popup | WType_Desktop ) ) { if ( ke->simpleData.is_press ) { if ( popup ) popup->close(); if ( active->inherits( "QDialog" ) ) { HackDialog * d = ( HackDialog * ) active; d->acceptIt(); return TRUE; } else if ( ( ( HackWidget * ) active ) ->needsOk() ) { QSignal s; s.connect( active, SLOT( accept() ) ); s.activate(); } else { // do the same as with the select key: Map to the default action of the widget: mapToDefaultAction( ke, Qt::Key_Return ); } } } } else if ( ke->simpleData.keycode == Qt::Key_F30 ) { // Use special "select" key to do whatever default action a widget has mapToDefaultAction( ke, Qt::Key_Space ); } else if ( ke->simpleData.keycode == Qt::Key_Escape && ke->simpleData.is_press ) { // Escape key closes app if focus on toplevel QWidget * active = activeWindow(); if ( active && active->testWFlags( WType_TopLevel ) && ( int ) active->winId() == ke->simpleData.window && !active->testWFlags( WStyle_Dialog | WStyle_Customize | WType_Popup | WType_Desktop ) ) { if ( active->inherits( "QDialog" ) ) { HackDialog * d = ( HackDialog * ) active; d->rejectIt(); return TRUE; } else /*if ( strcmp( argv() [ 0 ], "embeddedkonsole" ) != 0 )*/ { active->close(); } } } else if ( ke->simpleData.keycode >= Qt::Key_F1 && ke->simpleData.keycode <= Qt::Key_F29 ) { // this should be if ( ODevice::inst ( )-> buttonForKeycode ( ... )) // but we cannot access libopie function within libqpe :( QWidget * active = activeWindow ( ); if ( active && ((int) active-> winId ( ) == ke-> simpleData.window )) { if ( d-> kbgrabbed ) { // we grabbed the keyboard QChar ch ( ke-> simpleData.unicode ); QKeyEvent qke ( ke-> simpleData. is_press ? QEvent::KeyPress : QEvent::KeyRelease, ke-> simpleData.keycode, ch. latin1 ( ), ke-> simpleData.modifiers, QString ( ch ), ke-> simpleData.is_auto_repeat, 1 ); QObject *which = QWidget::keyboardGrabber ( ); if ( !which ) which = QApplication::focusWidget ( ); if ( !which ) which = QApplication::activeWindow ( ); if ( !which ) which = qApp; QApplication::sendEvent ( which, &qke ); } else { // we didn't grab the keyboard, so send the event to the launcher QCopEnvelope e ( "QPE/Launcher", "deviceButton(int,int,int)" ); e << int( ke-> simpleData.keycode ) << int( ke-> simpleData. is_press ) << int( ke-> simpleData.is_auto_repeat ); } } return true; } } if ( e->type == QWSEvent::Focus ) { QWSFocusEvent * fe = ( QWSFocusEvent* ) e; if ( !fe->simpleData.get_focus ) { QWidget * active = activeWindow(); while ( active && active->isPopup() ) { active->close(); active = activeWindow(); } } else { // make sure our modal widget is ALWAYS on top QWidget *topm = activeModalWidget(); if ( topm && static_cast<int>( topm->winId() ) != fe->simpleData.window) { topm->raise(); } } if ( fe->simpleData.get_focus && inputMethodDict ) { InputMethodHint m = inputMethodHint( QWidget::find( e->window() ) ); if ( m == AlwaysOff ) Global::hideInputMethod(); if ( m == AlwaysOn ) Global::showInputMethod(); } } return QApplication::qwsEventFilter( e ); } #endif /*! Destroys the QPEApplication. */ QPEApplication::~QPEApplication() { ungrabKeyboard(); #if defined(Q_WS_QWS) && !defined(QT_NO_COP) // Need to delete QCopChannels early, since the display will // be gone by the time we get to ~QObject(). delete sysChannel; delete pidChannel; #endif #ifdef OPIE_WITHROHFEEDBACK if( d->RoH ) delete d->RoH; #endif delete d; } /*! Returns <tt>$OPIEDIR/</tt>. */ QString QPEApplication::qpeDir() { const char * base = getenv( "OPIEDIR" ); if ( base ) return QString( base ) + "/"; return QString( "../" ); } /*! Returns the user's current Document directory. There is a trailing "/". .. well, it does now,, and there's no trailing '/' */ QString QPEApplication::documentDir() { const char* base = getenv( "HOME"); if ( base ) return QString( base ) + "/Documents"; return QString( "../Documents" ); } static int deforient = -1; /*! \internal */ int QPEApplication::defaultRotation() { if ( deforient < 0 ) { QString d = getenv( "QWS_DISPLAY" ); if ( d.contains( "Rot90" ) ) { deforient = 90; } else if ( d.contains( "Rot180" ) ) { deforient = 180; } else if ( d.contains( "Rot270" ) ) { deforient = 270; } else { deforient = 0; } } return deforient; } /*! \internal */ void QPEApplication::setDefaultRotation( int r ) { if ( qApp->type() == GuiServer ) { deforient = r; setenv( "QWS_DISPLAY", QString( "Transformed:Rot%1:0" ).arg( r ).latin1(), 1 ); Config config("qpe"); config.setGroup( "Rotation" ); config.writeEntry( "Rot", r ); } else { #ifndef QT_NO_COP { QCopEnvelope e( "QPE/System", "setDefaultRotation(int)" ); e << r; } #endif } } #include <qgfx_qws.h> #include <qwindowsystem_qws.h> #if QT_VERSION > 236 extern void qws_clearLoadedFonts(); #endif void QPEApplication::setCurrentMode( int x, int y, int depth ) { // Reset the caches #if QT_VERSION > 236 qws_clearLoadedFonts(); #endif QPixmapCache::clear(); // Change the screen mode qt_screen->setMode(x, y, depth); if ( qApp->type() == GuiServer ) { #if QT_VERSION > 236 // Reconfigure the GuiServer qwsServer->beginDisplayReconfigure(); qwsServer->endDisplayReconfigure(); #endif // Get all the running apps to reset QCopEnvelope env( "QPE/System", "reset()" ); } } void QPEApplication::reset() { // Reconnect to the screen qt_screen->disconnect(); qt_screen->connect( QString::null ); // Redraw everything applyStyle(); } #if (QT_VERSION < 238) && defined Q_OS_MACX bool qt_left_hand_scrollbars = false; #else #ifdef Q_OS_MACX #define WEAK_SYMBOL __attribute__((weak_import)) #else #define WEAK_SYMBOL __attribute__((weak)) #endif extern bool qt_left_hand_scrollbars WEAK_SYMBOL; #endif /*! \internal */ void QPEApplication::applyStyle() { Config config( "qpe" ); config.setGroup( "Appearance" ); #if QT_VERSION > 233 #if !defined(OPIE_NO_OVERRIDE_QT) // don't block ourselves ... Opie::force_appearance = 0; static QString appname = Opie::binaryName ( ); QStringList ex = config. readListEntry ( "NoStyle", ';' ); int nostyle = 0; for ( QStringList::Iterator it = ex. begin ( ); it != ex. end ( ); ++it ) { if ( QRegExp (( *it ). mid ( 1 ), false, true ). find ( appname, 0 ) >= 0 ) { nostyle = ( *it ). left ( 1 ). toInt ( 0, 32 ); break; } } #else int nostyle = 0; #endif // Widget style QString style = config.readEntry( "Style", "FlatStyle" ); // don't set a custom style if ( nostyle & Opie::Force_Style ) style = "FlatStyle"; internalSetStyle ( style ); // Colors - from /etc/colors/Liquid.scheme QColor bgcolor( config.readEntry( "Background", "#E0E0E0" ) ); QColor btncolor( config.readEntry( "Button", "#96c8fa" ) ); QPalette pal( btncolor, bgcolor ); QString color = config.readEntry( "Highlight", "#73adef" ); pal.setColor( QColorGroup::Highlight, QColor( color ) ); color = config.readEntry( "HighlightedText", "#FFFFFF" ); pal.setColor( QColorGroup::HighlightedText, QColor( color ) ); color = config.readEntry( "Text", "#000000" ); pal.setColor( QColorGroup::Text, QColor( color ) ); color = config.readEntry( "ButtonText", "#000000" ); pal.setColor( QPalette::Active, QColorGroup::ButtonText, QColor( color ) ); color = config.readEntry( "Base", "#FFFFFF" ); pal.setColor( QColorGroup::Base, QColor( color ) ); pal.setColor( QPalette::Disabled, QColorGroup::Text, pal.color( QPalette::Active, QColorGroup::Background ).dark() ); setPalette( pal, TRUE ); // Set the ScrollBar on the 'right' side but only if the weak symbol is present if (&qt_left_hand_scrollbars ) qt_left_hand_scrollbars = config.readBoolEntry( "LeftHand", false ); // Window Decoration QString dec = config.readEntry( "Decoration", "Flat" ); // don't set a custom deco if ( nostyle & Opie::Force_Decoration ) dec = ""; if ( dec != d->decorationName ) { qwsSetDecoration( new QPEDecoration( dec ) ); d->decorationName = dec; } // Font QString ff = config.readEntry( "FontFamily", font().family() ); int fs = config.readNumEntry( "FontSize", font().pointSize() ); // don't set a custom font if ( nostyle & Opie::Force_Font ) { ff = "Vera"; fs = 10; } setFont ( QFont ( ff, fs ), true ); #if !defined(OPIE_NO_OVERRIDE_QT) // revert to global blocking policy ... Opie::force_appearance = config. readBoolEntry ( "ForceStyle", false ) ? Opie::Force_All : Opie::Force_None; Opie::force_appearance &= ~nostyle; #endif #endif } void QPEApplication::systemMessage( const QCString& msg, const QByteArray& data ) { #ifdef Q_WS_QWS QDataStream stream( data, IO_ReadOnly ); if ( msg == "applyStyle()" ) { applyStyle(); } else if ( msg == "toggleApplicationMenu()" ) { QWidget *active = activeWindow ( ); if ( active ) { QPEMenuToolFocusManager *man = QPEMenuToolFocusManager::manager ( ); bool oldactive = man-> isActive ( ); man-> setActive( !man-> isActive() ); if ( !oldactive && !man-> isActive ( )) { // no menubar to toggle -> try O-Menu QCopEnvelope e ( "QPE/TaskBar", "toggleStartMenu()" ); } } } else if ( msg == "setDefaultRotation(int)" ) { if ( type() == GuiServer ) { int r; stream >> r; setDefaultRotation( r ); } } else if ( msg == "setCurrentMode(int,int,int)" ) { // Added: 2003-06-11 by Tim Ansell <mithro@mithis.net> if ( type() == GuiServer ) { int x, y, depth; stream >> x; stream >> y; stream >> depth; setCurrentMode( x, y, depth ); } } else if ( msg == "reset()" ) { if ( type() != GuiServer ) reset(); } else if ( msg == "setCurrentRotation(int)" ) { int r; stream >> r; setCurrentRotation( r ); } else if ( msg == "shutdown()" ) { if ( type() == GuiServer ) shutdown(); } else if ( msg == "quit()" ) { if ( type() != GuiServer ) tryQuit(); } else if ( msg == "forceQuit()" ) { if ( type() != GuiServer ) quit(); } else if ( msg == "restart()" ) { if ( type() == GuiServer ) restart(); } else if ( msg == "language(QString)" ) { if ( type() == GuiServer ) { QString l; stream >> l; QString cl = getenv( "LANG" ); if ( cl != l ) { if ( l.isNull() ) unsetenv( "LANG" ); else setenv( "LANG", l.latin1(), 1 ); restart(); } } } else if ( msg == "timeChange(QString)" ) { QString t; stream >> t; if ( t.isNull() ) unsetenv( "TZ" ); else setenv( "TZ", t.latin1(), 1 ); // emit the signal so everyone else knows... emit timeChanged(); } else if ( msg == "addAlarm(QDateTime,QCString,QCString,int)" ) { if ( type() == GuiServer ) { QDateTime when; QCString channel, message; int data; stream >> when >> channel >> message >> data; AlarmServer::addAlarm( when, channel, message, data ); } } else if ( msg == "deleteAlarm(QDateTime,QCString,QCString,int)" ) { if ( type() == GuiServer ) { QDateTime when; QCString channel, message; int data; stream >> when >> channel >> message >> data; AlarmServer::deleteAlarm( when, channel, message, data ); } } else if ( msg == "clockChange(bool)" ) { int tmp; stream >> tmp; emit clockChanged( tmp ); } else if ( msg == "weekChange(bool)" ) { int tmp; stream >> tmp; emit weekChanged( tmp ); } else if ( msg == "setDateFormat(DateFormat)" ) { DateFormat tmp; stream >> tmp; emit dateFormatChanged( tmp ); } else if ( msg == "setVolume(int,int)" ) { int t, v; stream >> t >> v; setVolume( t, v ); emit volumeChanged( muted ); } else if ( msg == "volumeChange(bool)" ) { stream >> muted; setVolume(); emit volumeChanged( muted ); } else if ( msg == "setMic(int,int)" ) { // Added: 2002-02-08 by Jeremy Cowgar <jc@cowgar.com> int t, v; stream >> t >> v; setMic( t, v ); emit micChanged( micMuted ); } else if ( msg == "micChange(bool)" ) { // Added: 2002-02-08 by Jeremy Cowgar <jc@cowgar.com> stream >> micMuted; setMic(); emit micChanged( micMuted ); } else if ( msg == "setBass(int,int)" ) { // Added: 2002-12-13 by Maximilian Reiss <harlekin@handhelds.org> int t, v; stream >> t >> v; setBass( t, v ); } else if ( msg == "bassChange(bool)" ) { // Added: 2002-12-13 by Maximilian Reiss <harlekin@handhelds.org> setBass(); } else if ( msg == "setTreble(int,int)" ) { // Added: 2002-12-13 by Maximilian Reiss <harlekin@handhelds.org> int t, v; stream >> t >> v; setTreble( t, v ); } else if ( msg == "trebleChange(bool)" ) { // Added: 2002-12-13 by Maximilian Reiss <harlekin@handhelds.org> setTreble(); } else if ( msg == "getMarkedText()" ) { if ( type() == GuiServer ) { const ushort unicode = 'C'-'@'; const int scan = Key_C; qwsServer->processKeyEvent( unicode, scan, ControlButton, TRUE, FALSE ); qwsServer->processKeyEvent( unicode, scan, ControlButton, FALSE, FALSE ); } } else if ( msg == "newChannel(QString)") { QString myChannel = "QPE/Application/" + d->appName; QString channel; stream >> channel; if (channel == myChannel) { processQCopFile(); d->sendQCopQ(); } } #endif } /*! \internal */ bool QPEApplication::raiseAppropriateWindow() { bool r=FALSE; // 1. Raise the main widget QWidget *top = d->qpe_main_widget; if ( !top ) top = mainWidget(); if ( top && d->keep_running ) { if ( top->isVisible() ) r = TRUE; else if (d->preloaded) { // We are preloaded and not visible.. pretend we just started.. #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "fastAppShowing(QString)"); e << d->appName; #endif } d->show_mx(top,d->nomaximize, d->appName); top->raise(); } QWidget *topm = activeModalWidget(); // 2. Raise any parentless widgets (except top and topm, as they // are raised before and after this loop). Order from most // recently raised as deepest to least recently as top, so // that repeated calls cycle through widgets. QWidgetList *list = topLevelWidgets(); if ( list ) { bool foundlast = FALSE; QWidget* topsub = 0; if ( d->lastraised ) { for (QWidget* w = list->first(); w; w = list->next()) { if ( !w->parentWidget() && w != topm && w->isVisible() && !w->isDesktop() ) { if ( w == d->lastraised ) foundlast = TRUE; if ( foundlast ) { w->raise(); topsub = w; } } } } for (QWidget* w = list->first(); w; w = list->next()) { if ( !w->parentWidget() && w != topm && w->isVisible() && !w->isDesktop() ) { if ( w == d->lastraised ) break; w->raise(); topsub = w; } } d->lastraised = topsub; delete list; } // 3. Raise the active modal widget. if ( topm ) { topm->show(); topm->raise(); // If we haven't already handled the fastAppShowing message if (!top && d->preloaded) { #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "fastAppShowing(QString)"); e << d->appName; #endif } r = FALSE; } return r; } void QPEApplication::pidMessage( const QCString& msg, const QByteArray& data) { #ifdef Q_WS_QWS if ( msg == "quit()" ) { tryQuit(); } else if ( msg == "quitIfInvisible()" ) { if ( d->qpe_main_widget && !d->qpe_main_widget->isVisible() ) quit(); } else if ( msg == "close()" ) { hideOrQuit(); } else if ( msg == "disablePreload()" ) { d->preloaded = FALSE; d->keep_running = TRUE; /* so that quit will quit */ } else if ( msg == "enablePreload()" ) { if (d->qpe_main_widget) d->preloaded = TRUE; d->keep_running = TRUE; /* so next quit won't quit */ } else if ( msg == "raise()" ) { d->keep_running = TRUE; d->notbusysent = FALSE; raiseAppropriateWindow(); // Tell the system we're still chugging along... QCopEnvelope e("QPE/System", "appRaised(QString)"); e << d->appName; } else if ( msg == "flush()" ) { emit flush(); // we need to tell the desktop QCopEnvelope e( "QPE/Desktop", "flushDone(QString)" ); e << d->appName; } else if ( msg == "reload()" ) { emit reload(); } else if ( msg == "setDocument(QString)" ) { d->keep_running = TRUE; QDataStream stream( data, IO_ReadOnly ); QString doc; stream >> doc; QWidget *mw = mainWidget(); if ( !mw ) mw = d->qpe_main_widget; if ( mw ) Global::setDocument( mw, doc ); } else if ( msg == "QPEProcessQCop()" ) { processQCopFile(); d->sendQCopQ(); }else { bool p = d->keep_running; d->keep_running = FALSE; emit appMessage( msg, data); if ( d->keep_running ) { d->notbusysent = FALSE; raiseAppropriateWindow(); if ( !p ) { // Tell the system we're still chugging along... #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "appRaised(QString)"); e << d->appName; #endif } } if ( p ) d->keep_running = p; } #endif } /*! Sets widget \a mw as the mainWidget() and shows it. For small windows, consider passing TRUE for \a nomaximize rather than the default FALSE. \sa showMainDocumentWidget() */ void QPEApplication::showMainWidget( QWidget* mw, bool nomaximize ) { // setMainWidget(mw); this breaks FastLoading because lastWindowClose() would quit d->show(mw, nomaximize ); } /*! Sets widget \a mw as the mainWidget() and shows it. For small windows, consider passing TRUE for \a nomaximize rather than the default FALSE. This calls designates the application as a \link docwidget.html document-oriented\endlink application. The \a mw widget \e must have this slot: setDocument(const QString&). \sa showMainWidget() */ void QPEApplication::showMainDocumentWidget( QWidget* mw, bool nomaximize ) { if ( mw && argc() == 2 ) Global::setDocument( mw, QString::fromUtf8(argv()[1]) ); // setMainWidget(mw); see above d->show(mw, nomaximize ); } /*! If an application is started via a \link qcop.html QCop\endlink message, the application will process the \link qcop.html QCop\endlink message and then quit. If the application calls this function while processing a \link qcop.html QCop\endlink message, after processing its outstanding \link qcop.html QCop\endlink messages the application will start 'properly' and show itself. \sa keepRunning() */ void QPEApplication::setKeepRunning() { if ( qApp && qApp->inherits( "QPEApplication" ) ) { QPEApplication * qpeApp = ( QPEApplication* ) qApp; qpeApp->d->keep_running = TRUE; } } /*! Returns TRUE if the application will quit after processing the current list of qcop messages; otherwise returns FALSE. \sa setKeepRunning() */ bool QPEApplication::keepRunning() const { return d->keep_running; } /*! \internal */ void QPEApplication::internalSetStyle( const QString &style ) { #if QT_VERSION >= 300 if ( style == "QPE" ) { setStyle( new QPEStyle ); } else { QStyle *s = QStyleFactory::create( style ); if ( s ) setStyle( s ); } #else if ( style == "Windows" ) { setStyle( new QWindowsStyle ); } else if ( style == "QPE" ) { setStyle( new QPEStyle ); } else if ( style == "Light" ) { setStyle( new LightStyle ); } #ifndef QT_NO_STYLE_PLATINUM else if ( style == "Platinum" ) { setStyle( new QPlatinumStyle ); } #endif #ifndef QT_NO_STYLE_MOTIF else if ( style == "Motif" ) { setStyle( new QMotifStyle ); } #endif #ifndef QT_NO_STYLE_MOTIFPLUS else if ( style == "MotifPlus" ) { setStyle( new QMotifPlusStyle ); } #endif else { QStyle *sty = 0; QString path = QPEApplication::qpeDir ( ) + "/plugins/styles/"; #ifdef Q_OS_MACX if ( style. find ( ".dylib" ) > 0 ) path += style; else path = path + "lib" + style. lower ( ) + ".dylib"; // compatibility #else if ( style. find ( ".so" ) > 0 ) path += style; else path = path + "lib" + style. lower ( ) + ".so"; // compatibility #endif static QLibrary *lastlib = 0; static StyleInterface *lastiface = 0; QLibrary *lib = new QLibrary ( path ); StyleInterface *iface = 0; if (( lib-> queryInterface ( IID_Style, ( QUnknownInterface ** ) &iface ) == QS_OK ) && iface ) sty = iface-> style ( ); if ( sty ) { setStyle ( sty ); if ( lastiface ) lastiface-> release ( ); lastiface = iface; if ( lastlib ) { lastlib-> unload ( ); delete lastlib; } lastlib = lib; } else { if ( iface ) iface-> release ( ); delete lib; setStyle ( new LightStyle ( )); } } #endif } /*! \internal */ void QPEApplication::prepareForTermination( bool willrestart ) { if ( willrestart ) { // Draw a big wait icon, the image can be altered in later revisions // QWidget *d = QApplication::desktop(); QImage img = Resource::loadImage( "launcher/new_wait" ); QPixmap pix; pix.convertFromImage( img.smoothScale( 1 * img.width(), 1 * img.height() ) ); QLabel *lblWait = new QLabel( 0, "wait hack!", QWidget::WStyle_Customize | QWidget::WStyle_NoBorder | QWidget::WStyle_Tool ); lblWait->setPixmap( pix ); lblWait->setAlignment( QWidget::AlignCenter ); lblWait->show(); lblWait->showMaximized(); } #ifndef SINGLE_APP { QCopEnvelope envelope( "QPE/System", "forceQuit()" ); } processEvents(); // ensure the message goes out. sleep( 1 ); // You have 1 second to comply. #endif } /*! \internal */ void QPEApplication::shutdown() { // Implement in server's QPEApplication subclass } /*! \internal */ void QPEApplication::restart() { // Implement in server's QPEApplication subclass } static QPtrDict<void>* stylusDict = 0; static void createDict() { if ( !stylusDict ) stylusDict = new QPtrDict<void>; } /*! Returns the current StylusMode for widget \a w. \sa setStylusOperation() StylusMode */ QPEApplication::StylusMode QPEApplication::stylusOperation( QWidget* w ) { if ( stylusDict ) return ( StylusMode ) ( int ) stylusDict->find( w ); return LeftOnly; } /*! \enum QPEApplication::StylusMode \value LeftOnly the stylus only generates LeftButton events (the default). \value RightOnHold the stylus generates RightButton events if the user uses the press-and-hold gesture. \sa setStylusOperation() stylusOperation() */ /*! Causes widget \a w to receive mouse events according to the stylus \a mode. \sa stylusOperation() StylusMode */ void QPEApplication::setStylusOperation( QWidget * w, StylusMode mode ) { createDict(); if ( mode == LeftOnly ) { stylusDict->remove ( w ); w->removeEventFilter( qApp ); } else { stylusDict->insert( w, ( void* ) mode ); connect( w, SIGNAL( destroyed() ), qApp, SLOT( removeSenderFromStylusDict() ) ); w->installEventFilter( qApp ); } } /*! \reimp */ bool QPEApplication::eventFilter( QObject *o, QEvent *e ) { if ( !o->isWidgetType() ) return FALSE; if ( stylusDict && e->type() >= QEvent::MouseButtonPress && e->type() <= QEvent::MouseMove ) { QMouseEvent * me = ( QMouseEvent* ) e; StylusMode mode = (StylusMode)(int)stylusDict->find(o); switch (mode) { case RightOnHold: switch ( me->type() ) { case QEvent::MouseButtonPress: if ( me->button() == LeftButton ) { static long Pref = 500; // #### pref. d->presswidget = (QWidget*)o; d->presspos = me->pos(); d->rightpressed = FALSE; #ifdef OPIE_WITHROHFEEDBACK if( ! d->RoH ) d->RoH = new Opie::Internal::RoHFeedback; d->RoH->init( me->globalPos(), d->presswidget ); Pref = d->RoH->delay(); #endif if (!d->presstimer ) d->presstimer = startTimer( Pref ); // #### pref. } break; case QEvent::MouseMove: if (d->presstimer && (me->pos() - d->presspos).manhattanLength() > 8) { killTimer(d->presstimer); #ifdef OPIE_WITHROHFEEDBACK d->RoH->stop(); #endif d->presstimer = 0; } break; case QEvent::MouseButtonRelease: if ( me->button() == LeftButton ) { if ( d->presstimer ) { killTimer(d->presstimer); #ifdef OPIE_WITHROHFEEDBACK d->RoH->stop( ); #endif d->presstimer = 0; } if ( d->rightpressed && d->presswidget ) { printf( "Send ButtonRelease\n" ); // Right released postEvent( d->presswidget, new QMouseEvent( QEvent::MouseButtonRelease, me->pos(), RightButton, LeftButton + RightButton ) ); // Left released, off-widget postEvent( d->presswidget, new QMouseEvent( QEvent::MouseMove, QPoint( -1, -1), LeftButton, LeftButton ) ); postEvent( d->presswidget, new QMouseEvent( QEvent::MouseButtonRelease, QPoint( -1, -1), LeftButton, LeftButton ) ); d->rightpressed = FALSE; return TRUE; // don't send the real Left release } } break; default: break; } break; default: ; } } else if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease ) { QKeyEvent *ke = (QKeyEvent *)e; if ( ke->key() == Key_Enter ) { if ( o->isA( "QRadioButton" ) || o->isA( "QCheckBox" ) ) { postEvent( o, new QKeyEvent( e->type(), Key_Space, ' ', ke->state(), " ", ke->isAutoRepeat(), ke->count() ) ); return TRUE; } } } return FALSE; } /*! \reimp */ void QPEApplication::timerEvent( QTimerEvent *e ) { if ( e->timerId() == d->presstimer && d->presswidget ) { // Right pressed postEvent( d->presswidget, new QMouseEvent( QEvent::MouseButtonPress, d->presspos, RightButton, LeftButton ) ); killTimer( d->presstimer ); d->presstimer = 0; d->rightpressed = TRUE; #ifdef OPIE_WITHROHFEEDBACK d->RoH->stop(); #endif } } void QPEApplication::removeSenderFromStylusDict() { stylusDict->remove ( ( void* ) sender() ); if ( d->presswidget == sender() ) d->presswidget = 0; } /*! \internal */ bool QPEApplication::keyboardGrabbed() const { return d->kbgrabbed; } /*! Reverses the effect of grabKeyboard(). This is called automatically on program exit. */ void QPEApplication::ungrabKeyboard() { ((QPEApplication *) qApp )-> d-> kbgrabbed = false; } /*! Grabs the physical keyboard keys, e.g. the application's launching keys. Instead of launching applications when these keys are pressed the signals emitted are sent to this application instead. Some games programs take over the launch keys in this way to make interaction easier. \sa ungrabKeyboard() */ void QPEApplication::grabKeyboard() { ((QPEApplication *) qApp )-> d-> kbgrabbed = true; } /*! \reimp |