Commit d45e0efbc033d630338552b15f59f00975d91c50

libopie2: add support for special key/button combinations

  * Add support for arbitrary key/button combinations. Currently these are
    only for special hardcoded combos.
  * Implement "recalibrate screen" combo for iPAQs & Zauruses (centre of
    joypad + Calendar). Fixes bug #1831.
  * Implement hold-down of record button to recalibrate when screen is
    locked (a la GPE) for iPAQs with a record button.
  
199199 else
200200 locked = loginlock;
201201
202 // Do hardcoded button combos
203 if( !autoRepeat && ( locked || !keyRegistered( keycode ) ) ) {
204 if( ODevice::inst()->comboKeyEvent( keycode, press, locked ) )
205 return true;
206 }
207
202208 if ( locked
203209 // Permitted keys
204210 && keycode != Key_F34 // power
  
193193
194194 d->m_holdtime = 1000; // 1000ms
195195 d->m_buttons = 0;
196 d->m_buttonCombos = 0;
196197 d->m_cpu_frequencies = new QStrList;
197198
198199
220220 break;
221221 }
222222 }
223
224 d->m_heldCombo = 0;
225 d->m_heldComboTimer = new QTimer( this );
226 connect( d->m_heldComboTimer, SIGNAL(timeout()), this, SLOT(holdCheckCombo()) );
223227}
224228
225229void ODevice::systemMessage( const QCString &msg, const QByteArray & )
261261 reloadButtonMapping();
262262}
263263
264/**
265* This method initialises the special combo mapping
266*/
267void ODevice::initButtonCombos()
268{
269 if ( d->m_buttonCombos )
270 return;
271
272 d->m_buttonCombos = new QValueList<ODeviceButtonCombo>;
273}
274
275void ODevice::loadButtonCombos( const ODeviceButtonComboStruct combos[], uint length )
276{
277 for ( uint i = 0; i < length; i++ ) {
278 const ODeviceButtonComboStruct *cs = combos + i;
279 ODeviceButtonCombo c;
280
281 if (( cs->model & d->m_model ) == d->m_model ) {
282 c.setKeycodes( cs->keycode1, cs->keycode2, cs->keycode3 );
283 c.setHold( cs->hold );
284 c.setKeycodeDesc( QObject::tr ( "Button", cs->keycodedesc ));
285 c.setAction( OQCopMessage( makeChannel ( cs->actionchan ), cs->actionmsg ));
286 c.setActionDesc( QObject::tr ( "ComboAction", cs->actiondesc ));
287 c.setLockedOnly( cs->lockedonly );
288
289 d->m_buttonCombos->append( c );
290 }
291 }
292}
293
264294ODevice::~ODevice()
265295{
266296 // we leak m_devicebuttons and m_cpu_frequency
626626}
627627
628628/**
629* @return a list of special button combos
630*/
631const QValueList <ODeviceButtonCombo> &ODevice::buttonCombos()
632{
633 initButtonCombos();
634
635 return *d->m_buttonCombos;
636}
637
638/**
629639* @return The amount of time that would count as a hold
630640*/
631641uint ODevice::buttonHoldTime() const
659659 return &(*it);
660660 }
661661 return 0;
662}
663
664bool ODevice::comboKeyEvent( ushort keycode, bool press, bool locked )
665{
666 initButtonCombos();
667
668 for( QValueListIterator<ODeviceButtonCombo> it = d->m_buttonCombos->begin(); it != d->m_buttonCombos->end(); ++it ) {
669 if( (*it).keyCodeEvent( keycode, press, locked ) ) {
670 if( (*it).hold() ) {
671 // This combo needs to be held down to activate
672 if( press ) {
673 d->m_heldCombo = &(*it);
674 d->m_heldComboTimer->start( d->m_holdtime, true );
675 }
676 else
677 d->m_heldComboTimer->stop();
678 }
679 return true;
680 }
681 }
682 return false;
683}
684
685void ODevice::holdCheckCombo()
686{
687 d->m_heldCombo->checkActivate();
662688}
663689
664690void ODevice::reloadButtonMapping()
  
