Quick KDE KWin hack: Ignore global shortcuts except alt-tab

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’re 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 🙂

Context

I’m 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. Kwin, KDE’s window manager defines quite a few out of the box.

Problem

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’s a pain to learn a new scheme, you start to feel frustrated. Learning a new shortcut scheme seems the best solution but this doesn’t 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’s computer).

A typical example here would be some IDE, for example Intellij IDEA. 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’m using Intellij or Visual Studio.

Another possibility is that the application really needs that much shortcuts that it just can’t bother with the shortcuts which may or may not be defined by the environment or workspace. One example of such complex application is Blender. Try it out and you’ll see what I mean. 😉

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.

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 “Walk through windows” 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. 🙂

Solution

So how to fix this? Just like any other problem you have with an open source application: fetch the source, fix and build! 😉

Since I just wanted a quick fix (I thought, let’s check this out for 30 mins, which turned out to be a lot longer of course), I chose to patch the behavior of the “Ignore global shortcuts” setting to exclude the Alt+Tab shortcut (more precisely, the shortcut currently assigned to the “Walk through windows” action). I briefly investigated KWin’s scripting abilities but it turns out the required functionality is not exposed.

I will now document the process, which took place on opensuse leap 42.3. You may want to tune out now if you don’t care about the gritty tech details. 😉

Where is the source?

I thought it had to be kwin, right? So I checked out the source from github and started searching for “Ignore global shortcuts”. It turned out to just call something in kglobalaccel which is not part of kwin.

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)

Browsing the source, I finally find a possible tweaking point in the src/runtime/component.cpp -> deactivateShortcuts method. It disables all shortcuts when a window is entered which has a “Ignore global shortcuts” rule. So I simply added an exclusion for the “switch windows” action.

Building a patched rpm

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 “sourceinstall” of the rpm in case. For that, we first have to know which rpm contains the affected shared object (.so file).

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 “rpm -qf <.so>”

An alternative way would be to find a kde related rpm matching “global” and then checking its contents (using “rpm -q –filesbypkg <rpm>”) for the .so file.

Once you know the rpm, you can easily install all required build dependencies by issueing a zypper sourceinstall command: “zypper si <rpm>”

The hard part: logging

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’d think patching the code was the hard part, guess what.. 😉

I had played with logging before in KDE, but of course things have changed with KDE 5. Nowadays, KDE uses Qt’s default logging mechanism. 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: “kglobalaccel-runtime”. 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.

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  | grep deactivate), etc.. Until I realised I didn’t check the journal (journalctl -b -0) yet, there it was. 🙂 Bonus points: the code change had its intended effect!

End result

So there I had it, a working patch WITH logging ⇒ pure SATISFACTION 🙂

Feel free to share this satisfaction by downloading the .so and installing it in /usr/lib64 (use at own risk). I’ve been using it for 2 months now without problems. It’s a good hack until a more fundamental solution is in place. First steps have been taken! 😉

VLC on opensuse 12.3

Last week, I installed opensuse 12.3 and encountered the following problem with VLC:

main decoder error: no suitable decoder module for fourcc `mpgv’. VLC probably does not support this sound or video format.

I had this for about any video format (mpgv for a DVD in this case). Turned out it is a package problem. Simply install vlc-codecs and you should be good to go.

Update: apparently, this is not a bug, but a feature, see
google+ post
mailing list post

Query recently installed rpm’s

Last night I was fooling around with lwjgl (nice lib btw), when suddenly I started getting the following exception:

org.lwjgl.LWJGLException: Could not choose GLX13 config
	at org.lwjgl.opengl.LinuxDisplayPeerInfo.initDefaultPeerInfo(Native Method)
	at org.lwjgl.opengl.LinuxDisplayPeerInfo.(LinuxDisplayPeerInfo.java:61)
	at org.lwjgl.opengl.LinuxDisplay.createPeerInfo(LinuxDisplay.java:782)
	at org.lwjgl.opengl.DrawableGL.setPixelFormat(DrawableGL.java:61)
	at org.lwjgl.opengl.Display.create(Display.java:871)
	at org.lwjgl.opengl.Display.create(Display.java:782)
	at org.lwjgl.opengl.Display.create(Display.java:764)

I googled and some Minecraft stuff turned up (seems it uses lwjgl as well), but only with mysterious “solutions”. I thought it was because I tried to run it from console (it ran fine before in IntelliJ), but it stopped working there too. Then I suspected mixing openjdk compiled code run by sun jre was the problem (seems lwjgl requires sun jre). Than I fumbled around with the java.library.path variable because it looked like a 64bit vs 32bit issue. NONE OF THAT!
I screwed up and it was late, so I decided to admit my defeat and go to bed.

Today I started my suse box, suddenly I realized my KDE desktop effects were disabled. Nvidia driver borked? Reinstalled my nvidia, even rebooted, all in vein!
I checked hardware acceleration with Urban Terror, smooth gaming!

Then I started to retrace my steps of last night.. I tried to install glc which in the past had proven to be quite a decent opengl capture program for linux.

I checked my repos and noticed I accidentally installed the 12.1 version! Uninstalling that does not fix it of course, probably some dependency messed up things good (although still quite subtle to keep everything else working ;)).

I finally come to the point of this post 😉 I wanted to know what I installed last night in the late hours that seriously borked my system.

Turns out rpm has a neat option just for that: –last !
So it goes like this:

# rpm -qa --last | less

yields amongst others:

libcurl4-7.21.2-10.11.1                       Mon 30 Jan 2012 11:06:02 PM CET
libcurl4-32bit-7.21.2-10.11.1                 Mon 30 Jan 2012 11:06:02 PM CET
glibc-locale-2.14.1-14.18.1                   Mon 30 Jan 2012 01:46:16 AM CET
glibc-devel-2.14.1-14.18.1                    Mon 30 Jan 2012 01:46:11 AM CET
parallel-printer-support-1.00-5.1             Mon 30 Jan 2012 01:46:10 AM CET
glibc-2.14.1-14.18.1                          Mon 30 Jan 2012 01:46:08 AM CET
gpg-pubkey-b185393d-47965930                  Mon 30 Jan 2012 01:45:55 AM CET
phpMyAdmin-3.4.9-30.1                         Thu 19 Jan 2012 09:22:30 PM CET

I managed to fubar my glibc 🙂 culprit found! Reverting this to the previous version fixed it!

Extra keywords: query rpm history

Android USB debugging on openSUSE 11.4

Debugging your android app using a hardware device has several advantages, ie faster and more testing possibilities. On windows you have to install a custom USB driver, on linux it’s a matter of configuring your udev rules:

  • add a rules files in /etc/udev/rules.d , ie 44-android.rules
  • enter a line like this:
    SUBSYSTEM=="usb", ATTR{idVendor}=="0bb4", MODE="0666", GROUP="users"

    and adapt the vendor id using this table.

  • Reload udev rules: udevadm control --reload-rules

When you run adb devices, it should now list your device:

List of devices attached 
emulator-5554   device
SH14FPL06953    device

Before, you would rather have something like this:

List of devices attached 
emulator-5554   device
????????????    no permissions

On succesful connection, the system log shows something like:

kernel: [11172.551464] usb 2-1: USB disconnect, address 4
kernel: [11178.813044] usb 2-1: new high speed USB device using ehci_hcd and address 5
kernel: [11178.942137] usb 2-1: New USB device found, idVendor=0bb4, idProduct=0c87
kernel: [11178.942150] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
kernel: [11178.942157] usb 2-1: Product: Android Phone
kernel: [11178.942162] usb 2-1: Manufacturer: HTC
kernel: [11178.942166] usb 2-1: SerialNumber: SH14FPL06953
kernel: [11178.943867] scsi8 : usb-storage 2-1:1.0
mtp-probe: checking bus 2, device 5: "/sys/devices/pci0000:00/0000:00:04.1/usb2/2-1"
mtp-probe: bus: 2, device: 5 was not an MTP device
kernel: [11179.953172] scsi 8:0:0:0: Direct-Access     HTC      Android Phone    0100 PQ: 0 ANSI: 2
kernel: [11179.953375] sd 8:0:0:0: Attached scsi generic sg4 type 0
kernel: [11179.961631] sd 8:0:0:0: [sdd] Attached SCSI removable disk

Note that it seems normal that a usb storage device is detected, although I did not have it enabled on the phone.

Configuring an ad hoc network on suse

Since I don’t own a gigabit router but I do have Gbit NICs on my laptop and main computer, I set up a peer to peer network for optimal performance when I have to transfer a large volume. I don’t do that often so I end up losing time every time. So I decided to write a small blog post about it. 🙂 My concrete setup is transfering between a windows and linux machine.

In windows, when the network adapter is configured for DHCP but it can’t find a DHCP server, it automatically falls back to link-local addressing. On IPv4, this is the 169.254.0.0/16 block. (Apparently, Microsoft likes to calls this APIPA.)
However, on my opensuse 11.1 box, it seems not automatically configured for that. When you open Yast -> Network Settings, edit the network interface and enable “zeroconf” under “dynamic address”.
Yast network zeroconfig configuration
All easy peasy and intuitive.

But now comes the catch! After applying these settings, it works… but stops working after a few secs/mins! I checked the messages log and found out the dhcp client tries to restore the old lease if it doesn’t receive an offer. This causes the zeroconf address to be invalidated. So, before enabling Zeroconf, be sure to release the lease first. You can do this as follows:

sudo dhclient -r

Possibly if you keep the DHCP+Zeroconf setting in yast, you can just release the lease when you want to setup a local network and it would fallback to zeroconf. Didn’t verify it though (had to go online to document this ;))

Repair grub after windows install

Last week I installed Windows 7 RC (which still works these days, btw) on my brother’s computer so he could practice Autodesk Inventor at home. Since Windows stubbornly still denies the existence of any other OS, it consequently wipes the MBR and installs its own boot loader. Bottom line, we need to reinstall the GRUB boot loader.

There are several ways to do that, but since my brother uses openSUSE, I will use the openSUSE install dvd:

  • Boot from the install dvd
  • Select “Rescue system”. This will give you a console. (I also tried the automatic repair option, but that somehow did not work..)
  • log in with root. no password is asked.

From here on, it is not openSUSE specific anymore:

  • Run “grub”. It starts scanning your disks and after some time you should get a grub> prompt.
  • (Optional) Find the partition where grub is installed:
    grub> find /boot/grub/stage1
  • Set grub’s root partition (example: first harddisk, first partition):
    grub> root (hd0,0)
  • Execute grub installation into MBR:
    grub> setup (hd0)
  • If you would have wanted to install into a specific partition instead of the MBR, simply specify the partition instead:
    grub> setup (hd0,0)

You can find all this info and more in the grub manual.

Controlling XMMS using a gamepad

On windows I used to control winamp using global shortcuts. Since I didn’t immediately find this plugin on linux (although google seems to suggest it exists), I tried the joystick control plugin. But I never used a joystick before on linux.. 🙂

I plugged in my Logitech Dual Action Gamepad and a cpu spike indicated something got detected. 😉 I didn’t have high hopes it would work in XMMS though, since that’s about as archaic as one can get with a gui app. 😉 I enabled the libjoy.so plugin and set the path right to /dev/input/js0 instead of the default /dev/js0. I tried some button and some joystick. It didn’t do anything.

Let’s have a look at Yast. Yes, it has a joystick module, but it didn’t seem to list my gamepad. But then I read in the side column that you don’t have to configure anything if you use an USB gamepad. So next thing was to try KDE’s control center which turns out to also have joystick module. Indeed, the gamepad with all its axes and buttons was properly detected! While I was there, I also did a calibration, mostly for fun, as it didn’t seem necessary. So why didn’t it work with XMMS, because it was just too old?

In a final attempt, I tried testing a “general analog joystick” in yast, which triggered a package install (don’t remember which one). I don’t know if it was the package that did the trick, but after that, it worked in XMMS! It was just a matter of finding out the right buttons by trial and error (the mapping didn’t correspond to KDE’s mapping).

opensuse 11.0 to 11.1 upgrade story

I am always a bit reluctant to upgrade instead of just install because it is a much less tested use case and there is always the conflict between your own preferences and new defaults: who has precedence? But an OS should be meant to be upgradable, right? I know, most people are not confronted with the issue since Windows isn’t exactly what I would call an good example of an upgradable OS 😉 Linux users are much more confronted with the upgrade issue since most distro’s put out at least one release a year. I always give the upgrade a shot, but most of the time I also do a new install just to know how the new release was meant to be conceived. 😉

So here is my upgrade story for my laptop: it’s a Dell D830 with Nvidia Quadro NVS 140 and Intel(R) PRO/Wireless 3945ABG.

The upgrade procedure itself went smooth although I never really know if I have to enable more repositories or not when asked. The upgrade will by default only take the default suse repo’s into account. So I left it that way, but it could explain a few issues I ran into later..

Anyway, after the upgrade reboot, I don’t get a graphical login screen.. I run sax2, and this fixes the issue, but nvidia driver is not used. So I add the nvidia repo from the community repository list. I see there is now a new driver “G02” instead of the “G01” I used to use. So I mark this package for installation, but some dependencies fail.. I don’t know the exact list anymore, but one of them was related to the kernel, which surprised me as I just upgraded (but I did have the jengelh realtime kernel installed before I upgraded).

Something was odd with the package management.. and I also got an error that updates could not be found because no backend was configured. what the..? So next thing to do, was configure the online update. When I tried that, it wouldn’t work because “SSL negotation failed”. This definitely smelled like a bug, so I filed one and it has already been confirmed by a suse employee by now.

So I added the update repo manually (although I had read about the new smolt integration and would’ve loved to register my system) and configured the new updater applet (kupdateapplet, which supports packagekit) to use the zypper backend which I first had to install manually (kde4-kupdateapplet-zypp). Finally some updates were found, but the new tool failed to install the patches (have to file a bug next time patches are issued) and asked me if I wanted to use yast instead. Funny how they anticipated problems there. 🙂 Using yast, there was no problem of course. The smolt update even triggered a proper nvidia install without dependency problems.

Having updated, after I relogged on, the nvidia driver was effective and remembered its configuration from before the upgrade. Since the version was now called G02, I had high hopes that this would incorporate all the fixes NVidia addressed in their beta drivers to get rid of the KDE4 desktop effects performance problems, but alas, it seems this is still beta. I might want to install the beta driver after all, I’m tired of the bad performance. 😉 My ATI radeon 9800 PRO in my desktop performs better! Although I have to admit, even the stable nvidia drivers seem to have received a few improvements the last few months.

That’s it for now!

Optimizing the linux boot process

How fast your linux boots, really depends on your distro and of course it’s their job to have it boot as fast as possible. They try as much as possible scenarios and make sane decisions on where to optimize. But they can’t test every possible configuration, so what if you just end up with a suboptimal situation (possibly without realizing? :)). Even if you know your boot takes too much time, how would you locate the culprit(s)?

This is where Bootchart jumps in. Bootchart is a tool which makes it possible assess resource consumption throughout boot time. It is really simple to set up, just add a kernel param! Data is collected in memory using tmpfs and dumped to disk at the end of the boot process. This data then gets processed by a java app which outputs an SVG/PNG.

It seems the opensuse guys, actually coolo, used this tool to optimize boot performance for opensuse 10.3. I must say I am quite satisfied with my opensuse boot times although I do have the impression that 11.0 seems to be a tad slower than 10.3. So I’m definitely going to try out this tool and compare the results 🙂

Thanks to my brother for the tip.

Part 2

Accidentally, a few hours after writing this post, I ran into this very interesting article about boot speedups presented at the Linux Plumbers Conference last month. (Watch a modified fedora boot in 5 secs on an eeePC)