#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "extension.h" 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; // TQStringList dirs = TDEGlobal::dirs()->findDirs ( "tmp", "" ); // m_tempDir = dirs.count() == 0 ? "/tmp/" : dirs[0]; m_tempDir = locateLocal("tmp", ""); } bool XKBExtension::init() { // Verify the Xlib has matching XKB extension. int major = XkbMajorVersion; int minor = XkbMinorVersion; if (!XkbLibraryVersion(&major, &minor)) { kdError() << "[kxkb-extension] Xlib 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); // watch group change events XkbSelectEventDetails(m_dpy, XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask, XkbGroupStateMask); return true; } XKBExtension::~XKBExtension() { /* if( m_compiledLayoutFileNames.isEmpty() == false ) deletePrecompiledLayouts();*/ } bool XKBExtension::setXkbOptions(const XkbOptions options) { TQString exe = TDEGlobal::dirs()->findExe("setxkbmap"); if (exe.isEmpty()) return false; TDEProcess p; p << exe; if (!options.layouts.isEmpty()) { p << "-layout"; p << options.layouts; } if (!options.variants.isEmpty()) { p << "-variant"; p << options.variants; } if (!options.model.isEmpty()) { p << "-model"; p << options.model; } if (options.resetOld) { p << "-option"; } if (!options.options.isEmpty()) { if (options.resetOld) { p << "-option" << options.options; } else { // Avoid duplication of options in Append mode TQStringList srvOptions = TQStringList::split(",", XKBExtension::getServerOptions()); TQStringList kxkbOptions = TQStringList::split(",", options.options); TQStringList newOptions; for (TQStringList::Iterator it = kxkbOptions.begin(); it != kxkbOptions.end(); ++it) { TQString option(*it); if (!srvOptions.contains(option)) { newOptions << option; } } if (!newOptions.isEmpty()) { p << "-option" << newOptions.join(","); } } } kdDebug() << "[setXkbOptions] Command: " << p.args() << endl; p.start(TDEProcess::Block); return p.normalExit() && (p.exitStatus() == 0); } TQString 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; } bool XKBExtension::setGroup(unsigned int group) { kdDebug() << "[kxkb-extension] Setting group " << group << endl; return XkbLockGroup( m_dpy, XkbUseCoreKbd, group ); } unsigned int XKBExtension::getGroup() const { XkbStateRec 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 */ void XKBExtension::processXEvent(XEvent *event) { XkbEvent* xkb_event = (XkbEvent*)event; if (xkb_event->any.xkb_type == XkbStateNotify) { emit groupChanged(xkb_event->state.group); } } #include "extension.moc"