Kxkb: layout switching and UI bugfixes and minor refactoring

* Layout switching
  - Improved layout change logic (indicator is now always updated when the actual switch occurs). This fixes layout switching triggered by the X11 shortcut not being synchronized with layout switching from the tray icon click and the TDE shortcut.
  - Kxkb will ignore XkbStateNotify events not related to XkbGroupState which caused strange behaviour with the system tray context menu.
  - Reapply Xkb settings when a keyboard device changes state
  - Do not run setxkbmap without arguments
  - Catch and process changes to Xkb layouts and options
  - Always check for Xkb opcode in X11 events, this fixes invalid group issue (Michele Calgaro)

* Tray indicator
  - Do not reload all Kxkb settings every time we are requested to get a pixmap!
  - Tray indicator pixmap manager improvements
  - Fix Quit tray icon menu item

* Configuration
  - Optimize settings reloading
  - Do not reload settings every time getKxkbOptions() is called; if settings actually need to be re-read, it must be done maunally before calling this function
  - Use pointer to global KxkbConfig instance instead of keeping own copy
  - Fixed optimized loading of initial settings using KxkbConfig::LOAD_INIT_OPTIONS (I had sort of broken it in the past)
  - Removed unused KxkbConfig::LOAD_ACTIVE_OPTIONS
  - `newInstance()` now delegates calling setLayout() to readSettings()
  - Merged `initTray()` into `readSettings()` - no reason to exist as separate function

* Refactoring
  - Merged KxkbLabelController into KxkbSystemTray
  - Rename LayoutIcon to LayoutIconManager for clarity
  - Minor code cleanup in LayoutIconManager
  - Remove use of singleton pattern for LayoutIconManager
  - Make XKBExtension a singleton.
  - Add mutex to XKBExtension to prevent it from processing configuration changes likely caused by KXkb
  - `XKBExtension::getServerOptions()` now also returns layout and variant information in a XkbOptions struct
  - New `KxkbConfig::setFromXkbOptions()` member can update current configuration from a XkbOptions struct
  - No need to use `tdeApp` pointer in KXKBApp (KUniqueApplication) class
  - Consistent code style and more appropriate function names and return types
  - Commented option sections for clarity
  - Removed superfluous debug messages
  - Add proper copyright header to extension.*

* Settings GUI
  - Make "Transparent background" checkbox available for theme colors in the GUI
  - Add customization options "Stretch flag", "Dim flag", "Show indicator bevel"
  - Disable KMilo checkbox when layout notifications disabled
  - Fix reading settings for TDE layout hotkeys

This resolves #547.

Signed-off-by: Mavridis Philippe <mavridisf@gmail.com>
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
pull/550/head
Mavridis Philippe 11 months ago
parent 1686be58c6
commit aed24cdf3f

@ -67,5 +67,5 @@ tde_add_tdeinit_executable( kxkb AUTOMOC
extension.cpp x11helper.cpp rules.cpp kxkbconfig.cpp extension.cpp x11helper.cpp rules.cpp kxkbconfig.cpp
pixmap.cpp layoutmap.cpp kxkb.cpp kxkbtraywindow.cpp pixmap.cpp layoutmap.cpp kxkb.cpp kxkbtraywindow.cpp
kxkb.skel kxkb.skel
LINK tdeui-shared ${XKBFILE_LIBRARIES} LINK tdeui-shared ${XKBFILE_LIBRARIES} ${TDEHW_LIBRARIES}
) )

@ -5,4 +5,9 @@ Comment=TDE Keyboard Tool
[LayoutChange] [LayoutChange]
Name=Keyboard layout switch Name=Keyboard layout switch
Comment=The keyboard layout was switched Comment=The keyboard layout was switched
default_presentation=16
[Error]
Name=Keyboard layout switching error
Comment=Error while attempting to switch the keyboard layout
default_presentation=16 default_presentation=16

@ -1,3 +1,32 @@
/*******************************************************************************
Xkb extension for KXkb
Copyright © 2009-2025 Trinity Desktop project
Copyright © 2001 S.R. Haque <srhaque@iee.org>
Derived from an original by Matthias H<EFBFBD>zer-Klpfel released under the QPL.
Some portions come from kkbswitch released under the GNU GPL v2 (or later).
Copyright © 2001 Leonid Zeitlin <lz@europe.com>
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*******************************************************************************/
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
@ -5,10 +34,13 @@
#include <tqmap.h> #include <tqmap.h>
#include <tqfile.h> #include <tqfile.h>
#include <tqdir.h> #include <tqdir.h>
#include <tqtimer.h>
#include <kdebug.h> #include <kdebug.h>
#include <tdeapplication.h>
#include <tdestandarddirs.h> #include <tdestandarddirs.h>
#include <tdeprocess.h> #include <tdeprocess.h>
#include <dcopclient.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/Xos.h> #include <X11/Xos.h>
@ -21,58 +53,77 @@
#include "extension.h" #include "extension.h"
extern "C"
{
static int IgnoreXError(Display *, XErrorEvent *) { return 0; }
}
static TQString getLayoutKey(const TQString& layout, const TQString& variant) static TQString getLayoutKey(const TQString& layout, const TQString& variant)
{ {
return layout + "." + variant; return layout + "." + variant;
} }
XKBExtension::XKBExtension(Display *d) static XKBExtension *xkbExtension = nullptr;
XKBExtension *XKBExtension::the()
{ {
if ( d == NULL ) if (!xkbExtension)
d = tqt_xdisplay(); {
m_dpy = d; xkbExtension = new XKBExtension;
if (!xkbExtension->init())
// TQStringList dirs = TDEGlobal::dirs()->findDirs ( "tmp", "" ); {
// m_tempDir = dirs.count() == 0 ? "/tmp/" : dirs[0]; kdFatal() << "xkb initialization failed, exiting..." << endl;
m_tempDir = locateLocal("tmp", ""); ::exit(1);
}
}
return xkbExtension;
} }
bool XKBExtension::init() bool XKBExtension::init()
{ {
// Verify the Xlib has matching XKB extension. m_configureFilterCounter = 0;
int major = XkbMajorVersion; kdDebug() << "[kxkb-extension] Initializing Xkb extension" << endl;
int minor = XkbMinorVersion; m_dpy = tqt_xdisplay();
if (!XkbLibraryVersion(&major, &minor)) // Verify the Xlib has matching XKB extension.
{ int major = XkbMajorVersion;
kdError() << "[kxkb-extension] Xlib XKB extension " << major << '.' << minor << int minor = XkbMinorVersion;
" != " << XkbMajorVersion << '.' << XkbMinorVersion << endl;
return false; if (!XkbLibraryVersion(&major, &minor))
} {
kdError() << "[kxkb-extension] Xlib XKB extension " << major << '.' << minor <<
// Verify the X server has matching XKB extension. " != " << XkbMajorVersion << '.' << XkbMinorVersion << endl;
return false;
int opcode_rtrn; }
int error_rtrn;
int xkb_opcode; // Verify the X server has matching XKB extension.
if (!XkbQueryExtension(m_dpy, &opcode_rtrn, &xkb_opcode, &error_rtrn, int opcode_rtrn;
&major, &minor)) int error_rtrn;
{ if (!XkbQueryExtension(m_dpy, &opcode_rtrn, &m_xkb_opcode, &error_rtrn, &major, &minor))
kdError() << "[kxkb-extension] X server XKB extension " << major << '.' << minor << {
" != " << XkbMajorVersion << '.' << XkbMinorVersion << endl; kdError() << "[kxkb-extension] X server XKB extension " << major << '.' << minor <<
return false; " != " << XkbMajorVersion << '.' << XkbMinorVersion << endl;
} return false;
}
// Do it, or face horrible memory corrupting bugs
::XkbInitAtoms(NULL); enableConfigureFilter();
// watch group change events // Do it, or face horrible memory corrupting bugs
XkbSelectEventDetails(m_dpy, XkbUseCoreKbd, XkbStateNotify, ::XkbInitAtoms(nullptr);
XkbAllStateComponentsMask, XkbGroupStateMask);
// Watch for interesting events
return true; XkbSelectEventDetails(m_dpy, XkbUseCoreKbd, XkbStateNotify,
XkbAllStateComponentsMask, XkbGroupStateMask);
XkbSelectEventDetails(m_dpy, XkbUseCoreKbd, XkbNewKeyboardNotify,
XkbAllNewKeyboardEventsMask, XkbAllNewKeyboardEventsMask);
m_tempDir = locateLocal("tmp", "");
disableConfigureFilter();
return true;
} }
XKBExtension::~XKBExtension() XKBExtension::~XKBExtension()
@ -81,11 +132,32 @@ XKBExtension::~XKBExtension()
deletePrecompiledLayouts();*/ deletePrecompiledLayouts();*/
} }
void XKBExtension::enableConfigureFilter()
{
++m_configureFilterCounter;
}
void XKBExtension::disableConfigureFilter()
{
// Without this protection in place KXkb would react to configuration
// changes caused by itself
TQTimer::singleShot(500, this, TQ_SLOT(slotReleaseConfigureLock()));
}
void XKBExtension::slotReleaseConfigureLock()
{
--m_configureFilterCounter;
}
bool XKBExtension::setXkbOptions(const XkbOptions options) bool XKBExtension::setXkbOptions(const XkbOptions options)
{ {
enableConfigureFilter();
TQString exe = TDEGlobal::dirs()->findExe("setxkbmap"); TQString exe = TDEGlobal::dirs()->findExe("setxkbmap");
if (exe.isEmpty()) if (exe.isEmpty())
{
return false; return false;
}
TDEProcess p; TDEProcess p;
p << exe; p << exe;
@ -101,7 +173,7 @@ bool XKBExtension::setXkbOptions(const XkbOptions options)
p << "-variant"; p << "-variant";
p << options.variants; p << options.variants;
} }
if (!options.model.isEmpty()) { if (!options.model.isEmpty()) {
p << "-model"; p << "-model";
p << options.model; p << options.model;
@ -119,7 +191,8 @@ bool XKBExtension::setXkbOptions(const XkbOptions options)
else else
{ {
// Avoid duplication of options in Append mode // Avoid duplication of options in Append mode
TQStringList srvOptions = TQStringList::split(",", XKBExtension::getServerOptions()); XkbOptions _opt = getServerOptions();
TQStringList srvOptions = TQStringList::split(",", _opt.options);
TQStringList kxkbOptions = TQStringList::split(",", options.options); TQStringList kxkbOptions = TQStringList::split(",", options.options);
TQStringList newOptions; TQStringList newOptions;
for (TQStringList::Iterator it = kxkbOptions.begin(); it != kxkbOptions.end(); ++it) for (TQStringList::Iterator it = kxkbOptions.begin(); it != kxkbOptions.end(); ++it)
@ -136,44 +209,81 @@ bool XKBExtension::setXkbOptions(const XkbOptions options)
} }
} }
if (p.args().count() < 2)
{
// Either the user has not configured any Xkb options or these options
// are already set and we are in append mode so we want to avoid
// duplicates
kdWarning() << "[setXkbOptions] No options need to be set" << endl;
slotReleaseConfigureLock(); // immediately release the lock
return true;
}
p << "-synch";
kdDebug() << "[setXkbOptions] Command: " << p.args() << endl; kdDebug() << "[setXkbOptions] Command: " << p.args() << endl;
p.start(TDEProcess::Block); p.start(TDEProcess::Block);
disableConfigureFilter();
return p.normalExit() && (p.exitStatus() == 0); return p.normalExit() && (p.exitStatus() == 0);
} }
TQString XKBExtension::getServerOptions() XkbOptions XKBExtension::getServerOptions()
{ {
XkbRF_VarDefsRec vd; XkbOptions options;
if (XkbRF_GetNamesProp(tqt_xdisplay(), nullptr, &vd) && vd.options) XkbRF_VarDefsRec vd;
{ if (XkbRF_GetNamesProp(tqt_xdisplay(), nullptr, &vd))
kdDebug() << "[kxkb-extension] Got server options " << vd.options << endl; {
return TQString(vd.options); options.model = vd.model;
} options.layouts = vd.layout;
return TQString::null; options.variants = vd.variant;
options.options = vd.options;
}
return options;
} }
bool XKBExtension::setGroup(unsigned int group) bool XKBExtension::setGroup(unsigned int group)
{ {
kdDebug() << "[kxkb-extension] Setting group " << group << endl; kdDebug() << "[kxkb-extension] Setting group " << group << endl;
return XkbLockGroup( m_dpy, XkbUseCoreKbd, group ); return XkbLockGroup(m_dpy, XkbUseCoreKbd, group);
} }
unsigned int XKBExtension::getGroup() const uint XKBExtension::getGroup() const
{ {
XkbStateRec xkbState; XkbStateRec xkbState;
XkbGetState( m_dpy, XkbUseCoreKbd, &xkbState ); XkbGetState(m_dpy, XkbUseCoreKbd, &xkbState);
return xkbState.group; return xkbState.group;
} }
/** Examines an X Event passed to it and takes actions if the event is of bool XKBExtension::kcmlayoutRunning()
* interest to KXkb */ {
return tdeApp->dcopClient()->isApplicationRegistered("TDECModuleProxy-keyboard_layout");
}
// Examines an X Event passed to it and takes actions if the event is of
// interest to KXkb
void XKBExtension::processXEvent(XEvent *event) { void XKBExtension::processXEvent(XEvent *event) {
XkbEvent* xkb_event = (XkbEvent*)event; if (event->type == m_xkb_opcode)
if (xkb_event->any.xkb_type == XkbStateNotify) { {
emit groupChanged(xkb_event->state.group); XkbEvent *xkb_event = (XkbEvent*)event;
} if (xkb_event->any.xkb_type == XkbStateNotify && xkb_event->state.changed & XkbGroupStateMask)
{
emit groupChanged((uint)xkb_event->state.group);
}
else if (xkb_event->any.xkb_type == XkbNewKeyboardNotify)
{
if (m_configureFilterCounter > 0 || kcmlayoutRunning())
{
return;
}
enableConfigureFilter();
emit optionsChanged();
disableConfigureFilter();
}
}
} }
#include "extension.moc" #include "extension.moc"

