You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeaccessibility/kbstateapplet/kbstate.cpp

1080 lines
30 KiB

/*
* Copyright (c) 2004 Gunnar Schmi Dt <gunnar@schmi-dt.de>
*
* 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.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
*/
#include <tqpainter.h>
#include <tqtooltip.h>
#include <tqdrawutil.h>
#include <tqcursor.h>
#include <tqimage.h>
#include <tqpopupmenu.h>
#include <kaboutapplication.h>
#include <kpopupmenu.h>
#include <kaboutdata.h>
#include <klocale.h>
#include <kglobal.h>
#include <kglobalsettings.h>
#include <kapplication.h>
#include <kiconloader.h>
#include <kiconeffect.h>
#include <knotifyclient.h>
#include <kshortcut.h>
#include <kkeynative.h>
#include <kdemacros.h>
#include <kprocess.h>
#include "kdeexportfix.h"
#include "kbstate.h"
#include "kbstate.moc"
extern "C"
{
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/XKBlib.h>
#define XK_MISCELLANY
#define XK_XKB_KEYS
#include <X11/keysymdef.h>
#include <X11/extensions/XKB.h>
KDE_EXPORT KPanelApplet* init(TQWidget *parent, const TQString& configFile)
{
KGlobal::locale()->insertCatalogue("kbstateapplet");
KbStateApplet *applet = new KbStateApplet(configFile, KPanelApplet::Normal, KPanelApplet::About, parent, "kbstateapplet");
return applet;
}
}
struct ModifierKey {
const unsigned int mask;
const KeySym keysym;
const char *name;
const char *icon;
const char *text;
const bool isModifier;
};
static ModifierKey modifierKeys[] = {
{ ShiftMask, 0, I18N_NOOP("Shift"), "shiftkey", "", true },
{ ControlMask, 0, I18N_NOOP("Control"), "controlkey", "", true },
{ 0, XK_Alt_L, I18N_NOOP("Alt"), "altkey", "", true },
{ 0, 0, I18N_NOOP("Win"), "superkey", "", true },
{ 0, XK_Meta_L, I18N_NOOP("Meta"), "metakey", "", true },
{ 0, XK_Super_L, I18N_NOOP("Super"), "superkey", "", true },
{ 0, XK_Hyper_L, I18N_NOOP("Hyper"), "hyperkey", "", true },
{ 0, 0, I18N_NOOP("Alt Graph"), "", I18N_NOOP("æ"), true },
{ 0, XK_Num_Lock, I18N_NOOP("Num Lock"), "lockkey", I18N_NOOP("Num"), false },
{ LockMask, 0, I18N_NOOP("Caps Lock"), "capskey", "", false },
{ 0, XK_Scroll_Lock, I18N_NOOP("Scroll Lock"), "lockkey", I18N_NOOP("Scroll"), false },
{ 0, 0, "", "", "", false }
};
/********************************************************************/
KbStateApplet::KbStateApplet(const TQString& configFile, Type t, int actions,
TQWidget *parent, const char *name)
: KPanelApplet( configFile, t, actions, parent, name )
{
for (int i = 0; i < 8; i++) {
icons[i] = 0;
}
instance = new KInstance ("kbstateapplet");
loadConfig();
initMasks();
mouse = new MouseIcon (instance, this, "mouse");
sticky = new TimeoutIcon (instance, "", "kbstate_stickykeys", this, "sticky");
slow = new TimeoutIcon (instance, "", "kbstate_slowkeys", this, "slow");
bounce = new TimeoutIcon (instance, "", "", this, "bounce");
xkb = XkbGetMap(qt_xdisplay(), 0, XkbUseCoreKbd);
if (xkb != 0) {
XkbGetControls (qt_xdisplay(), XkbAllControlsMask, xkb);
if (xkb->ctrls != 0)
accessxFeatures = xkb->ctrls->enabled_ctrls;
else
accessxFeatures = 0;
}
else
accessxFeatures = 0;
//startTimer(100); // ten times a second
connect(kapp, TQT_SIGNAL(kdisplayPaletteChanged()), TQT_SLOT(paletteChanged()));
kapp->installX11EventFilter (this);
int opcode_rtn, error_rtn;
XkbQueryExtension (this->x11Display(), &opcode_rtn, &xkb_base_event_type, &error_rtn, NULL, NULL);
XkbSelectEvents (this->x11Display(), XkbUseCoreKbd, XkbAllEventsMask,
XkbAllEventsMask);
buildPopupMenu();
}
KbStateApplet::~KbStateApplet() {
kapp->removeX11EventFilter (this);
setCustomMenu(0);
delete instance;
delete popup;
delete sizePopup;
}
// Builds, connects _popup menu
void KbStateApplet::buildPopupMenu()
{
sizePopup=new KPopupMenu(this);
sizePopup->setCheckable( true );
sizePopup->insertItem(i18n("Small"), 13);
sizePopup->insertItem(i18n("Medium"), 20);
sizePopup->insertItem(i18n("Large"), 26);
connect(sizePopup,TQT_SIGNAL(activated(int)), this, TQT_SLOT(setIconDim(int)));
showPopup=new KPopupMenu(this);
showPopup->setCheckable( true );
modifierItem=showPopup->insertItem(i18n("Modifier Keys"), this, TQT_SLOT(toggleModifier()));
lockkeysItem=showPopup->insertItem(i18n("Lock Keys"), this, TQT_SLOT(toggleLockkeys()));
mouseItem=showPopup->insertItem(i18n("Mouse Status"), this, TQT_SLOT(toggleMouse()));
accessxItem=showPopup->insertItem(i18n("AccessX Status"), this, TQT_SLOT(toggleAccessX()));
popup = new KPopupMenu(this);
popup->setCheckable( true );
popup->insertTitle(0, i18n("Keyboard Status Applet"));
popup->insertItem(i18n("Set Icon Size"),sizePopup);
fillSpaceItem = popup->insertItem(i18n("Fill Available Space"),
this, TQT_SLOT(toggleFillSpace()));
popup->insertItem(i18n("Show"),showPopup);
popup->insertItem(i18n("Configure AccessX Features..."), this, TQT_SLOT(configureAccessX()));
popup->insertItem(i18n("Configure Keyboard..."), this, TQT_SLOT(configureKeyboard()));
popup->insertItem(i18n("Configure Mouse..."), this, TQT_SLOT(configureMouse()));
popup->insertSeparator();
popup->insertItem(i18n("About"), this, TQT_SLOT(about()));
setCustomMenu(popup);
updateMenu();
}
void KbStateApplet::updateMenu()
{ if (popup) {
showPopup->setItemChecked (modifierItem, showModifiers);
showPopup->setItemChecked (lockkeysItem, showLockkeys);
showPopup->setItemChecked (mouseItem, showMouse);
showPopup->setItemChecked (accessxItem, showAccessX);
popup->setItemChecked (fillSpaceItem, fillSpace);
sizePopup->setItemChecked(13, size == 13);
sizePopup->setItemChecked(20, size == 20);
sizePopup->setItemChecked(26, size == 26);
}
}
void calculateSizes (int space, int modifiers, int lockkeys, int accessx,
bool showMouse, int &lines, int &length, int &size)
// Calculates the tqlayout based on a given number of modifiers, lockkeys and
// accessx features.
// Output:
// lines: number of lines
// length: number of icons per line
// size: size of the icons
{
// Calculate lines and length
if (showMouse)
++accessx;
lines = space>=size ? space/size : 1;
length = modifiers + lockkeys + accessx;
if (length > 0 && lines >= 2) {
length = (length + lines-1)/lines;
// As we want to have some line breaks, we need to do some corrections:
// Calculate the number of lines that are really needed:
int linesNeeded = (modifiers+length-1)/length + (lockkeys+length-1)/length;
int tmp1 = modifiers%length == 0 ? 0 : length - modifiers%length;
int tmp2 = lockkeys%length == 0 ? 0 : length - lockkeys%length;
if ((tmp1 + tmp2) < accessx)
linesNeeded = (modifiers+lockkeys+accessx + length-1)/length;
// If we need more lines than we have, try with more icons per line:
while (linesNeeded > lines) {
length++;
linesNeeded = (modifiers+length-1)/length + (lockkeys+length-1)/length;
int tmp1 = modifiers%length == 0 ? 0 : length - modifiers%length;
int tmp2 = lockkeys%length == 0 ? 0 : length - lockkeys%length;
if ((tmp1 + tmp2) < accessx)
linesNeeded = (modifiers+lockkeys+accessx + length-1)/length;
}
lines = linesNeeded;
}
}
int KbStateApplet::widthForHeight(int h) const {
int lines, length;
int size = this->size;
int accessx = 0;
if ((accessxFeatures & XkbStickyKeysMask) != 0)
accessx++;
if ((accessxFeatures & XkbSlowKeysMask) != 0)
accessx++;
if ((accessxFeatures & XkbBounceKeysMask) != 0)
accessx++;
calculateSizes (h, showModifiers?modifiers.count():0,
showLockkeys?lockkeys.count():0,
showAccessX?accessx:0,
showMouse, lines, length, size);
if (fillSpace)
size = h/lines;
return length*size;
}
int KbStateApplet::heightForWidth(int w) const {
int lines, length;
int size = this->size;
int accessx = 0;
if ((accessxFeatures & XkbStickyKeysMask) != 0)
accessx++;
if ((accessxFeatures & XkbSlowKeysMask) != 0)
accessx++;
if ((accessxFeatures & XkbBounceKeysMask) != 0)
accessx++;
calculateSizes (w, showModifiers?modifiers.count():0,
showLockkeys?lockkeys.count():0,
showAccessX?accessx:0,
showMouse, lines, length, size);
if (fillSpace)
size = w/lines;
return length*size;
}
void KbStateApplet::mousePressEvent(TQMouseEvent *e) {
if (e->button() == Qt::RightButton)
popup->popup(e->globalPos());
}
void KbStateApplet::setIconDim (int size) {
this->size = size;
saveConfig();
updateMenu();
update();
updateGeometry();
emit updateLayout();
}
void KbStateApplet::toggleFillSpace() {
fillSpace = !fillSpace;
saveConfig();
updateMenu();
tqlayout();
updateGeometry();
emit updateLayout();
}
void KbStateApplet::resizeEvent( TQResizeEvent*e ) {
TQWidget::resizeEvent(e);
tqlayout();
}
void KbStateApplet::tqlayout() {
int size = this->size;
int lines, length, x,y,dx,dy, ldx,ldy;
int modifierCount = showModifiers?modifiers.count():0;
int lockkeyCount = showLockkeys?lockkeys.count():0;
int accessxCount = 0;
if (showAccessX) {
if ((accessxFeatures & XkbStickyKeysMask) != 0)
accessxCount++;
if ((accessxFeatures & XkbSlowKeysMask) != 0)
accessxCount++;
if ((accessxFeatures & XkbBounceKeysMask) != 0)
accessxCount++;
}
if (orientation() ==Qt::Vertical) {
calculateSizes (width(), modifierCount, lockkeyCount, accessxCount,
showMouse, lines, length, size);
if (fillSpace)
size = width()/lines;
x = (width()-lines*size)/2;
y = 0;
dx = 0;
dy = size;
ldx= size;
ldy= 0;
}
else {
calculateSizes (height(), modifierCount, lockkeyCount, accessxCount,
showMouse, lines, length, size);
if (fillSpace)
size = height()/lines;
x = 0;
y = (height()-lines*size)/2;
dx = size;
dy = 0;
ldx= 0;
ldy= size;
}
StatusIcon *icon;
int item = 1;
for (icon = modifiers.first(); icon; icon = modifiers.next()) {
if (showModifiers) {
icon->setGeometry (x, y, size, size);
icon->show();
icon->update();
item++; x+=dx; y+=dy;
if (item > length) {
x = x - length*dx + ldx;
y = y - length*dy + ldy;
item = 1;
}
}
else
icon->hide();
}
int lockkeyLines = (lockkeyCount+length-1)/length;
int accessxLines = lines - (modifierCount+length-1)/length - lockkeyLines;
if (showMouse)
++accessxCount;
if (lockkeyLines*length + accessxLines*length
>= lockkeyCount + accessxCount)
{
if (lines > 1 && item > 1) {
x = x - (item-1)*dx + ldx;
y = y - (item-1)*dy + ldy;
item = 1;
}
}
else {
accessxLines++;
}
if (showMouse && showAccessX && accessxLines > 0) {
mouse->setGeometry (x, y, size, size);
mouse->show();
mouse->update();
accessxCount--;
item++; x+=dx; y+=dy;
if (item > length) {
x = x - length*dx + ldx;
y = y - length*dy + ldy;
item = 1;
accessxLines--;
}
}
else
mouse->hide();
if ((accessxFeatures & XkbStickyKeysMask) != 0
&& showAccessX && accessxLines > 0)
{
sticky->setGeometry (x, y, size, size);
sticky->show();
sticky->update();
accessxCount--;
item++; x+=dx; y+=dy;
if (item > length) {
x = x - length*dx + ldx;
y = y - length*dy + ldy;
item = 1;
accessxLines--;
}
}
else
sticky->hide();
if ((accessxFeatures & XkbSlowKeysMask) != 0
&& showAccessX && accessxLines > 0)
{
slow->setGeometry (x, y, size, size);
slow->show();
slow->update();
accessxCount--;
item++; x+=dx; y+=dy;
if (item > length) {
x = x - length*dx + ldx;
y = y - length*dy + ldy;
item = 1;
accessxLines--;
}
}
else
slow->hide();
if ((accessxFeatures & XkbBounceKeysMask) != 0
&& showAccessX && accessxLines > 0)
{
bounce->setGeometry (x, y, size, size);
bounce->show();
bounce->update();
accessxCount--;
item++; x+=dx; y+=dy;
if (item > length) {
x = x - length*dx + ldx;
y = y - length*dy + ldy;
item = 1;
accessxLines--;
}
}
else
bounce->hide();
if (lines > 1) {
if (item != 1) {
x = x - (item-1)*dx + ldx;
y = y - (item-1)*dy + ldy;
}
item = 1;
}
for (icon = lockkeys.first(); icon; icon = lockkeys.next()) {
if (showLockkeys) {
icon->setGeometry (x, y, size, size);
icon->show();
icon->update();
item++; x+=dx; y+=dy;
if (item > length) {
x = x - length*dx + ldx;
y = y - length*dy + ldy;
item = 1;
}
}
else
icon->hide();
}
if ((accessxFeatures & XkbBounceKeysMask) != 0
&& showAccessX && accessxCount > 0)
{
bounce->setGeometry (x, y, size, size);
bounce->show();
bounce->update();
item++; x+=dx; y+=dy;
accessxCount--;
}
if ((accessxFeatures & XkbSlowKeysMask) != 0
&& showAccessX && accessxCount > 0)
{
slow->setGeometry (x, y, size, size);
slow->show();
slow->update();
item++; x+=dx; y+=dy;
accessxCount--;
}
if ((accessxFeatures & XkbStickyKeysMask) != 0
&& showAccessX && accessxCount > 0)
{
sticky->setGeometry (x, y, size, size);
sticky->show();
sticky->update();
item++; x+=dx; y+=dy;
accessxCount--;
}
if (showMouse && accessxCount > 0)
{
mouse->setGeometry (x, y, size, size);
mouse->show();
mouse->update();
item++; x+=dx; y+=dy;
accessxCount--;
}
}
void KbStateApplet::paletteChanged() {
for (int i = 0; i < 8; i++) {
if (icons[i])
icons[i]->updateImages();
}
mouse->update();
sticky->update();
slow->update();
bounce->update();
}
void KbStateApplet::initMasks() {
for (int i = 0; i < 8; i++) {
if (icons[i])
delete icons[i];
icons[i] = 0;
}
state = 0;
for (int i = 0; strcmp(modifierKeys[i].name, "") != 0; i++) {
int mask = modifierKeys[i].mask;
if (mask == 0)
if (modifierKeys[i].keysym != 0)
mask = XkbKeysymToModifiers (this->x11Display(), modifierKeys[i].keysym);
else if (!strcmp(modifierKeys[i].name, "Win"))
mask = KKeyNative::modX(KKey::WIN);
else
mask = XkbKeysymToModifiers (this->x11Display(), XK_Mode_switch)
| XkbKeysymToModifiers (this->x11Display(), XK_ISO_Level3_Shift)
| XkbKeysymToModifiers (this->x11Display(), XK_ISO_Level3_Latch)
| XkbKeysymToModifiers (this->x11Display(), XK_ISO_Level3_Lock);
int map = 0;
for (map = 0; map < 8; map++) {
if ((mask & (1 << map)) != 0)
break;
}
if ((map <= 7) && !(icons[map])) {
icons[map] = new KeyIcon (i, instance, this, modifierKeys[i].name);
TQToolTip::add (icons[map], i18n (modifierKeys[i].name));
connect (icons[map], TQT_SIGNAL(stateChangeRequest (KeyIcon*,bool,bool)),
TQT_SLOT(stateChangeRequest (KeyIcon*,bool,bool)));
if (modifierKeys[i].isModifier)
modifiers.append(icons[map]);
else
lockkeys.append(icons[map]);
}
}
}
bool KbStateApplet::x11Event (XEvent *evt) {
if (evt->type == xkb_base_event_type + XkbEventCode) {
XkbEvent *kbevt = (XkbEvent *)evt;
switch (kbevt->any.xkb_type) {
case XkbStateNotify:
timerEvent (0);
mouse->setState (kbevt->state.ptr_buttons);
break;
case XkbAccessXNotify:
switch (kbevt->accessx.detail) {
case XkbAXN_SKPress:
slow->setGlyth(i18n("a (the first letter in the alphabet)", "a"));
slow->setImage("unlatched");
break;
case XkbAXN_SKAccept:
slow->setImage("keypressok");
break;
case XkbAXN_SKRelease:
slow->setGlyth(" ");
slow->setImage("kbstate_slowkeys");
break;
case XkbAXN_SKReject:
slow->setImage("keypressno", kbevt->accessx.sk_delay>150?kbevt->accessx.sk_delay:150);
break;
case XkbAXN_BKAccept:
slow->setGlyth(i18n("a (the first letter in the alphabet)", "a"));
bounce->setImage("keypressok", kbevt->accessx.sk_delay>150?kbevt->accessx.sk_delay:150);
break;
case XkbAXN_BKReject:
slow->setGlyth(i18n("a (the first letter in the alphabet)", "a"));
bounce->setImage("keypressno", kbevt->accessx.sk_delay>150?kbevt->accessx.sk_delay:150);
break;
}
break;
case XkbControlsNotify: {
XkbControlsNotifyEvent* event = (XkbControlsNotifyEvent*)evt;
accessxFeatures = event->enabled_ctrls;
if ((accessxFeatures & XkbMouseKeysMask) != 0) {
XkbGetControls (qt_xdisplay(), XkbMouseKeysMask, xkb);
if (xkb->ctrls->mk_dflt_btn < 1)
mouse->setActiveKey (1);
else if (xkb->ctrls->mk_dflt_btn > 3)
mouse->setActiveKey (1);
else
mouse->setActiveKey (xkb->ctrls->mk_dflt_btn);
}
else
mouse->setActiveKey (0);
tqlayout();
updateGeometry();
emit updateLayout();
break;
}
case XkbExtensionDeviceNotify:
/* This is a hack around the fact that XFree86's XKB doesn't give AltGr notifications */
break;
default:
break;
}
}
return false;
}
void KbStateApplet::timerEvent(TQTimerEvent*) {
XkbStateRec state_return;
XkbGetState (this->x11Display(), XkbUseCoreKbd, &state_return);
unsigned char latched = XkbStateMods (&state_return);
unsigned char locked = XkbModLocks (&state_return);
int mods = ((int)latched)<<8 | locked;
if (state != mods) {
state = mods;
for (int i = 0; i < 8; i++) {
if (icons[i])
icons[i]->setState ((latched&(1<<i)) != 0, (locked&(1<<i)) != 0);
}
}
}
void KbStateApplet::stateChangeRequest (KeyIcon *source, bool latched, bool locked) {
for (int i = 0; i < 8; i++) {
if (icons[i] == source) {
if (locked)
XkbLockModifiers (this->x11Display(), XkbUseCoreKbd, 1<<i, 1<<i);
else if (latched) {
XkbLockModifiers (this->x11Display(), XkbUseCoreKbd, 1<<i, 0);
XkbLatchModifiers (this->x11Display(), XkbUseCoreKbd, 1<<i, 1<<i);
}
else {
XkbLockModifiers (this->x11Display(), XkbUseCoreKbd, 1<<i, 0);
XkbLatchModifiers (this->x11Display(), XkbUseCoreKbd, 1<<i, 0);
}
}
}
}
void KbStateApplet::toggleModifier() {
showModifiers = !showModifiers;
updateMenu();
tqlayout();
updateGeometry();
saveConfig();
emit updateLayout();
}
void KbStateApplet::toggleLockkeys() {
showLockkeys = !showLockkeys;
updateMenu();
tqlayout();
updateGeometry();
saveConfig();
emit updateLayout();
}
void KbStateApplet::toggleMouse() {
showMouse = !showMouse;
updateMenu();
tqlayout();
updateGeometry();
saveConfig();
emit updateLayout();
}
void KbStateApplet::toggleAccessX() {
showAccessX = !showAccessX;
updateMenu();
tqlayout();
updateGeometry();
saveConfig();
emit updateLayout();
}
void KbStateApplet::configureAccessX() {
kapp->startServiceByDesktopName("kcmaccess");
}
void KbStateApplet::configureKeyboard() {
// The modulename "keyboard" is ambiguous on SuSE systems
// as there is also a YaST-module called "keyboard".
KProcess proc;
proc << "kcmshell";
proc << "kde/keyboard";
proc.start(KProcess::DontCare);
proc.detach();
}
void KbStateApplet::configureMouse() {
kapp->startServiceByDesktopName("mouse");
}
void KbStateApplet::about() {
KAboutData about("kbstateapplet", I18N_NOOP("Keyboard Status Applet"), "0.2",
I18N_NOOP("Panel applet that shows the state of the modifier keys"), KAboutData::License_GPL_V2, "(C) 2004 Gunnar Schmi Dt");
KAboutApplication a(&about, this);
a.exec();
}
void KbStateApplet::loadConfig()
{
KConfig *c = config();
c->setGroup("General");
size = c->readNumEntry("IconDim", 20);
fillSpace = c->readBoolEntry("fill space", true);
showModifiers = c->readBoolEntry("Modifierkeys visible",true);
showLockkeys = c->readBoolEntry("Lockkeys visible",true);
showMouse = c->readBoolEntry("Mouse status visible",true);
showAccessX = c->readBoolEntry("Slowkeys status visible",true);
showAccessX = c->readBoolEntry("AccessX status visible",showAccessX);
}
void KbStateApplet::saveConfig()
{
KConfig *c = config();
c->setGroup("General");
c->writeEntry("IconDim", size);
c->writeEntry("fill space", fillSpace);
c->writeEntry("Modifierkeys visible", showModifiers);
c->writeEntry("Lockkeys visible", showLockkeys);
c->writeEntry("Mouse status visible", showMouse);
c->writeEntry("AccessX status visible", showAccessX);
c->sync();
}
/********************************************************************/
KeyIcon::KeyIcon (int keyId, KInstance *instance,
TQWidget *parent, const char *name)
: StatusIcon (modifierKeys[keyId].name, parent, name) {
this->instance = instance;
this->keyId = keyId;
this->tristate = (modifierKeys[keyId].isModifier);
isLocked = false;
isLatched = false;
updateImages ();
connect (this, TQT_SIGNAL(clicked()), TQT_SLOT(clickedSlot()));
}
KeyIcon::~KeyIcon () {
}
void KeyIcon::setState (bool latched, bool locked) {
latched = latched | locked;
isLatched = latched;
isLocked = locked;
update();
}
void KeyIcon::clickedSlot () {
if (tristate)
emit stateChangeRequest (this, !isLocked, isLatched&!isLocked);
else
emit stateChangeRequest (this, false, !isLocked);
}
void KeyIcon::resizeEvent( TQResizeEvent*e )
{
TQWidget::resizeEvent(e);
updateImages();
}
void KeyIcon::updateImages () {
int size = width()<height() ? width() : height();
locked = instance->iconLoader()->loadIcon("lock_overlay", KIcon::Panel, size-4);
if (strcmp(modifierKeys[keyId].icon, "")) {
latched = instance->iconLoader()->loadIcon(modifierKeys[keyId].icon, KIcon::NoGroup, size-4);
unlatched = instance->iconLoader()->loadIcon(modifierKeys[keyId].icon, KIcon::NoGroup, size-4);
TQImage img = latched.convertToImage();
KIconEffect::colorize(img, KGlobalSettings::highlightedTextColor(), 1.0);
latched.convertFromImage (img);
img = unlatched.convertToImage();
KIconEffect::colorize(img, KGlobalSettings::textColor(), 1.0);
unlatched.convertFromImage (img);
}
update();
}
void KeyIcon::drawButton (TQPainter *p) {
TQColor black;
int x = (width()-locked.width())/2;
int y = (height()-locked.height())/2;
int o = 0;
if (isLocked || isLatched) {
qDrawShadePanel (p, 0, 0, width(), height(), tqcolorGroup(), true, 1, NULL);
p->fillRect (1,1,width()-2,height()-2, KGlobalSettings::highlightColor());
if (strcmp(modifierKeys[keyId].icon, ""))
p->drawPixmap (x+1,y+1, latched);
black = KGlobalSettings::highlightedTextColor();
o = 1;
}
else {
qDrawShadePanel (p, 0, 0, width(), height(), tqcolorGroup(), false, 1, NULL);
if (strcmp(modifierKeys[keyId].icon, ""))
p->drawPixmap (x,y, unlatched);
black = KGlobalSettings::textColor();
}
TQString text = i18n(modifierKeys[keyId].text);
if (!text.isEmpty() && !text.isNull()) {
TQFont font = KGlobalSettings::generalFont();
font.setWeight(TQFont::Black);
TQFontMetrics metrics(font);
TQRect rect = metrics.boundingRect (text);
int size;
if (!strcmp(modifierKeys[keyId].name, "Alt Graph"))
size = rect.width()>rect.height()?rect.width():rect.height();
else
size = rect.width()>12*rect.height()/5?rect.width():12*rect.height()/5;
if (font.pixelSize() != -1)
font.setPixelSize (font.pixelSize()*width()*19/size/32);
else
font.setPointSizeFloat (font.pointSizeFloat()*width()*19/size/32);
p->setPen (black);
p->setFont (font);
if (!strcmp(modifierKeys[keyId].name, "Alt Graph"))
p->drawText (o,o, width(), height(), TQt::AlignCenter, text);
else
p->drawText (o,o, width(), height()*(251)/384, TQt::AlignCenter, text);
}
if (tristate && isLocked) {
p->drawPixmap(x+o,y+o, locked);
}
}
/********************************************************************/
MouseIcon::MouseIcon (KInstance *instance, TQWidget *parent, const char *name)
: StatusIcon ("", parent, name)
{
this->instance = instance;
state = 0;
activekey = 0;
updateImages ();
connect (this, TQT_SIGNAL(clicked()), TQT_SLOT(clickedSlot()));
}
MouseIcon::~MouseIcon () {
}
void MouseIcon::setState (int state) {
this->state = state;
update();
}
void MouseIcon::setActiveKey (int activekey) {
this->activekey = activekey;
update();
}
void MouseIcon::resizeEvent( TQResizeEvent*e )
{
TQWidget::resizeEvent(e);
updateImages();
}
TQPixmap loadIcon(KInstance *instance, int size, TQColor color, TQString name) {
KIconLoader *loader = instance->iconLoader();
TQPixmap result = loader->loadIcon(name, KIcon::NoGroup, size);
TQImage img = result.convertToImage();
KIconEffect::colorize(img, color, 1.0);
result.convertFromImage (img);
return result;
}
void MouseIcon::updateImages () {
int size = width()<height() ? width() : height();
TQColor textcolor = KGlobalSettings::textColor();
TQColor basecolor = KGlobalSettings::baseColor();
mouse = loadIcon (instance, size, textcolor, "kbstate_mouse");
leftSelected = loadIcon (instance, size, textcolor,
"kbstate_mouse_left_selected");
middleSelected = loadIcon (instance, size, textcolor,
"kbstate_mouse_mid_selected");
rightSelected = loadIcon (instance, size, textcolor,
"kbstate_mouse_right_selected");
leftDot = loadIcon (instance, size, textcolor, "kbstate_mouse_left");
middleDot = loadIcon (instance, size, textcolor, "kbstate_mouse_mid");
rightDot = loadIcon (instance, size, textcolor, "kbstate_mouse_right");
leftDotSelected = loadIcon (instance, size, basecolor,
"kbstate_mouse_left");
middleDotSelected = loadIcon (instance, size, basecolor,
"kbstate_mouse_mid");
rightDotSelected = loadIcon (instance, size, basecolor,
"kbstate_mouse_right");
update();
}
void MouseIcon::drawButton (TQPainter *p) {
p->drawPixmap(0,0, mouse);
if ((state & Button1Mask) != 0)
p->drawPixmap(0,0, leftSelected);
if ((state & Button2Mask) != 0)
p->drawPixmap(0,0, middleSelected);
if ((state & Button3Mask) != 0)
p->drawPixmap(0,0, rightSelected);
switch (activekey) {
case 0:
break;
case 1:
if ((state & Button1Mask) != 0)
p->drawPixmap(0,0, leftDotSelected);
else
p->drawPixmap(0,0, leftDot);
break;
case 2:
if ((state & Button2Mask) != 0)
p->drawPixmap(0,0, middleDotSelected);
else
p->drawPixmap(0,0, middleDot);
break;
case 3:
if ((state & Button3Mask) != 0)
p->drawPixmap(0,0, rightDotSelected);
else
p->drawPixmap(0,0, rightDot);
break;
}
}
/********************************************************************/
TimeoutIcon::TimeoutIcon (KInstance *instance, const TQString &text,
const TQString &featurename,
TQWidget *parent, const char *name)
: StatusIcon (text, parent, name) {
this->instance = instance;
this->featurename = featurename;
glyth = " ";
setImage (featurename);
connect (&timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(timeout()));
}
TimeoutIcon::~TimeoutIcon () {
}
void TimeoutIcon::update () {
int size = width()<height() ? width() : height();
if (pixmap.width() != size)
pixmap = instance->iconLoader()->loadIcon(iconname, KIcon::NoGroup, size);
TQImage img = pixmap.convertToImage();
KIconEffect::colorize(img, KGlobalSettings::textColor(), 1.0);
pixmap.convertFromImage (img);
image = pixmap;
TQWidget::update();
}
void TimeoutIcon::setGlyth (const TQString &glyth) {
timer.stop();
this->glyth = glyth;
TQImage img = pixmap.convertToImage();
KIconEffect::colorize(img, KGlobalSettings::textColor(), 1.0);
pixmap.convertFromImage (img);
image = pixmap;
update();
}
void TimeoutIcon::setImage (const TQString &name, int timeout) {
timer.stop();
iconname = name;
if (!name.isNull() && !name.isEmpty()) {
int size = width()<height() ? width() : height();
pixmap = instance->iconLoader()->loadIcon(iconname, KIcon::NoGroup, size);
TQImage img = pixmap.convertToImage();
KIconEffect::colorize(img, KGlobalSettings::textColor(), 1.0);
pixmap.convertFromImage (img);
image = pixmap;
}
update();
if (timeout > 0)
timer.start (timeout, true);
}
void TimeoutIcon::timeout () {
setGlyth (" ");
setImage(featurename);
}
void TimeoutIcon::drawButton (TQPainter *p) {
TQString text = glyth;
int count = 1;
int factor = 19;
if (!iconname.isNull() && !iconname.isEmpty())
p->drawPixmap(0,0, image);
else if (glyth == " ") {
text = i18n("a (the first letter in the alphabet)", "a");
count = 3;
factor = 64;
}
TQFont font = KGlobalSettings::generalFont();
font.setWeight(TQFont::Black);
TQFontMetrics metrics(font);
TQRect rect = metrics.boundingRect (text);
int size = count*rect.width() > rect.height()
? count*rect.width() : rect.height();
if (font.pixelSize() != -1)
font.setPixelSize (font.pixelSize()*width()*factor/size/64);
else
font.setPointSizeFloat (font.pointSizeFloat()*width()*factor/size/64);
p->setFont (font);
if (count == 1) {
p->setPen (KGlobalSettings::textColor());
p->drawText (0,0, width()/2, height()/2, TQt::AlignCenter, text);
}
else {
TQColor t = KGlobalSettings::textColor();
TQColor b = KGlobalSettings::baseColor();
p->setPen (TQColor ((2*t.red()+3*b.red())/5,
(2*t.green()+3*b.green())/5,
(2*t.blue()+3*b.blue())/5));
p->drawText (width()/2,0, width()/2, height(), TQt::AlignCenter, text);
p->setPen (TQColor ((2*t.red()+b.red())/3,
(2*t.green()+b.green())/3,
(2*t.blue()+b.blue())/3));
p->drawText (0,0, width(), height(), TQt::AlignCenter, text);
p->setPen (KGlobalSettings::textColor());
p->drawText (0,0, width()/2, height(), TQt::AlignCenter, text);
}
}
/********************************************************************/
StatusIcon::StatusIcon (const TQString &text, TQWidget *parent, const char *name)
: TQPushButton (text, parent, name) {
tqsetSizePolicy(TQSizePolicy(TQSizePolicy::Ignored, TQSizePolicy::Ignored));
}
StatusIcon::~StatusIcon () {
}
TQSize StatusIcon::tqminimumSizeHint () const {
return TQSize (0,0);
}