3838#include <qnamespace.h>
3939#include <qobject.h>
4040#include <qstring.h>
41#include <qtimer.h>
4142
4243
4344#include <qstrlist.h>
8383
8484 Model_Zaurus = ( 3 << 20 ),
8585
86 Model_Zaurus_All = ( Model_Zaurus | 0xfffff ),
8687 Model_Zaurus_SL5000 = ( Model_Zaurus | 0x00001 ),
8788 Model_Zaurus_SL5500 = ( Model_Zaurus | 0x00002 ),
8889 Model_Zaurus_SLA300 = ( Model_Zaurus | 0x00004 ),
269269 char *fheldaction;
270270};
271271
272struct ODeviceButtonComboStruct {
273 uint model;
274 Qt::Key keycode1;
275 Qt::Key keycode2;
276 Qt::Key keycode3;
277 bool hold;
278 const char *keycodedesc;
279 const char *actionchan;
280 const char *actionmsg;
281 const char *actiondesc;
282 bool lockedonly;
283};
284
272285/**
273286 * A singleton which gives informations about device specefic option
274287 * like the Hardware used, LEDs, the Base Distribution and
304304 ODevice();
305305 virtual void init(const QString&);
306306 virtual void initButtons();
307 virtual void initButtonCombos();
307308 static void sendSuspendmsg();
309 void loadButtonCombos( const ODeviceButtonComboStruct combos[], uint length );
308310
309311 ODeviceData *d;
310312
404404 */
405405 uint buttonHoldTime() const;
406406
407 /**
408 * Returns the button combos set up for this device. At the moment these are intended
409 * to be hard-coded eg. for launching screen calibration.
410 *
411 */
412 const QValueList<ODeviceButtonCombo> &buttonCombos();
413
414 /**
415 * Try all registered button combos and launch action if one has been activated
416 * @returns true if the combo was activated, false otherwise
417 */
418 bool comboKeyEvent( ushort keycode, bool press, bool locked );
419
407420signals:
408421 void buttonMappingChanged();
409422
410423private slots:
411424 void systemMessage ( const QCString &, const QByteArray & );
425 void holdCheckCombo();
412426
413427protected:
414428 void addPreHandler(QWSServer::KeyboardFilter*aFilter);
453453 QString m_qteDriver;
454454
455455 QValueList <ODeviceButton> *m_buttons;
456 QValueList <ODeviceButtonCombo> *m_buttonCombos;
456457 uint m_holdtime;
457458 QStrList *m_cpu_frequencies;
458459 bool m_initializedButtonQcop : 1;
460 ODeviceButtonCombo *m_heldCombo;
461 QTimer *m_heldComboTimer;
459462};
460463
461464extern bool isQWS();
  
150150
151151};
152152
153struct ODeviceButtonComboStruct ipaq_combos[] = {
154 // Centre of joypad + Calendar -> recalibrate
155 { Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx | Model_Keyboardless_2_6,
156 Qt::Key_Return, Qt::Key_F9, Qt::Key_unknown, false, QT_TRANSLATE_NOOP("Button", "Joypad + Calendar"),
157 "QPE/Application/calibrate", "raise()", QT_TRANSLATE_NOOP("ComboAction", "Recalibrate screen"), false },
158 // Hold down Record (only when device locked) -> recalibrate
159 { Model_iPAQ_H191x | Model_iPAQ_HX4700 | Model_iPAQ_H4xxx |
160 Model_iPAQ_H31xx | Model_iPAQ_H36xx | Model_iPAQ_H37xx | Model_iPAQ_H38xx | Model_iPAQ_H39xx | Model_iPAQ_H5xxx,
161 Qt::Key_F24, Qt::Key_unknown, Qt::Key_unknown, true, QT_TRANSLATE_NOOP("Button", "Record Button"),
162 "QPE/Application/calibrate", "raise()", QT_TRANSLATE_NOOP("ComboAction", "Recalibrate screen"), true }
163};
164
153165void iPAQ::init(const QString& model)
154166{
155167 d->m_vendorstr = "HP";
258258 }
259259 }
260260 reloadButtonMapping();
261}
262
263void iPAQ::initButtonCombos()
264{
265 d->m_buttonCombos = new QValueList<ODeviceButtonCombo>;
266 loadButtonCombos( ipaq_combos, sizeof( ipaq_combos ) / sizeof( ODeviceButtonComboStruct ) );
261267}
262268
263269QValueList <OLed> iPAQ::ledList() const
  
4545 protected:
4646 virtual void init(const QString&);
4747 virtual void initButtons();
48 virtual void initButtonCombos();
4849
4950 public:
5051 virtual bool setDisplayStatus ( bool on );
  