@ -1,7 +1,36 @@
/*******************************************************************************
Xkb extension for KXkb
Copyright © 2009-2025 Trinity Desktop project
Copyright © 2001 S.R. Haque <srhaque@iee.org>
Derived from an original by Matthias H<EFBFBD>zer-Klpfel released under the QPL.
Some portions come from kkbswitch released under the GNU GPL v2 (or later).
Copyright © 2001 Leonid Zeitlin <lz@europe.com>
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*******************************************************************************/
#ifndef __EXTENSION_H__ #ifndef __EXTENSION_H__
#define __EXTENSION_H__ #define __EXTENSION_H__
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <tqobject.h> #include <tqobject.h>
#include "kxkbconfig.h" #include "kxkbconfig.h"
@ -11,24 +40,44 @@ class XKBExtension : public TQObject
TQ_OBJECT TQ_OBJECT
public: public:
XKBExtension(Display *display=NULL); static XKBExtension *the();
~XKBExtension(); ~XKBExtension();
XKBExtension(XKBExtension const&) = delete;
void operator=(XKBExtension const&) = delete;
bool init(); bool init();
static bool setXkbOptions(const XkbOptions options); bool setXkbOptions(const XkbOptions options);
static TQString getServerOptions(); bool setGroup(uint group);
bool setGroup(unsigned int group);
unsigned int getGroup() const; uint getGroup() const;
XkbOptions getServerOptions();
void processXEvent(XEvent *ev); void processXEvent(XEvent *ev);
void enableConfigureFilter();
void disableConfigureFilter();
bool kcmlayoutRunning();
private slots:
void slotReleaseConfigureLock();
protected:
XKBExtension() {}
private: private:
Display *m_dpy; Display *m_dpy;
TQString m_tempDir; TQString m_tempDir;
int m_keycode; int m_keycode;
static TQMap<TQString, FILE*> fileCache; static TQMap<TQString, FILE*> fileCache;
int m_configureFilterCounter;
int m_xkb_opcode;
signals: signals:
void groupChanged(uint group); void groupChanged(uint group);
void optionsChanged();
}; };
#endif #endif

