Kde

Solid Hardware Without Device File Archaeology

I left an import dialog open, pulled the card reader, and clicked Import. The dialog still had a pointer to a Solid::StorageAccess interface from the device it had displayed. The hardware was gone; my object graph had not heard the news.

Hotplug makes lifetime the main problem, not discovery. A device can disappear between filling a menu and handling its action. A mount can vanish while a job is queued. Keeping /dev/sdb1 does not fix that, and keeping a frontend interface pointer around is worse because it looks usable right up to the point that it is not.

The dialog now stores the device’s unique device identifier, not a borrowed interface object. When the user starts an import, it asks Solid for the device again, checks that it is still valid, obtains the storage interface for that operation, and then checks the current accessibility state. No lookup, no import.

I also listen for deviceRemoved(QString). If the identifier matches the open dialog, the UI disables Import and says the device was removed. Any queued work receives the same cancellation instead of continuing with a path that happened to exist a moment ago.

There is a small race even with the fresh lookup: unplugging is allowed to win after the check. The operation still needs to handle mount or I/O failure. The lookup keeps stale application objects out of the way; it cannot promise that a human will leave the cable alone.

deviceAdded gets less special treatment now. It gives me an identifier to inspect, and I query capabilities when I need them. The removal signal is the one that tears down assumptions.

This fixed a second oddity too: unplugging and reinserting the same reader could produce a new frontend object while the dialog held the old one. Keying the UI by identifier and reacquiring the device made that boring, which is exactly what hotplug code should be.

Phonon and the Boring Audio Button

My sound preview worked with the Xine Phonon backend and failed as soon as I switched the machine to GStreamer. Same file, same button, no sound. So much for my five-line multimedia triumph.

The application called play() and immediately checked state(). Xine reached PlayingState quickly on my machine. GStreamer was still in LoadingState, which my code treated as failure and answered with stop(). I had accidentally made backend speed part of the program’s contract.

Phonon state changes are asynchronous. The fix was to let the MediaObject report stateChanged() and handle ErrorState there instead of demanding synchronous playback:

connect(media, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
        this, SLOT(mediaStateChanged(Phonon::State, Phonon::State)));
media->setCurrentSource(fileName);
media->play();

The slot updates the button when playback really starts and displays errorString() if the object enters ErrorState. LoadingState is just progress, not proof that the backend rejected the file.

Switching backends was useful precisely because it broke this. The common API kept Xine and GStreamer details out of the application, but it did not turn asynchronous operations into synchronous ones. One backend had merely been fast enough to hide my bad assumption.

The preview button is boring again. I left both backends in the test pass; otherwise the next timing assumption will wait for a user to find it.

KWin Compositing Without the Circus

I used to respond to a sluggish desktop by disabling compositing. That made the lag disappear, but also threw away the only useful fact: something in the composed path was expensive. It did not say whether the problem was KWin, one effect, the backend, or the driver.

This week I used a repeatable little test instead. I dragged the same terminal across the same busy screen for thirty seconds, watched KWin’s Show FPS display for missed frames, and recorded KWin and X CPU use. It is not a laboratory benchmark, but it is consistent enough to compare one setting at a time.

With all effects enabled, resizing caused regular stalls. Suspending compositing was the baseline, not the fix. I turned composition back on and disabled effects one by one. Blur was the expensive one on this hardware; the compositor with shadows and ordinary transitions stayed smooth. Disabling everything had hidden that distinction.

The FPS overlay needs some skepticism. A high frame count does not prove input feels responsive, and displaying the counter adds work of its own. I care more about visible pauses during the same action and whether CPU time changes in the same direction. Numbers are useful here as comparisons, not medals.

I repeated the run with OpenGL and XRender. XRender used a little more CPU but had steadier frame delivery with this driver. That is a local result, not a declaration that one backend is universally faster. Different cards and drivers can reverse it.

So compositing stays on, blur stays off, and I have notes I can repeat after the next driver update. “Feels slow” gave me one giant switch. A crude measurement found the smaller one.

Plasma Is Not Just a Panel

I wanted a tiny display for a script: one number, updated every few seconds, sitting in the panel. My first thought was to write another panel applet, which is exactly the sort of thought one has after years of assuming the panel is a special little kingdom.

Plasma makes that model obsolete. The desktop and panels are containments, and the things placed in them are applets. An applet does not have to know whether it lives beside the clock or floats on the desktop. The containment supplies geometry and constraints; the applet supplies its representation and behavior.

That distinction explained several things I had mistaken for needless abstraction. An applet receives constraint changes when its size or location changes. A wide desktop representation can become a compact panel representation without maintaining two unrelated implementations. It can also publish actions to the shell instead of building its own private collection of buttons.

Data comes through another layer. A Plasma data engine gathers and names information, while applets subscribe to sources. This keeps the code that reads a device, queries a service or runs a command away from the code that paints it. Several applets can consume one engine, and the engine controls update intervals rather than allowing every widget to wake the machine whenever inspiration strikes.

For my number display, this meant writing less code than expected. The engine owned the script result and timer. The applet listened for updates and painted the value. Moving it from desktop to panel changed layout constraints, not the source of the data. I had originally put the timer in the applet, because apparently I enjoy rediscovering coupling by hand.

The package structure is useful too. Metadata describes the applet, resources travel with it, and the shell can discover it without a hard-coded list. Scripted applets lower the cost of small experiments, while C++ remains available when the job needs libraries or tighter control.

There is a price. Debugging a small widget now involves understanding the applet, its containment and perhaps a data engine. Plasma’s vocabulary can sound grandiose when all I want is a number beside the clock. For one fixed panel, the old model was simpler.

I still prefer Plasma’s separation for anything that may grow or be reused. It treats the desktop as a collection of cooperating components rather than a panel plus decorative exceptions. The implementation is young and occasionally reminds me of that fact, but the mechanism is much more interesting than the collection of wobbly widgets suggests.

KDE 4.1 Feels Like a Desktop Again

I installed KDE 4.0 on a spare partition earlier this year and lasted about two days. It was interesting in the same sense that taking apart a toaster is interesting: there were clever pieces everywhere, but I still could not make breakfast.

KDE 4.1 is different. I have been using it for ordinary work since the release and, for the first time, I am spending more time in applications than arranging the desktop around them. That sounds like faint praise. For a desktop, however, becoming boring enough to disappear is a real achievement.

The panel is finally manageable. I can resize it, move it, add launchers and arrange the system tray without feeling that I am negotiating with a prototype. Plasma still exposes some rough edges, especially when widgets make optimistic assumptions about available space, but the basic shell now holds together.

KWin’s compositing also behaves much better on my Intel machine. Effects are not the important part; being able to leave compositing enabled without wondering whether the next window resize will turn into a slide show is. The new cover switch is amusing for several minutes, while smoother painting remains useful all day.

Dolphin has improved enough that I no longer immediately start Konqueror for every file operation. The tree view, tabs and saner selection behavior remove many small annoyances. There are still missing conveniences from KDE 3.5, and anyone depending on a particular panel applet should check before moving. “Newer” is not a substitute for “contains the thing I need.”

What changed my mind is not one large feature. It is the accumulation of small repairs: configuration modules that work, widgets that remember where they belong, fewer painting glitches and applications that look like parts of the same system. KDE 4’s new architecture was always ambitious; 4.1 is where some of that ambition starts paying rent.

I would now choose 4.1 for a machine I use myself, with a KDE 3.5 session nearby for emergencies. I would not yet migrate a room full of people who regard a moved icon as a personal attack. Progress is real, but so are users.