{"id":874,"date":"2018-05-09T23:19:14","date_gmt":"2018-05-09T21:19:14","guid":{"rendered":"http:\/\/mattiesworld.gotdns.org\/weblog\/?p=874"},"modified":"2018-05-09T23:46:12","modified_gmt":"2018-05-09T21:46:12","slug":"quick-kde-kwin-hack-ignore-global-shortcuts-except-alt-tab","status":"publish","type":"post","link":"https:\/\/mattiesworld.gotdns.org\/weblog\/2018\/05\/09\/quick-kde-kwin-hack-ignore-global-shortcuts-except-alt-tab\/","title":{"rendered":"Quick KDE KWin hack: Ignore global shortcuts except alt-tab"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">From time to time a pet peeve can reach a critical level of annoyance at which it starts to irritate. You google it, hoping to find a solution or at least some allies, but if none turns up and you\u2019re out of time, you simply give up and hope a solution will magically manifest itself one other day. But what if that day never comes? Luckily for us, open source enthousiasts, we can do something about it ourselves \ud83d\ude42<\/span><\/p>\n<h1><span style=\"font-weight: 400;\">Context<\/span><\/h1>\n<p><span style=\"font-weight: 400;\">I\u2019m quite an avid shortcut user. Linux\/KDE is an environment where this type of user feels right at home. Not only do most actions in a software have a shortcut, you can also define lots of system-wide or global shortcuts. <a href=\"https:\/\/en.wikipedia.org\/wiki\/KWin\">Kwin<\/a>, KDE\u2019s window manager defines quite a few out of the box. <\/span><\/p>\n<h1><span style=\"font-weight: 400;\">Problem<\/span><\/h1>\n<p><span style=\"font-weight: 400;\">This is all fine and dandy until you want to use this cross-platform software which you got used to in a different environment (i.e. windows at work) and you want to start using it at home. When the application is not (KDE) shortcut friendly or you are so used to the windows keymap that it\u2019s a pain to learn a new scheme, you start to feel frustrated. Learning a new shortcut scheme seems the best solution but this doesn\u2019t work well when you have to maintain 2 shortcut schemes in your head, depending on your environment (home vs work, your computer at work versus a colleague\u2019s computer). <\/span><\/p>\n<p><span style=\"font-weight: 400;\">A typical example here would be some IDE, for example <a href=\"https:\/\/www.jetbrains.com\/idea\/\">Intellij IDEA<\/a>. Although the IDE does provide a KDE keymap by now, I started using it ages ago when there simply was no alternative keymap (nor a community edition or even official linux version, I guess). Also, I used linux only occasionally back then. These shortcuts are hard-wired by now and it is already hard enough to keep in mind whether I\u2019m using Intellij or Visual Studio. <\/span><\/p>\n<p><span style=\"font-weight: 400;\">Another possibility is that the application really needs that much shortcuts that it just can\u2019t bother with the shortcuts which may or may not be defined by the environment or workspace. One example of such complex application is <a href=\"https:\/\/www.blender.org\/\">Blender<\/a>. Try it out and you\u2019ll see what I mean. \ud83d\ude09<\/span><\/p>\n<p><span style=\"font-weight: 400;\">KDE, being the configurable desktop environment, does offer some configuration settings. For each window, Kwin allows you to define rules which match certain windows \/ applications which creates a config. Using this config, you can configure special window attributes. One setting is to block all global shortcuts. <\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-884\" src=\"https:\/\/mattiesworld.gotdns.org\/weblog\/wp-content\/uploads\/2018\/05\/kwinhack_ignoreglobalshortcuts-e1525900037525.png\" alt=\"\" width=\"750\" height=\"814\" srcset=\"https:\/\/mattiesworld.gotdns.org\/weblog\/wp-content\/uploads\/2018\/05\/kwinhack_ignoreglobalshortcuts-e1525900037525.png 750w, https:\/\/mattiesworld.gotdns.org\/weblog\/wp-content\/uploads\/2018\/05\/kwinhack_ignoreglobalshortcuts-e1525900037525-276x300.png 276w\" sizes=\"auto, (max-width: 750px) 100vw, 750px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">This allows you to use your favorite application with its favorite native shortcuts. Of course, most people use more than 1 application at the same time. However, since all global shortcuts are blocked, the alt+tab shortcut to switch windows is blocked too. Alt+tab is not a special shortcut to KDE, it simply is a shortcut that happens to be assigned globally to the \u201cWalk through windows\u201d action exposed by the KWin component to the System Settings. Lacking any window switching shortcut, you adapt and start using the mouse to switch applications. There are times you cope just fine. But there are other times it is just one thing too much that annoys you. \ud83d\ude42<\/span><\/p>\n<h1><span style=\"font-weight: 400;\">Solution<\/span><\/h1>\n<p><span style=\"font-weight: 400;\">So how to fix this? Just like any other problem you have with an open source application: fetch the source, fix and build! \ud83d\ude09<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Since I just wanted a quick fix (I thought, let\u2019s check this out for 30 mins, which turned out to be a lot longer of course), I chose to patch the behavior of the \u201cIgnore global shortcuts\u201d setting to exclude the Alt+Tab shortcut (more precisely, the shortcut currently assigned to the \u201cWalk through windows\u201d action). I briefly investigated <a href=\"https:\/\/techbase.kde.org\/Development\/Tutorials\/KWin\/Scripting\">KWin&#8217;s scripting<\/a> abilities but it turns out the required functionality is not exposed.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">I will now document the process, which took place on opensuse leap 42.3. You may want to tune out now if you don\u2019t care about the gritty tech details. \ud83d\ude09<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">Where is the source?<\/span><\/h3>\n<p><span style=\"font-weight: 400;\">I thought it had to be kwin, right? So I checked out the source from github and started searching for \u201cIgnore global shortcuts\u201d. It turned out to just call something in <a href=\"https:\/\/api.kde.org\/frameworks\/kglobalaccel\/html\/index.html\">kglobalaccel<\/a> which is not part of kwin. <\/span><\/p>\n<p><span style=\"font-weight: 400;\">Getting my hands dirty, I first fired up a VM I had lying around in order not to f*ck up my currently running system. Next I installed Qt Creator to easily navigate the code. Also, never forget you have to checkout the tag for the version you are currently running! (can be a treasure hunt by itself)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Browsing the source, I finally find a possible tweaking point in the src\/runtime\/component.cpp -&gt; <a href=\"https:\/\/lxr.kde.org\/source\/frameworks\/kglobalaccel\/src\/runtime\/component.cpp#0217\">deactivateShortcuts<\/a> method. It disables all shortcuts when a window is entered which has a \u201cIgnore global shortcuts\u201d rule. So I simply added an exclusion for the \u201cswitch windows\u201d action.<\/span><\/p>\n<p><a href=\"https:\/\/mattiesworld.gotdns.org\/weblog\/wp-content\/uploads\/2018\/05\/kwinhack_code.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-878 size-full\" src=\"https:\/\/mattiesworld.gotdns.org\/weblog\/wp-content\/uploads\/2018\/05\/kwinhack_code.png\" alt=\"\" width=\"743\" height=\"276\" srcset=\"https:\/\/mattiesworld.gotdns.org\/weblog\/wp-content\/uploads\/2018\/05\/kwinhack_code.png 743w, https:\/\/mattiesworld.gotdns.org\/weblog\/wp-content\/uploads\/2018\/05\/kwinhack_code-300x111.png 300w, https:\/\/mattiesworld.gotdns.org\/weblog\/wp-content\/uploads\/2018\/05\/kwinhack_code-500x186.png 500w\" sizes=\"auto, (max-width: 743px) 100vw, 743px\" \/><\/a><\/p>\n<h3>Building a patched rpm<\/h3>\n<p><span style=\"font-weight: 400;\">Time to try it out! In order to build it, you will need to install its dependencies. On an rpm based system, the easiest way to go forward is to do a \u201csourceinstall\u201d of the rpm in case. For that, we first have to know which rpm contains the affected shared object (.so file). <\/span><\/p>\n<p><span style=\"font-weight: 400;\">You can take different routes to pin point the rpm. I checked the CMakeLists.txt to see what the output targets were. When you build, you can also see the class pass by and check into which library it gets linked into. Using that .so file, you can find the rpm using &#8220;<\/span><span style=\"font-weight: 400;\">rpm -qf &lt;.so&gt;&#8221;<\/span><\/p>\n<p><span style=\"font-weight: 400;\">An alternative way would be to find a kde related rpm matching \u201cglobal\u201d and then checking its contents (using &#8220;rpm -q &#8211;filesbypkg &lt;rpm&gt;&#8221;) for the .so file.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Once you know the rpm, you can easily install all required build dependencies by issueing a zypper sourceinstall command: &#8220;zypper si &lt;rpm&gt;&#8221;<\/span><\/p>\n<h3>The hard part: logging<\/h3>\n<p><span style=\"font-weight: 400;\">I wanted to add some debug output to see if I was looking at the right place in the source base and how frequently the code got called. Now things got messy. You\u2019d think patching the code was the hard part, guess what.. \ud83d\ude09 <\/span><\/p>\n<p><span style=\"font-weight: 400;\">I had played with logging before in KDE, but of course <a href=\"https:\/\/community.kde.org\/Guidelines_and_HOWTOs\/Debugging\/Using_Error_Messages\">things have changed with KDE 5<\/a>. Nowadays, KDE uses <\/span><a href=\"http:\/\/doc.qt.io\/qt-5\/qloggingcategory.html#details\"><span style=\"font-weight: 400;\">Qt\u2019s default logging mechanism<\/span><\/a><span style=\"font-weight: 400;\">. It meant figuring out the logging category used by kglobalaccel and finding a way to activate it. The logging category was nicely tucked away in logging_p.h: &#8220;kglobalaccel-runtime\u201d. Activating it seemed to be trickier. According to the Qt documentation, you can alter the log level through an env var QT_LOGGING_RULES. Since I was adapting a core component, I needed to set the env var before logging in. On opensuse you can create a file \/etc\/profile.local which gets sourced by \/etc\/profile.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">I added the env var and it seemed to work (=showed up), unfortunately still no logging. More precisely, nothing showed up in ~\/.xsession-errors-:0. I started adding log statements all over the place, analysing the .so file to check whether my modified method was actually included in it (readelf -Ws libKF5GlobalAccelPrivate.so.5.32.0 \u00a0| grep deactivate), etc.. Until I realised I didn\u2019t check the journal (journalctl -b -0) yet, there it was. \ud83d\ude42 Bonus points: the code change had its intended effect!<\/span><\/p>\n<h3>End result<\/h3>\n<p><span style=\"font-weight: 400;\">So there I had it, a working patch WITH logging \u21d2 pure SATISFACTION \ud83d\ude42<\/span><\/p>\n<p>Feel free to share this satisfaction by <a href=\"https:\/\/mattiesworld.gotdns.org\/weblog\/2018\/05\/09\/quick-kde-kwin-hack-ignore-global-shortcuts-except-alt-tab\/libkf5globalaccelprivate-so-5-32-0-tar\/\" rel=\"attachment wp-att-880\">downloading the .so<\/a>\u00a0and installing it in \/usr\/lib64 (use at own risk).\u00a0I&#8217;ve been using it for 2 months now without problems. It&#8217;s a good hack until a more fundamental solution is in place. First steps have been taken! \ud83d\ude09<\/p>\n","protected":false},"excerpt":{"rendered":"<p>From time to time a pet peeve can reach a critical level of annoyance at which it starts to irritate. You google it, hoping to find a solution or at least some allies, but if none turns up and you\u2019re out of time, you simply give up and hope a solution will magically manifest itself &hellip; <a href=\"https:\/\/mattiesworld.gotdns.org\/weblog\/2018\/05\/09\/quick-kde-kwin-hack-ignore-global-shortcuts-except-alt-tab\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Quick KDE KWin hack: Ignore global shortcuts except alt-tab<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[22,13,25,4,5,6,20,10],"tags":[],"class_list":["post-874","post","type-post","status-publish","format-standard","hentry","category-1-night-stands","category-coding-excursions","category-kde","category-linux","category-programming","category-software","category-suse","category-tweaking"],"_links":{"self":[{"href":"https:\/\/mattiesworld.gotdns.org\/weblog\/wp-json\/wp\/v2\/posts\/874","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mattiesworld.gotdns.org\/weblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mattiesworld.gotdns.org\/weblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mattiesworld.gotdns.org\/weblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mattiesworld.gotdns.org\/weblog\/wp-json\/wp\/v2\/comments?post=874"}],"version-history":[{"count":10,"href":"https:\/\/mattiesworld.gotdns.org\/weblog\/wp-json\/wp\/v2\/posts\/874\/revisions"}],"predecessor-version":[{"id":891,"href":"https:\/\/mattiesworld.gotdns.org\/weblog\/wp-json\/wp\/v2\/posts\/874\/revisions\/891"}],"wp:attachment":[{"href":"https:\/\/mattiesworld.gotdns.org\/weblog\/wp-json\/wp\/v2\/media?parent=874"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mattiesworld.gotdns.org\/weblog\/wp-json\/wp\/v2\/categories?post=874"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mattiesworld.gotdns.org\/weblog\/wp-json\/wp\/v2\/tags?post=874"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}