/***************************************************************************
kkeyled.cpp - description
-------------------
begin : Mon Apr 23 13:06:31 CEST 2001
copyright : (C) 2001 by Dieter Landolt
email : dieter.landolt@secs.ch
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <klocale.h>
#include <qwidget.h>
#include <kmessagebox.h>
#include <kpopupmenu.h>
#include <ksimpleconfig.h>
#include <kicondialog.h>
#include <kiconloader.h>
#include <ktoolbarbutton.h>
#include <qvbox.h>
#include <qhbox.h>
#include <qevent.h>
#include <qframe.h>
#include <kpushbutton.h>
#include <qcheckbox.h>
#include <qtooltip.h>
#include <qwhatsthis.h>
#include <kmainwindow.h>
#include <kglobal.h>
#include "dockwidget.h"
#include "kkeyled.h"
#include "kkeyleddtlcfg.h"
extern "C" {
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
}
Kkeyled::Kkeyled(QWidget *parent, const char *name, Qt::WFlags f)
: KMainWindow(parent, name, f)
{
KGlobal::config()->reparseConfiguration();
/* Create and Connect to the try widgets */
nl = new DockWidget(this,"numlock",DockWidget::Numlock);
cl = new DockWidget(this,"capslock",DockWidget::Capslock);
sl = new DockWidget(this,"scrollock",DockWidget::Scrollock);
setCaption(i18n("Keyboard led setup Window"));
blink = new QTimer(this);
connect(blink,SIGNAL(timeout()),SLOT(checkState()));
connect(this,SIGNAL(numLockKeyChanged(State)),nl, SLOT(setState(State)));
connect(this,SIGNAL(capsLockKeyChanged(State)),cl, SLOT(setState(State)));
connect(this,SIGNAL(scrollLockKeyChanged(State)),sl, SLOT(setState(State)));
connect(nl,SIGNAL(stateChanged(bool)), this, SLOT(setNumLockState(bool)));
connect(cl,SIGNAL(stateChanged(bool)), this, SLOT(setCapsLockState(bool)));
connect(sl,SIGNAL(stateChanged(bool)), this, SLOT(setScrollLockState(bool)));
blink->start(125); // sets the Timer to 1/8 sek.
/* start the design for the config window */
/*
*******************************
* vb *
* *************************** *
* * hb *
* * ********** *********** * *
* * * * * * * *
* * * vb1 * * vb2 * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * ********** *********** * *
* *************************** *
*******************************
*/
QVBox *vb = new QVBox(this);
QHBox *hb = new QHBox(vb); // create a hbox inside the vbox for the first entry
QVBox *vb1 = new QVBox(hb);
QVBox *vb2 = new QVBox(hb);
vb->setLineWidth(4);
vb->setMargin(4);
vb->setFrameStyle(QFrame::Box | QFrame::Raised);
cbnl = new QCheckBox(i18n("Numlock"),vb1,"Numlock");
cbcl = new QCheckBox(i18n("Capslock"),vb1,"Capslock");
cbsl = new QCheckBox(i18n("Scrollock"),vb1,"Scrollock");
// add a little button for the what's this help in this dialog, it's easier then
// point to the led click the right mose key an chose it in the submenu
// QPushButton *qtb = new QPushButton(QIconSet(BarIcon("contexthelp", kapp), QSize(32,32)),i18n("What's &This?"),vb2,"helpicon");
QPushButton *qtb = new QPushButton(vb2,"helpicon");
// qtb->setIconSet(QIconSet(BarIcon("contexthelp")));
qtb->setPixmap(BarIcon("contexthelp"));
QToolTip::add(qtb, i18n("What's This?"));
QWhatsThis::add(qtb, i18n("this button activate's the what's This help"));
connect(qtb, SIGNAL(clicked()),this, SLOT(whatsThis()));
// add the Button for the Detailconfig Dialog
QPushButton *qdd = new QPushButton(i18n("&detail"),vb2);
QToolTip::add(qdd, i18n("click for detail configuration"));
QWhatsThis::add(qdd, i18n("click it to make a detailed configuration like the pixmap to use"));
connect(qdd, SIGNAL(clicked()),this, SLOT(detailconfig()));
QToolTip::add(cbnl, i18n("you can change the visibility for the numlock led here"));
QToolTip::add(cbcl, i18n("you can change the visibility for the capslock led here"));
QToolTip::add(cbsl, i18n("you can change the visibility for the scrollock led here"));
QWhatsThis::add(cbnl, i18n("click on the box to toggle the visibilitie\n"
"of the numlock key led in the panel."
));
QWhatsThis::add(cbcl, i18n("click on the box to toggle the visibilitie\n"
"of the capslock key led in the panel."
));
QWhatsThis::add(cbsl, i18n("click on the box to toggle the visibilitie\n"
"of the scrollock key led in the panel."
));
QFrame *myqf = new QFrame(vb);
myqf->setLineWidth(3);
myqf->setGeometry( QRect( 120, 170, 281, 20 ) );
myqf->setFrameStyle( QFrame::HLine | QFrame::Sunken );
// read the configuration
restLedstate = new QCheckBox(i18n("restore state"),vb,"restorestate");
QToolTip::add(restLedstate, i18n("check this box if you like to restore saved state at startup"));
QWhatsThis::add(restLedstate, i18n("if you activate this box the state of the led's\n"
"will be restored as it was by clicking the save button."
));
QPushButton *saveLedStateB = new QPushButton(vb,"save");
saveLedStateB->setText(i18n("&save"));
QToolTip::add(saveLedStateB, i18n("save the state of the led's"));
QWhatsThis::add(saveLedStateB, i18n("you can save here the actual state off the\n"
"capslock,numlock and scrolllock key.\n"
"if you checked the box over it will restored at the starttime"
));
saveLedStateB->adjustSize();
// KSimpleConfig conf ("Kkeyledrc");
KGlobal::config()->setGroup("Trayvisible");
cbnl->setChecked( KGlobal::config()->readBoolEntry("Numlock",true));
cbcl->setChecked( KGlobal::config()->readBoolEntry("Capslock",true));
cbsl->setChecked( KGlobal::config()->readBoolEntry("Scrollock",true));
// and now reduce the visibility when its nessesary
if(! cbnl->isOn() )
nl->hide();
if(! cbcl->isOn() )
cl->hide();
if(! cbsl->isOn() )
sl->hide();
// restore the keystat's if it's so configured
KGlobal::config()->setGroup("Restore");
restLedstate->setChecked(KGlobal::config()->readBoolEntry("Restore",false));
if(restLedstate->isChecked()) {
setNumLockState(KGlobal::config()->readBoolEntry("Numlock",false));
setCapsLockState(KGlobal::config()->readBoolEntry("Capslock",false));
setScrollLockState(KGlobal::config()->readBoolEntry("Scrollock",false));
nl->setlocked(KGlobal::config()->readBoolEntry("numlocked",false));
cl->setlocked(KGlobal::config()->readBoolEntry("capslocked",false));
sl->setlocked(KGlobal::config()->readBoolEntry("scrollocked",false));
}
vb->adjustSize();
// connect the checkboxes for set to visible invsible
connect(cbnl, SIGNAL(stateChanged(int)),nl, SLOT(changeVisible(int)));
connect(cbcl, SIGNAL(stateChanged(int)),cl, SLOT(changeVisible(int)));
connect(cbsl, SIGNAL(stateChanged(int)),sl, SLOT(changeVisible(int)));
// connect the checkboxes for set to save alltrue the config
connect(cbnl, SIGNAL(stateChanged(int)),SLOT(configSave(int)));
connect(cbcl, SIGNAL(stateChanged(int)),SLOT(configSave(int)));
connect(cbsl, SIGNAL(stateChanged(int)),SLOT(configSave(int)));
connect(restLedstate, SIGNAL(stateChanged(int)),SLOT(configSave(int)));
// save a spezific lockstate for restoring
connect(saveLedStateB, SIGNAL(clicked()), SLOT(configSaveState()));
// Use the focus Policy
setFocusPolicy(QWidget::StrongFocus);
// set a position if no led is as visible configured
QWidget *desktop = QApplication::desktop();
int wi = desktop->width(); // returns screen width
int hi = desktop->height(); // returns screen height
resize(vb->width(),vb->height());
move(wi - width(),hi - height());
if( ! cbnl->isOn() && ! cbcl->isOn() && ! cbsl->isOn() ) {
setFocus();
show();
} else {
hide();
}
}
Kkeyled::~Kkeyled()
{
}
/** Handels the Timer event and modifies
the Keyboardstate and after sends the signal to
the right Object
*/
void Kkeyled::checkState(){
unsigned int states;
static unsigned int oldstates=255;
XkbGetIndicatorState(this->x11Display(),XkbUseCoreKbd,&states);
if (oldstates != states ) {
oldstates = states;
int i, bit;
for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1)
{
int flag;
flag=states&bit;
switch (i)
{
case 1: // Numlock
if (flag)
numLockKeyChanged(On);
else
numLockKeyChanged(Off);
break;
case 0: // CapsLock
if (flag)
capsLockKeyChanged(On);
else
capsLockKeyChanged(Off);
break;
case 2: //ScrollLock
if (flag)
scrollLockKeyChanged(On);
else
scrollLockKeyChanged(Off);
break;
}
}
}
}
/** sets the Numlockkey to a spezified value */
void Kkeyled::setNumLockState(bool st){
unsigned int mask;
if( !xkb_init())
return;
mask = xkb_lock_mask((char*) "NumLock");
setLockState(st, mask);
}
/** sets the Capslockkey to a spezified value */
void Kkeyled::setCapsLockState(bool st){
unsigned int mask;
if( !xkb_init())
return;
mask = xkb_lock_mask((char*) "Caps Lock");
setLockState(st, mask);
}
/** sets the Scrollockkey to a spezified value */
void Kkeyled::setScrollLockState(bool st){
unsigned int mask;
if( !xkb_init())
return;
mask = xkb_lock_mask((char*) "ScrollLock");
setLockState(st, mask);
}
/** set the keystate */
void Kkeyled::setLockState(bool st, unsigned int &mask){
if( mask == 0 )
return;
if(st) {
XkbLockModifiers ( this->x11Display(), XkbUseCoreKbd, mask, mask);
} else {
XkbLockModifiers ( this->x11Display(), XkbUseCoreKbd, mask, 0);
}
}
/** overwright the show event for repositioning the window on top
of the icon */
void Kkeyled::showEvent(QShowEvent *e){
if ( nl->globalPos->x() > 0) { // Neupositionierung nur wenn statische Variable > 0;
QWidget *desktop = QApplication::desktop();
int wi = desktop->width(); // returns screen width
// int hi = desktop->height(); // returns screen height
QPoint nPos;
if(nl->globalPos->y() -height() > 0 ) { // it's not on top
nPos.setY(nl->globalPos->y() -height());
nPos.setX(nl->globalPos->x() - (width() / 2));
} else {
if( nl->globalPos->y() > 0 ) {
nPos.setY(nl->globalPos->y() + nl->height() );
nPos.setX(nl->globalPos->x() - (width() / 2));
}
}
if ( nPos.x() < 0 ) {
nPos.setX(nl->globalPos->x() + nl->width());
} else {
if ( nl->globalPos->x() + (width() / 2) > wi ) {
nPos.setX(nl->globalPos->x() - width());
}
}
move(nPos);
}
QWidget::showEvent(e); // execute the normal showevent
raise();
}
/** Saving the Configfile */
void Kkeyled::configSave(int){
KGlobal::config()->setGroup("Trayvisible");
KGlobal::config()->writeEntry("Numlock",cbnl->isOn(),true,false,false);
KGlobal::config()->writeEntry("Capslock",cbcl->isOn(),true,false,false);
KGlobal::config()->writeEntry("Scrollock",cbsl->isOn(),true,false,false);
KGlobal::config()->setGroup("Restore");
KGlobal::config()->writeEntry("Restore",restLedstate->isOn(),true,false,false);
/*
To be shure we have allready the focus.
it's nessesary when we like to check the lost of the focus.
we lost the focus when no led checkbosx is checked to be visibel
the user moves also to a other window then this
the user comes back and checks also a led to be visibel, the mainwindow need's the
also to set as active.
*/
setActiveWindow();
}
/** Saving the state of the Le'ds to Config file Configfile */
void Kkeyled::configSaveState(){
// KSimpleConfig conf ("Kkeyledrc");
KGlobal::config()->setGroup("Restore");
KGlobal::config()->writeEntry("Numlock",nl->getState(),true,false,false);
KGlobal::config()->writeEntry("Capslock",cl->getState(),true,false,false);
KGlobal::config()->writeEntry("Scrollock",sl->getState(),true,false,false);
KGlobal::config()->writeEntry("numlocked", nl->isLocked(),true,false,false);
KGlobal::config()->writeEntry("capslocked", cl->isLocked(),true,false,false);
KGlobal::config()->writeEntry("scrollocked", sl->isLocked(),true,false,false);
}
/** Initialize the xkeyboard */
int Kkeyled::xkb_init(){
int xkb_opcode, xkb_event, xkb_error;
int xkb_lmaj = XkbMajorVersion;
int xkb_lmin = XkbMinorVersion;
return XkbLibraryVersion( &xkb_lmaj, &xkb_lmin )
&& XkbQueryExtension( this->x11Display(), &xkb_opcode, &xkb_event, &xkb_error,
&xkb_lmaj, &xkb_lmin );
}
/** Modifie the Keyboardmask */
unsigned int Kkeyled::xkb_mask_modifier( XkbDescPtr xkb, const char *name ){
unsigned int mask=0;
int i;
if( !xkb || !xkb->names )
return 0;
if ( strcmp(name, "Caps Lock") == 0 )
return 2; // this is a workaround then function does not return this 2 witch works
// needs moor debuging to find the real Problem here
for( i = 0; i <= XkbNumVirtualMods; i++ ) {
char* modStr = XGetAtomName( xkb->dpy, xkb->names->vmods[i] );
// qDebug("Name = *%s* modStr = *%s*\n", name, modStr);
if( modStr != NULL && strcmp(name, modStr) == 0 )
{
// found the keyname and convert it
XkbVirtualModsToReal( xkb, 1 << i, &mask );
// qDebug("Mask = %i / i = %i\n", mask, i);
return mask;
}
}
return 0;
}
/** generallfunction to return the mask for the modifier key */
unsigned int Kkeyled::xkb_lock_mask(char* keyname){
XkbDescPtr xkb;
if(( xkb = XkbGetKeyboard( this->x11Display(), XkbAllComponentsMask, XkbUseCoreKbd )) != NULL )
{
unsigned int mask = xkb_mask_modifier( xkb, keyname );
XkbFreeKeyboard( xkb, 0, True );
return mask;
}
return 0;
}
/** Starts and handles the detailconfig dialog */
void Kkeyled::detailconfig(){
kkeyleddtlcfg *lcfgdia = new kkeyleddtlcfg(this);
// connect signals for reconfiguration
connect(lcfgdia,SIGNAL(configChanged()),cl,SLOT(readConfig()));
connect(lcfgdia,SIGNAL(configChanged()),nl,SLOT(readConfig()));
connect(lcfgdia,SIGNAL(configChanged()),sl,SLOT(readConfig()));
lcfgdia->show();
hide();
}
/*!
\fn Kkeyled::show()
If the windosstile is overwritten by the sessionmanagement set it first to the state we need
*/
void Kkeyled::show()
{
WFlags f;
f = Qt::WStyle_Customize | Qt::WStyle_StaysOnTop | Qt::WStyle_NoBorder | Qt::WX11BypassWM;
if ( ! testWFlags(f)) {
setWFlags(f);
reparent(0,getWFlags(),pos());
}
QWidget::show();
setActiveWindow();
raise();
}
/** Hides the window if at lease one led is on */
void Kkeyled::focusOutEvent( QFocusEvent * ){
if( cbnl->isOn() || cbcl->isOn() || cbsl->isOn() ) {
hide();
} else {
setActiveWindow();
}
#ifdef debug
qDebug("Focus lost\n");
#endif
}
syntax highlighted by Code2HTML, v. 0.9.1