diff options
Diffstat (limited to 'kxkb/extension.cpp')
-rw-r--r-- | kxkb/extension.cpp | 214 |
1 files changed, 161 insertions, 53 deletions
diff --git a/kxkb/extension.cpp b/kxkb/extension.cpp index 8197043aa..a9efb8226 100644 --- a/kxkb/extension.cpp +++ b/kxkb/extension.cpp @@ -1,3 +1,32 @@ +/******************************************************************************* + + Xkb extension for KXkb + Copyright © 2009-2025 Trinity Desktop project + Copyright © 2001 S.R. Haque <[email protected]> + + Derived from an original by Matthias H�zer-Klpfel released under the QPL. + + Some portions come from kkbswitch released under the GNU GPL v2 (or later). + Copyright © 2001 Leonid Zeitlin <[email protected]> + + 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 <errno.h> @@ -5,10 +34,13 @@ #include <tqmap.h> #include <tqfile.h> #include <tqdir.h> +#include <tqtimer.h> #include <kdebug.h> +#include <tdeapplication.h> #include <kstandarddirs.h> #include <tdeprocess.h> +#include <dcopclient.h> #include <X11/Xatom.h> #include <X11/Xos.h> @@ -21,58 +53,80 @@ #include "extension.h" +extern "C" +{ + static int IgnoreXError(Display *, XErrorEvent *) { return 0; } +} static TQString getLayoutKey(const TQString& layout, const TQString& variant) { return layout + "." + variant; } -XKBExtension::XKBExtension(Display *d) -{ - if ( d == NULL ) - d = tqt_xdisplay(); - m_dpy = d; +static XKBExtension *xkbExtension = nullptr; -// TQStringList dirs = TDEGlobal::dirs()->findDirs ( "tmp", "" ); -// m_tempDir = dirs.count() == 0 ? "/tmp/" : dirs[0]; - m_tempDir = locateLocal("tmp", ""); +XKBExtension *XKBExtension::the() +{ + if (!xkbExtension) + { + xkbExtension = new XKBExtension; + if (!xkbExtension->init()) + { + kdFatal() << "xkb initialization failed, exiting..." << endl; + ::exit(1); + } + } + return xkbExtension; } bool XKBExtension::init() { - // Verify the Xlib has matching XKB extension. + m_configureLock = 0; + acquireConfigureLock(); - int major = XkbMajorVersion; - int minor = XkbMinorVersion; + kdDebug() << "[kxkb-extension] Initializing Xkb extension" << endl; + m_dpy = tqt_xdisplay(); - if (!XkbLibraryVersion(&major, &minor)) - { - kdError() << "[kxkb-extension] Xlib XKB extension " << major << '.' << minor << - " != " << XkbMajorVersion << '.' << XkbMinorVersion << endl; - return false; - } + // Verify the Xlib has matching XKB extension. + int major = XkbMajorVersion; + int minor = XkbMinorVersion; - // Verify the X server has matching XKB extension. + if (!XkbLibraryVersion(&major, &minor)) + { + kdError() << "[kxkb-extension] Xlib XKB extension " << major << '.' << minor << + " != " << XkbMajorVersion << '.' << XkbMinorVersion << endl; + return false; + } - int opcode_rtrn; - int error_rtrn; - int xkb_opcode; - if (!XkbQueryExtension(m_dpy, &opcode_rtrn, &xkb_opcode, &error_rtrn, - &major, &minor)) - { - kdError() << "[kxkb-extension] X server XKB extension " << major << '.' << minor << - " != " << XkbMajorVersion << '.' << XkbMinorVersion << endl; - return false; - } + // Verify the X server has matching XKB extension. + int opcode_rtrn; + int error_rtrn; + int xkb_opcode; + if (!XkbQueryExtension(m_dpy, &opcode_rtrn, &xkb_opcode, &error_rtrn, + &major, &minor)) + { + kdError() << "[kxkb-extension] X server XKB extension " << major << '.' << minor << + " != " << XkbMajorVersion << '.' << XkbMinorVersion << endl; + return false; + } // Do it, or face horrible memory corrupting bugs - ::XkbInitAtoms(NULL); + ::XkbInitAtoms(nullptr); + + // Watch for interesting events + XkbSelectEventDetails(m_dpy, XkbUseCoreKbd, XkbStateNotify, + XkbAllStateComponentsMask, XkbGroupStateMask); - // watch group change events - XkbSelectEventDetails(m_dpy, XkbUseCoreKbd, XkbStateNotify, - XkbAllStateComponentsMask, XkbGroupStateMask); + XkbSelectEventDetails(m_dpy, XkbUseCoreKbd, XkbNewKeyboardNotify, + XkbAllNewKeyboardEventsMask, XkbAllNewKeyboardEventsMask); + + +// TQStringList dirs = TDEGlobal::dirs()->findDirs ( "tmp", "" ); +// m_tempDir = dirs.count() == 0 ? "/tmp/" : dirs[0]; + m_tempDir = locateLocal("tmp", ""); - return true; + releaseConfigureLock(); + return true; } XKBExtension::~XKBExtension() @@ -81,11 +135,32 @@ XKBExtension::~XKBExtension() deletePrecompiledLayouts();*/ } +void XKBExtension::acquireConfigureLock() +{ + ++m_configureLock; +} + +void XKBExtension::releaseConfigureLock() +{ + // 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_configureLock; +} + bool XKBExtension::setXkbOptions(const XkbOptions options) { + acquireConfigureLock(); + TQString exe = TDEGlobal::dirs()->findExe("setxkbmap"); if (exe.isEmpty()) + { return false; + } TDEProcess p; p << exe; @@ -119,7 +194,8 @@ bool XKBExtension::setXkbOptions(const XkbOptions options) else { // 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 newOptions; for (TQStringList::Iterator it = kxkbOptions.begin(); it != kxkbOptions.end(); ++it) @@ -136,46 +212,78 @@ 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; p.start(TDEProcess::Block); + releaseConfigureLock(); + return p.normalExit() && (p.exitStatus() == 0); } -TQString XKBExtension::getServerOptions() +XkbOptions XKBExtension::getServerOptions() { - XkbRF_VarDefsRec vd; - if (XkbRF_GetNamesProp(tqt_xdisplay(), nullptr, &vd) && vd.options) - { - kdDebug() << "[kxkb-extension] Got server options " << vd.options << endl; - return TQString(vd.options); - } - return TQString::null; + XkbOptions options; + XkbRF_VarDefsRec vd; + if (XkbRF_GetNamesProp(tqt_xdisplay(), nullptr, &vd)) + { + options.model = vd.model; + options.layouts = vd.layout; + options.variants = vd.variant; + options.options = vd.options; + } + return options; } bool XKBExtension::setGroup(unsigned int group) { kdDebug() << "[kxkb-extension] Setting group " << group << endl; - return XkbLockGroup( m_dpy, XkbUseCoreKbd, group ); + return XkbLockGroup(m_dpy, XkbUseCoreKbd, group); } uint XKBExtension::getGroup() const { XkbStateRec xkbState; - XkbGetState( m_dpy, XkbUseCoreKbd, &xkbState ); + XkbGetState(m_dpy, XkbUseCoreKbd, &xkbState); return xkbState.group; } -/** Examines an X Event passed to it and takes actions if the event is of - * interest to KXkb */ +bool XKBExtension::kcmlayoutRunning() +{ + return kapp->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) { - XkbEvent* xkb_event = (XkbEvent*)event; - if (xkb_event->any.xkb_type == XkbStateNotify && - xkb_event->state.changed & XkbGroupStateMask) - { - emit groupChanged((uint)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_configureLock > 0 || kcmlayoutRunning()) + { + return; + } + acquireConfigureLock(); + emit optionsChanged(); + releaseConfigureLock(); + } } -#include "extension.moc" +#include "extension.moc"
\ No newline at end of file |