@ -14,6 +14,7 @@
#include <tqbuttongroup.h> #include <tqbuttongroup.h>
#include <tqspinbox.h> #include <tqspinbox.h>
#include <tqvbox.h> #include <tqvbox.h>
#include <tqtimer.h>
#include <tdefontrequester.h> #include <tdefontrequester.h>
#include <kcolorbutton.h> #include <kcolorbutton.h>
@ -107,6 +108,9 @@ LayoutConfig::LayoutConfig(TQWidget *parent, const char *name)
m_forceGrpOverwrite(false) m_forceGrpOverwrite(false)
{ {
X11Helper::initializeTranslations(); X11Helper::initializeTranslations();
m_icoMgr = new LayoutIconManager(&m_kxkbConfig);
TQVBoxLayout *main = new TQVBoxLayout(this, 0, KDialog::spacingHint()); TQVBoxLayout *main = new TQVBoxLayout(this, 0, KDialog::spacingHint());
widget = new LayoutConfigWidget(this, "widget"); widget = new LayoutConfigWidget(this, "widget");
@ -143,6 +147,9 @@ LayoutConfig::LayoutConfig(TQWidget *parent, const char *name)
connect( widget->grpSwitching, TQ_SIGNAL( clicked( int ) ), TQ_SLOT(changed())); connect( widget->grpSwitching, TQ_SIGNAL( clicked( int ) ), TQ_SLOT(changed()));
connect( widget->grpLabel, TQ_SIGNAL( clicked( int ) ), TQ_SLOT(changed())); connect( widget->grpLabel, TQ_SIGNAL( clicked( int ) ), TQ_SLOT(changed()));
connect( widget->chkFitToBox, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
connect( widget->chkDimFlag, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
connect( widget->bgColor, TQ_SIGNAL( changed(const TQColor&) ), this, TQ_SLOT(changed())); connect( widget->bgColor, TQ_SIGNAL( changed(const TQColor&) ), this, TQ_SLOT(changed()));
connect( widget->fgColor, TQ_SIGNAL( changed(const TQColor&) ), this, TQ_SLOT(changed())); connect( widget->fgColor, TQ_SIGNAL( changed(const TQColor&) ), this, TQ_SLOT(changed()));
connect( widget->chkBgTransparent, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT(changed())); connect( widget->chkBgTransparent, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT(changed()));
@ -150,11 +157,14 @@ LayoutConfig::LayoutConfig(TQWidget *parent, const char *name)
connect( widget->chkLabelShadow, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT(changed())); connect( widget->chkLabelShadow, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT(changed()));
connect( widget->shColor, TQ_SIGNAL( changed(const TQColor&) ), this, TQ_SLOT(changed())); connect( widget->shColor, TQ_SIGNAL( changed(const TQColor&) ), this, TQ_SLOT(changed()));
connect( widget->chkBevel, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
connect( widget->chkEnableSticky, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed())); connect( widget->chkEnableSticky, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
connect( widget->spinStickyDepth, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(changed())); connect( widget->spinStickyDepth, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(changed()));
connect(widget->chkEnableNotify, TQ_SIGNAL(toggled(bool)), TQ_SLOT(changed())); connect(widget->chkEnableNotify, TQ_SIGNAL(toggled(bool)), TQ_SLOT(changed()));
connect(widget->chkNotifyUseKMilo, TQ_SIGNAL(toggled(bool)), TQ_SLOT(changed())); connect(widget->chkNotifyUseKMilo, TQ_SIGNAL(toggled(bool)), TQ_SLOT(changed()));
connect(widget->chkEnableNotify, TQ_SIGNAL(toggled(bool)), widget->chkNotifyUseKMilo, TQ_SLOT(setEnabled(bool)));
widget->listLayoutsSrc->setColumnText(LAYOUT_COLUMN_FLAG, ""); widget->listLayoutsSrc->setColumnText(LAYOUT_COLUMN_FLAG, "");
widget->listLayoutsDst->setColumnText(LAYOUT_COLUMN_FLAG, ""); widget->listLayoutsDst->setColumnText(LAYOUT_COLUMN_FLAG, "");
@ -180,29 +190,39 @@ LayoutConfig::LayoutConfig(TQWidget *parent, const char *name)
#define NOSLOTS #define NOSLOTS
keys = new TDEGlobalAccel(this); keys = new TDEGlobalAccel(this);
#include "kxkbbindings.cpp" #include "kxkbbindings.cpp"
keys->readSettings();
makeOptionsTab(); makeOptionsTab();
load();
makeShortcutsTab(); makeShortcutsTab();
TQTimer::singleShot(0, this, TQ_SLOT(load()));
} }
LayoutConfig::~LayoutConfig() LayoutConfig::~LayoutConfig()
{ {
delete m_rules; delete m_rules;
delete m_icoMgr;
} }
void LayoutConfig::load() void LayoutConfig::load()
{ {
m_kxkbConfig.load(KxkbConfig::LOAD_ALL); bool modified = false;
m_kxkbConfig.load(KxkbConfig::LOAD_ALL_OPTIONS);
keys->readSettings(); // Check if the active settings are different from the saved settings
if (m_kxkbConfig.m_useKxkb)
{
XkbOptions options = XKBExtension::the()->getServerOptions();
modified = m_kxkbConfig.setFromXkbOptions(options);
}
initUI(); m_kxkbConfig.load(KxkbConfig::LOAD_ALL_OPTIONS);
keys->readSettings();
initUI(modified);
} }
void LayoutConfig::initUI() { void LayoutConfig::initUI(bool modified) {
const char* modelName = m_rules->models()[m_kxkbConfig.m_model]; const char* modelName = m_rules->models()[m_kxkbConfig.m_model];
if( modelName == NULL ) if( modelName == NULL )
modelName = DEFAULT_MODEL; modelName = DEFAULT_MODEL;
@ -219,7 +239,6 @@ void LayoutConfig::initUI() {
for ( ; src_it.current(); ++src_it ) { for ( ; src_it.current(); ++src_it ) {
TQListViewItem* srcItem = src_it.current(); TQListViewItem* srcItem = src_it.current();
if ( layoutUnit.layout == src_it.current()->text(LAYOUT_COLUMN_MAP) ) { // check if current config knows about this layout if ( layoutUnit.layout == src_it.current()->text(LAYOUT_COLUMN_MAP) ) { // check if current config knows about this layout
TQListViewItem* newItem = copyLVI(srcItem, widget->listLayoutsDst); TQListViewItem* newItem = copyLVI(srcItem, widget->listLayoutsDst);
@ -260,6 +279,8 @@ void LayoutConfig::initUI() {
widget->radFlagLabel->setChecked( showFlag && showLabel ); widget->radFlagLabel->setChecked( showFlag && showLabel );
widget->radFlagOnly->setChecked( showFlag && !showLabel ); widget->radFlagOnly->setChecked( showFlag && !showLabel );
widget->radLabelOnly->setChecked( !showFlag && showLabel ); widget->radLabelOnly->setChecked( !showFlag && showLabel );
widget->chkFitToBox->setChecked(m_kxkbConfig.m_fitToBox);
widget->chkDimFlag->setChecked(m_kxkbConfig.m_dimFlag);
widget->xkbOptsMode->setButton(m_kxkbConfig.m_resetOldOptions ? 0 : 1); widget->xkbOptsMode->setButton(m_kxkbConfig.m_resetOldOptions ? 0 : 1);
@ -271,11 +292,15 @@ void LayoutConfig::initUI() {
widget->chkLabelShadow->setChecked( m_kxkbConfig.m_labelShadow ); widget->chkLabelShadow->setChecked( m_kxkbConfig.m_labelShadow );
widget->shColor->setColor( m_kxkbConfig.m_colorShadow ); widget->shColor->setColor( m_kxkbConfig.m_colorShadow );
widget->chkBevel->setChecked(m_kxkbConfig.m_bevel);
widget->grpLabel->setDisabled(showFlag && !showLabel); widget->grpLabel->setDisabled(showFlag && !showLabel);
widget->grpLabelColors->setDisabled(m_kxkbConfig.m_useThemeColors); widget->grpLabelColors->setDisabled(m_kxkbConfig.m_useThemeColors);
widget->labelBgColor->setDisabled(showFlag); widget->labelBgColor->setDisabled(showFlag);
widget->bgColor->setDisabled(showFlag); widget->bgColor->setDisabled(showFlag);
widget->chkBgTransparent->setDisabled(showFlag); widget->chkBgTransparent->setDisabled(showFlag);
widget->grpFlag->setEnabled(showFlag);
widget->chkDimFlag->setEnabled(showFlag && showLabel);
switch( m_kxkbConfig.m_switchingPolicy ) { switch( m_kxkbConfig.m_switchingPolicy ) {
default: default:
@ -296,6 +321,7 @@ void LayoutConfig::initUI() {
widget->chkEnableNotify->setChecked(m_kxkbConfig.m_enableNotify); widget->chkEnableNotify->setChecked(m_kxkbConfig.m_enableNotify);
widget->chkNotifyUseKMilo->setChecked(m_kxkbConfig.m_notifyUseKMilo); widget->chkNotifyUseKMilo->setChecked(m_kxkbConfig.m_notifyUseKMilo);
widget->chkNotifyUseKMilo->setEnabled(m_kxkbConfig.m_enableNotify);
updateStickyLimit(); updateStickyLimit();
@ -341,7 +367,7 @@ void LayoutConfig::initUI() {
updateOptionsCommand(); updateOptionsCommand();
updateHotkeyCombo(true); updateHotkeyCombo(true);
emit TDECModule::changed( false ); emit TDECModule::changed(modified);
} }
@ -353,6 +379,9 @@ void LayoutConfig::save()
m_kxkbConfig.m_resetOldOptions = widget->radXkbOverwrite->isOn(); m_kxkbConfig.m_resetOldOptions = widget->radXkbOverwrite->isOn();
m_kxkbConfig.m_options = createOptionString(); m_kxkbConfig.m_options = createOptionString();
m_kxkbConfig.m_fitToBox = widget->chkFitToBox->isChecked();
m_kxkbConfig.m_dimFlag = widget->chkDimFlag->isChecked();
m_kxkbConfig.m_useThemeColors = widget->radLabelUseTheme->isChecked(); m_kxkbConfig.m_useThemeColors = widget->radLabelUseTheme->isChecked();
m_kxkbConfig.m_colorBackground = widget->bgColor->color(); m_kxkbConfig.m_colorBackground = widget->bgColor->color();
m_kxkbConfig.m_colorLabel = widget->fgColor->color(); m_kxkbConfig.m_colorLabel = widget->fgColor->color();
@ -361,6 +390,8 @@ void LayoutConfig::save()
m_kxkbConfig.m_labelShadow = widget->chkLabelShadow->isChecked(); m_kxkbConfig.m_labelShadow = widget->chkLabelShadow->isChecked();
m_kxkbConfig.m_colorShadow = widget->shColor->color(); m_kxkbConfig.m_colorShadow = widget->shColor->color();
m_kxkbConfig.m_bevel = widget->chkBevel->isChecked();
TQListViewItem *item = widget->listLayoutsDst->firstChild(); TQListViewItem *item = widget->listLayoutsDst->firstChild();
TQValueList<LayoutUnit> layouts; TQValueList<LayoutUnit> layouts;
while (item) { while (item) {
@ -415,7 +446,8 @@ void LayoutConfig::save()
if (m_forceGrpOverwrite) if (m_forceGrpOverwrite)
{ {
// First get all the server's options // First get all the server's options
TQStringList srvOptions = TQStringList::split(",", XKBExtension::getServerOptions()); XkbOptions _opt = XKBExtension::the()->getServerOptions();
TQStringList srvOptions = TQStringList::split(",", _opt.options);
TQStringList newOptions; TQStringList newOptions;
// Then remove all grp: options // Then remove all grp: options
@ -432,7 +464,7 @@ void LayoutConfig::save()
xkbOptions.options = newOptions.join(","); xkbOptions.options = newOptions.join(",");
xkbOptions.resetOld = true; xkbOptions.resetOld = true;
if (!XKBExtension::setXkbOptions(xkbOptions)) if (!XKBExtension::the()->setXkbOptions(xkbOptions))
{ {
kdWarning() << "[LayoutConfig::save] Could not overwrite previous grp: options!" << endl; kdWarning() << "[LayoutConfig::save] Could not overwrite previous grp: options!" << endl;
} }
@ -990,7 +1022,8 @@ void LayoutConfig::updateHotkeyCombo(bool initial) {
// Get server options first // Get server options first
if (initial || widget->xkbOptsMode->selectedId() == 1) if (initial || widget->xkbOptsMode->selectedId() == 1)
{ {
TQStringList opts = TQStringList::split(",", XKBExtension::getServerOptions()); XkbOptions _opt = XKBExtension::the()->getServerOptions();
TQStringList opts = TQStringList::split(",", _opt.options);
for (TQStringList::Iterator it = opts.begin(); it != opts.end(); ++it) for (TQStringList::Iterator it = opts.begin(); it != opts.end(); ++it)
{ {
TQString option(*it); TQString option(*it);
@ -1141,7 +1174,7 @@ void LayoutConfig::loadRules()
TQString layoutName = it2.current(); TQString layoutName = it2.current();
TQListViewItem *item = new TQListViewItem(widget->listLayoutsSrc); TQListViewItem *item = new TQListViewItem(widget->listLayoutsSrc);
item->setPixmap(LAYOUT_COLUMN_FLAG, LayoutIcon::getInstance().findPixmap(layout, false)); item->setPixmap(LAYOUT_COLUMN_FLAG, m_icoMgr->find(layout, PIXMAP_STYLE_CONTEXTMENU));
item->setText(LAYOUT_COLUMN_NAME, i18n(layoutName.latin1())); item->setText(LAYOUT_COLUMN_NAME, i18n(layoutName.latin1()));
item->setText(LAYOUT_COLUMN_MAP, layout); item->setText(LAYOUT_COLUMN_MAP, layout);
++it2; ++it2;
@ -1250,7 +1283,7 @@ extern "C"
tdeApp->startServiceByDesktopName("kxkb"); tdeApp->startServiceByDesktopName("kxkb");
} }
else { else {
if (!XKBExtension::setXkbOptions(m_kxkbConfig.getKXkbOptions())) { if (!XKBExtension::the()->setXkbOptions(m_kxkbConfig.getKXkbOptions())) {
kdDebug() << "Setting XKB options failed!" << endl; kdDebug() << "Setting XKB options failed!" << endl;
} }
} }

@ -11,6 +11,7 @@
class OptionListItem; class OptionListItem;
class LayoutIconManager;
class LayoutConfigWidget; class LayoutConfigWidget;
class XkbRules; class XkbRules;
@ -22,11 +23,13 @@ public:
LayoutConfig(TQWidget *parent = 0L, const char *name = 0L); LayoutConfig(TQWidget *parent = 0L, const char *name = 0L);
virtual ~LayoutConfig(); virtual ~LayoutConfig();
void initUI(bool modified = false);
virtual TQString handbookDocPath() const;
public slots:
void load(); void load();
void save(); void save();
void defaults(); void defaults();
void initUI();
virtual TQString handbookDocPath() const;
protected: protected:
TQString createOptionString(); TQString createOptionString();
@ -52,6 +55,7 @@ protected slots:
void changed(); void changed();
private: private:
LayoutIconManager *m_icoMgr;
LayoutConfigWidget* widget; LayoutConfigWidget* widget;
XkbRules *m_rules; XkbRules *m_rules;

@ -8,8 +8,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>709</width> <width>700</width>
<height>563</height> <height>600</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -22,8 +22,8 @@
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>600</width> <width>700</width>
<height>510</height> <height>600</height>
</size> </size>
</property> </property>
<grid> <grid>
@ -904,36 +904,19 @@
</size> </size>
</property> </property>
</spacer> </spacer>
<spacer row="4" column="0">
<property name="name">
<cstring>spacer22</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Fixed</enum>
</property>
<property name="sizeHint">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
<widget class="TQCheckBox" row="4" column="1" rowspan="1" colspan="3">
<property name="name">
<cstring>chkBgTransparent</cstring>
</property>
<property name="text">
<string>Transparent background</string>
</property>
<property name="whatsThis" stdset="0">
<string>Check this to remove the indicator's background. Only applicable in "Label only" mode.</string>
</property>
</widget>
</grid> </grid>
</widget> </widget>
<widget class="TQCheckBox" row="4" column="0" rowspan="1" colspan="4">
<property name="name">
<cstring>chkBgTransparent</cstring>
</property>
<property name="text">
<string>Transparent background</string>
</property>
<property name="whatsThis" stdset="0">
<string>Check this to remove the indicator's background. Only applicable in "Label only" mode.</string>
</property>
</widget>
<widget class="KSeparator" row="5" column="0" rowspan="1" colspan="3"> <widget class="KSeparator" row="5" column="0" rowspan="1" colspan="3">
<property name="name"> <property name="name">
<cstring>separator1</cstring> <cstring>separator1</cstring>
@ -992,7 +975,8 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
</widget> <spacer row="7" column="2"> </widget>
<spacer row="7" column="2">
<property name="name"> <property name="name">
<cstring>spacer23</cstring> <cstring>spacer23</cstring>
</property> </property>
@ -1011,6 +995,35 @@
</spacer> </spacer>
</grid> </grid>
</widget> </widget>
<widget class="TQButtonGroup" row="2" column="0" column="0" colspan="2">
<property name="name">
<cstring>grpFlag</cstring>
</property>
<property name="title">
<string>Flag Style</string>
</property>
<vbox>
<widget class="TQCheckBox">
<property name="name">
<cstring>chkFitToBox</cstring>
</property>
<property name="text">
<string>Stretc&amp;h flag</string>
</property>
<property name="whatsThis" stdset="0">
<string>If this option is enabled, the flag will be stretched to fit the tray indicator size.</string>
</property>
</widget>
<widget class="TQCheckBox">
<property name="name">
<cstring>chkDimFlag</cstring>
</property>
<property name="text">
<string>Dim flag to make the label more visible</string>
</property>
</widget>
</vbox>
</widget>
<widget class="TQButtonGroup" row="0" column="1"> <widget class="TQButtonGroup" row="0" column="1">
<property name="name"> <property name="name">
<cstring>grpMisc</cstring> <cstring>grpMisc</cstring>
@ -1027,6 +1040,17 @@
<string>Show indicator for single layout</string> <string>Show indicator for single layout</string>
</property> </property>
</widget> </widget>
<widget class="TQCheckBox">
<property name="name">
<cstring>chkBevel</cstring>
</property>
<property name="text">
<string>Show indicator bevel</string>
</property>
<property name="whatsThis" stdset="0">
<string>If this option is enabled, the layout indicator will be drawn with a thin 3D bevel around it.</string>
</property>
</widget>
</vbox> </vbox>
</widget> </widget>
</grid> </grid>
@ -1209,8 +1233,8 @@
<signal>toggled(bool)</signal> <signal>toggled(bool)</signal>
<receiver>bgColor</receiver> <receiver>bgColor</receiver>
<slot>setEnabled(bool)</slot> <slot>setEnabled(bool)</slot>
</connection> </connection>
<connection> <connection>
<sender>radLabelOnly</sender> <sender>radLabelOnly</sender>
<signal>toggled(bool)</signal> <signal>toggled(bool)</signal>
<receiver>labelBgColor</receiver> <receiver>labelBgColor</receiver>
@ -1234,6 +1258,30 @@
<receiver>chkNotifyUseKMilo</receiver> <receiver>chkNotifyUseKMilo</receiver>
<slot>setEnabled(bool)</slot> <slot>setEnabled(bool)</slot>
</connection> </connection>
<connection>
<sender>radFlagOnly</sender>
<signal>toggled(bool)</signal>
<receiver>grpFlag</receiver>
<slot>setEnabled(bool)</slot>
</connection>
<connection>
<sender>radFlagLabel</sender>
<signal>toggled(bool)</signal>
<receiver>grpFlag</receiver>
<slot>setEnabled(bool)</slot>
</connection>
<connection>
<sender>radLabelOnly</sender>
<signal>toggled(bool)</signal>
<receiver>grpFlag</receiver>
<slot>setDisabled(bool)</slot>
</connection>
<connection>
<sender>radFlagLabel</sender>
<signal>toggled(bool)</signal>
<receiver>chkDimFlag</receiver>
<slot>setEnabled(bool)</slot>
</connection>
</connections> </connections>
<includes> <includes>
<include location="local" impldecl="in implementation">kiconloader.h</include> <include location="local" impldecl="in implementation">kiconloader.h</include>

@ -24,16 +24,17 @@ DESCRIPTION
*/ */
#include <unistd.h> #include <unistd.h>
#include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <tqregexp.h> #include <tqregexp.h>
#include <tqfile.h> #include <tqfile.h>
#include <tqstringlist.h> #include <tqstringlist.h>
#include <tqimage.h> #include <tqimage.h>
#include <tqtimer.h>
#include <tdeaboutdata.h> #include <tdeaboutdata.h>
#include <tdecmdlineargs.h> #include <tdecmdlineargs.h>
#include <tdehardwaredevices.h>
#include <tdeglobal.h> #include <tdeglobal.h>
#include <tdeglobalaccel.h> #include <tdeglobalaccel.h>
#include <tdelocale.h> #include <tdelocale.h>
@ -64,17 +65,14 @@ DESCRIPTION
KXKBApp::KXKBApp(bool allowStyles, bool GUIenabled) KXKBApp::KXKBApp(bool allowStyles, bool GUIenabled)
: TDEUniqueApplication(allowStyles, GUIenabled), : TDEUniqueApplication(allowStyles, GUIenabled),
m_prevWinId(X11Helper::UNKNOWN_WINDOW_ID), m_prevWinId(X11Helper::UNKNOWN_WINDOW_ID),
m_rules(NULL), m_rules(nullptr),
m_tray(NULL), m_tray(nullptr),
kWinModule(NULL) kWinModule(nullptr)
{ {
X11Helper::initializeTranslations(); X11Helper::initializeTranslations();
m_extension = new XKBExtension(); XKBExtension *xkb = XKBExtension::the();
if( !m_extension->init() ) { connect(xkb, TQ_SIGNAL(groupChanged(uint)), this, TQ_SLOT(slotGroupChanged(uint)));
kdDebug() << "xkb initialization failed, exiting..." << endl; connect(xkb, TQ_SIGNAL(optionsChanged()), this, TQ_SLOT(slotSyncXkbOptions()));
::exit(1);
}
connect(m_extension, TQ_SIGNAL(groupChanged(uint)), this, TQ_SLOT(slotGroupChanged(uint)));
m_layoutOwnerMap = new LayoutMap(kxkbConfig); m_layoutOwnerMap = new LayoutMap(kxkbConfig);
@ -84,14 +82,17 @@ KXKBApp::KXKBApp(bool allowStyles, bool GUIenabled)
connect( this, TQ_SIGNAL(settingsChanged(int)), TQ_SLOT(slotSettingsChanged(int)) ); connect( this, TQ_SIGNAL(settingsChanged(int)), TQ_SLOT(slotSettingsChanged(int)) );
addKipcEventMask( KIPC::SettingsChanged ); addKipcEventMask( KIPC::SettingsChanged );
}
TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
connect(hwdevices, TQ_SIGNAL(hardwareAdded(TDEGenericDevice*)), this, TQ_SLOT(hardwareChanged(TDEGenericDevice*)));
connect(hwdevices, TQ_SIGNAL(hardwareRemoved(TDEGenericDevice*)), this, TQ_SLOT(hardwareChanged(TDEGenericDevice*)));
connect(hwdevices, TQ_SIGNAL(hardwareUpdated(TDEGenericDevice*)), this, TQ_SLOT(hardwareChanged(TDEGenericDevice*)));
}
KXKBApp::~KXKBApp() KXKBApp::~KXKBApp()
{ {
delete m_tray; delete m_tray;
delete m_rules; delete m_rules;
delete m_extension;
delete m_layoutOwnerMap; delete m_layoutOwnerMap;
delete kWinModule; delete kWinModule;
delete keys; delete keys;
@ -99,231 +100,296 @@ KXKBApp::~KXKBApp()
int KXKBApp::newInstance() int KXKBApp::newInstance()
{ {
if (settingsRead()) { readSettings();
layoutApply();
}
return 0; return 0;
} }
bool KXKBApp::settingsRead() void KXKBApp::readSettings()
{ {
XkbOptions options = kxkbConfig.getKXkbOptions(); // Xkb options
if( !m_extension->setXkbOptions(options) ) { kxkbConfig.load(KxkbConfig::LOAD_INIT_OPTIONS);
kdDebug() << "Setting XKB options failed!" << endl;
}
if ( kxkbConfig.m_useKxkb == false ) { if (!kxkbConfig.m_useKxkb)
tdeApp->quit(); {
return false; kdDebug() << "kxkb is disabled, applying xkb options and exiting" << endl;
applyXkbOptions();
quit();
return;
} }
m_prevWinId = X11Helper::UNKNOWN_WINDOW_ID; kdDebug() << "applying xkb options and layouts" << endl;
kxkbConfig.load(KxkbConfig::LOAD_ALL_OPTIONS);
if( kxkbConfig.m_switchingPolicy == SWITCH_POLICY_GLOBAL ) { applyXkbOptions();
delete kWinModule;
kWinModule = NULL; // Active window watcher
} m_prevWinId = X11Helper::UNKNOWN_WINDOW_ID;
else {
TQDesktopWidget desktopWidget; if (kxkbConfig.m_switchingPolicy == SWITCH_POLICY_GLOBAL)
if( desktopWidget.numScreens() > 1 && desktopWidget.isVirtualDesktop() == false ) { {
kdWarning() << "With non-virtual desktop only global switching policy supported on non-primary screens" << endl; delete kWinModule;
//TODO: find out how to handle that kWinModule = nullptr;
} }
if( kWinModule == NULL ) { else
kWinModule = new KWinModule(0, KWinModule::INFO_DESKTOP); {
connect(kWinModule, TQ_SIGNAL(activeWindowChanged(WId)), TQ_SLOT(windowChanged(WId))); TQDesktopWidget desktopWidget;
} if (desktopWidget.numScreens() > 1 && !desktopWidget.isVirtualDesktop())
m_prevWinId = kWinModule->activeWindow(); {
kdDebug() << "Active window " << m_prevWinId << endl; kdWarning() << "With non-virtual desktop only global switching policy supported on non-primary screens" << endl;
} //TODO: find out how to handle that
}
m_layoutOwnerMap->reset();
m_layoutOwnerMap->setCurrentWindow( m_prevWinId ); if (!kWinModule)
{
if( m_rules == NULL ) kWinModule = new KWinModule(nullptr, KWinModule::INFO_DESKTOP);
m_rules = new XkbRules(false); connect(kWinModule, TQ_SIGNAL(activeWindowChanged(WId)), TQ_SLOT(windowChanged(WId)));
}
for(int ii=0; ii<(int)kxkbConfig.m_layouts.count(); ii++) {
LayoutUnit& layoutUnit = kxkbConfig.m_layouts[ii]; m_prevWinId = kWinModule->activeWindow();
} kdDebug() << "Active window " << m_prevWinId << endl;
}
m_currentLayout = kxkbConfig.m_layouts[0];
kdDebug() << "default layout is " << m_currentLayout.toPair() << endl; // Init layout owner map
m_layoutOwnerMap->reset();
if( kxkbConfig.m_layouts.count() == 1 && !kxkbConfig.m_showSingle) { m_layoutOwnerMap->setCurrentWindow( m_prevWinId );
tdeApp->quit();
return false; // Init rules
} if (!m_rules)
{
initTray(); m_rules = new XkbRules(false);
}
TDEGlobal::config()->reparseConfiguration(); // kcontrol modified kdeglobals
keys->readSettings(); // Init layouts
keys->updateConnections(); for (int i = 0; i < kxkbConfig.m_layouts.count(); i++)
{
return true; LayoutUnit& layoutUnit = kxkbConfig.m_layouts[i];
}
m_currentLayout = kxkbConfig.m_layouts[0];
setLayout(m_currentLayout);
kdDebug() << "default layout is " << m_currentLayout.toPair() << endl;
if (kxkbConfig.m_layouts.count() == 1 && !kxkbConfig.m_showSingle)
{
quit();
return;
}
TDEGlobal::config()->reparseConfiguration(); // kcontrol modified kdeglobals
// Init tray
if (!m_tray)
{
m_tray = new KxkbSystemTray(&kxkbConfig);
connect(m_tray, TQ_SIGNAL(menuActivated(int)), this, TQ_SLOT(menuActivated(int)));
connect(m_tray, TQ_SIGNAL(toggled()), this, TQ_SLOT(nextLayout()));
}
m_tray->initLayoutList(kxkbConfig.m_layouts, *m_rules);
m_tray->setCurrentLayout(m_currentLayout);
m_tray->show();
// Init keybindings
keys->readSettings();
keys->updateConnections();
} }
void KXKBApp::initTray() void KXKBApp::applyXkbOptions()
{ {
if( !m_tray ) XkbOptions options = kxkbConfig.getKXkbOptions();
{ if (!XKBExtension::the()->setXkbOptions(options)) {
KSystemTray* sysTray = new KxkbSystemTray(); kdWarning() << "Setting XKB options failed!" << endl;
TDEPopupMenu* popupMenu = sysTray->contextMenu(); }
// popupMenu->insertTitle( tdeApp->miniIcon(), tdeApp->caption() );
m_tray = new KxkbLabelController(sysTray, popupMenu);
connect(popupMenu, TQ_SIGNAL(activated(int)), this, TQ_SLOT(menuActivated(int)));
connect(sysTray, TQ_SIGNAL(toggled()), this, TQ_SLOT(nextLayout()));
}
m_tray->setShowFlag(kxkbConfig.m_showFlag);
m_tray->initLayoutList(kxkbConfig.m_layouts, *m_rules);
m_tray->setCurrentLayout(m_currentLayout);
m_tray->show();
} }
// This function activates the keyboard layout specified by the void KXKBApp::hardwareChanged(TDEGenericDevice *dev)
// configuration members (m_currentLayout)
void KXKBApp::layoutApply()
{ {
setLayout(m_currentLayout); if (dev->type() == TDEGenericDeviceType::Keyboard)
{
TQTimer::singleShot(500, this, TQ_SLOT(applyXkbOptions()));
}
} }
// kdcop // kdcop
bool KXKBApp::setLayout(const TQString& layoutPair) bool KXKBApp::setLayout(const TQString& layoutPair)
{ {
const LayoutUnit layoutUnitKey(layoutPair); return setLayout((LayoutUnit)layoutPair);
if( kxkbConfig.m_layouts.contains(layoutUnitKey) ) {
return setLayout( *kxkbConfig.m_layouts.find(layoutUnitKey) );
}
return false;
} }
// Activates the keyboard layout specified by 'layoutUnit' // Activates the keyboard layout specified by 'layoutUnit'
bool KXKBApp::setLayout(const LayoutUnit& layoutUnit) bool KXKBApp::setLayout(const LayoutUnit& layoutUnit)
{ {
uint group = kxkbConfig.m_layouts.findIndex(layoutUnit); const int group = kxkbConfig.m_layouts.findIndex(layoutUnit);
bool res = m_extension->setGroup(group); if (group >= 0) {
if (res) { return setLayout(group);
m_currentLayout = layoutUnit; }
maybeShowLayoutNotification(); return false;
}
if (m_tray) {
if (res) {
m_tray->setCurrentLayout(layoutUnit);
} else {
m_tray->setError(layoutUnit.toPair());
}
}
return res;
} }
// Activates the keyboard layout specified by group number // Activates the keyboard layout specified by group number
bool KXKBApp::setLayout(const uint group) bool KXKBApp::setLayout(const uint group)
{ {
bool res = m_extension->setGroup(group); // If this group is already set, just show the notification and return
if (res) { if (XKBExtension::the()->getGroup() == group) {
m_currentLayout = kxkbConfig.m_layouts[group]; if (kxkbConfig.m_enableNotify) {
} showLayoutNotification();
}
return true;
}
if (m_tray) { bool ok = XKBExtension::the()->setGroup(group);
if (res) if (!ok) {
m_tray->setCurrentLayout(m_currentLayout); TQString layout = kxkbConfig.m_layouts[group].toPair();
else if (m_tray) {
m_tray->setError(m_currentLayout.toPair()); m_tray->setError(layout);
} }
return res; if (kxkbConfig.m_enableNotify) {
showErrorNotification(layout);
}
}
return ok;
} }
void KXKBApp::nextLayout() void KXKBApp::nextLayout()
{ {
const LayoutUnit& layout = m_layoutOwnerMap->getNextLayout().layoutUnit; const LayoutUnit& layout = m_layoutOwnerMap->getNextLayout().layoutUnit;
setLayout(layout); setLayout(layout);
} }
void KXKBApp::prevLayout() void KXKBApp::prevLayout()
{ {
const LayoutUnit& layout = m_layoutOwnerMap->getPrevLayout().layoutUnit; const LayoutUnit& layout = m_layoutOwnerMap->getPrevLayout().layoutUnit;
setLayout(layout); setLayout(layout);
} }
void KXKBApp::menuActivated(int id) void KXKBApp::menuActivated(int id)
{ {
if( KxkbLabelController::START_MENU_ID <= id if (id >= KxkbSystemTray::START_MENU_ID &&
&& id < KxkbLabelController::START_MENU_ID + (int)kxkbConfig.m_layouts.count() ) id < KxkbSystemTray::START_MENU_ID + kxkbConfig.m_layouts.count())
{ {
const LayoutUnit& layout = kxkbConfig.m_layouts[id - KxkbLabelController::START_MENU_ID]; setLayout(id - KxkbSystemTray::START_MENU_ID);
m_layoutOwnerMap->setCurrentLayout( layout ); }
setLayout( layout ); else if (id == KxkbSystemTray::CONFIG_MENU_ID)
}
else if (id == KxkbLabelController::CONFIG_MENU_ID)
{ {
TDEProcess p; TDEProcess p;
p << "tdecmshell" << "keyboard_layout"; p << "tdecmshell" << "keyboard_layout";
p.start(TDEProcess::DontCare); p.start(TDEProcess::DontCare);
} }
else if (id == KxkbLabelController::HELP_MENU_ID) else if (id == KxkbSystemTray::HELP_MENU_ID)
{ {
tdeApp->invokeHelp(0, "kxkb"); invokeHelp(0, "kxkb");
} }
// else else
// { {
// quit(); quit();
// } }
} }
void KXKBApp::slotGroupChanged(uint group) void KXKBApp::slotGroupChanged(uint group)
{ {
if (group >= kxkbConfig.m_layouts.count()) if (!kxkbConfig.m_layouts.count()) {
{ kdError() << "[kxkb] no layout found!" << endl;
group = 0; return;
} }
m_currentLayout = kxkbConfig.m_layouts[group];
m_tray->setCurrentLayout(m_currentLayout);
maybeShowLayoutNotification();
}
void KXKBApp::maybeShowLayoutNotification() { if (group >= kxkbConfig.m_layouts.count()) {
if (!kxkbConfig.m_enableNotify) return; kdError() << "[kxkb] unknown group requested: " << group << endl;
if (m_tray)
{
m_tray->setError(i18n("Unknown"));
}
if (kxkbConfig.m_enableNotify)
{
showErrorNotification(i18n("Unknown"));
}
return;
}
m_currentLayout = kxkbConfig.m_layouts[group];
m_layoutOwnerMap->setCurrentLayout(m_currentLayout);
if (m_tray) {
m_tray->setCurrentLayout(m_currentLayout);
}
if (kxkbConfig.m_enableNotify) {
showLayoutNotification();
}
}
TQString layoutName(m_rules->getLayoutName(m_currentLayout)); void KXKBApp::slotSyncXkbOptions()
bool useKMilo = kxkbConfig.m_notifyUseKMilo; {
bool notificationSent = false; // Make sure the X11 server has had enough time to apply the change
TQTimer::singleShot(100, this, TQ_SLOT(syncXkbOptions()));
}
// Query KDED whether KMiloD is loaded void KXKBApp::syncXkbOptions()
if (useKMilo) { {
QCStringList modules; XkbOptions options = XKBExtension::the()->getServerOptions();
TQCString replyType; if (kxkbConfig.setFromXkbOptions(options))
TQByteArray replyData; {
if (tdeApp->dcopClient()->call("kded", "kded", "loadedModules()", m_layoutOwnerMap->reset();
TQByteArray(), replyType, replyData)) if (m_tray)
{ {
if (replyType == "QCStringList") { m_tray->initLayoutList(kxkbConfig.m_layouts, *m_rules);
TQDataStream reply(replyData, IO_ReadOnly);
reply >> modules;
if (!modules.contains("kmilod")) {
useKMilo = false;
}
}
} }
} }
slotGroupChanged(XKBExtension::the()->getGroup());
}
if (useKMilo) { void KXKBApp::showLayoutNotification()
DCOPRef kmilo("kded", "kmilod"); {
if (kmilo.send("displayText(TQString,TQPixmap)", layoutName, tdeApp->miniIcon())) bool useKMilo = kxkbConfig.m_notifyUseKMilo && isKMiloAvailable(),
notificationSent = true; notificationSent = false;
}
if (!notificationSent) { TQString layoutName(m_rules->getLayoutName(m_currentLayout));
KNotifyClient::event(m_tray->winId(), "LayoutChange", layoutName);
} if (useKMilo) {
DCOPRef kmilo("kded", "kmilod");
if (kmilo.send("displayText(TQString,TQPixmap)", layoutName, miniIcon())) {
notificationSent = true;
}
}
if (!notificationSent) {
WId wid = (m_tray ? m_tray->winId() : 0);
KNotifyClient::event(wid, "LayoutChange", layoutName);
}
}
void KXKBApp::showErrorNotification(TQString layout) {
bool useKMilo = kxkbConfig.m_notifyUseKMilo && isKMiloAvailable(),
notificationSent = false;
if (useKMilo) {
DCOPRef kmilo("kded", "kmilod");
if (kmilo.send("displayText(TQString,TQPixmap)", i18n("Error changing keyboard layout to '%1'").arg(layout), miniIcon())) {
notificationSent = true;
}
}
if (!notificationSent) {
WId wid = (m_tray ? m_tray->winId() : 0);
KNotifyClient::event(wid, "Error");
}
}
bool KXKBApp::isKMiloAvailable() {
QCStringList modules;
TQCString replyType;
TQByteArray replyData;
if (dcopClient()->call("kded", "kded", "loadedModules()",
TQByteArray(), replyType, replyData))
{
if (replyType == "QCStringList") {
TQDataStream reply(replyData, IO_ReadOnly);
reply >> modules;
return modules.contains("kmilod");
}
}
return false;
} }
// TODO: we also have to handle deleted windows // TODO: we also have to handle deleted windows
@ -336,18 +402,18 @@ void KXKBApp::windowChanged(WId winId)
} }
kdDebug() << "old WinId: " << m_prevWinId << ", new WinId: " << winId << endl; kdDebug() << "old WinId: " << m_prevWinId << ", new WinId: " << winId << endl;
if( m_prevWinId != X11Helper::UNKNOWN_WINDOW_ID ) { // saving layout from previous window if( m_prevWinId != X11Helper::UNKNOWN_WINDOW_ID ) { // saving layout from previous window
// m_layoutOwnerMap->setCurrentWindow(m_prevWinId); // m_layoutOwnerMap->setCurrentWindow(m_prevWinId);
m_layoutOwnerMap->setCurrentLayout(m_currentLayout); m_layoutOwnerMap->setCurrentLayout(m_currentLayout);
} }
m_prevWinId = winId; m_prevWinId = winId;
if( winId != X11Helper::UNKNOWN_WINDOW_ID ) { if( winId != X11Helper::UNKNOWN_WINDOW_ID ) {
m_layoutOwnerMap->setCurrentWindow(winId); m_layoutOwnerMap->setCurrentWindow(winId);
const LayoutState& layoutState = m_layoutOwnerMap->getCurrentLayout(); const LayoutState& layoutState = m_layoutOwnerMap->getCurrentLayout();
if( layoutState.layoutUnit != m_currentLayout ) { if( layoutState.layoutUnit != m_currentLayout ) {
kdDebug() << "switching to " << layoutState.layoutUnit.toPair() << " for " << winId << endl; kdDebug() << "switching to " << layoutState.layoutUnit.toPair() << " for " << winId << endl;
setLayout(layoutState.layoutUnit); setLayout(layoutState.layoutUnit);
@ -355,7 +421,6 @@ void KXKBApp::windowChanged(WId winId)
} }
} }
void KXKBApp::slotSettingsChanged(int category) void KXKBApp::slotSettingsChanged(int category)
{ {
if (category == TDEApplication::SETTINGS_SHORTCUTS) { if (category == TDEApplication::SETTINGS_SHORTCUTS) {
@ -367,7 +432,7 @@ void KXKBApp::slotSettingsChanged(int category)
bool KXKBApp::x11EventFilter(XEvent *e) { bool KXKBApp::x11EventFilter(XEvent *e) {
// let the extension process the event and emit signals if necessary // let the extension process the event and emit signals if necessary
m_extension->processXEvent(e); XKBExtension::the()->processXEvent(e);
return TDEApplication::x11EventFilter(e); return TDEApplication::x11EventFilter(e);
} }

@ -32,6 +32,7 @@ DESCRIPTION
#include <tqptrqueue.h> #include <tqptrqueue.h>
#include <tdeuniqueapplication.h> #include <tdeuniqueapplication.h>
#include <tdegenericdevice.h>
#include "kxkbtraywindow.h" #include "kxkbtraywindow.h"
#include "kxkbconfig.h" #include "kxkbconfig.h"
@ -72,19 +73,23 @@ public slots:
protected slots: protected slots:
void menuActivated(int id); void menuActivated(int id);
void windowChanged(WId winId); void windowChanged(WId winId);
void layoutApply();
void slotGroupChanged(uint group); void slotGroupChanged(uint group);
void slotSettingsChanged(int category); void slotSettingsChanged(int category);
void maybeShowLayoutNotification(); void showLayoutNotification();
void showErrorNotification(TQString layout);
protected: void hardwareChanged(TDEGenericDevice *dev);
// Read settings, and apply them.
bool settingsRead(); void readSettings();
void applyXkbOptions();
void slotSyncXkbOptions();
void syncXkbOptions();
private: private:
void initTray(); void initTray();
bool x11EventFilter(XEvent *e); bool x11EventFilter(XEvent *e);
bool isKMiloAvailable();
private: private:
KxkbConfig kxkbConfig; KxkbConfig kxkbConfig;
@ -96,7 +101,7 @@ private:
XKBExtension *m_extension; XKBExtension *m_extension;
XkbRules *m_rules; XkbRules *m_rules;
KxkbLabelController *m_tray; KxkbSystemTray *m_tray;
TDEGlobalAccel *keys; TDEGlobalAccel *keys;
KWinModule* kWinModule; KWinModule* kWinModule;
bool m_forceSetXKBMap; bool m_forceSetXKBMap;

@ -30,112 +30,150 @@ static const char* switchModes[SWITCH_POLICY_COUNT] = {
const LayoutUnit DEFAULT_LAYOUT_UNIT = LayoutUnit("us", ""); const LayoutUnit DEFAULT_LAYOUT_UNIT = LayoutUnit("us", "");
const char* DEFAULT_MODEL = "pc104"; const char* DEFAULT_MODEL = "pc104";
bool KxkbConfig::load(int loadMode) void KxkbConfig::load(int loadMode)
{ {
// INITIAL OPTIONS (loaded regardless of whether KXkb is enabled)
TDEConfig *config = new TDEConfig("kxkbrc", true, false); TDEConfig *config = new TDEConfig("kxkbrc", true, false);
config->setGroup("Layout"); config->setGroup("Layout");
if( loadMode == LOAD_ALL ) {
m_resetOldOptions = config->readBoolEntry("ResetOldOptions", true);
m_options = config->readEntry("Options", "");
}
m_useKxkb = config->readBoolEntry("Use", false); m_useKxkb = config->readBoolEntry("Use", false);
kdDebug() << "Use kxkb " << m_useKxkb << endl;
if( (m_useKxkb == false && loadMode == LOAD_ACTIVE_OPTIONS ) m_resetOldOptions = config->readBoolEntry("ResetOldOptions", true);
|| loadMode == LOAD_INIT_OPTIONS ) m_options = config->readEntry("Options", "");
return true;
if (loadMode == LOAD_INIT_OPTIONS)
{
return;
}
// BASIC OPTIONS (passed to setxkbmap)
m_model = config->readEntry("Model", DEFAULT_MODEL); m_model = config->readEntry("Model", DEFAULT_MODEL);
kdDebug() << "Model: " << m_model << endl;
// Layouts
TQStringList layoutList; TQStringList layoutList;
if( config->hasKey("LayoutList") ) { if (config->hasKey("LayoutList"))
{
layoutList = config->readListEntry("LayoutList"); layoutList = config->readListEntry("LayoutList");
} }
else { // old config else
{ // old config
TQString mainLayout = config->readEntry("Layout", DEFAULT_LAYOUT_UNIT.toPair()); TQString mainLayout = config->readEntry("Layout", DEFAULT_LAYOUT_UNIT.toPair());
layoutList = config->readListEntry("Additional"); layoutList = config->readListEntry("Additional");
layoutList.prepend(mainLayout); layoutList.prepend(mainLayout);
} }
if( layoutList.count() == 0 )
if (layoutList.count() == 0)
{
layoutList.append("us"); layoutList.append("us");
}
TQStringList::ConstIterator it;
m_layouts.clear(); m_layouts.clear();
for(TQStringList::ConstIterator it = layoutList.begin(); it != layoutList.end() ; ++it) { for (it = layoutList.begin(); it != layoutList.end(); ++it)
{
m_layouts.append( LayoutUnit(*it) ); m_layouts.append( LayoutUnit(*it) );
kdDebug() << " layout " << LayoutUnit(*it).toPair() << " in list: " << m_layouts.contains( LayoutUnit(*it) ) << endl; kdDebug() << " layout " << LayoutUnit(*it).toPair() << " in list: " << m_layouts.contains(LayoutUnit(*it)) << endl;
} }
kdDebug() << "Found " << m_layouts.count() << " layouts" << endl; kdDebug() << "Found " << m_layouts.count() << " layouts" << endl;
// Display names
TQStringList displayNamesList = config->readListEntry("DisplayNames", ','); TQStringList displayNamesList = config->readListEntry("DisplayNames", ',');
for(TQStringList::ConstIterator it = displayNamesList.begin(); it != displayNamesList.end() ; ++it) { for (it = displayNamesList.begin(); it != displayNamesList.end() ; ++it)
{
TQStringList displayNamePair = TQStringList::split(':', *it ); TQStringList displayNamePair = TQStringList::split(':', *it );
if( displayNamePair.count() == 2 ) { if (displayNamePair.count() == 2)
LayoutUnit layoutUnit( displayNamePair[0] ); {
if( m_layouts.contains( layoutUnit ) ) { LayoutUnit layoutUnit(displayNamePair[0]);
if (m_layouts.contains(layoutUnit))
{
m_layouts[m_layouts.findIndex(layoutUnit)].displayName = displayNamePair[1].left(3); m_layouts[m_layouts.findIndex(layoutUnit)].displayName = displayNamePair[1].left(3);
} }
} }
} }
if (loadMode == LOAD_BASIC_OPTIONS)
{
return;
}
// ALL OTHER OPTIONS (of interest only to KXkb itself)
// Tray indicator
m_showSingle = config->readBoolEntry("ShowSingle", false); m_showSingle = config->readBoolEntry("ShowSingle", false);
m_showFlag = config->readBoolEntry("ShowFlag", true); m_showFlag = config->readBoolEntry("ShowFlag", true);
m_showLabel = config->readBoolEntry("ShowLabel", true); m_showLabel = config->readBoolEntry("ShowLabel", true);
m_fitToBox = config->readBoolEntry("FitFlagToBox", true);
m_useThemeColors = config->readBoolEntry("UseThemeColors", false); m_useThemeColors = config->readBoolEntry("UseThemeColors", false);
m_colorBackground = config->readColorEntry("ColorBackground", new TQColor(TQt::gray)); m_colorBackground = config->readColorEntry("ColorBackground", new TQColor(TQt::gray));
m_bgTransparent = config->readBoolEntry("BgTransparent", false); m_bgTransparent = config->readBoolEntry("BgTransparent", false);
m_colorLabel = config->readColorEntry("ColorLabel", new TQColor(TQt::white)); m_colorLabel = config->readColorEntry("ColorLabel", new TQColor(TQt::white));
m_labelFont = config->readFontEntry("LabelFont", new TQFont("sans", 10, TQFont::Bold)); m_labelFont = config->readFontEntry("LabelFont", new TQFont("sans", 10, TQFont::Bold));
m_labelShadow = config->readBoolEntry("LabelShadow", true); m_labelShadow = config->readBoolEntry("LabelShadow", true);
m_colorShadow = config->readColorEntry("ColorShadow", new TQColor(TQt::black)); m_colorShadow = config->readColorEntry("ColorShadow", new TQColor(TQt::black));
m_dimFlag = config->readBoolEntry("DimFlag", true);
m_bevel = config->readBoolEntry("IndicatorBevel", false);
// Switching policy
TQString layoutOwner = config->readEntry("SwitchMode", "Global"); TQString layoutOwner = config->readEntry("SwitchMode", "Global");
if( layoutOwner == "WinClass" ) { if (layoutOwner == "WinClass")
{
m_switchingPolicy = SWITCH_POLICY_WIN_CLASS; m_switchingPolicy = SWITCH_POLICY_WIN_CLASS;
} }
else if( layoutOwner == "Window" ) { else if (layoutOwner == "Window")
{
m_switchingPolicy = SWITCH_POLICY_WINDOW; m_switchingPolicy = SWITCH_POLICY_WINDOW;
} }
else /*if( layoutOwner == "Global" )*/ { else
{
m_switchingPolicy = SWITCH_POLICY_GLOBAL; m_switchingPolicy = SWITCH_POLICY_GLOBAL;
} }
if( m_layouts.count() < 2 && m_switchingPolicy != SWITCH_POLICY_GLOBAL ) { if (m_layouts.count() < 2 && m_switchingPolicy != SWITCH_POLICY_GLOBAL)
{
kdWarning() << "Layout count is less than 2, using Global switching policy" << endl; kdWarning() << "Layout count is less than 2, using Global switching policy" << endl;
m_switchingPolicy = SWITCH_POLICY_GLOBAL; m_switchingPolicy = SWITCH_POLICY_GLOBAL;
} }
kdDebug() << "Layout owner mode " << layoutOwner << endl; kdDebug() << "Layout owner mode " << layoutOwner << endl;
// Sticky switching
m_stickySwitching = config->readBoolEntry("StickySwitching", false); m_stickySwitching = config->readBoolEntry("StickySwitching", false);
m_stickySwitchingDepth = config->readEntry("StickySwitchingDepth", "2").toInt(); m_stickySwitchingDepth = config->readNumEntry("StickySwitchingDepth", 2);
if( m_stickySwitchingDepth < 2 ) if (m_stickySwitchingDepth < 2)
{
m_stickySwitchingDepth = 2; m_stickySwitchingDepth = 2;
}
if( m_stickySwitching == true ) { if (m_stickySwitching)
if( m_layouts.count() < 3 ) { {
if (m_layouts.count() < 3)
{
kdWarning() << "Layout count is less than 3, sticky switching will be off" << endl; kdWarning() << "Layout count is less than 3, sticky switching will be off" << endl;
m_stickySwitching = false; m_stickySwitching = false;
} }
else else if (m_layouts.count() - 1 < m_stickySwitchingDepth)
if( (int)m_layouts.count() - 1 < m_stickySwitchingDepth ) { {
kdWarning() << "Sticky switching depth is more than layout count -1, adjusting..." << endl; kdWarning() << "Sticky switching depth is more than layout count -1, adjusting..." << endl;
m_stickySwitchingDepth = m_layouts.count() - 1; m_stickySwitchingDepth = m_layouts.count() - 1;
} }
} }
// Notifications
config->setGroup("Notifications"); config->setGroup("Notifications");
m_enableNotify = config->readBoolEntry("Enable", false); m_enableNotify = config->readBoolEntry("Enable", false);
m_notifyUseKMilo = config->readBoolEntry("UseKMilo", true); m_notifyUseKMilo = config->readBoolEntry("UseKMilo", true);
delete config; delete config;
return true;
} }
void KxkbConfig::save() void KxkbConfig::save()
@ -143,55 +181,65 @@ void KxkbConfig::save()
TDEConfig *config = new TDEConfig("kxkbrc", false, false); TDEConfig *config = new TDEConfig("kxkbrc", false, false);
config->setGroup("Layout"); config->setGroup("Layout");
config->writeEntry("Model", m_model); config->writeEntry("Use", m_useKxkb);
config->writeEntry("ResetOldOptions", m_resetOldOptions); config->writeEntry("ResetOldOptions", m_resetOldOptions);
config->writeEntry("Options", m_options ); config->writeEntry("Options", m_options );
config->writeEntry("Model", m_model);
// Layouts
TQStringList layoutList; TQStringList layoutList;
TQStringList displayNamesList; TQStringList displayNamesList;
TQValueList<LayoutUnit>::ConstIterator it; TQValueList<LayoutUnit>::ConstIterator it;
for(it = m_layouts.begin(); it != m_layouts.end(); ++it) { for (it = m_layouts.begin(); it != m_layouts.end(); ++it) {
const LayoutUnit& layoutUnit = *it; const LayoutUnit& layoutUnit = *it;
layoutList.append(layoutUnit.toPair());
layoutList.append( layoutUnit.toPair() ); // Display name
TQString displayName(layoutUnit.displayName);
TQString displayName( layoutUnit.displayName ); if (!displayName.isEmpty() && displayName != layoutUnit.layout)
kdDebug() << " displayName " << layoutUnit.toPair() << " : " << displayName << endl; {
if( displayName.isEmpty() == false && displayName != layoutUnit.layout ) {
displayName = TQString("%1:%2").arg(layoutUnit.toPair(), displayName); displayName = TQString("%1:%2").arg(layoutUnit.toPair(), displayName);
displayNamesList.append( displayName ); displayNamesList.append(displayName);
} }
} }
config->writeEntry("LayoutList", layoutList); config->writeEntry("LayoutList", layoutList);
kdDebug() << "Saving Layouts: " << layoutList << endl; config->writeEntry("DisplayNames", displayNamesList);
// if( displayNamesList.empty() == false )
config->writeEntry("DisplayNames", displayNamesList);
// else
// config->deleteEntry("DisplayNames");
config->writeEntry("Use", m_useKxkb); // Tray indicator
config->writeEntry("ShowSingle", m_showSingle); config->writeEntry("ShowSingle", m_showSingle);
config->writeEntry("ShowFlag", m_showFlag); config->writeEntry("ShowFlag", m_showFlag);
config->writeEntry("ShowLabel", m_showLabel); config->writeEntry("ShowLabel", m_showLabel);
config->writeEntry("FitFlagToBox", m_fitToBox);
config->writeEntry("UseThemeColors", m_useThemeColors); config->writeEntry("UseThemeColors", m_useThemeColors);
config->writeEntry("ColorBackground", m_colorBackground); config->writeEntry("ColorBackground", m_colorBackground);
config->writeEntry("BgTransparent", m_bgTransparent); config->writeEntry("BgTransparent", m_bgTransparent);
config->writeEntry("ColorLabel", m_colorLabel); config->writeEntry("ColorLabel", m_colorLabel);
config->writeEntry("LabelFont", m_labelFont); config->writeEntry("LabelFont", m_labelFont);
config->writeEntry("LabelShadow", m_labelShadow); config->writeEntry("LabelShadow", m_labelShadow);
config->writeEntry("ColorShadow", m_colorShadow); config->writeEntry("ColorShadow", m_colorShadow);
config->writeEntry("DimFlag", m_dimFlag);
config->writeEntry("IndicatorBevel", m_bevel);
// Switching policy
config->writeEntry("SwitchMode", switchModes[m_switchingPolicy]); config->writeEntry("SwitchMode", switchModes[m_switchingPolicy]);
// Sticky switching
config->writeEntry("StickySwitching", m_stickySwitching); config->writeEntry("StickySwitching", m_stickySwitching);
config->writeEntry("StickySwitchingDepth", m_stickySwitchingDepth); config->writeEntry("StickySwitchingDepth", m_stickySwitchingDepth);
// Notifications
config->setGroup("Notifications");
config->writeEntry("Enable", m_enableNotify);
config->writeEntry("UseKMilo", m_notifyUseKMilo);
// remove old options // remove old options
config->deleteEntry("Variants"); config->deleteEntry("Variants");
config->deleteEntry("Includes"); config->deleteEntry("Includes");
@ -200,12 +248,7 @@ void KxkbConfig::save()
config->deleteEntry("Additional"); config->deleteEntry("Additional");
config->deleteEntry("Layout"); config->deleteEntry("Layout");
config->setGroup("Notifications");
config->writeEntry("Enable", m_enableNotify);
config->writeEntry("UseKMilo", m_notifyUseKMilo);
config->sync(); config->sync();
delete config; delete config;
} }
@ -222,6 +265,10 @@ void KxkbConfig::setDefaults()
m_useKxkb = false; m_useKxkb = false;
m_showSingle = false; m_showSingle = false;
m_showFlag = true; m_showFlag = true;
m_fitToBox = true;
m_dimFlag = true;
m_bevel = false;
m_switchingPolicy = SWITCH_POLICY_GLOBAL; m_switchingPolicy = SWITCH_POLICY_GLOBAL;
@ -229,6 +276,74 @@ void KxkbConfig::setDefaults()
m_stickySwitchingDepth = 2; m_stickySwitchingDepth = 2;
} }
bool KxkbConfig::setFromXkbOptions(XkbOptions options)
{
XkbOptions curOptions = getKXkbOptions();
bool modified = false;
// We need to fix the variants string if it is empty, otherwise the
// comparison below will often wrongly assume that the variants have
// changed
if (options.variants.isEmpty())
{
options.variants = ""; // ensure the string is empty but not null
for (int i = 0; i < options.layouts.contains(","); ++i)
{
options.variants += ",";
}
}
// Check if keyboard layout options have changed
if ((options.model != curOptions.model && !options.model.isNull()))
{
modified = true;
m_model = options.model;
}
if ((options.layouts != curOptions.layouts) || (options.variants != curOptions.variants))
{
modified = true;
m_layouts.clear();
TQStringList layouts = TQStringList::split(",", options.layouts, true);
TQStringList variants = TQStringList::split(",", options.variants, true);
TQStringList::Iterator lit = layouts.begin();
TQStringList::Iterator vit = variants.begin();
if (layouts.empty())
{
layouts << "us";
}
while (lit != layouts.end())
{
TQString layout = *lit;
TQString variant = vit != variants.end() ? *vit : TQString::null;
m_layouts.append(LayoutUnit(layout, variant));
++lit;
if (vit != variants.end())
{
++vit;
}
}
}
TQStringList serverOpts = TQStringList::split(",", options.options);
TQStringList kxkbOpts = TQStringList::split(",", curOptions.options);
serverOpts.sort();
kxkbOpts.sort();
if (serverOpts != kxkbOpts)
{
modified = true;
m_options = options.options;
}
return modified;
}
TQStringList KxkbConfig::getLayoutStringList(/*bool compact*/) TQStringList KxkbConfig::getLayoutStringList(/*bool compact*/)
{ {
TQStringList layoutList; TQStringList layoutList;
@ -275,22 +390,25 @@ TQString KxkbConfig::getDefaultDisplayName(const LayoutUnit& layoutUnit, bool si
} }
const XkbOptions KxkbConfig::getKXkbOptions() { const XkbOptions KxkbConfig::getKXkbOptions() {
load(LOAD_ALL);
XkbOptions options; XkbOptions options;
TQStringList layouts; TQStringList layouts;
TQStringList variants; TQStringList variants;
for(TQValueList<LayoutUnit>::ConstIterator it = m_layouts.begin(); it != m_layouts.end(); ++it) { for (TQValueList<LayoutUnit>::ConstIterator it = m_layouts.begin(); it != m_layouts.end(); ++it) {
const LayoutUnit& layoutUnit = *it; const LayoutUnit& layoutUnit = *it;
layouts << layoutUnit.layout; layouts << layoutUnit.layout;
variants << layoutUnit.variant; variants << layoutUnit.variant;
} }
options.layouts = layouts.join(","); options.layouts = layouts.join(",");
options.variants = variants.join(","); options.variants = variants.join(",");
options.model = m_model;
options.options = m_options; options.options = m_options;
kdDebug() << "[getKXkbOptions] options: " << m_options << endl;
options.resetOld = m_resetOldOptions; options.resetOld = m_resetOldOptions;
options.model = m_model;
if (options.model.isEmpty())
{
options.model = DEFAULT_MODEL;
}
return options; return options;
} }
@ -329,4 +447,4 @@ const TQString LayoutUnit::parseVariant(const TQString &layvar)
if( pos < 2 || len < 2 ) if( pos < 2 || len < 2 )
return ""; return "";
return varLine.mid(pos+1, len-2); return varLine.mid(pos+1, len-2);
} }

@ -45,12 +45,15 @@ extern const char* DEFAULT_MODEL;
class KxkbConfig class KxkbConfig
{ {
public: public:
enum { LOAD_INIT_OPTIONS, LOAD_ACTIVE_OPTIONS, LOAD_ALL }; enum { LOAD_INIT_OPTIONS, LOAD_BASIC_OPTIONS, LOAD_ALL_OPTIONS };
bool m_useKxkb; bool m_useKxkb;
bool m_showSingle; bool m_showSingle;
bool m_showFlag; bool m_showFlag;
bool m_showLabel; bool m_showLabel;
bool m_fitToBox;
bool m_dimFlag;
bool m_bevel;
bool m_enableXkbOptions; bool m_enableXkbOptions;
bool m_resetOldOptions; bool m_resetOldOptions;
SwitchingPolicy m_switchingPolicy; SwitchingPolicy m_switchingPolicy;
@ -71,7 +74,7 @@ public:
TQString m_options; TQString m_options;
TQValueList<LayoutUnit> m_layouts; TQValueList<LayoutUnit> m_layouts;
bool load(int loadMode); void load(int loadMode);
void save(); void save();
void setDefaults(); void setDefaults();
@ -79,6 +82,7 @@ public:
static TQString getDefaultDisplayName(const TQString& code_); static TQString getDefaultDisplayName(const TQString& code_);
static TQString getDefaultDisplayName(const LayoutUnit& layoutUnit, bool single=false); static TQString getDefaultDisplayName(const LayoutUnit& layoutUnit, bool single=false);
bool setFromXkbOptions(XkbOptions options);
const XkbOptions getKXkbOptions(); const XkbOptions getKXkbOptions();
private: private:

@ -21,105 +21,97 @@
#include "kxkbtraywindow.h" #include "kxkbtraywindow.h"
#include "pixmap.h" #include "pixmap.h"
#include "rules.h" #include "rules.h"
#include "kxkbconfig.h"
KxkbSystemTray::KxkbSystemTray(KxkbConfig *kxkbConfig)
KxkbLabelController::KxkbLabelController(TQLabel* label_, TDEPopupMenu* contextMenu_) : : KSystemTray(nullptr),
label(label_), m_prevLayoutCount(0)
contextMenu(contextMenu_),
m_menuStartIndex(contextMenu_->count()),
m_prevLayoutCount(0)
{ {
// kdDebug() << "Creating KxkbLabelController with " << label_ << ", " << contextMenu_ << endl; m_icoMgr = new LayoutIconManager(kxkbConfig);
// kdDebug() << "Creating KxkbLabelController with startMenuIndex " << m_menuStartIndex << endl;
} }
void KxkbLabelController::setToolTip(const TQString& tip) KxkbSystemTray::~KxkbSystemTray()
{ {
TQToolTip::remove(label); delete m_icoMgr;
TQToolTip::add(label, tip);
} }
void KxkbLabelController::setPixmap(const TQPixmap& pixmap) void KxkbSystemTray::setToolTip(const TQString& tip)
{ {
TDEIconEffect iconeffect; TQToolTip::remove(this);
label->setPixmap( iconeffect.apply(pixmap, TDEIcon::Panel, TDEIcon::DefaultState) ); TQToolTip::add(this, tip);
} }
void KxkbSystemTray::setPixmap(const TQPixmap& pix)
void KxkbLabelController::setCurrentLayout(const LayoutUnit& layoutUnit)
{ {
setToolTip(m_descriptionMap[layoutUnit.toPair()]); TDEIconEffect iconeffect;
setPixmap( LayoutIcon::getInstance().findPixmap(layoutUnit.layout, PIXMAP_STYLE_INDICATOR, layoutUnit.displayName) ); KSystemTray::setPixmap(iconeffect.apply(pix, TDEIcon::Panel, TDEIcon::DefaultState));
} }
void KxkbSystemTray::setCurrentLayout(const LayoutUnit& layoutUnit)
{
setToolTip(m_descriptionMap[layoutUnit.toPair()]);
setPixmap(m_icoMgr->find(layoutUnit.layout, PIXMAP_STYLE_INDICATOR, layoutUnit.displayName));
}
void KxkbLabelController::setError(const TQString& layoutInfo) void KxkbSystemTray::setError(const TQString& layoutInfo)
{ {
TQString msg = i18n("Error changing keyboard layout to '%1'").arg(layoutInfo); TQString layout(layoutInfo);
setToolTip(msg); if (layout.isNull()) {
layout = i18n("Unknown");
}
label->setPixmap(LayoutIcon::getInstance().findPixmap("error", PIXMAP_STYLE_NORMAL)); TQString msg = i18n("Error changing keyboard layout to '%1'").arg(layoutInfo);
setToolTip(msg);
setPixmap(m_icoMgr->find(ERROR_CODE, PIXMAP_STYLE_NORMAL));
} }
void KxkbSystemTray::initLayoutList(const TQValueList<LayoutUnit>& layouts, const XkbRules& rules)
void KxkbLabelController::initLayoutList(const TQValueList<LayoutUnit>& layouts, const XkbRules& rules)
{ {
TDEPopupMenu* menu = contextMenu;
m_descriptionMap.clear(); m_descriptionMap.clear();
for(int ii=0; ii<m_prevLayoutCount; ++ii) { int i;
menu->removeItem(START_MENU_ID + ii); for (i = 0; i < m_prevLayoutCount; ++i) {
kdDebug() << "remove item: " << START_MENU_ID + ii << endl; contextMenu()->removeItem(START_MENU_ID + i);
} }
TDEIconEffect iconeffect; TDEIconEffect iconeffect;
int cnt = 0; i = 0;
TQValueList<LayoutUnit>::ConstIterator it; TQValueList<LayoutUnit>::ConstIterator it;
for (it=layouts.begin(); it != layouts.end(); ++it) for (it = layouts.begin(); it != layouts.end(); ++it)
{ {
const TQString layoutName = (*it).layout; const TQString layoutName = (*it).layout;
const TQString variantName = (*it).variant; const TQString variantName = (*it).variant;
const TQPixmap& layoutPixmap = m_icoMgr->find((*it).layout, PIXMAP_STYLE_CONTEXTMENU, (*it).displayName);
const TQPixmap pix = iconeffect.apply(layoutPixmap, TDEIcon::Small, TDEIcon::DefaultState);
TQString fullName = rules.getLayoutName((*it));
contextMenu()->insertItem(pix, fullName, START_MENU_ID + i, i + 1);
const TQPixmap& layoutPixmap = LayoutIcon::getInstance().findPixmap( m_descriptionMap.insert((*it).toPair(), fullName);
(*it).layout, PIXMAP_STYLE_CONTEXTMENU, (*it).displayName);
const TQPixmap pix = iconeffect.apply(layoutPixmap, TDEIcon::Small,
TDEIcon::DefaultState);
TQString fullName = rules.getLayoutName((*it)); ++i;
contextMenu->insertItem(pix, fullName, START_MENU_ID + cnt, }
m_menuStartIndex + cnt);
m_prevLayoutCount = i;
m_descriptionMap.insert((*it).toPair(), fullName); if (contextMenu()->indexOf(CONFIG_MENU_ID) == -1) {
contextMenu()->insertSeparator();
contextMenu()->insertItem(SmallIcon("configure"), i18n("Configure..."), CONFIG_MENU_ID);
cnt++; if (contextMenu()->indexOf(HELP_MENU_ID) == -1) {
contextMenu()->insertItem(SmallIcon("help"), i18n("Help"), HELP_MENU_ID);
}
} }
m_prevLayoutCount = cnt; connect(contextMenu(), TQ_SIGNAL(activated(int)), this, TQ_SIGNAL(menuActivated(int)));
// if show config, if show help
if( menu->indexOf(CONFIG_MENU_ID) == -1 ) {
contextMenu->insertSeparator();
contextMenu->insertItem(SmallIcon("configure"), i18n("Configure..."), CONFIG_MENU_ID);
if( menu->indexOf(HELP_MENU_ID) == -1 )
contextMenu->insertItem(SmallIcon("help"), i18n("Help"), HELP_MENU_ID);
}
/* if( index != -1 ) { //not first start
menu->insertSeparator();
TDEAction* quitAction = KStdAction::quit(this, TQ_SIGNAL(quitSelected()), actionCollection());
if (quitAction)
quitAction->plug(menu);
}*/
} }
// void KxkbLabelController::mouseReleaseEvent(TQMouseEvent *ev) void KxkbSystemTray::mouseReleaseEvent(TQMouseEvent *ev) {
// { if (ev->button() == TQt::LeftButton) {
// if (ev->button() == TQMouseEvent::LeftButton) emit toggled();
// emit toggled(); }
// KSystemTray::mouseReleaseEvent(ev); KSystemTray::mouseReleaseEvent(ev);
// } }
#include "kxkbtraywindow.moc" #include "kxkbtraywindow.moc"

@ -1,7 +1,7 @@
// //
// C++ Interface: kxkbtraywindow // C++ Interface: kxkbtraywindow
// //
// Description: // Description:
// //
// //
// Author: Andriy Rysin <rysin@kde.org>, (C) 2006 // Author: Andriy Rysin <rysin@kde.org>, (C) 2006
@ -17,77 +17,40 @@
#include <tqstring.h> #include <tqstring.h>
#include <tqvaluelist.h> #include <tqvaluelist.h>
#include "kxkbconfig.h" #include "layoutunit.h"
class TQLabel;
class TDEPopupMenu;
class XkbRules; class XkbRules;
class KxkbConfig;
class LayoutIconManager;
/* This class is responsible for displaying flag/label for the layout, class KxkbSystemTray : public KSystemTray
catching keyboard/mouse events and displaying menu when selected
*/
class KxkbLabelController: public TQObject
{ {
// TQ_OBJECT TQ_OBJECT
public:
enum { START_MENU_ID = 100, CONFIG_MENU_ID = 130, HELP_MENU_ID = 131 };
KxkbLabelController(TQLabel *label, TDEPopupMenu* contextMenu);
void initLayoutList(const TQValueList<LayoutUnit>& layouts, const XkbRules& rule); public:
void setCurrentLayout(const LayoutUnit& layout); KxkbSystemTray(KxkbConfig *kxkbConfig);
// void setCurrentLayout(const TQString& layout, const TQString &variant); ~KxkbSystemTray();
void setError(const TQString& layoutInfo=""); void initLayoutList(const TQValueList<LayoutUnit>& layouts, const XkbRules& rule);
void setShowFlag(bool showFlag) { m_showFlag = showFlag; } void setCurrentLayout(const LayoutUnit& layout);
void show() { label->show(); } void setError(const TQString& layoutInfo = TQString::null);
WId winId() { return label->winId(); } enum { START_MENU_ID = 100, CONFIG_MENU_ID = 130, HELP_MENU_ID = 131 };
// signals:
//
// void menuActivated(int);
// void toggled();
// protected: protected:
// void mouseReleaseEvent(TQMouseEvent *ev);
// void mouseReleaseEvent(TQMouseEvent *);
private:
TQLabel* label;
TDEPopupMenu* contextMenu;
const int m_menuStartIndex;
bool m_showFlag;
int m_prevLayoutCount;
TQMap<TQString, TQString> m_descriptionMap;
void setToolTip(const TQString& tip);
void setPixmap(const TQPixmap& pixmap);
};
private slots:
void setToolTip(const TQString& tip);
void setPixmap(const TQPixmap& pix);
class KxkbSystemTray : public KSystemTray signals:
{ void menuActivated(int);
TQ_OBJECT void toggled();
public:
KxkbSystemTray():
KSystemTray(NULL)
{}
void mouseReleaseEvent(TQMouseEvent *ev)
{
if (ev->button() == TQt::LeftButton)
emit toggled();
KSystemTray::mouseReleaseEvent(ev);
}
signals: private:
void menuActivated(int); LayoutIconManager *m_icoMgr;
void toggled(); int m_prevLayoutCount;
TQMap<TQString, TQString> m_descriptionMap;
}; };

@ -1,9 +1,11 @@
#include <tqapplication.h>
#include <tqimage.h> #include <tqimage.h>
#include <tqbitmap.h> #include <tqbitmap.h>
#include <tqfont.h> #include <tqfont.h>
#include <tqpainter.h> #include <tqpainter.h>
#include <tqregexp.h> #include <tqregexp.h>
#include <tqdict.h> #include <tqdict.h>
#include <tqdrawutil.h>
#include <tdestandarddirs.h> #include <tdestandarddirs.h>
#include <tdeglobalsettings.h> #include <tdeglobalsettings.h>
@ -13,56 +15,42 @@
#include "pixmap.h" #include "pixmap.h"
#include "x11helper.h" #include "x11helper.h"
const TQString LayoutIconManager::flagTemplate("l10n/%1/flag.png");
static const int FLAG_MAX_DIM = 24; LayoutIconManager::LayoutIconManager(KxkbConfig *kxkbConfig)
: m_pixmapCache(80),
const TQString LayoutIcon::flagTemplate("l10n/%1/flag.png"); m_kxkbConfig(kxkbConfig)
const TQString& LayoutIcon::ERROR_CODE("error");
LayoutIcon* LayoutIcon::instance;
LayoutIcon& LayoutIcon::getInstance() {
if( instance == NULL ) {
instance = new LayoutIcon();
}
return *instance;
}
LayoutIcon::LayoutIcon():
m_pixmapCache(80)
{ {
} }
const TQPixmap& const TQPixmap& LayoutIconManager::find(const TQString& code_, int pixmapStyle, const TQString& displayName_)
LayoutIcon::findPixmap(const TQString& code_, int pixmapStyle, const TQString& displayName_)
{ {
m_kxkbConfig.load(KxkbConfig::LOAD_ALL); // (re)load settings if (m_kxkbConfig->m_useThemeColors) { // use colors from color scheme
if (m_kxkbConfig.m_useThemeColors) { // use colors from color scheme
m_bgColor = TDEGlobalSettings::highlightColor(); m_bgColor = TDEGlobalSettings::highlightColor();
m_fgColor = TDEGlobalSettings::highlightedTextColor(); m_fgColor = TDEGlobalSettings::highlightedTextColor();
} else { } else {
m_bgColor = m_kxkbConfig.m_colorBackground; m_bgColor = m_kxkbConfig->m_colorBackground;
m_fgColor = m_kxkbConfig.m_colorLabel; m_fgColor = m_kxkbConfig->m_colorLabel;
} }
m_labelFont = m_kxkbConfig.m_labelFont; m_labelFont = m_kxkbConfig->m_labelFont;
m_labelShadow = m_kxkbConfig.m_labelShadow; m_labelShadow = m_kxkbConfig->m_labelShadow;
m_shColor = m_kxkbConfig.m_colorShadow; m_shColor = m_kxkbConfig->m_colorShadow;
m_bgTransparent = m_kxkbConfig.m_bgTransparent; m_bgTransparent = m_kxkbConfig->m_bgTransparent;
m_fitToBox = m_kxkbConfig->m_fitToBox;
m_dimFlag = m_kxkbConfig->m_dimFlag;
m_bevel = m_kxkbConfig->m_bevel && !m_bgTransparent && pixmapStyle == PIXMAP_STYLE_INDICATOR;
// Decide on how to style the pixmap // Decide on how to style the pixmap
switch(pixmapStyle) { switch(pixmapStyle) {
case PIXMAP_STYLE_NORMAL: case PIXMAP_STYLE_NORMAL:
m_fitToBox = true;
m_showFlag = true; m_showFlag = true;
m_showLabel = false; m_showLabel = false;
break; break;
case PIXMAP_STYLE_INDICATOR: case PIXMAP_STYLE_INDICATOR:
m_fitToBox = true; m_showFlag = m_kxkbConfig->m_showFlag;
m_showFlag = m_kxkbConfig.m_showFlag; m_showLabel = m_kxkbConfig->m_showLabel;
m_showLabel = m_kxkbConfig.m_showLabel;
break; break;
case PIXMAP_STYLE_CONTEXTMENU: case PIXMAP_STYLE_CONTEXTMENU:
@ -73,7 +61,7 @@ LayoutIcon::findPixmap(const TQString& code_, int pixmapStyle, const TQString& d
} }
// Label only mode is always 'fit to box' // Label only mode is always 'fit to box'
if( m_showLabel && !m_showFlag ) if (m_showLabel && !m_showFlag)
m_fitToBox = true; m_fitToBox = true;
TQPixmap* pm = NULL; TQPixmap* pm = NULL;
@ -89,57 +77,92 @@ LayoutIcon::findPixmap(const TQString& code_, int pixmapStyle, const TQString& d
TQString displayName(displayName_); TQString displayName(displayName_);
if( displayName.isEmpty() ) { if (displayName.isEmpty()) {
displayName = KxkbConfig::getDefaultDisplayName(code_); displayName = KxkbConfig::getDefaultDisplayName(code_);
} }
if( displayName.length() > 3 ) if (displayName.length() > 3)
displayName = displayName.left(3); displayName = displayName.left(3);
const TQString pixmapKey( const TQString pixmapKey(
TQString( m_showFlag ? "f" : "" ) + TQString( m_showLabel ? "l" : "" ) + TQString( m_labelShadow ? "s" : "" ) + "." + TQString(m_showFlag ? "f" : "") + TQString(m_showLabel ? "l" : "") + TQString(m_labelShadow ? "s" : "") + "." +
TQString(m_fitToBox ? "F" : "") + TQString(m_dimFlag ? "D" : "") + TQString(m_bevel ? "B" : "") + "." +
m_labelFont.key() + "." + ( m_bgTransparent ? "x" : m_bgColor.name() ) + "." + m_fgColor.name() + "." + m_shColor.name() + '.' + code_ + "." + displayName m_labelFont.key() + "." + ( m_bgTransparent ? "x" : m_bgColor.name() ) + "." + m_fgColor.name() + "." + m_shColor.name() + '.' + code_ + "." + displayName
); );
// Only use cache for indicator // Only use cache for indicator
if( pixmapStyle == PIXMAP_STYLE_INDICATOR ) { if (pixmapStyle == PIXMAP_STYLE_INDICATOR) {
pm = m_pixmapCache[pixmapKey]; pm = m_pixmapCache[pixmapKey];
if( pm ) if (pm)
return *pm; return *pm;
} }
// Need to create new pixmap pm = new TQPixmap(FLAG_MAX_DIM, FLAG_MAX_DIM);
pm = new TQPixmap();
if( m_fitToBox ) // Resize to box size TQRect r = pm->rect();
pm->resize(FLAG_MAX_DIM, FLAG_MAX_DIM); TQPainter p_(pm);
if( m_showFlag ) { if (m_showFlag) {
TQString countryCode = getCountryFromLayoutName( code_ ); TQString countryCode = getCountryFromLayoutName(code_);
TQString flag = locate("locale", flagTemplate.arg(countryCode)); TQString flag = locate("locale", flagTemplate.arg(countryCode));
if( flag.isEmpty() ) { if (flag.isEmpty()) {
pm->fill(m_bgColor); pm->fill(m_bgColor);
m_showLabel = true; m_showLabel = true;
} else { } else {
if( m_fitToBox ) { // Resize flag TQPixmap fp(flag);
TQPainter p_(pm);
p_.drawPixmap(TQRect(0, 0, FLAG_MAX_DIM, FLAG_MAX_DIM), flag); if (m_dimFlag && m_showLabel)
} else { // Show the flag as is {
pm->load(flag); TQImage image = fp.convertToImage();
for (int y = 0; y < image.height(); y++)
{
for(int x = 0; x < image.width(); x++)
{
TQRgb rgb = image.pixel(x,y);
TQRgb dimRgb(tqRgb(tqRed(rgb) * 3/4, tqGreen(rgb) * 3/4, tqBlue(rgb) * 3/4));
image.setPixel(x, y, dimRgb);
}
}
fp.convertFromImage(image);
}
if (!m_fitToBox)
{
r = TQRect((FLAG_MAX_DIM - fp.width()) / 2, (FLAG_MAX_DIM - fp.height()) / 2, fp.width(), fp.height());
}
TQRect fr(r); // flag rect might be smaller to accomodate the bevel
if (m_bevel)
{
fr.setX(fr.x() + 1);
fr.setY(fr.y() + 1);
fr.setWidth(fr.width() - 1);
fr.setHeight(fr.height() - 1);
} }
if( m_showLabel ) // only dim for label p_.drawPixmap(fr, fp);
dimPixmap( *pm );
// If we don't stretch the flag, we need to apply a mask to it
if (!m_fitToBox)
{
TQPixmap fpmask(FLAG_MAX_DIM, FLAG_MAX_DIM);
TQPainter fpmaskp(&fpmask);
fpmask.fill(TQt::white);
fpmaskp.fillRect(r, TQt::black);
TQBitmap fpmask_;
fpmask_ = fpmask;
pm->setMask((TQBitmap)fpmask_);
}
} }
} else { } else {
pm->fill(m_bgColor); pm->fill(m_bgColor);
} }
if( m_showLabel ) { if (m_showLabel) {
TQPainter p(pm); TQPainter p(pm);
p.setFont(m_labelFont); p.setFont(m_labelFont);
if( m_labelShadow ) { if (m_labelShadow) {
p.setPen(m_shColor); p.setPen(m_shColor);
p.drawText(1, 1, pm->width(), pm->height(), TQt::AlignCenter, displayName); p.drawText(1, 1, pm->width(), pm->height(), TQt::AlignCenter, displayName);
} }
@ -168,8 +191,14 @@ LayoutIcon::findPixmap(const TQString& code_, int pixmapStyle, const TQString& d
} }
} }
if (m_bevel)
{
TQPainter p_(pm);
qDrawShadePanel(&p_, r.x(), r.y(), r.width(), r.height(), tqApp->palette().active(), false, 1, nullptr);
}
if( pixmapStyle == PIXMAP_STYLE_INDICATOR ) if (pixmapStyle == PIXMAP_STYLE_INDICATOR)
m_pixmapCache.insert(pixmapKey, pm); m_pixmapCache.insert(pixmapKey, pm);
return *pm; return *pm;
@ -178,7 +207,7 @@ LayoutIcon::findPixmap(const TQString& code_, int pixmapStyle, const TQString& d
/** /**
@brief Try to get country code from layout name in xkb before xorg 6.9.0 @brief Try to get country code from layout name in xkb before xorg 6.9.0
*/ */
TQString LayoutIcon::getCountryFromLayoutName(const TQString& layoutName) TQString LayoutIconManager::getCountryFromLayoutName(const TQString& layoutName)
{ {
TQString flag; TQString flag;
@ -285,24 +314,8 @@ TQString LayoutIcon::getCountryFromLayoutName(const TQString& layoutName)
return flag; return flag;
} }
void LayoutIcon::dimPixmap(TQPixmap& pm)
{
TQImage image = pm.convertToImage();
for (int y=0; y<image.height(); y++)
for(int x=0; x<image.width(); x++)
{
TQRgb rgb = image.pixel(x,y);
TQRgb dimRgb(tqRgb(tqRed(rgb)*3/4, tqGreen(rgb)*3/4, tqBlue(rgb)*3/4));
image.setPixel(x, y, dimRgb);
}
pm.convertFromImage(image);
}
static const char* ERROR_LABEL = "err";
//private //private
TQPixmap* LayoutIcon::createErrorPixmap() TQPixmap* LayoutIconManager::createErrorPixmap()
{ {
TQPixmap* pm = new TQPixmap(21, 14); TQPixmap* pm = new TQPixmap(21, 14);
pm->fill(TQt::white); pm->fill(TQt::white);

@ -8,41 +8,34 @@
#include "kxkbconfig.h" #include "kxkbconfig.h"
enum PixmapStyle { #define ERROR_CODE "error"
PIXMAP_STYLE_NORMAL = 0, #define ERROR_LABEL "!"
PIXMAP_STYLE_INDICATOR = 1,
PIXMAP_STYLE_CONTEXTMENU = 2
};
class LayoutIcon {
private: #define FLAG_MAX_DIM 24
static LayoutIcon* instance;
static const TQString flagTemplate;
KxkbConfig m_kxkbConfig; enum PixmapStyle {
bool m_showFlag; PIXMAP_STYLE_NORMAL = 0,
bool m_showLabel; PIXMAP_STYLE_INDICATOR = 1,
TQColor m_bgColor; PIXMAP_STYLE_CONTEXTMENU = 2
bool m_bgTransparent; };
TQColor m_fgColor;
TQFont m_labelFont;
bool m_labelShadow;
TQColor m_shColor;
bool m_fitToBox;
TQDict<TQPixmap> m_pixmapCache; class LayoutIconManager {
public:
LayoutIconManager(KxkbConfig *kxkbConfig);
const TQPixmap& find(const TQString& code, int pixmapStyle, const TQString& displayName = TQString::null);
LayoutIcon(); private:
TQPixmap* createErrorPixmap(); TQPixmap* createErrorPixmap();
void dimPixmap(TQPixmap& pixmap); TQString getCountryFromLayoutName(const TQString& layoutName);
TQString getCountryFromLayoutName(const TQString& layoutName);
public: private:
static const TQString& ERROR_CODE; KxkbConfig *m_kxkbConfig;
static const TQString flagTemplate;
bool m_showFlag, m_showLabel, m_bgTransparent, m_labelShadow, m_fitToBox, m_dimFlag, m_bevel;
TQColor m_bgColor, m_fgColor, m_shColor;
TQFont m_labelFont;
static LayoutIcon& getInstance(); TQDict<TQPixmap> m_pixmapCache;
const TQPixmap& findPixmap(const TQString& code, int pixmapStyle, const TQString& displayName="");
}; };
#endif #endif

Loading…
Cancel
Save