Changeset View
Changeset View
Standalone View
Standalone View
libtaskmanager/xwindowtasksmodel.cpp
Show First 20 Lines • Show All 511 Lines • ▼ Show 20 Line(s) | 511 | if (!url.isEmpty()) { | |||
---|---|---|---|---|---|
512 | return url; | 512 | return url; | ||
513 | } | 513 | } | ||
514 | } | 514 | } | ||
515 | 515 | | |||
516 | // Check to see if this wmClass matched a saved one ... | 516 | // Check to see if this wmClass matched a saved one ... | ||
517 | KConfigGroup grp(rulesConfig, "Mapping"); | 517 | KConfigGroup grp(rulesConfig, "Mapping"); | ||
518 | KConfigGroup set(rulesConfig, "Settings"); | 518 | KConfigGroup set(rulesConfig, "Settings"); | ||
519 | 519 | | |||
520 | // Evaluate MatchCommandLineFirst directives from config first. | ||||
520 | // Some apps have different launchers depending upon command line ... | 521 | // Some apps have different launchers depending upon command line ... | ||
521 | QStringList matchCommandLineFirst = set.readEntry("MatchCommandLineFirst", QStringList()); | 522 | QStringList matchCommandLineFirst = set.readEntry("MatchCommandLineFirst", QStringList()); | ||
522 | 523 | | |||
523 | if (!classClass.isEmpty() && matchCommandLineFirst.contains(classClass)) { | 524 | if (!classClass.isEmpty() && matchCommandLineFirst.contains(classClass)) { | ||
524 | triedPid = true; | 525 | triedPid = true; | ||
525 | services = servicesFromPid(pid); | 526 | services = servicesFromPid(pid); | ||
526 | } | 527 | } | ||
527 | 528 | | |||
528 | // Try to match using className also. | 529 | // Try to match using className also. | ||
529 | if (!className.isEmpty() && matchCommandLineFirst.contains("::"+className)) { | 530 | if (!className.isEmpty() && matchCommandLineFirst.contains("::"+className)) { | ||
530 | triedPid = true; | 531 | triedPid = true; | ||
531 | services = servicesFromPid(pid); | 532 | services = servicesFromPid(pid); | ||
532 | } | 533 | } | ||
533 | 534 | | |||
534 | // If the user has manually set a mapping, respect this first... | 535 | if (!classClass.isEmpty()) { | ||
536 | // Evaluate any mapping rules that map to a specific .desktop file. | ||||
535 | QString mapped(grp.readEntry(classClass + "::" + className, QString())); | 537 | QString mapped(grp.readEntry(classClass + "::" + className, QString())); | ||
536 | 538 | | |||
537 | if (mapped.endsWith(QLatin1String(".desktop"))) { | 539 | if (mapped.endsWith(QLatin1String(".desktop"))) { | ||
538 | url = QUrl(mapped); | 540 | url = QUrl(mapped); | ||
539 | return url; | 541 | return url; | ||
540 | } | 542 | } | ||
541 | 543 | | |||
542 | if (!classClass.isEmpty()) { | | |||
543 | if (mapped.isEmpty()) { | 544 | if (mapped.isEmpty()) { | ||
544 | mapped = grp.readEntry(classClass, QString()); | 545 | mapped = grp.readEntry(classClass, QString()); | ||
545 | 546 | | |||
546 | if (mapped.endsWith(QLatin1String(".desktop"))) { | 547 | if (mapped.endsWith(QLatin1String(".desktop"))) { | ||
547 | url = QUrl(mapped); | 548 | url = QUrl(mapped); | ||
548 | return url; | 549 | return url; | ||
549 | } | 550 | } | ||
550 | } | 551 | } | ||
551 | 552 | | |||
552 | // Some apps, such as Wine, cannot use className to map to launcher name - as Wine itself is not a GUI app | 553 | // Some apps, such as Wine, cannot use className to map to launcher name - as Wine itself is not a GUI app | ||
553 | // So, Settings/ManualOnly lists window classes where the user will always have to manualy set the launcher ... | 554 | // So, Settings/ManualOnly lists window classes where the user will always have to manualy set the launcher ... | ||
554 | QStringList manualOnly = set.readEntry("ManualOnly", QStringList()); | 555 | QStringList manualOnly = set.readEntry("ManualOnly", QStringList()); | ||
555 | 556 | | |||
556 | if (!classClass.isEmpty() && manualOnly.contains(classClass)) { | 557 | if (!classClass.isEmpty() && manualOnly.contains(classClass)) { | ||
557 | return url; | 558 | return url; | ||
558 | } | 559 | } | ||
559 | 560 | | |||
561 | // Try matching both WM_CLASS instance and general class against StartupWMClass. | ||||
562 | // We do this before evaluating the mapping rules further, because StartupWMClass | ||||
563 | // is essentially a mapping rule, and we expect it to be set deliberately and | ||||
564 | // sensibly to instruct us what to do. Also, mapping rules | ||||
565 | // | ||||
566 | // StartupWMClass=STRING | ||||
567 | // | ||||
568 | // If true, it is KNOWN that the application will map at least one | ||||
569 | // window with the given string as its WM class or WM name hint. | ||||
570 | // | ||||
571 | // Source: https://specifications.freedesktop.org/startup-notification-spec/startup-notification-0.1.txt | ||||
572 | if (services.empty()) { | ||||
573 | services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), QStringLiteral("exist Exec and ('%1' =~ StartupWMClass)").arg(classClass)); | ||||
574 | } | ||||
575 | | ||||
576 | if (services.empty()) { | ||||
577 | services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), QStringLiteral("exist Exec and ('%1' =~ StartupWMClass)").arg(className)); | ||||
578 | } | ||||
579 | | ||||
580 | // Evaluate rewrite rules from config. | ||||
581 | if (services.empty()) { | ||||
560 | KConfigGroup rewriteRulesGroup(rulesConfig, QStringLiteral("Rewrite Rules")); | 582 | KConfigGroup rewriteRulesGroup(rulesConfig, QStringLiteral("Rewrite Rules")); | ||
561 | if (rewriteRulesGroup.hasGroup(classClass)) { | 583 | if (rewriteRulesGroup.hasGroup(classClass)) { | ||
562 | KConfigGroup rewriteGroup(&rewriteRulesGroup, classClass); | 584 | KConfigGroup rewriteGroup(&rewriteRulesGroup, classClass); | ||
563 | 585 | | |||
564 | const QStringList &rules = rewriteGroup.groupList(); | 586 | const QStringList &rules = rewriteGroup.groupList(); | ||
565 | for (const QString &rule : rules) { | 587 | for (const QString &rule : rules) { | ||
566 | KConfigGroup ruleGroup(&rewriteGroup, rule); | 588 | KConfigGroup ruleGroup(&rewriteGroup, rule); | ||
567 | 589 | | |||
Show All 33 Lines | 611 | if (match.hasMatch()) { | |||
601 | services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), QStringLiteral("exist Exec and ('%1' =~ %2)").arg(rewrittenString, serviceSearchIdentifier)); | 623 | services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), QStringLiteral("exist Exec and ('%1' =~ %2)").arg(rewrittenString, serviceSearchIdentifier)); | ||
602 | 624 | | |||
603 | if (!services.isEmpty()) { | 625 | if (!services.isEmpty()) { | ||
604 | break; | 626 | break; | ||
605 | } | 627 | } | ||
606 | } | 628 | } | ||
607 | } | 629 | } | ||
608 | } | 630 | } | ||
631 | } | ||||
609 | 632 | | |||
633 | // Try matching mapped name against DesktopEntryName. | ||||
610 | if (!mapped.isEmpty() && services.empty()) { | 634 | if (!mapped.isEmpty() && services.empty()) { | ||
611 | services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), QStringLiteral("exist Exec and ('%1' =~ DesktopEntryName)").arg(mapped)); | 635 | services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), QStringLiteral("exist Exec and ('%1' =~ DesktopEntryName)").arg(mapped)); | ||
612 | } | 636 | } | ||
613 | 637 | | |||
638 | // Try matching mapped name against 'Name'. | ||||
614 | if (!mapped.isEmpty() && services.empty()) { | 639 | if (!mapped.isEmpty() && services.empty()) { | ||
615 | services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), QStringLiteral("exist Exec and ('%1' =~ Name)").arg(mapped)); | 640 | services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), QStringLiteral("exist Exec and ('%1' =~ Name)").arg(mapped)); | ||
616 | } | 641 | } | ||
617 | 642 | | |||
618 | // To match other docks (docky, unity, etc.) attempt to match on DesktopEntryName first ... | 643 | // Try matching WM_CLASS general class against DesktopEntryName. | ||
619 | if (services.empty()) { | 644 | if (services.empty()) { | ||
620 | services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), QStringLiteral("exist Exec and ('%1' =~ DesktopEntryName)").arg(classClass)); | 645 | services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), QStringLiteral("exist Exec and ('%1' =~ DesktopEntryName)").arg(classClass)); | ||
621 | } | 646 | } | ||
622 | 647 | | |||
623 | // Try StartupWMClass. | 648 | // Try matching WM_CLASS general class against 'Name'. | ||
624 | if (services.empty()) { | 649 | // This has a shaky chance of success as WM_CLASS is untranslated, but 'Name' may be localized. | ||
625 | services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), QStringLiteral("exist Exec and ('%1' =~ StartupWMClass)").arg(classClass)); | | |||
626 | } | | |||
627 | | ||||
628 | // Try 'Name' - unfortunately this can be translated, so has a good chance of failing! (As it does for KDE's own "System Settings" (even in English!!)) | | |||
629 | if (services.empty()) { | 650 | if (services.empty()) { | ||
630 | services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), QStringLiteral("exist Exec and ('%1' =~ Name)").arg(classClass)); | 651 | services = KServiceTypeTrader::self()->query(QStringLiteral("Application"), QStringLiteral("exist Exec and ('%1' =~ Name)").arg(classClass)); | ||
631 | } | 652 | } | ||
632 | } | 653 | } | ||
633 | 654 | | |||
634 | // Ok, absolute *last* chance, try matching via pid (but only if we have not already tried this!) ... | 655 | // Ok, absolute *last* chance, try matching via pid (but only if we have not already tried this!) ... | ||
635 | if (services.empty() && !triedPid) { | 656 | if (services.empty() && !triedPid) { | ||
636 | services = servicesFromPid(pid); | 657 | services = servicesFromPid(pid); | ||
▲ Show 20 Lines • Show All 715 Lines • Show Last 20 Lines |