191191 "sound", "raise()" },
192192};
193193
194struct ODeviceButtonComboStruct z_combos[] = {
195 // Centre of joypad (OK) + Calendar -> recalibrate
196 { Model_Zaurus_All,
197 Qt::Key_Return, Qt::Key_F9, Qt::Key_unknown, false, QT_TRANSLATE_NOOP("Button", "OK + Calendar"),
198 "QPE/Application/calibrate", "raise()", QT_TRANSLATE_NOOP("ComboAction", "Recalibrate screen"), false },
199};
200
201
194202// FIXME This gets unnecessary complicated. We should think about splitting the Zaurus
195203// class up into individual classes. We would need three classes
196204//
390390 reloadButtonMapping();
391391}
392392
393void Zaurus::initButtonCombos()
394{
395 d->m_buttonCombos = new QValueList<ODeviceButtonCombo>;
396 loadButtonCombos( z_combos, sizeof( z_combos ) / sizeof( ODeviceButtonComboStruct ) );
397}
393398
394399
395400typedef struct sharp_led_status {
  
102102 protected:
103103 virtual void init(const QString&);
104104 virtual void initButtons();
105 void initButtonCombos();
105106 void initHingeSensor();
106107
107108 protected slots:
  
4545 QCString m_message;
4646 QByteArray m_data;
4747};
48
4849}
4950
5051using namespace Opie::Core;
262262void ODeviceButton::setHeldAction(const OQCopMessage& action)
263263{
264264 m_HeldAction = action;
265}
266
267/////////////////////////////////////////////////////////////////
268
269ODeviceButtonCombo::ODeviceButtonCombo()
270 : m_keycode1( 0 )
271 , m_keycode2( 0 )
272 , m_keycode3( 0 )
273 , m_down1( false )
274 , m_down2( false )
275 , m_down3( false )
276 , m_lockedOnly( false )
277 , m_hold( false )
278 , d( 0 )
279{
280}
281
282ODeviceButtonCombo::~ODeviceButtonCombo()
283{
284}
285
286QString ODeviceButtonCombo::keycodeDesc() const
287{
288 return m_keycodeDesc;
289}
290
291QString ODeviceButtonCombo::actionDesc() const
292{
293 return m_actionDesc;
294}
295
296OQCopMessage ODeviceButtonCombo::action() const
297{
298 return m_action;
299}
300
301bool ODeviceButtonCombo::keyCodeEvent( ushort keycode, bool down, bool locked )
302{
303 bool res = false;
304 if( m_down1 && m_down2 && m_down3 )
305 res = true;
306
307 if( keycode == m_keycode1 )
308 m_down1 = down;
309 else if( keycode == m_keycode2 )
310 m_down2 = down;
311 else if( keycode == m_keycode3 )
312 m_down3 = down;
313 else
314 return false;
315
316 if( !locked && m_lockedOnly ) {
317 return false;
318 }
319
320 if( m_down1 && m_down2 && m_down3 ) {
321 if( !m_hold )
322 m_action.send();
323 return true;
324 }
325 else
326 return res;
327}
328
329void ODeviceButtonCombo::setKeycodes( ushort keycode1, ushort keycode2, ushort keycode3 )
330{
331 m_keycode1 = keycode1;
332 m_keycode2 = keycode2;
333 m_keycode3 = keycode3;
334
335 if( m_keycode2 == Qt::Key_unknown ) {
336 m_down2 = true;
337 m_keycode2 = 0;
338 }
339 if( m_keycode3 == Qt::Key_unknown ) {
340 m_down3 = true;
341 m_keycode3 = 0;
342 }
343}
344
345void ODeviceButtonCombo::setAction( const OQCopMessage& qcopMessage )
346{
347 m_action = qcopMessage;
348}
349
350void ODeviceButtonCombo::setActionDesc( const QString& desc )
351{
352 m_actionDesc = desc;
353}
354
355void ODeviceButtonCombo::setKeycodeDesc( const QString& desc )
356{
357 m_keycodeDesc = desc;
358}
359
360void ODeviceButtonCombo::setLockedOnly( bool lockedOnly )
361{
362 m_lockedOnly = lockedOnly;
363}
364
365void ODeviceButtonCombo::setHold( bool hold )
366{
367 m_hold = hold;
368}
369
370bool ODeviceButtonCombo::hold() const
371{
372 return m_hold;
373}
374
375bool ODeviceButtonCombo::checkActivate()
376{
377 if( m_down1 && m_down2 && m_down3 ) {
378 m_action.send();
379 return true;
380 }
381 else
382 return false;
265383}
266384
267385}
  
106106 Private *d;
107107};
108108
109/**
110 * This class represents a combination of physical buttons on a device.
111 * This is intended to be used for rarely used hard-coded actions such as
112 * launching screen calibration.
113 *
114 * @version 1.0
115 * @author Paul Eggleton
116 * @short A representation of special multi-button combinations
117 */
118class ODeviceButtonCombo
119{
120 public:
121 ODeviceButtonCombo();
122 virtual ~ODeviceButtonCombo();
123
124 QString keycodeDesc() const;
125 QString actionDesc() const;
126 OQCopMessage action() const;
127 bool hold() const;
128 bool keyCodeEvent( ushort keycode, bool down, bool locked );
129
130 void setKeycodes( ushort keycode1, ushort keycode2, ushort keycode3 );
131 void setAction( const OQCopMessage& qcopMessage );
132 void setActionDesc( const QString& desc );
133 void setKeycodeDesc( const QString& desc );
134 void setLockedOnly( bool lockedOnly );
135 void setHold( bool hold );
136 public:
137 bool checkActivate();
138
139 private:
140 ushort m_keycode1;
141 ushort m_keycode2;
142 ushort m_keycode3;
143 bool m_down1;
144 bool m_down2;
145 bool m_down3;
146 OQCopMessage m_action;
147 QString m_actionDesc;
148 QString m_keycodeDesc;
149 bool m_lockedOnly;
150 bool m_hold;
151 class Private;
152 Private *d;
153};
154
155
109156}
110157}
111158