more mpv hacks
[jrugr.git] / src / jrugr.cpp
blob6dfd19e604801cc9429a698d584e2bf29c7f63d0
1 ////////////////////////////////////////
2 // Copyright : GPL //
3 ////////////////////////////////////////
4 #include "jrugr.h"
7 ////////////////////////////////////////////////////////////////////////////////
8 static Atom
9 atomActWin = None,
10 atomClientList = None,
11 atomCurDesk = None;
14 ////////////////////////////////////////////////////////////////////////////////
15 static inline bool isMPlayer (const QString &name) {
16 return (
17 name.startsWith("mplayer", Qt::CaseInsensitive) ||
18 name.startsWith("mplayer2", Qt::CaseInsensitive) ||
19 name.startsWith("mpv", Qt::CaseInsensitive) ||
20 name.endsWith(" - mpv", Qt::CaseInsensitive)
25 static inline bool isMPlayerClass (const QString &name) {
26 return (name == "xv" || name == "gl" || name == "vdpau");
30 ////////////////////////////////////////////////////////////////////////////////
31 static bool makeFacehugger (Window w) {
32 //WARNING! this WILL NOT work as expected on our own windows!
33 return XSelectInput(QX11Info::display(), w, /*SubstructureNotifyMask |*/ StructureNotifyMask) == Success;
37 static void dumpWinInfo (const char *msg, Window w) {
38 Window pw;
40 if (w == None) return;
41 pw = X11Tools::windowTransientFor(w);
42 qDebug() << msg << (int)(w) <<
43 "class:" << X11Tools::windowClass(w) <<
44 "name:" << X11Tools::windowName(w) <<
45 "pid:" << X11Tools::windowPID(w) <<
46 "transientfor:" << pw;
47 //dumpWinInfo(" parent (tr)", pw);
51 ////////////////////////////////////////////////////////////////////////////////
52 Jrugr::Jrugr (int &argc, char **argv) :
53 QApplication(argc, argv),
55 mActiveGroup(0),
56 mXkb(0),
57 mTrayIcon(0),
58 mTrayMenu(0),
59 jCfg(0),
60 mDeskJustChanged(false)
62 if (atomActWin == None) atomActWin = XInternAtom(QX11Info::display(), "_NET_ACTIVE_WINDOW", True);
63 if (atomClientList == None) atomClientList = XInternAtom(QX11Info::display(), "_NET_CLIENT_LIST", True);
64 if (atomCurDesk == None) atomCurDesk = XInternAtom(QX11Info::display(), "_NET_CURRENT_DESKTOP", True);
65 // mandatory to keep it running after closing about dialogs...
66 setQuitOnLastWindowClosed(false);
67 setWindowIcon(QIcon(":/about/jrugr.png"));
69 mCfgFileName = QDir::homePath()+"/.config/jrugr.cfg";
73 Jrugr::~Jrugr () {
74 delete mXkb;
75 delete mTrayMenu;
76 delete jCfg;
77 //! \warning the trayIcon *has* to be deleted here to prevent XFreeColormap() free corruption.
78 delete mTrayIcon;
82 bool Jrugr::firstStart () {
83 if (!QFile::exists(mCfgFileName)) {
84 QString themePath;
86 qDebug() << " Jrugr:Config file not found in:" << mCfgFileName;
87 QSettings jrugr(mCfgFileName, QSettings::IniFormat);
88 QDir themeDir("/usr/share/jrugr/theme/default");
89 if (themeDir.exists()) themePath = themeDir.path();
90 else themePath = QCoreApplication::applicationDirPath()+"/theme/default";;
91 jrugr.beginGroup("Style");
92 mLangThemePath = themePath;
93 jrugr.setValue("path", mLangThemePath);
94 jrugr.endGroup(); //Style
95 return true;
97 return false;
101 void Jrugr::startup () {
102 if (firstStart()) configure();
105 QSettings jrugr(mCfgFileName, QSettings::IniFormat, this);
106 jrugr.beginGroup("Style");
107 mLangThemePath = jrugr.value("path").toString()+"/language/";
108 jrugr.endGroup(); //Style
110 jCfg = JrugrCfg::load(mCfgFileName);
111 if (!jCfg) abort();
112 if (jCfg->workMode == USE_XKB) configureXkb();
113 mMplayerHack = jCfg->mplayerHack;
115 mXkb = new XKeyboard();
116 mXkb->groupInfo(mGroupInfo);
118 connect(mXkb, SIGNAL(groupChanged(int)), this, SLOT(onGroupChanged(int)), Qt::QueuedConnection);
119 connect(mXkb, SIGNAL(layoutChanged()), this, SLOT(onLayoutChanged()), Qt::QueuedConnection);
120 connect(this, SIGNAL(changeLayout(int)), this, SLOT(onChangeLayout(int)), Qt::QueuedConnection);
122 connect(this, SIGNAL(activeWindowChanged()), this, SLOT(doActiveWindowChanged()), Qt::QueuedConnection);
123 connect(this, SIGNAL(activeDesktopChanged()), this, SLOT(doActiveDesktopChanged()), Qt::QueuedConnection);
124 connect(this, SIGNAL(clientListChanged()), this, SLOT(onClientListChanged()), Qt::QueuedConnection);
126 #ifdef K8_MPLAYER_HACK
127 mMPFix = new QTimer(this);
128 mMPFix->setSingleShot(true);
129 connect(mMPFix, SIGNAL(timeout()), this, SLOT(onMPFix()), Qt::QueuedConnection);
130 #endif
134 void Jrugr::initialize () {
135 mXkb->groupInfo(mGroupInfo);
137 mMplayerHack = jCfg->mplayerHack;
138 mActiveGroup = mXkb->activeGroup();
139 mActiveWindow = X11Tools::activeWindow();
140 mCurDesk = X11Tools::activeDesktop();
141 setDeskActiveWindow(mCurDesk, X11Tools::activeWindow());
143 mTrayIcon = new QSystemTrayIcon(this);
144 connect(mTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayClicked(QSystemTrayIcon::ActivationReason)));
146 createMenu();
147 buildIcon();
149 installFacehuggers();
153 void Jrugr::reconfigure () {
154 JrugrCfg *newConf = JrugrCfg::load(mCfgFileName);
156 if (newConf) {
157 QXkbLayoutList nl;
159 mXkb->groupInfo(nl);
160 bool diffGI = nl.size() != mGroupInfo.size();
162 if (!diffGI) {
163 for (int f = nl.size()-1; f >= 0; --f) if (nl[f].name != mGroupInfo[f].name || nl[f].sym != mGroupInfo[f].sym) { diffGI = true; break; }
166 if (diffGI || newConf->layouts != jCfg->layouts || newConf->showFlag != jCfg->showFlag ||
167 newConf->workMode != jCfg->workMode || newConf->switching != jCfg->switching ||
168 mMplayerHack != newConf->mplayerHack) {
169 delete jCfg;
170 jCfg = newConf;
171 mMplayerHack = jCfg->mplayerHack;
172 mGroupInfo = nl;
173 createMenu();
174 buildIcon();
175 } else {
176 delete newConf;
182 int Jrugr::setKeyLayout (QString keyConf) {
183 qDebug() << "Jrugr::setKeyLayout:" << keyConf;
184 QStringList argument = keyConf.split(" ");
185 qDebug() << " Jrugr:setxkbmap argumetns:" << argument;
186 int result = QProcess::execute("setxkbmap", argument);
187 qDebug() << " Jrugr:setxkbmap result:" << result;
188 return result;
192 void Jrugr::configureXkb () {
193 QString layout, variant, option;
194 QString model = jCfg->model;
196 for (int f = 0; f < jCfg->layouts.count(); ++f) {
197 layout += jCfg->layouts[f].layout;
198 variant += jCfg->layouts[f].variant;
199 if (f < jCfg->layouts.count()-1) { layout += ','; variant += ','; }
201 option = jCfg->options.join(",");
202 qDebug() << "Set layout:" << layout;
203 if (!(model.isEmpty() || model.isNull()) && !(layout.isEmpty() || layout.isNull())) {
204 QString args = "-model "+model+" -layout "+layout;
205 QString tmp = variant;
206 if (!variant.isNull() && !variant.isEmpty() && !tmp.remove(",").isEmpty()) args +=" -variant "+variant;
207 if (!option.isNull() && !option.isEmpty()) args +=" -option "+option;
208 qDebug() << " Jrugr:XKB args " << args;
209 if (setKeyLayout(args) == QProcess::CrashExit) {
210 qDebug() << " Jrugr:XKB isn`t set";
211 qDebug() << " Jrugr:------------------------------";
212 return;
214 qDebug() << " Jrugr:XKB set";
219 void Jrugr::configure () {
220 JrugrConfigForm *mCfgForm = new JrugrConfigForm(mCfgFileName);
221 connect(mCfgForm, SIGNAL(saveConfig()), SLOT(reconfigure()));
222 mCfgForm->exec(); // the form will die on closing
226 int Jrugr::layIndex (Window w, const QString &propname, bool unknownIsZero) const {
227 QString alay(X11Tools::getjprop(w, propname.toUtf8().constData()));
229 if (alay.size() > 0) {
230 int idx = XKeyboard::findBySym(mGroupInfo, alay);
232 qDebug() << "Win:" << w << "alay:" << alay << "idx:" << idx;
233 return idx;
235 return unknownIsZero ? 0 : -1;
239 bool Jrugr::isKnownWindow (Window w) const {
240 return mKnownWindows.contains(w);
244 bool Jrugr::isKnownApp (Window w) const {
245 return mKnownApps.contains(X11Tools::appWindow(w));
249 WinInfo *Jrugr::findWindowInfo (Window w) {
250 return mKnownWindows.value(w, 0);
254 // find application info for the given window
255 WinInfo *Jrugr::findAppInfo (Window w) {
256 return mKnownApps.value(X11Tools::appWindow(w), 0);
260 int Jrugr::desktopLayout (int desk) const {
261 if (desk < 0 || desk >= mDeskLangs.size()) return 0;
262 return mDeskLangs.at(desk);
266 void Jrugr::setDesktopLayout (int desk, int group) {
267 if (desk >= 0 && group < mGroupInfo.size()) {
268 X11Tools::setjprop(None, QString("DESK%1_LAYOUT").arg(desk), mGroupInfo[group].sym);
270 if (desk < 0 || desk > 42) return; // invalid desktop number
271 while (mDeskLangs.size() <= desk) {
272 QString ln(QString("DESK%1_LAYOUT").arg(mDeskLangs.size()));
273 int idx = layIndex(None, ln.toLatin1().constData(), true);
275 //qDebug() << "desk:" << mDeskLangs.size() << "layidx:" << idx;
276 if (group < mGroupInfo.size()) X11Tools::setjprop(None, ln, mGroupInfo[group].sym);
277 mDeskLangs << idx;
279 mDeskLangs[desk] = group;
283 Window Jrugr::deskActiveWindow (int desk) {
284 if (desk < 0 || desk >= mDeskActiveWindows.size()) return None;
285 return mDeskActiveWindows.at(desk);
289 void Jrugr::setDeskActiveWindow (int desk, Window w) {
290 if (desk < 0 || desk > 42) return; // invalid desktop number
291 while (mDeskActiveWindows.size() <= desk) mDeskActiveWindows << None;
292 mDeskActiveWindows[desk] = w;
293 if (w != None) {
294 qDebug() << "DESK:" << desk <<
295 "class:" << X11Tools::windowClass(w) <<
296 "name:" << X11Tools::windowName(w);
297 } else {
298 qDebug() << "DESK:" << desk << "None";
303 void Jrugr::installFacehuggers () {
304 QX11WindowList wl = X11Tools::topLevelWindows();
305 QSet<WId> qtwl;
308 //QWidgetList twl = QApplication::allWidgets();
309 QWidgetList twl = QApplication::topLevelWidgets();
310 foreach (QWidget *wd, twl) {
311 WId w = wd->effectiveWinId();
312 if (w != None) qtwl << w;
316 for (int f = 0; f < wl.size(); ++f) {
317 if (wl[f] != None && !qtwl.contains(wl[f]) && !isKnownWindow(wl[f])) {
318 WinInfo *wi = new WinInfo;
320 wi->w = wl[f];
321 wi->appWindow = X11Tools::appWindow(wl[f]);
322 wi->layout = layIndex(wi->w, "WIN_LAYOUT", true);
323 if (wi->layout < mGroupInfo.size()) X11Tools::setjprop(wi->w, "WIN_LAYOUT", mGroupInfo[wi->layout].sym);
324 mKnownWindows[wl[f]] = wi;
325 makeFacehugger(wi->w);
327 if (wi->appWindow == wi->w && !isKnownApp(wi->w)) {
328 WinInfo *w2 = new WinInfo;
330 w2->appWindow = w2->w = wi->w;
331 w2->layout = layIndex(w2->w, "APP_LAYOUT", false);
332 if (w2->layout < 0) w2->layout = wi->layout;
333 if (w2->layout < mGroupInfo.size()) X11Tools::setjprop(w2->w, "APP_LAYOUT", mGroupInfo[w2->layout].sym);
334 mKnownApps[w2->w] = w2;
341 void Jrugr::doActiveWindowChanged () {
342 //qDebug() << "doActiveWindowChanged";
343 onActiveWindowChanged(X11Tools::activeWindow());
347 void Jrugr::doActiveDesktopChanged () {
348 //qDebug() << "doActiveDesktopChanged";
349 onActiveDesktopChanged(X11Tools::activeDesktop());
353 void Jrugr::onLayoutChanged () {
354 qDebug()<<"Jrugr::onLayoutChanged : reconfig";
355 reconfigure();
356 qDebug()<<"Jrugr::onLayoutChanged : done";
360 QIcon Jrugr::langIcon (const QString &lsym, int wdt, int hgt, bool noFlag) {
361 if (!noFlag) {
362 QString path = mLangThemePath+fixLayoutName(lsym, jCfg->useSU);
363 QString SVGfile = path+".svg";
365 if (QFile::exists(SVGfile)) {
366 QSvgRenderer flagSVG(SVGfile);
367 if (flagSVG.isValid()) {
368 QPixmap pix(wdt, hgt);
369 QPainter painter;
370 painter.begin(&pix);
371 flagSVG.render(&painter, QRectF(0, 0, wdt, hgt));
372 painter.end();
373 return QIcon(pix);
377 QString PNGfile = path+".png";
378 if (QFile::exists(PNGfile)) {
379 return QIcon(PNGfile);
384 qDebug() << ":::" << lsym;
385 QFont font("Helvetica [Cronyx]", 15); //FIXME: should be configurable
386 //QFont font("Tahoma", 15);
387 font.setBold(true);
388 font.setLetterSpacing(QFont::PercentageSpacing, 120);
389 QPixmap pix(lsym.length()*20, 26);
390 QPainter painter;
391 painter.begin(&pix);
392 painter.setFont(font);
393 painter.fillRect(pix.rect(), Qt::darkGray);
394 painter.setPen(Qt::white);
395 painter.drawText(pix.rect(), Qt::AlignVCenter|Qt::AlignCenter, lsym);
396 painter.end();
397 return QIcon(pix);
402 void Jrugr::createMenu () {
403 if (!mTrayMenu) {
404 mTrayMenu = new QMenu();
405 connect(mTrayMenu, SIGNAL(triggered(QAction *)), SLOT(actionsActivate(QAction *)));
406 } else {
407 mTrayMenu->clear();
410 for (int index = 0; index < mGroupInfo.size(); ++index) {
411 QString lname = mGroupInfo[index].name, lsym = mGroupInfo[index].sym;
413 QAction *act = new QAction(lname, this);
414 act->setIcon(langIcon(lsym));
415 act->setData(lname);
416 mTrayMenu->addAction(act);
419 mTrayMenu->addSeparator();
420 QAction *config = new QAction(tr("Configure"), this);
421 config->setData("configure");
422 mTrayMenu->addAction(config);
424 mTrayMenu->addSeparator();
425 QAction *about_jrugr = new QAction(tr("About Jrugr"), this);
426 about_jrugr->setData("about_jrugr");
427 mTrayMenu->addAction(about_jrugr);
429 QAction *about_qt = new QAction(tr("About Qt"), this);
430 about_qt->setData("about_qt");
431 mTrayMenu->addAction(about_qt);
433 mTrayMenu->addSeparator();
434 QAction *jrugrExit = new QAction(tr("Exit"), this);
435 jrugrExit->setData("exit");
436 mTrayMenu->addAction(jrugrExit);
440 void Jrugr::buildIcon () {
441 if (!mTrayIcon) return;
442 mTrayIcon->setIcon(langIcon(mGroupInfo[mActiveGroup].sym, 32, 22, !jCfg->showFlag));
443 mTrayIcon->setToolTip(mGroupInfo[mActiveGroup].name);
444 if (mTrayMenu) mTrayIcon->setContextMenu(mTrayMenu);
445 mTrayIcon->show();
449 void Jrugr::trayClicked (QSystemTrayIcon::ActivationReason reason) {
450 switch (reason) {
451 case QSystemTrayIcon::Trigger: setNextGroup(); break;
452 case QSystemTrayIcon::DoubleClick: setNextGroup(); break;
453 case QSystemTrayIcon::MiddleClick: setPrevGroup(); break;
454 default: ;
459 // new layout activated; fix all necessary shit
460 void Jrugr::onGroupChanged (int index) {
461 qDebug() << "Jrugr::onGroupChanged: index:" << index;
462 mActiveGroup = index;
463 buildIcon();
465 if (mActiveWindow != None) {
466 WinInfo *wi = findWindowInfo(mActiveWindow);
468 if (!wi) {
469 qDebug() << "new window";
470 installFacehuggers();
471 wi = findWindowInfo(mActiveWindow);
474 if (wi) {
475 qDebug() << "fixing window layout";
476 wi->layout = index;
477 if (index < mGroupInfo.size()) X11Tools::setjprop(wi->w, "WIN_LAYOUT", mGroupInfo[index].sym);
478 if (jCfg->switching == APP_LAYOUT) {
479 wi = findAppInfo(mActiveWindow);
480 if (wi) {
481 qDebug() << "fixing app layout";
482 wi->layout = index;
483 if (index < mGroupInfo.size()) X11Tools::setjprop(wi->w, "APP_LAYOUT", mGroupInfo[index].sym);
484 } else {
485 qWarning() << "***APP SHIT!***";
488 } else {
489 qWarning() << "***WINDOW SHIT!***";
493 setDesktopLayout(X11Tools::activeDesktop(), mActiveGroup);
497 void Jrugr::setNextGroup () {
498 mXkb->setActiveGroup(mActiveGroup+1>=mGroupInfo.size()?0:mActiveGroup+1);
502 void Jrugr::setPrevGroup () {
503 mXkb->setActiveGroup(mActiveGroup-1<0?mGroupInfo.size()-1:mActiveGroup-1);
507 void Jrugr::windowDies (Window w) {
508 if (w != None) {
509 qDebug("**************************** FACEHUGGER PARENT DIES ****************************");
510 Window appW = None;
511 // remove window
513 QWIHashMutableIterator i(mKnownWindows);
514 while (i.hasNext()) {
515 WinInfo *wi = i.next().value();
517 if (wi->w == w) {
518 i.remove();
519 if (wi->w == wi->appWindow) {
520 if (appW == None) appW = wi->w;
521 else if (appW != wi->w) qWarning("*** WTF?! ***");
523 delete wi;
527 if (appW != None) {
528 // remove application
529 QWIHashMutableIterator i(mKnownApps);
530 while (i.hasNext()) {
531 WinInfo *wi = i.next().value();
533 if (wi->w == appW) {
534 i.remove();
535 delete wi;
543 void Jrugr::onChangeLayout (int index) {
544 qDebug() << "Jrugr::changeLayout:" << index;
545 mXkb->setActiveGroup(index);
549 void Jrugr::actionsActivate (QAction *action) {
550 QString cmd = action->data().toString();
552 qDebug() << "Jrugr::actionsActivate() command" << cmd;
553 if (cmd == "configure") {
554 configure();
555 } else if (cmd == "about_qt") {
556 aboutQt();
557 } else if (cmd == "about_jrugr") {
558 QMessageBox::about(0,
559 tr("About Jrugr"),
560 tr("<h2>Jrugr, the keyboard layout switcher</h2>"
561 "<b>Version</b>: %1<p>"
562 "Gui tool to configure XKB extentions of X server.<p>"
563 "(c) 2009-2011 Fedor Chelbarakh, Petr Vanek, Ketmar").arg(JRUGR_VERSION));
564 } else if (cmd == "exit") {
565 qDebug() << "Jrugr::actionsActivate() exit";
566 quit();
567 } else {
568 for (int f = mGroupInfo.size()-1; f >= 0; --f) {
569 if (cmd == mGroupInfo[f].name) {
570 emit changeLayout(f);
571 break;
578 #ifdef K8_MPLAYER_HACK
579 static bool isMPlayer (Window w) {
580 if (w != None) {
581 if (X11Tools::windowDesktop(w) == -1 && isMPlayerClass(X11Tools::windowClass(w))) {
582 QString name = X11Tools::windowName(w).toLower();
583 if (isMPlayer(name)) return true;
586 return false;
590 static QX11WindowList getPossibleActives (Window mpw) {
591 QX11WindowList res, wl = X11Tools::topLevelWindowStack();
592 int desk = X11Tools::activeDesktop();
593 Window wine = None;
595 qDebug() << "looking for window to refocus...";
596 for (int f = 0; f < wl.size(); ++f) {
597 Window w = wl.at(f);
598 int wd = X11Tools::windowDesktop(w);
600 if (wd == desk) {
601 // skip 'special' windows
602 QStringList sl = X11Tools::windowStateNames(w);
603 if (sl.indexOf("_NET_WM_STATE_STICKY") < 0 &&
604 sl.indexOf("_NET_WM_STATE_HIDDEN") < 0 &&
605 sl.indexOf("_NET_WM_STATE_SHADED") < 0 &&
606 sl.indexOf("_NET_WM_STATE_SKIP_TASKBAR") < 0 &&
607 sl.indexOf("_NET_WM_STATE_ABOVE") < 0 &&
608 sl.indexOf("_NET_WM_STATE_BELOW") < 0) {
609 QString cls(X11Tools::windowClass(w));
610 if (isMPlayerClass(cls)) {
611 QString name(X11Tools::windowName(w).toLower());
612 if (isMPlayer(name)) continue;
614 if (wine == None && cls == "explorer.exe") {
615 wine = w;
616 qDebug() << " WINE:" << cls;
617 } else {
618 //FIXME: this will not work as expected!
619 if (f > 0 && wl.at(f-1) == mpw) {
620 res.prepend(w);
621 } else {
622 res << w;
624 qDebug() << " NORM:" << cls;
630 if (wine != None) res << wine;
632 return res;
636 bool Jrugr::deactivateMPlayer () {
637 qDebug() << "onActiveWindowChanged";
638 Window aw = X11Tools::activeWindow();
639 bool changeFocus = false;
641 if (aw != None) {
642 if (X11Tools::windowDesktop(aw) == -1 && isMPlayerClass(X11Tools::windowClass(aw))) {
643 QString name = X11Tools::windowName(aw).toLower();
644 if (isMPlayer(name)) {
645 qDebug() << "MPlayer hack!";
646 changeFocus = true;
649 } else {
650 qDebug() << "Empty window hack!";
651 changeFocus = true;
654 if (changeFocus) {
655 // find previous window
656 Window pw = deskActiveWindow(mCurDesk);
657 int dsk = X11Tools::windowDesktop(pw);
658 if (pw == None || isMPlayer(pw) || (dsk != -1 && dsk != mCurDesk)) {
659 QX11WindowList wl = getPossibleActives(aw);
661 if (wl.size() > 0) pw = wl.at(wl.size()-1); else pw = None;
663 if (pw != None) {
664 qDebug() << "CHANGING FOCUS!" <<
665 "class:" << X11Tools::windowClass(pw) <<
666 "name:" << X11Tools::windowName(pw) <<
667 "pid:" << X11Tools::windowPID(pw);
669 X11Tools::setActiveWindow(pw);
670 return true;
673 return false;
677 void Jrugr::onMPFix () {
678 if (!deactivateMPlayer()) setDeskActiveWindow(mCurDesk, mActiveWindow);
680 #endif
683 void Jrugr::onActiveWindowChanged (Window w) {
684 qDebug() << "onActiveWindowChanged";
685 if (w == None) {
686 #ifdef K8_MPLAYER_HACK
687 if (mDeskJustChanged) {
688 //deactivateMPlayer();
689 if (mMplayerHack) {
690 mMPFix->start(MPLAYER_HACK_TIMEOUT);
692 mDeskJustChanged = false;
694 #else
695 setDeskActiveWindow(mCurDesk, w);
696 #endif
697 mActiveWindow = None;
698 qDebug() << "new active window: NONE";
699 return;
701 qDebug() << "new active window:" << (int)w << "desktop:" << X11Tools::windowDesktop(w);
702 dumpWinInfo("new active window:", w);
704 if (mDeskJustChanged) {
705 qDebug() << "*** mDeskJustChanged ***";
706 mDeskJustChanged = false;
707 #ifdef K8_MPLAYER_HACK
708 if (mMplayerHack && isMPlayer(w)) {
709 //mMPFix->start(MPLAYER_HACK_TIMEOUT);
710 if (deactivateMPlayer()) return;
712 #endif
715 #ifdef K8_MPLAYER_HACK
716 if (!mMplayerHack || !isMPlayer(w))
717 #endif
718 setDeskActiveWindow(mCurDesk, w);
720 WinInfo *wi = findWindowInfo(w), *aw;
721 if (!wi) {
722 qDebug() << "new window";
723 installFacehuggers();
724 wi = findWindowInfo(w);
726 if (wi) {
727 switch (jCfg->switching) {
728 case APP_LAYOUT:
729 if ((aw = findAppInfo(w)) != findAppInfo(mActiveWindow)) {
730 qDebug("application changed!");
731 if (aw) {
732 if (aw->layout != mActiveGroup) {
733 qDebug("enforcing layout %d", aw->layout);
734 emit changeLayout(aw->layout);
736 } else {
737 qWarning("*** APP SHIT! ***");
740 break;
741 case WIN_LAYOUT:
742 if (wi->layout != mActiveGroup) {
743 qDebug("enforcing layout %d", wi->layout);
744 emit changeLayout(wi->layout);
746 break;
747 default: break;
751 mActiveWindow = w;
755 void Jrugr::onClientListChanged () {
756 qDebug() << "onClientListChanged";
757 installFacehuggers();
761 void Jrugr::onActiveDesktopChanged (int desk) {
762 qDebug() << "onActiveDesktopChanged:" << desk;
763 mDeskJustChanged = true;
764 #ifdef K8_MPLAYER_HACK
765 //if (deactivateMPlayer()) mDeskJustChanged = false;
766 if (mMplayerHack) {
767 mMPFix->start(MPLAYER_HACK_TIMEOUT);
769 #endif
770 if (jCfg->switching == DESK_LAYOUT && mCurDesk != desk) {
771 int ll = desktopLayout(desk);
772 setDesktopLayout(desk, ll); // expand desktop list
773 if (ll != mActiveGroup) {
774 qDebug("enforce layout %d for desktop %d", ll, desk);
775 emit changeLayout(mDeskLangs.at(desk));
778 mCurDesk = desk;
782 bool Jrugr::x11EventFilter (XEvent *event) {
784 //qDebug() << "Jrugr::x11EventFilter:" << x11EventName(event);
785 switch (event->type) {
786 case DestroyNotify:
787 windowDies(event->xdestroywindow.window);
788 break;
789 case PropertyNotify:
790 if (event->xproperty.state == PropertyNewValue) {
791 if (atomActWin != None && event->xproperty.atom == atomActWin) {
792 //qDebug() << "emit: activeWindowChanged";
793 emit activeWindowChanged();
795 if (atomCurDesk != None && event->xproperty.atom == atomCurDesk) {
796 //qDebug() << "emit: activeDesktopChanged";
797 emit activeDesktopChanged();
799 if (atomClientList != None && event->xproperty.atom == atomClientList) {
800 qDebug() << "emit: clientListChanged";
801 emit clientListChanged();
804 //qDebug() << "PropertyNotify complete";
805 break;
806 default:
807 if (mXkb) mXkb->processEvent(event);
808 //return false;
809 break;
811 return false; // normal dispatching