GNOME.ORG

24 hours a day, 7 days a week, 365 days per year...

September 23, 2016

We’re looking for a GNOME developer

We in the Red Hat desktop team are looking for a junior software developer who will work on GNOME. Particularly in printing and document viewing areas of the project.

The location of the position is Brno, Czech Republic, where you’d join a truly international team of desktop developers. It’s a junior position, so candidates just off the university, or even still studying are welcome. We require solid English communication skills and experience with C (and ideally C++, too). But what is a huge plus is experience with GNOME development and participation in the community.

Interested? You can directly apply for the position at jobs.redhat.com or if you have any question, you can write me: eischmann [] redhat [] com.

198px-gnomelogo-svg


LibreOffice Conference 2016

LibreOffice Conference 2016 is over and for us organizers it’s a time to reflect.

libocon16-logo

It was the third big open source desktop conference we’ve managed to get to Brno (after GUADEC 2013 and Akademy 2014). 3 days of talks, 150 attendees from all over the world, 4 social events.

The conference went pretty well from the organizational point of view. Feedback has been very positive so far. People liked the city, the venue (FIT BUT campus is really, really nice), the parties, and catering during the conference. TDF board even lifted Red Hat to the highest sponsorship level for the amount of work we did for the conference. The only major bummer we had was no online streaming. It’s quite easy to set it up with the university’s built-in video recording system, but the university didn’t allow it in the end. Nevertheless, we treated online streaming as nice-to-have. Video recordings are important to us and we’ll do our best to get them online as soon as possible.

I’ve (co)organized quite a few international conferences, but what was new for me was an attendee who gets seriously sick and needs medical services. One of the Libocon attendees got a serious infection in his leg and we spent a lot of time driving between hospitals, talking to doctors, arranging things. Everything ended well and the attendee got so better than he was even able to fly back home as he planned originally which didn’t look very likely at the beginning.

What I really don’t like doing is being an organizer and speaker at the same conference. As an organizer you’re just too busy and can’t concentrate on a talk you’re supposed to deliver. I volunteered to do an introductory talk in the Friday’s Czech track. I was even given already prepared slides and using someone else’s slides is another thing I don’t like doing. So as you can imagine it was not one of the best talks of my career🙂 But the Czech track turned out to be quite good overall. I just wish more people had come, but if you only have <2 weeks to promote the program you won’t get crowds to the conference.

I’d like to thank The Document Foundation for a great cooperation, and all attendees for being so kind and forgiving us minor glitches in the organization. It was an exhausting, but great experience, and I hope to see everyone in Rome next year where I can again be in the comfortable seat of a visitor.


September 22, 2016

Making money from copylefted code

I wanted to put this out there while I still have it fresh in my mind. Here at the copyleft BoF with Bradlely Kuhn at LAS GNOME. One of the biggest take away from this is something that Bryan Lunduke said that people are able to make money off from copyleft if we don’t actually brand it as free and open source software. So it seems that if we don’t advertise something as free or open source or that there is software available, then there is a decent chance that you can make money.

Which goes back to the interesting conversation we had the previous day on pretty much the same topic. Just fascinating stuff.

2016-09-22 Thursday.

  • Mail chew, actioning items etc. customer call, ESC call. Increasingly thrilled with new Dell Inspiron 7000 - fast (at least running Linux), quiet, powerful etc. suspends, (and better resumes again) etc. Poked at Apple's iCloud apps a little; interesting.
  • After a very long time of trying to de-bong Thunderbird's plain-text editing behaviour - by searching in the global 'send' options (to stop HTML mail sending), and on the brink of quitting back to Evolution - I finally discovered a magic per-account setting in "Composition and Addressing" with the lovely legend:
    "[x] Compose messages in HTML format" - which, when turned off appears to make the mail composer actually usable for plain-text loving developers; nice !
  • Finally got my blog back together on the re-constituted machine.

WebKitGTK+ 2.14 and the Web Engines Hackfest

Next week our friends at Igalia will be hosting this year’s Web Engines Hackfest. Collabora will be there! We are gold sponsors, and have three developers attending. It will also be an opportunity to celebrate Igalia’s 15th birthday \o/. Looking forward to meet you there! =)

Carlos Garcia has recently released WebKitGTK+ 2.14, the latest stable release. This is a great release that brings a lot of improvements and works much better on Wayland, which is becoming mature enough to be used by default. In particular, it fixes the clipboard, which was one of the main missing features, thanks to Carlos Garnacho! We have also been able to contribute a bit to this release =)

One of the biggest changes this cycle is the threaded compositor, which was implemented by Igalia’s Gwang Yoon Hwang. This work improves performance by not stalling other web engine features while compositing. Earlier this year we contributed fixes to make the threaded compositor work with the web inspector and fixed elements, helping with the goal of enabling it by default for this release.

Wayland was also lacking an accelerated compositing implementation. There was a patch to add a nested Wayland compositor to the UIProcess, with the WebProcesses connecting to it as Wayland clients to share the final rendering so that it can be shown to screen. It was not ready though and there were questions as to whether that was the way to go and alternative proposals were floating around on how to best implement it.

At last year’s hackfest we had discussions about what the best path for that would be where collaborans Emanuele Aina and Daniel Stone (proxied by Emanuele) contributed quite a bit on figuring out how to implement it in a way that was both efficient and platform agnostic.

We later picked up the old patchset, rebased on the then-current master and made it run efficiently as proof of concept for the Apertis project on an i.MX6 board. This was done using the fancy GL support that landed in GTK+ in the meantime, with some API additions and shortcuts to sidestep performance issues. The work was sponsored by Robert Bosch Car Multimedia.

Igalia managed to improve and land a very well designed patch that implements the nested compositor, though it was still not as efficient as it could be, as it was using glReadPixels to get the final rendering of the page to the GTK+ widget through cairo. I have improved that code by ensuring we do not waste memory when using HiDPI.

As part of our proof of concept investigation, we got this WebGL car visualizer running quite well on our sabrelite imx6 boards. Some of it went into the upstream patches or proposals mentioned below, but we have a bunch of potential improvements still in store that we hope to turn into upstreamable patches and advance during next week’s hackfest.

One of the improvements that already landed was an alternate code path that leverages GTK+’s recent GL super powers to render using gdk_cairo_draw_from_gl(), avoiding the expensive copying of pixels from the GPU to the CPU and making it go faster. That improvement exposed a weird bug in GTK+ that causes a black patch to appear when shrinking the window, which I have a tentative fix for.

We originally proposed to add a new gdk_cairo_draw_from_egl() to use an EGLImage instead of a GL texture or renderbuffer. On our proof of concept we noticed it is even more efficient than the texturing currently used by GTK+, and could give us even better performance for WebKitGTK+. Emanuele Bassi thinks it might be better to add EGLImage as another code branch inside from_gl() though, so we will look into that.

Another very interesting igalian addition to this release is support for the MemoryPressureHandler even on systems with no cgroups set up. The memory pressure handler is a WebKit feature which flushes caches and frees resources that are not being used when the operating system notifies it memory is scarce.

We worked with the Raspberry Pi Foundation to add support for that feature to the Raspberry Pi browser and contributed it upstream back in 2014, when Collabora was trying to squeeze as much as possible from the hardware. We had to add a cgroups setup to wrap Epiphany in, back then, so that it would actually benefit from the feature.

With this improvement, it will benefit even without the custom cgroups setups as well, by having the UIProcess monitor memory usage and notify each WebProcess when memory is tight.

Some of these improvements were achieved by developers getting together at the Web Engines Hackfest last year and laying out the ground work or ideas that ended up in the code base. I look forward to another great few days of hackfest next week! See you there o/

GNOME 3.22 Release Party – Confirmed

Sorry, this entry is only available in Português.

#photos happenings

Out of a mojito bar in South Beach with a lobotomised plastic picnic spoon and a crew of control freaks.

3.22 is here

We recently released GNOME 3.22. It will be in Fedora Workstation 25. Go look at the video — it’s awesome!

GNOME Photos has again taken significant strides forward – just like we did six months ago in 3.20. One of the big things that we added this time was sharing. This nicely rounds out our existing online acccounts integration, and complements the work we did on editing six months ago.

gnome-photos-sharing

Sharing is an important step towards a more tightly integrated online account experience in GNOME. We have been interested in a desktop-wide sharing service for some time. With Flatpak portals becoming a reality, I hope that the sharing feature in Photos can be spun off into a portal for GNOME.

Thanks to Umang Jain, our GSoC intern this summer for working on sharing.

We overhauled a lot of hairy architectural issues, which will let us have nicer overview grids in the near future. Alessandro created a Flatpak. This means that going forward, you can easily try out the nightly builds of Photos thanks to the Flatpak support in GNOME Software 3.22.

gnome-photos-flatpak2

Thanks to Kalev Lember for the wonderful screenshot.

The future

I think that we are reaching a point where we can recommend Photos to a wider group of users. With editing and sharing in place, we have filled some of the bigger gaps in the user experience that we want to offer. Yes, there are some missing features and rough edges that we are aware of, so we we are going to spend the next six months addressing the ones that are most important. You can look at our roadmap for the full picture, but I am going to highlight a few.

Better overview grids (GNOME #690623)

We have been using GtkIconView to display the grid of thumbnails that we call the overview. GtkIconView has been around for a long while, but it has some issues – both visual and performance. Therefore, we want to replace it with GtkFlowBox so (a) that the application remains responsive while we are populating the grid, and (b) we can have really pretty visuals.

Eventually, we want this:

photos-photos

Import from device (GNOME #751212)

This is one of the biggest missing features, in my opinion. We really need a way to import content from removable devices and cameras that doesn’t involve mucking around with files and directories.

Petr Stetka has already started working on this, but I am sure he will appreciate any help with this.

More sharing (GNOME #766031)

Last but not the least, I definitely like showing off on Facebook and so do you! So I want to add a Facebook share-point and possibly a few more.

Come, join us

If any of this interests you, then feel free to jump right in. We have a curated list of newcomer bugs and a guide for those who are relatively new. If you are an experienced campaigner, you can look at the roadmap for more significant tasks.

For any help, discussions or general chitchat, #photos on GIMPNet is the place to be.


Comments about OARS and CSM age ratings

I’ve had quite a few comments from people stating that using age rating classification values based on American culture is wrong. So far I’ve been using the Common Sense Media research (and various other psychology textbooks) to essentially clean-room implement a content-rating to appropriate age algorithm.

Whilst I do agree that other cultures have different sensitivities (e.g. Smoking in Uganda, references to Nazis in Germany) there doesn’t appear to be much research on the suggested age ratings for different categories for those specific countries. Lots of things are outright banned for sale for various reasons (which the populous may completely ignore), but there doesn’t seem to be many statistics that back up the various anecdotal statements. For instance, are there any US-specific guidelines that say that the age rating for playing a game that involves taking illegal drugs should be 18, rather than the 14 which is inferred from CSM? Or the age rating should be 25+ for any game that features drinking alcohol in Saudi Arabia?

Suggestions (especially references) welcome. Thanks!

September 21, 2016

Help Send Conservancy to Embedded Linux Conference Europe

[ This blog was crossposted on Software Freedom Conservancy's website. ]

Last month, Conservancy made a public commitment to attend Linux-related events to get feedback from developers about our work generally, and Conservancy's GPL Compliance Program for Linux Developers specifically. As always, even before that, we were regularly submitting talks to nearly any event with Linux in its name. As a small charity, we always request travel funding from the organizers, who are often quite gracious. As I mentioned in my blog posts about LCA 2016 and GUADEC 2016, the organizers covered my travel funding there, and recently both Karen and I both received travel funding to speak at LCA 2017 and DebConf 2016, as well as many other events this year.

Recently, I submitted talks for the CFPs of Linux Foundation's Embedded Linux Conference Europe (ELC EU) and the Prpl Foundation's OpenWRT Summit. The latter was accepted, and the folks at the Prpl Foundation graciously offered to fund my flight costs to speak at the OpenWRT Summit! I've never spoken at an OpenWRT event before and I'm looking forward to the opportunity getting to know the OpenWRT and LEDE communities better by speaking at that event, and am excited to discuss Conservancy's work with them.

OpenWRT Summit, while co-located, is a wholly separate event from LF's ELC EU. Unfortunately, I was not so lucky in my talk submissions there: my talk proposal has been waitlisted since July. I was hopeful after a talk cancellation in mid-August. (I know because the speaker who canceled suggested that I request his slot for my waitlisted talk.) Unfortunately, the LF staff informed me that they understandably filled his open slot with a sponsored session that came in.

The good news is that my OpenWRT Summit flight is booked, and my friend (and Conservancy Board Member Emeritus) Loïc Dachary (who lives in Berlin) has agreed to let me crash with him for that week. So, I'll be in town for the entirety of ELC EU with almost no direct travel costs to Conservancy! The bad news is that it seems my ELC EU talk remains waitlisted. Therefore, I don't have a confirmed registration for the rest of ELC EU (beyond OpenWRT Summit).

While it seems like a perfect and cost-effective opportunity to be able to attend both events, that seems harder than I thought! Once I confirmed my OpenWRT Summit travel arrangements, I asked for the hobbyist discount to register for ELC EU, but LF staff informed me yesterday that the hobbyist (as well as the other discounts) are sold out. The moral of the story is that logistics are just plain tough and time-consuming when you work for a charity with an extremely limited travel budget. ☻

Yet, it seems a shame to waste the opportunity of being in town with so many Linux developers and not being able to see or talk to them, so Conservancy is asking for some help from you to fund the $680 of my registration costs for ELC EU. That's just about six new Conservancy supporter signups, so I hope we can get six new Supporters before Linux Foundation's ELC EU conference begins on October 10th. Either way, I look forward to seeing those developers who attend the co-located OpenWRT Summit! And, if the logistics work out — perhaps I'll see you at ELC EU as well!

is go an acceptable cml?

Yesterday I tried to summarize the things I know about Concurrent ML, and I came to the tentative conclusion that Go (and any Go-like system) was an acceptable CML. Turns out I was both wrong and right.

you were wrong when you said everything's gonna be all right

I was wrong, in the sense that programming against the CML abstractions lets you do more things than programming against channels-and-goroutines. Thanks to Sam Tobin-Hochstadt to pointing this out. As an example, consider a little process that tries to receive a message off a channel, and times out otherwise:

func withTimeout(ch chan int, timeout int) (result int) {
  var timeoutChannel chan int;
  var msg int;
  go func() {
    sleep(timeout)
    timeoutChannel <- 0
  }()
  select {
    case msg = <-ch: return msg;
    case msg = <-timeoutChannel: return 0;
  }
}

I think that's the first Go I've ever written. I don't even know if it's syntactically valid. Anyway, I think we see how it should work. We return the message from the channel, unless the timeout happens before.

But, what if the message is itself a composite message somehow? For example, say we have a transformer that reads a value from a channel and adds 1 to it:

func onePlus(in chan int) (result chan int) {
  var out chan int
  go func () { out <- 1 + <-in }()
  return out
}

What if we do a withTimeout(onePlus(numbers), 0)? Assume the timeout fires first and that's the result that select chooses. There's still that onePlus goroutine out there trying to read from in and at some point probably it will succeed, but nobody will read its value. At that point the number just vanishes into the ether. Maybe that's OK in certain domains, but certainly not in general!

What CML gives you is the ability to express an event (which is kinda like a possibility of sending or receiving a message on a channel) in such a way that we don't run into this situation. Specifically with the wrap combinator, we would make an event such that receiving on numbers would run a function on the received message and return that as the message value -- which is of course the same as what we have, except that in CML the select wouldn't actually read the message off unless it select'd that channel for input.

Of course in Go you could just rewrite your program, so that the select statement looks like this:

select {
  case msg = <-ch: return msg + 1;
  case msg = <-timeoutChannel: return 0;
}

But here we're operating at a lower level of abstraction; we were forced to intertwingle our concerns of adding 1 and our concerns of timeout. CML is more expressive than Go.

you were right when you said we're all just bricks in the wall

However! I was right in the sense that you can build a CML system on top of Go-like systems (though possibly not Go in particular). Thanks to Vesa Karvonen for this comment and the link to their proof-of-concept CML implementation in Clojure's core.async. I understand Vesa also has an implementation in F# as well.

Folks should read Vesa's code, after reading the Reppy papers of course; it's delightfully short and expressive. The basic idea is that event composition operators like choose and wrap build up data structures instead of doing things. The sync operation then grovels through those data structures to collect a list of channels to pass on to core.async's equivalent of select. When select returns, sync determines which event that chosen channel and message corresponds to, and proceeds to "activate" the event (and, as a side effect, possibly issue NACK messages to other channels).

Provided you can map from the chosen select channel/message back to the event, (something that core.async can mostly do, with a caveat; see the code), then you can build CML on top of channels and goroutines.

o/~ yeah you were wrong o/~

On the other hand! One advantage of CML is that its events are not limited to channel sends and receives. I understand that timeouts, thread joins, and maybe some other event types are first-class event kinds in many CML systems. Michael Sperber, current Scheme48 maintainer and functional programmer, tells me that simply wrapping events in channels+goroutines works but can incur a big performance overhead relative to supporting those event types natively, due to the need to make the new goroutine and channel and the scheduling costs. He quotes 10X as the overhead!

So although CML and Go appear to be inter-expressible, maybe a proper solution will base the simple channel send/receive interface on CML rather than the other way around.

Also, since these events are now second-class, it must be OK to lose these events, for the same reason that the naïve withTimeout could lose a message from numbers. This is the case for timeouts usually but maybe you have to think about this more, and possibly provide an infinite stream of the message. (Of course the wrapper goroutine would be collected if the channel becomes unreachable.)

you were right when you said this is the end

I've long wondered how contemporary musicians deal with the enormous, crushing weight of recorded music. I don't really pick any more but hoo am I feeling this now. I think for Guile, I will continue hacking on fibers in a separate library, and I think that things will remain that way for the next couple years and possibly more. We need more experience and more mistakes before blessing and supporting any particular formulation of highly concurrent programming. I will say though that I am delighted that we are able to actually do this experimentation on a library level and I look forward to seeing what works out :)

Thanks again to Vesa, Michael, and Sam for sharing their time and knowledge; all errors are of course mine. Happy hacking!

2016-09-21 Wednesday.

  • Laptop surgery; quite pleased with Windows 10 - but the latest openSUSE / Linux on an SSD whips it for speed and familiarity; as well as reliability for external USB/Sata bits. Moved VM pieces into the real world again; good.
  • Caught up with Kohei, team call.

Copyleft, attribution, and data: other considerations

Public licenses for databases don’t work well. Before going into solutions to that problem, though, I wanted to talk briefly about some things that are important to consider when thinking about solutions: real-world examples of the problems; a common, but bad, solution; and a discussion of the motivations behind public licenses.

2013-bullfrog-map-unavailable
Bullfrog map unavailable“, by Peter Desmets, under CC BY 3.0 unported

Real-world concerns, not just theoretical

When looking at solutions, it is important to understand that the practical concerns I blogged about aren’t just theoretical — they matter in practice too. For example, Peter Desmet has done a great job showing how overreaching licenses make bullfrog maps (and other data combinations) illegal. Alex Barth of OpenStreetMap has also discussed how ODbL creates problems for OSM users (though he got some Wikipedia-related facts wrong). And I’ve spoken to very well-intentioned organizations (including thoughtful, impactful non-profits) scared off from OSM for similar reasons.

On the flip side, because these rules are based on such flimsy legal grounds, sophisticated corporate legal departments often feel comfortable circumventing
the requirements by exploiting loopholes. (Needless to say, they don’t blog about the problems with the licenses – they just go ahead and use the loopholes.) So overreaching attempts to create new rights are, in many ways, the worst of both worlds: they hurt well-intentioned cooperation, and don’t dissuade parties with a significant interest in exploiting the commons.

What not to do: create new “rights”

When thinking about solutions, it is unfortunately also important to say what isn’t a good idea: create new rights, or override limitations on old ones. The Free Software Foundation, to their great credit, has always consistently said that if weakening copyright also weakens the GPL, they’ll take that tradeoff; and that vice-versa, the GPL should not ask for rights that go beyond copyright law. The most recent copyleft licenses from Creative Commons, Mozilla, and the FSF all make this explicit: limitations on copyright, like fair use, are not trumped by our licenses.

Unfortunately, many people have a good-faith desire to see copyleft-like results in other domains. As a result, they’ve gone the wrong way on this point. ODbL is probably the most blatant example of this: even at the time, Science Commons correctly pointed out that ODbL’s attempt to create database rights by contract outside of the EU was a bad idea. Unfortunately, well-intentioned people (including me!) pushed it through anyway. Similarly, open hardware proponents have tried to stretch copyright to cover functional works, with predictably messy results.

This is not just practically wrong, for the reasons I’ve explained in earlier posts. It is also ethically wrong for those of us who want to see more data sharing, because any “rights” we create by fiat are going to end up being used primarily to stop sharing, not encourage it.

Remembering why we do share-alike and attribution

Consider this section a brief sketch for a future post – if I forgot something
big, please let me know, but please don’t roast me in comments for being brief
or reductive about your favorite motivation.

It is important when writing about public licenses to remember why the idea of
placing restrictions on re-use is so intuitively appealing outside of software.
If we don’t understand why people want to do less-than-public domain, it’s hard
to come up with solutions that actually work. Motivations tend to be some
combination (varying from person to person and community to community) of:

  • Recognition: Many people want to at least be recognized for their work, even when they ask for nothing else. (When Creative Commons assessed usage after their 1.0 licenses, [97-98% of people chose attribution](https://creativecommons.org/2004/05/25/announcingandexplainingournew20licenses/).) This sentiment underlies many otherwise “permissive” licenses, as well as academic norms around plagiarism and attribution.
  • Reducing free riding: Lots of people are afraid that commons can be destroyed by people who use the resource without giving back. Historically, this “tragedy of the commons” was about [rivalrous](https://en.wikipedia.org/wiki/Rivalry_(economics)) goods (like fisheries), but the same concern is often raised in the context of collaborative communities, whose labor can be rivalrous even when their goods are non-rivalrous. Some people like share-alike requirements because, pragmatically, they feel such requirements are one way to prevent (or at least reduce) this risk by encouraging people to either participate fully or not participate at all. (If you’re interested in this point, I’ve [written about it before](http://lu.is/blog/2014/12/02/free-riding-and-copyleft-in-cultural-commons-like-flickr/).)
  • “Fairness”: Many people like share-alike out of a deep moral sense that if you take, you should also give back. This often looks the same as the previous point, but with the key distinction that at least some people focused on fairness care more about process and less about outcomes: a smaller, less productive community with more sharing may, for them, be better than a larger, more productive community where not everyone shares perfectly.
  • Access to allow self-help: Another variation on the previous two points is a use of copyleft that focuses less on “is the author helping me by cooperating” and more on “did the author give me materials I can then use to help myself”. In this view, increased access to raw material (like source code, or data) can be good even the authors are non-cooperative. (To those familiar with the Linux kernel discussions, this is essentially “I got a lousy driver, and the authors hate me, but at least I got *a* driver”.)
  • Ethical: Many people simply think data/source should never be proprietary, and so will use any means possible, like copyleft, to increase the amount of non-proprietary code in the world.

All of these motivations can be more or less valid at different points in time, in ways that (again) deserve a different post. (For example, automatic attribution may not have the same impact as “human” attribution, which may not be a surprise given the evidence on crowding out of intrinsic motivations.)

Finally, next (and final?) post: what solutions we’ve got.

Microsoft aren't forcing Lenovo to block free operating systems

There's a story going round that Lenovo have signed an agreement with Microsoft that prevents installing free operating systems. This is sensationalist, untrue and distracts from a genuine problem.

The background is straightforward. Intel platforms allow the storage to be configured in two different ways - "standard" (normal AHCI on SATA systems, normal NVMe on NVMe systems) or "RAID". "RAID" mode is typically just changing the PCI IDs so that the normal drivers won't bind, ensuring that drivers that support the software RAID mode are used. Intel have not submitted any patches to Linux to support the "RAID" mode.

In this specific case, Lenovo's firmware defaults to "RAID" mode and doesn't allow you to change that. Since Linux has no support for the hardware when configured this way, you can't install Linux (distribution installers will boot, but won't find any storage device to install the OS to).

Why would Lenovo do this? I don't know for sure, but it's potentially related to something I've written about before - recent Intel hardware needs special setup for good power management. The storage driver that Microsoft ship doesn't do that setup. The Intel-provided driver does. "RAID" mode prevents the Microsoft driver from binding and forces the user to use the Intel driver, which means they get the correct power management configuration, battery life is better and the machine doesn't melt.

(Why not offer the option to disable it? A user who does would end up with a machine that doesn't boot, and if they managed to figure that out they'd have worse power management. That increases support costs. For a consumer device, why would you want to? The number of people buying these laptops to run anything other than Windows is miniscule)

Things are somewhat obfuscated due to a statement from a Lenovo rep:This system has a Signature Edition of Windows 10 Home installed. It is locked per our agreement with Microsoft. It's unclear what this is meant to mean. Microsoft could be insisting that Signature Edition systems ship in "RAID" mode in order to ensure that users get a good power management experience. Or it could be a misunderstanding regarding UEFI Secure Boot - Microsoft do require that Secure Boot be enabled on all Windows 10 systems, but (a) the user must be able to manage the key database and (b) there are several free operating systems that support UEFI Secure Boot and have appropriate signatures. Neither interpretation indicates that there's a deliberate attempt to prevent users from installing their choice of operating system.

The real problem here is that Intel do very little to ensure that free operating systems work well on their consumer hardware - we still have no information from Intel on how to configure systems to ensure good power management, we have no support for storage devices in "RAID" mode and we have no indication that this is going to get better in future. If Intel had provided that support, this issue would never have occurred. Rather than be angry at Lenovo, let's put pressure on Intel to provide support for their hardware.

comment count unavailable comments

GNOME 3.22 core apps

GNOME 3.22 is scheduled to be released today. Along with this release come brand new recommendations for distributions on which applications should be installed by default, and which applications should not. I’ve been steadily working on these since joining the release team earlier this year, and I’m quite pleased with the result.

When a user installs a distribution and boots it for the first time, his or her first impression of the system will be influenced by the quality of the applications that are installed by default. Selecting the right set of default applications is critical to achieving a quality user experience. Installing redundant or overly technical applications by default can leave users confused and frustrated with the distribution. Historically, distributions have selected wildly different sets of default applications. There’s nothing inherently wrong with this, but it’s clear that some distributions have done a much better job of this than others. For instance, a default install of Debian 8 with the GNOME desktop includes two different chess applications, GNOME Chess and XBoard. Debian fails here: these applications are redundant, for starters, and the later app looks like an ancient Windows 95 application that’s clearly out of place with the rest of the system. It’s pretty clear that nobody is auditing the set of default applications here, as I doubt anyone would have intentionally included Xboard; it turns out that XBoard gets pulled in by Recommends via an obscure chess engine that’s pulled in by another Recommends from GNOME Chess, so I presume this is just an accident that nobody has ever cared to fix. Debian is far from the only offender here; you can find similar issues in most distributions. This is the motivation for providing the new default app recommendations.

Most distributions will probably ignore these, continue to select default apps on their own, and continue to do so badly. However, many distributions also strive to provide a pure, vanilla GNOME experience out-of-the-box. Such distributions are the target audience for the new default app guidelines. Fedora Workstation has already adopted them as the basis for selecting which apps will be present by default, and the result is a cleaner out-of-the-box experience.

Update: I want to be clear that these guidelines are not appropriate for all distros. Most distros are not interested in providing a “pure GNOME experience.” Distros should judge for themselves if these guidelines are relevant to them.

Classifications

The canonical source of these classifications is maintained in JHBuild, but that’s not very readable, so I’ll list them out here. The guidelines are as follows:

  • Applications classified as core are intended to be installed by default. Distributions should only claim to provide a vanilla GNOME experience if all such applications are included out-of-the-box.
  • Applications classified as extra are NOT intended to be installed by default. Distributions should not claim to provide a vanilla GNOME experience if any such applications are included out-of-the-box.
  • Applications classified as Incubator are somewhere in between. Incubator is a classification for applications that are designed to be core apps, but which have not yet reached a high enough level of quality that we can move them to core and recommend they be installed by default. If you’re looking for somewhere to help out in GNOME, the apps marked Incubator would be good places to start.

Core apps

Distributions that want to provide a pure GNOME experience MUST include all of the following apps by default:

  • Archive Manager (File Roller)
  • Boxes
  • Calculator
  • Calendar
  • Characters (gnome-characters, not gucharmap)
  • Cheese
  • Clocks
  • Contacts
  • Disk Usage Analyzer (Baobab)
  • Disks
  • Document Viewer (Evince)
  • Documents
  • Files (Nautilus)
  • Font Viewer
  • Help (Yelp)
  • Image Viewer (Eye of GNOME)
  • Logs (gnome-logs, not gnome-system-log)
  • Maps
  • Photos
  • Screenshot
  • Software
  • System Monitor
  • Terminal
  • Text Editor (gedit)
  • Videos (Totem)
  • Weather
  • Web (Epiphany)

Notice that all core apps present generic names (though it’s somewhat debatable if Cheese qualifies as a generic name, I think it sounds better than alternatives like Photo Booth). They all also (more or less) follow the GNOME Human Interface Guidelines.

The list of core apps is not set in stone. For example, if Photos or Documents eventually learn to provide good file previews, we wouldn’t need Image Viewer or Document Viewer anymore. And now that Files has native support for compressed archives (new in 3.22!), we may not need Archive Manager much longer.

Currently, about half of these applications are arbitrarily marked as “system” applications in Software, and are impossible to remove. We’ve received complaints about this and are mostly agreed that it should be possible to remove all but the most critical core applications (e.g. allowing users to remove Software itself would clearly be problematic). Unfortunately this didn’t get fixed in time for GNOME 3.22, so we will need to work on improving this situation for GNOME 3.24.

Incubator

Distributions that want to provide a pure GNOME experience REALLY SHOULD NOT include any of the following apps by default:

  • Dictionary
  • Music
  • Notes (Bijiben)
  • Passwords and Keys (Seahorse)

We think these apps are generally useful and should be in core; they’re just not good enough yet. Please help us improve them.

These are not the only apps that we would like to include in core, but they are the only ones that both (a) actually exist and (b) have actual releases. Take a look at our designs for core apps if you’re interested in working on something new.

Extra apps

Distributions that want to provide a pure GNOME experience REALLY SHOULD NOT include any of the following apps by default:

  • Accerciser
  • Builder
  • dconf Editor
  • Devhelp
  • Empathy
  • Evolution
  • Hex Editor (ghex)
  • gitg
  • Glade
  • Multi Writer
  • Nemiver
  • Network Tools (gnome-nettool)
  • Polari
  • Sound Recorder
  • To Do
  • Tweak Tool
  • Vinagre

Not listed are Shotwell, Rhythmbox, or other applications hosted on git.gnome.org that are not (or are no longer) part of official GNOME releases. These applications REALLY SHOULD NOT be included either.

Note that the inclusion of applications in core versus extra is not a quality judgment: that’s what Incubator is for. Rather, we  classify apps as extra when we do not believe they would be beneficial to the out-of-the-box user experience. For instance, even though Evolution is (in my opinion) the highest-quality desktop mail client that exists today, it can be very difficult to configure, the user interface is large and unintuitive, and most users would probably be better served by webmail. Some applications listed here are special purpose tools that are probably not generally useful to the typical user (like Sound Recorder). Other applications, like Builder, are here because they are developer tools, and developer tools are inherently extremely confusing to nontechnical users. (Update: I originally used Polari instead of Builder as the developer tool example in the previous sentence. It was a bad example.)

Games

What about games? It’s OK to install a couple of the higher-quality GNOME games by default, but none are necessary, and it doesn’t make sense to include too many, since they vary in quality. For instance, Fedora Workstation does not include any games, but Ubuntu installs GNOME Mahjongg, GNOME Mines, and GNOME Sudoku. This is harmless, and it seems like a good list. I might add GNOME Chess, or perhaps GNOME Taquin. I’ve omitted games from the list of extra apps up above, as they’re not my focus here.

Third party applications

It’s OK to include a few third-party, non-GNOME applications by default, but they should be kept to a reasonable minimum. For example Fedora Workstation includes Firefox (instead of Epiphany), Problem Reporting (ABRT), SELinux Troubleshooter, Shotwell (instead of GNOME Photos), Rhythmbox, and LibreOffice Calc, Draw, Impress, and Writer. Note that LibreOffice Base is not included here, because it’s not reasonable to include a database management tool on systems designed for nontechnical users. The LibreOffice start center is also not included, because it’s not an application.

Summing up

Distributions, consider following our recommendations when deciding what should be installed by default. Other distributions should feel encouraged to use these classifications as the basis for downstream package groups. At the very least, distributions should audit their set of default applications and decide for themselves if they are appropriate. A few distributions have some horrendous technical stuff visible in the overview by default; Fedora Workstation shows it does not have to be this way.

Talking at mrmcds 2016 in Darmstadt, Germany

A couple of weeks ago, I attended the mrmcds in Darmstadt, Germany. Just like I did the last years. Like the years before, the conference was nicely themed. This year, the theme was all things medical. So speakers were given doctors’ coats, conference staff were running around like surgeons, alcohol could be had intravenously …

mrmcd 2016 logo

The talk on medical device nightmares (video) showed some medical devices like which show and record vital signs such as the pulse or blood pressure. But also more fancy devices such as an MRI. Of course, he did not only show the devices themselves, but rather how they tested them on their external interfaces, i.e. the networking port. Speaking of the MRI: It exposed a few hundred open ports. The services listening on these ports crashed when nmap scanned the host… But at least apparently they recovered automatically. He also presented an anaesthetic monitoring device, which is supposed to show how much alive a patient still is. The device seems to have a telnet interface which you can log on to with default credentials. The telnet interface has, not surprisingly, a command injection vulnerability, which allowed them to take ownership of the device. The next step was then to hijack the framebuffer and to render whatever they wanted on it. For example nice looking vital data; as if the patient was still alive. Or, probably the more obvious thing to do: Show Rick Astley.

It’s been an entertaining talk which makes you realise how complicated the whole area of pharmaceutical or medical appliances is. They need to go through a long and troublesome certification process, not unlike other businesses (say, car manufacturers). Patching the underlying Windows is simply not possible without losing the certification. You may well ask whether a certificate or an up-to-date OS is better for your health. And while I make it look a bit ridiculous now, I do appreciate that it’s a tough subject.

My own talk on GNOME (video) was well visited. I explained why I think GNOME is a good candidate for shipping security software to the masses. I said that GNOME cares about its users and goes the extra mile to support as many users as possible. That includes making certain decisions to provide a secure by default system. I gave two examples of how I think GNOME pushes the envelope when it comes to making security usable. One was the problem of OpenPGP Keysigning. I mentioned that it’s a very geeky thing which mortals do not understand. Neither do many security people, to be honest. And you can’t even blame them because it’s a messy thing to do. Doing it properly™ involves a metric ton of OpSec to protect the integrity of the key to be signed. I think that we can make the process much more usable than it is right now while even maintaining security. This year, I had Andrei working with me to make this happen.

The other example I gave was the problem of USB security. Do you know when you use your USB? And do you know when you don’t? And do you know when other people use your USB? I talked about the possibility to lock down your USB ports while you’re not in front of your computer. The argument goes that you can’t possibly insert anything if you’re away. Of course, there are certain cases to keep in mind, like not forbidding a keyboard to be plugged in, in case the old one breaks. But there is little reason to allow your USB camera to work unless you are actively using your machine. I presented how this could look like by showing off the work the George did last summer.

My friend Jens talked about Reverse Engineering of applications. He started to explain why you would do that in first place. Analysing your freshly received malware or weaknesses (think backdoors or bypasses) in your software are motivations, he said. But you might as well tinker with old software which has no developer anymore or try to find APIs of other software for interoperational purposes, he said. Let me note that with Free Software, you wouldn’t have to reverse engineer the binary ;-) But he also mentioned that industrial espionage is a reason for people to reverse engineer a compiled programme. The tool he uses the most is the “file” tool. He went on to explain the various executable formats for various machine flavours (think: x86, ELF, PE, JVM). To go practical, he showed a .NET application which only writes “hello, world!”, because malware, he said, is written in .NET nowadays. In order to decompile the binary he recommended “iLspy” as a one-stop suite for reverse engineering .NET applications. Next up were Android applications. He showed how to pull the APK off the device and how to decompose it to JAR classes. Then he recommended CFR for decompiling those into Java code. His clients, mostly banks, he said, try to hide secret keys in their apps, so the first thing he does when having a new job is to grep for “secret”. In 80% of the cases, he said, it is successful. To make it harder for someone to reverse engineer the binary, obfuscators exist for Java, but also for C. He also mentioned some anti debugging techniques such as to check for the presence of certain DLLs or to throw certain interrupts to determine whether the application runs under a debugger. It was a very practical talk which certainly made it clear that the presented things are relevant today. Due to the limited time and the many examples, he could only scratch the surface, though.

It’s been a nice conference with 400ish attendees. I really like how they care about the details, also when it comes to make the speakers feel good. It’s too sad that it’s only one weekend. I’m looking forward to attending next year’s edition :-)

Who wrote GTK+ and more

I’ve just posted on the GTK+ development blog the latest article in the “who writes GTK+” series. Now that we have a proper development blog, this is the kind of content that should be present there instead of my personal blog.

If you’re not following the GTK+ development blog, you really should do so now. Additionally, you should follow @GTKToolkit on Twitter and, if you’re into niche social platforms, a kernel developer, or a Linus groupie, there’s the GTK+ page on Google Plus.

Additionally, if you’re contributing to GTK+, or using it, you should consider writing an article for the developers blog; just contact me on IRC (I’m ebassi on irc.gnome.org) or send me an email if you have an idea about something you worked on, a new feature, some new API, or the internals of the platform.

GNOME Software and Age Ratings

After all the tarballs for GNOME 3.22 the master branch of gnome-software is now open to new features. Along with the usual cleanups and speedups one new feature I’ve been working on is finally merging the age ratings work.

screenshot-from-2016-09-21-10-22-36

The age ratings are provided by the upstream-supplied OARS metadata in the AppData file (which can be generated easily online) and then an age classification is generated automatically using the advice from the appropriately-named Common Sense Media group. At the moment I’m not doing any country-specific mapping, although something like this will be required to show appropriate ratings when handling topics like alcohol and drugs.

At the moment the only applications with ratings in Fedora 26 will be Steam games, but I’ve also emailed any maintainer that includes an <update_contact> email address in the appdata file that also identifies as a game in the desktop categories. If you ship an application with an AppData and you think you should have an age rating please use the generator and add the extra few lines to your AppData file. At the moment there’s no requirement for the extra data, although that might be something we introduce just for games in the future.

I don’t think many other applications will need the extra application metadata, but if you know of any adult only applications (e.g. in Fedora there’s an application for the sole purpose of downloading p0rn) please let me know and I’ll contact the maintainer and ask what they think about the idea. Comments, as always, welcome. Thanks!

September 20, 2016

concurrent ml versus go

Peoples! Lately I've been navigating the guile-ship through waters unknown. This post is something of an echolocation to figure out where the hell this ship is and where it should go.

Concretely, I have been working on getting a nice lightweight concurrency system rolling for Guile. I'll write more about that later, but you can think of it as being modelled on Go, though built as a library. (I had previously described it as "Erlang-like", but that's just not accurate.)

Earlier this year at Curry On this topic was burning in my mind and of course when I saw the language-hacker fam there I had to bend their ears. My targets: Matthew Flatt, the amazing boundary-crossing engineer, hacker, teacher, researcher, and implementor of Racket, and Matthias Felleisen, the godfather of the PLT research family. I saw them sitting together and I thought, you know what, what can they have to say to each other? These people have been talking together for 30 years right? Surely they are actually waiting for some ignorant dude to saunter up to the PL genius bar, right?

So saunter I do, saying, "if someone says to you that they want to build a server that will handle 100K or so simultaneous connections on Racket, what abstraction do you tell them to use? Racket threads?" Apparently: yes. A definitive yes, in the case of Matthias, with a pointer to Robby Findler's paper on kill-safe abstractions; and still a yes from Matthew with the caveat that for the concrete level of concurrency that I described, you'd have to run tests. More fundamentally, I was advised to look at Concurrent ML (on which Racket's concurrency facilities were based), that CML was much better put together than many modern variants like Go.

This was very interesting and new to me. As y'all probably know, I don't have a formal background in programming languages, and although I've read a lot of literature, reading things only makes you aware of the growing dimension of the not-yet-read. Concurrent ML was even beyond my not-yet-read horizon.

So I went back and read a bunch of papers. Turns out Concurrent ML is like Lisp in that it has a tribe and a tightly-clutched history and a diaspora that reimplements it in whatever language they happen to be working in at the moment. Kinda cool, and, um... a bit hard to appreciate in the current-day context when the only good references are papers from 10 or 20 years ago.

However, after reading a bunch of John Reppy papers, here is my understanding of what Concurrent ML is. I welcome corrections; surely I am getting this wrong.

1. CML is like Go, composed of channels and goroutines. (Forgive the modern referent; I assume most folks know Go at this point.)

2. Unlike Go, in CML a channel is never buffered. To make a buffered channel in CML, you spawn a thread that manages a buffer between two channels.

3. Message send and receive operations in CML are built on a lower-level primitive called "events". (send ch x) is instead euivalent to (sync (send-event ch x)). It's like an event is the derivative of a message send with respect to time, or something.

4. Events can be combined and transformed using the choose and wrap combinators.

5. Doing a sync on an event created by choose allows a user to build select in "user-space", as a library. Cool stuff. So this is what events are for.

6. There are separate event type implementations for timeouts, channel send/recv blocking operations, file descriptor blocking operations, syscalls, thread joins, and the like. These are supported by the CML implementation.

7. The early implementations of Concurrent ML were concurrent but not parallel; they did not run multiple "goroutines" on separate CPU cores at the same time. It was only in like 2009 that people started to do CML in parallel. I do not know if this late parallelism has a practical impact on the viability of CML.

ok go

What is the relationship of CML to Go? Specifically, is CML more expressive than Go? (I assume the reverse is not the case, but that would also be an interesting result!)

There are a few languages that only allow you to select over message receives (not sends), but Go's select doesn't have this limitation, so that's not a differentiator.

Some people say that it's nice to have events as the common denominator, but I don't get this argument. If the only event under consideration is message send or receive over a channel, events + choose + sync is the same in expressive power as a built-in select, as far as I can see. If there are other events, then your runtime already has to support them either way, and something like (let ((ch (make-channel))) (spawn-fiber (lambda () (put-message ch exp))) (get-message ch)) should be sufficient for any runtime-supported event in exp, like sleeps or timeouts or thread joins or whatever.

To me it seems like Go has made the right choices here. I do not see the difference, and that's why I wrote all this, is to be shown the error of my ways. Choosing channels, send, receive, and select as the primitives seems to have the same power as SML events.

Let this post be a pentagram on the floor, then, to summon the CML cognoscenti. Well-actuallies are very welcome; hit me up in the comments!

[edit: Sam Tobin-Hochstadt tells me I got it wrong and I believe him :) In the meantime while I work out how I was wrong, examples are welcome!]

GNOME 3.22 Release Party

Sorry, this entry is only available in Português.

WebKitGTK+ 2.14

These six months has gone so fast and here we are again excited about the new WebKitGTK+ stable release. This is a release with almost no new API, but with major internal changes that we hope will improve all the applications using WebKitGTK+.

The threaded compositor

This is the most important change introduced in WebKitGTK+ 2.14 and what kept us busy for most of this release cycle. The idea is simple, we still render everything in the web process, but the accelerated compositing (all the OpenGL calls) has been moved to a secondary thread, leaving the main thread free to run all other heavy tasks like layout, JavaScript, etc. The result is a smoother experience in general, since the main thread is no longer busy rendering frames, it can process the JavaScript faster improving the responsiveness significantly. For all the details about the threaded compositor, read Yoon’s post here.

So, the idea is indeed simple, but the implementation required a lot of important changes in the whole graphics stack of WebKitGTK+.

  • Accelerated compositing always enabled: first of all, with the threaded compositor the accelerated mode is always enabled, so we no longer enter/exit the accelerating compositing mode when visiting pages depending on whether the contents require acceleration or not. This was the first challenge because there were several bugs related to accelerating compositing being always enabled, and even missing features like the web view background colors that didn’t work in accelerated mode.
  • Coordinated Graphics: it was introduced in WebKit when other ports switched to do the compositing in the UI process. We are still doing the compositing in the web process, but being in a different thread also needs coordination between the main thread and the compositing thread. We switched to use coordinated graphics too, but with some modifications for the threaded compositor case. This is the major change in the graphics stack compared to the previous one.
  • Adaptation to the new model: finally we had to adapt to the threaded model, mainly due to the fact that some tasks that were expected to be synchronous before became asyncrhonous, like resizing the web view.

This is a big change that we expect will drastically improve the performance of WebKitGTK+, especially in embedded systems with limited resources, but like all big changes it can also introduce new bugs or issues. Please, file a bug report if you notice any regression in your application. If you have any problem running WebKitGTK+ in your system or with your GPU drivers, please let us know. It’s still possible to disable the threaded compositor in two different ways. You can use the environment variable WEBKIT_DISABLE_COMPOSITING_MODE at runtime, but this will disable accelerated compositing support, so websites requiring acceleration might not work. To disable the threaded compositor and bring back the previous model you have to recompile WebKitGTK+ with the option ENABLE_THREADED_COMPOSITOR=OFF.

Wayland

WebKitGTK+ 2.14 is the first release that we can consider feature complete in Wayland. While previous versions worked in Wayland there were two important features missing that made it quite annoying to use: accelerated compositing and clipboard support.

Accelerated compositing

More and more websites require acceleration to properly work and it’s now a requirement of the threaded compositor too. WebKitGTK+ has supported accelerated compositing for a long time, but the implementation was specific to X11. The main challenge is compositing in the web process and sending the results to the UI process to be rendered on the actual screen. In X11 we use an offscreen redirected XComposite window to render in the web process, sending the XPixmap ID to the UI process that renders the window offscreen contents in the web view and uses XDamage extension to track the repaints happening in the XWindow. In Wayland we use a nested compositor in the UI process that implements the Wayland surface interface and a private WebKitGTK+ protocol interface to associate surfaces in the UI process to the web pages in the web process. The web process connects to the nested Wayland compositor and creates a new surface for the web page that is used to render accelerated contents. On every swap buffers operation in the web process, the nested compositor in the UI process is automatically notified through the Wayland surface protocol, and  new contents are rendered in the web view. The main difference compared to the X11 model, is that Wayland uses EGL in both the web and UI processes, so what we have in the UI process in the end is not a bitmap but a GL texture that can be used to render the contents to the screen using the GPU directly. We use gdk_cairo_draw_from_gl() when available to do that, falling back to using glReadPixels() and a cairo image surface for older versions of GTK+. This can make a huge difference, especially on embedded devices, so we are considering to use the nested Wayland compositor even on X11 in the future if possible.

Clipboard

The WebKitGTK+ clipboard implementation relies on GTK+, and there’s nothing X11 specific in there, however clipboard was read/written directly by the web processes. That doesn’t work in Wayland, even though we use GtkClipboard, because Wayland only allows clipboard operations between compositor clients, and web processes are not Wayland clients. This required to move the clipboard handling from the web process to the UI process. Clipboard handling is now centralized in the UI process and clipboard contents to be read/written are sent to the different WebKit processes using the internal IPC.

Memory pressure handler

The WebKit memory pressure handler is a monitor that watches the system memory (not only the memory used by the web engine processes) and tries to release memory under low memory conditions. This is quite important feature in embedded devices with memory limitations. This has been supported in WebKitGTK+ for some time, but the implementation is based on cgroups and systemd, that is not available in all systems, and requires user configuration. So, in practice nobody was actually using the memory pressure handler. Watching system memory in Linux is a challenge, mainly because /proc/meminfo is not pollable, so you need manual polling. In WebKit, there’s a memory pressure handler on every secondary process (Web, Plugin and Network), so waking up every second to read /proc/meminfo from every web process would not be acceptable. This is not a problem when using cgroups, because the kernel interface provides a way to poll an EventFD to be notified when memory usage is critical.

WebKitGTK+ 2.14 has a new memory monitor, used only when cgroups/systemd is not available or configured, based on polling /proc/meminfo to ensure the memory pressure handler is always available. The monitor lives in the UI process, to ensure there’s only one process doing the polling, and uses a dynamic poll interval based on the last system memory usage to read and parse /proc/meminfo in a secondary thread. Once memory usage is critical all the secondary processes are notified using an EventFD. Using EventFD for this monitor too, not only is more efficient than using a pipe or sending an IPC message, but also allows us to keep almost the same implementation in the secondary processes that either monitor the cgroups EventFD or the UI process one.

Other improvements and bug fixes

Like in all other major releases there are a lot of other improvements, features and bug fixes. The most relevant ones in WebKitGTK+ 2.14 are:

  • The HTTP disk cache implements speculative revalidation of resources.
  • The media backend now supports video orientation.
  • Several bugs have been fixed in the media backend to prevent deadlocks when playing HLS videos.
  • The amount of file descriptors that are kept open has been drastically reduced.
  • Fix the poor performance with the modesetting intel driver and DRI3 enabled.

libinput and the Lenovo T460 series trackstick

First a definition: a trackstick is also called trackpoint, pointing stick, or "that red knob between G, H, and B". I'll be using trackstick here, because why not.

This post is the continuation of libinput and the Lenovo T450 and T460 series touchpads where we focused on a stalling pointer when moving the finger really slowly. Turns out the T460s at least, possibly others in the *60 series have another bug that caused a behaviour that is much worse but we didn't notice for ages as we were focusing on the high-precision cursor movement. Specifically, the pointer would just randomly stop moving for a short while (spoiler alert: 300ms), regardless of the movement speed.

libinput has built-in palm detection and one of the things it does is to disable the touchpad when the trackstick is in use. It's not uncommon to rest the hand near or on the touchpad while using the trackstick and any detected touch would cause interference with the pointer motion. So events from the touchpad are ignored whenever the trackpoint sends events. [1]

On (some of) the T460s the trackpoint sends spurious events. In the recording I have we have random events at 9s, then again 3.5s later, then 14s later, then 2s later, etc. Each time, our palm detection could would assume the trackpoint was in use and disable the touchpad for 300ms. If you were using the touchpad while this was happening, the touchpad would suddenly stop moving for 300ms and then continue as normal. Depending on how often these spurious events come in and the user's current caffeination state, this was somewhere between odd, annoying and infuriating.

The good news is: this is fixed in libinput now. libinput 1.5 and the upcoming 1.4.3 releases will have a fix that ignores these spurious events and makes the touchpad stalls a footnote of history. Hooray.

[1] we still allow touchpad physical button presses, and trackpoint button clicks won't disable the touchpad

Need for PC - Part 2 - The build

As promised, back with the PowerMac G5 ATX mod final build pictures, as the PC is already complete and working. Actually, I have built the GNOME 3.22.0 release tarballs for several modules using this (and have tested building other stuff and also a bit of gaming, to see the temperatures, they are OK). Measured power consumption is almost all the time (even with all cores at 100%) below the one of my old PC idling (this one idles at ~35W and 65-70W under load or in-game).

With every component mounted
Intake fans in front
Rear exhaust fans
CPU cover mounted
Plastic cover in-place, before mounting the sidepanel

In a future post, I'll summarize the software setup, including GNOME Shell extensions I can't live without, of course, with some screenshots.

mrxvt looking for maintainers

Hi all!

mrxvt is a cool light-weight terminal emulator, not tied to a specific desktop environment and with minimal dependency. This was also one of my very first bigger contributions to Free Software. Well I had patches here and there before, but that’s one project where I stuck around longer and where I was quickly given commit rights. So it is dear to my heart. It was also my first big feature attempt since I started a branch to add UTF-8 support (actually any-encoding support), which is the normal way of things now but at the time, many software and distributions were still not working with UTF-8 as a default. Then I left for years-long wandering our planet on a motorcycle (as people who know me are aware) and because of this, drastically slowed down FLOSS contributions until a few years ago. Back as a contributor, mrxvt is not my main project anymore (you know which these are: GIMP and ZeMarmot!). I moved on.

Now I have to admit the awful truth: I don’t use mrxvt much anymore. My main reason is actually because I need dearly UTF-8 and even though I’d love to finish whatever I started on this topic years ago, I don’t have the opportunity to do this anymore. Whatever terminal I use now* is good for me.

Yet mrxvt is still used, and we have regularly people asking about its development. So this is just a small call, if not too late:

if anyone is interested into taking over mrxvt, you are welcome to do so!

I have recently moved the code from subversion (on Sourceforge) to git on gitlab. So consider this new repository as the new official upstream of mrxvt. But be it know that my goal here is not to take back active development. I just can’t make the time to it. I can only assure that I would maintain it with GI (historical maintainer who also has commit right on the new repo as well) and would review and merge any patch which makes sense. If any developer who previously had commit rights on our subversion repository asks me for, I can give you commit rights there too.

Last but not least: if anyone wants to take over, we will gladly give ownership. But please send a few patches first. We had a few people who wanted to become the upstream without even showing a piece of code. Well we want to give the baby, but making sure first we give it to someone who cares. So just make a few patches that we can review, and we’ll happily give over mrxvt.


* Full disclosure: my current terminal of choice is Guake. Well it has unfortunately its share of bugs, but I really love the “making it appear and disappear in a click”. Considering that the terminal emulator is undoubtly the software I use the most daily, making it a special one, with its own windowing (not lost in alt-tab hell) is a very good trick to me.

We’re going to partay, karamu, fiesta, forever

GNOME release 3.22 happens to be during one of the core days of the Libre Application Summit Hosted by GNOME (LAS GNOME) On top of a high rise, in Portland Oregon, we’re going to celebrate GNOME 3.22 in grand style with the conference participants and end the core days at LAS GNOME!

September 19, 2016

GUPnP reaching 1.0

After 10 years or so, GSSDP 1.0 and GUPnP 1.0 were released today!

Looking forward GNOME 3.22

The old GNOME mantra:

The best GNOME release is the next GNOME release.

is still true! Between backend reworks, Summer of Code projects and spontaneous contributions from awsome random contributors, here are the things that I’m looking forward with GNOME 3.22 release.

Nautilus

Let’s face it: Nautilus is heading towards a bright future and it’s getting in a very good shape – and the community that is growing around it is absolutely gorgeous. Obviously, this is not random; Carlos Soriano is working very hard to make it happen.

This leads not only to fun IRC chats, but tons of contributions. Nautilus’ codebase had its style unified, making it very nice for newcomers to send their patches. After a huge work on Nautilus’ internals, things are in a better shape now and new features are popping up. If you want a more complete list of Nautilus improvements, check Carlos’ blog post about it. Below, the ones that caught my attention.

Batch rename

I didn’t notice how a batch rename tool could simplify one’s life. I personally wasn’t confident this would be useful, but now I can’t live without it! Thanks to Alex Pandelea, we can do things like this now:

captura-de-tela-de-2016-09-19-12-12-12The new batch rename dialog

Integrated compressed files

Another detail that required lots of improvements on how Nautilus works is the integration of compressed files. This is the kind of thing that gives Nautilus a kudo for the attention to details. Having progress report in the Nautilus progress popover and a built-in way to create compressed files makes me feel like Nautilus cares about me🙂 Thanks Razvan!

compress window.pngDialog to compress a set of files (picture made by Carlos)
compression.pngProgress of the compression in the popover (picture made by Carlos)

 

GNOME Calendar

This cycle I focused my efforts at GNOME Calendar. I already wrote about it multiple times, but in short, Calendar received:

 

GNOME Music

In one phrase: I can use Music now. My music collection is considerable (over 9000 individual songs) and GNOME Music simply couldn’t handle it.

Let me be crystal clear: Tracker is fast as hell. GNOME Music was slow to death. Retrieving the list of songs from Tracker takes about 0.25 second, putting the songs into a window and presenting it used to take ~85 seconds. Yes, that’s right, 340x slower.

Fortunately, this is fixed and will be distributed with GNOME Music 3.22🙂

 

GNOME Games

This new app is surprising me. A lot. I was trying to play Spyro 3 – Year of the dragon for months, without success. Then I tried GNOME Games – without success too. But at least, I could report my issues to Adrien, and what a supportive guy he is! With his help, we were able to debug my failures and, surprise!, he fixed it right after.

captura-de-tela-de-2016-09-19-13-06-18Not only it automagically discovers my games, it also searches for nice covers (thanks to Bastien Nocera’s Grilo work)

And now, after a journey through different PS1 emulators, I can play Spyro again. I could only get it working using Games from Flatpak’s nightly builds – but hey, it works, that’s what matters.

captura-de-tela-de-2016-09-19-13-06-29Good old time, huh?

Yay! That’s very promosing! (Although I wonder how much  it will impact my productivity :P)

Gtk+

Thanks to the amazing team that leads the development of Gtk+, it keeps receiving a flow of new features, improvements and fixes so fast that it’s hard to track. This round, I was able to add a small feature, the CSS background-blend-mode property support. It definitely isn’t a big thing, but I learned a lot throughout the whole process and I plan to work on more CSS3 features like filters, blend groups and others (and finally give Lapo all the tools he wants to create his crazy themes).

But wait! The greatest thing that Gtk+ will receive in 3.24 (or rather, 4.0 if I understood the new release scheme correctly) is the Gtk+ Scene Graph (aka GSK), thanks to Emmanuele. I’m looking forward using it in a future release!

Not everything is perfect…

Some things didn’t make for this release. I’m particularly sad about GNOME Control Center, which received a new UI but won’t switch to it because not all panels got ready in time. Also, Nautilus’ actionbar wasn’t good enough too – we weren’t satisfied with the end result, and decided it needs more research and love.

Basically, everything I touched outside GNOME Calendar. Sorry, folks!

… but we’ll get there!

So now it’s time to start planning the next cycle – this time, I want to try something new and decide some features based only on community input. I’ll run pools and decide the priorities with that, ask around and really try to get the community involved in the whole process. Stay tuned!

I’d like to thank my employer Endless for allowing me to work on GNOME – it’s awsome that I can do what I love to do as part of my job. Thanks, Endless!

banner down

Epiphany 3.22 (and a couple new stable releases too!)

It’s that time of year again! A new major release of Epiphany is out now, representing another six months of incremental progress. That’s a fancy way of saying that not too much has changed (so how did this blog post get so long?). It’s not for lack of development effort, though. There’s actually lot of action in git master and on sidebranches right now, most of it thanks to my awesome Google Summer of Code students, Gabriel Ivascu and Iulian Radu. However, I decided that most of the exciting changes we’re working on would be deferred to Epiphany 3.24, to give them more time to mature and to ensure quality. And since this is a blog post about Epiphany 3.22, that means you’ll have to wait until next time if you want details about the return of the traditional address bar, the brand-new user interface for bookmarks, the new support for syncing data between Epiphany browsers on different computers with Firefox Sync, or Prism source code view, all features that are brewing for 3.24. This blog also does not cover the cool new stuff in WebKitGTK+ 2.14, like new support for copy/paste and accelerated compositing in Wayland.

New stuff

So, what’s new in 3.22?

  • A new Paste and Go context menu option in the address bar, implemented by Iulian. It’s so simple, but it’s also the greatest thing ever. Why did nobody implement this earlier?
  • A new Duplicate Tab context menu option on tabs, implemented by Gabriel. It’s not something I use myself, but it seems some folks who use it in other browsers were disappointed it was missing in Epiphany.
  • A new keyboard shortcuts dialog is available in the app menu, implemented by Gabriel.

Gabriel also redesigned all the error pages. My favorite one is the new TLS error page, based on a mockup from Jakub Steiner:

Web app improvements

Pivoting to web apps, Daniel Aleksandersen turned his attention to the algorithm we use to pick a desktop icon for newly-created web apps. It was, to say the least, subpar; in Epiphany 3.20, it normally always fell back to using the website’s 16×16 favicon, which doesn’t look so great in a desktop environment where all app icons are expected to be at least 256×256. Epiphany 3.22 will try to pick better icons when websites make it possible. Read more on Daniel’s blog, which goes into detail on how to pick good web app icons.

Also new is support for system-installed web apps. Previously, Epiphany could only handle web apps installed in home directories, which meant it was impossible to package a web app in an RPM or Debian package. That limitation has now been removed. (Update: I had forgotten that limitation was actually removed for GNOME 3.20, but the web apps only worked when running in GNOME and not in other desktops, so it wasn’t really usable. That’s fixed now in 3.22.) This was needed to support packaging Fedora Developer Portal, but of course it can be used to package up any website. It’s probably only interesting to distributions that ship Epiphany by default, though. (Epiphany is installed by default in Fedora Workstation as it’s needed by GNOME Software to run web apps, it’s just hidden from the shell overview unless you “install” it.) At least one media outlet has amusingly reported this as Epiphany attempting to compete generally with Electron, something I did write in a commit message, but which is only true in the specific case where you need to just show a website with absolutely no changes in the GNOME desktop. So if you were expecting to see Visual Studio running in Epiphany: haha, no.

Shortcut woes

On another note, I’m pleased to announce that we managed to accidentally stomp on both shortcuts for opening the GTK+ inspector this cycle, by mapping Duplicate Tab to Ctrl+Shift+D, and by adding a new Ctrl+Shift+I shortcut to open the WebKit web inspector (in addition to F12). Go team! We caught the problem with Ctrl+Shift+D and removed the shortcut in time for the release, so at least you can still use that to open the GTK+ inspector, but I didn’t notice the issue with the web inspector until it was too late, and Ctrl+Shift+I will no longer work as expected in GTK+ apps. Suggestions welcome for whether we should leave the clashing Ctrl+Shift+I shortcut or get rid of it. I am leaning towards removing it, because we normally match Epiphany behavior with GTK+, and only match other browsers when it doesn’t conflict with GTK+. That’s called desktop integration, and it’s worked well for us so far. But a case can be made for matching other browsers, too.

Stable releases

On top of Epiphany 3.22, I’ve also rolled new stable releases 3.20.4 and 3.18.8. I don’t normally blog about stable releases since they only include bugfixes and are usually boring, so why are these worth mentioning here? Two reasons. First, one of the fixes in these releases is quite significant: I discovered that a few important features were broken when multiple tabs share the same web process behind the scenes (a somewhat unusual condition): the load anyway button on the unacceptable TLS certificate error page, password storage with GNOME keyring, removing pages from the new tab overview, and deleting web applications. It was one subtle bug that was to blame for breaking all of those features in this odd corner case, which finally explains some difficult-to-reproduce complaints we’d been getting, so it’s good to put out that bug of the way. Of course, that’s also fixed in Epiphany 3.22, but new stable releases ensure users don’t need a full distribution upgrade to pick up a simple bugfix.

Additionally, the new stable releases are compatible with WebKitGTK+ 2.14 (to be released later this week). The Epiphany 3.20.4 and 3.18.8 releases will intentionally no longer build with older versions of WebKitGTK+, as new WebKitGTK+ releases are important and all distributions must upgrade. But wait, if WebKitGTK+ is kept API and ABI stable in order to encourage distributions to release updates, then why is the new release incompatible with older versions of Epiphany? Well, in addition to stable API, there’s also an unstable DOM API that changes willy-nilly without any soname bumps; we don’t normally notice when it changes, since it’s autogenerated from web IDL files. Sounds terrible, right? In practice, no application has (to my knowledge) ever been affected by an unstable DOM API break before now, but that has changed with WebKitGTK+ 2.14, and an Epiphany update is required. Most applications don’t have to worry about this, though; the unstable API is totally undocumented and not available unless you #define a macro to make it visible, so applications that use it know to expect breakage. But unannounced ABI changes without soname bumps are obviously a big a problem for distributions, which is why we’re fixing this problem once and for all in WebKitGTK+ 2.16. Look out for a future blog post about that, probably from Carlos Garcia.

elementary OS

Lastly, I’m pleased to note that elementary OS Loki is out now. elementary is kinda (totally) competing with us GNOME folks, but it’s cool too, and the default browser has changed from Midori to Epiphany in this release due to unfixed security problems with Midori. They’ve shipped Epiphany 3.18.5, so if there are any elementary fans in the audience, it’s worth asking them to upgrade to 3.18.8. elementary does have some downstream patches to improve desktop integration with their OS — notably, they’ve jumped ahead of us in bringing back the traditional address bar — but desktop integration is kinda the whole point of Epiphany, so I can’t complain. Check it out! (But be sure to complain if they are not releasing WebKit security updates when advised to do so.)

Manchester GNOME 3.22 Release Party – Friday 23rd Sept. @ MADLab

We are hosting a party for the new GNOME release this Friday (23rd September).

The venue is MADLab in Manchester city centre (here’s a map). We will be there between 18:00 and 21:00. There will be some free refreshments, an overview of the new features in 3.22, advice on how install a free desktop OS on your computer and how contribute to GNOME or a related Free Software project.

Everyone is welcome, including users of rival desktop environments & operating systems🙂

release-party-invite


Understanding evdev

This post explains how the evdev protocol works. After reading this post you should understand what evdev is and how to interpret evdev event dumps to understand what your device is doing. The post is aimed mainly at users having to debug a device, I will thus leave out or simplify some of the technical details. I'll be using the output from evemu-record as example because that is the primary debugging tool for evdev.

What is evdev?

evdev is a Linux-only generic protocol that the kernel uses to forward information and events about input devices to userspace. It's not just for mice and keyboards but any device that has any sort of axis, key or button, including things like webcams and remote controls. Each device is represented as a device node in the form of /dev/input/event0, with the trailing number increasing as you add more devices. The node numbers are re-used after you unplug a device, so don't hardcode the device node into a script. The device nodes are also only readable by root, thus you need to run any debugging tools as root too.

evdev is the primary way to talk to input devices on Linux. All X.Org drivers on Linux use evdev as protocol and libinput as well. Note that "evdev" is also the shortcut used for xf86-input-evdev, the X.Org driver to handle generic evdev devices, so watch out for context when you read "evdev" on a mailing list.

Communicating with evdev devices

Communicating with a device is simple: open the device node and read from it. Any data coming out is a struct input_event, defined in /usr/include/linux/input.h:


struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
I'll describe the contents later, but you can see that it's a very simple struct.

Static information about the device such as its name and capabilities can be queried with a set of ioctls. Note that you should always use libevdevto interact with a device, it blunts the few sharp edges evdev has. See the libevdev documentation for usage examples.

evemu-record, our primary debugging tool for anything evdev is very simple. It reads the static information about the device, prints it and then simply reads and prints all events as they come in. The output is in machine-readable format but it's annotated with human-readable comments (starting with #). You can always ignore the non-comment bits. There's a second command, evemu-describe, that only prints the description and exits without waiting for events.

Relative devices and keyboards

The top part of an evemu-record output is the device description. This is a list of static properties that tells us what the device is capable of. For example, the USB mouse I have plugged in here prints:


# Input device name: "PIXART USB OPTICAL MOUSE"
# Input device ID: bus 0x03 vendor 0x93a product 0x2510 version 0x110
# Supported events:
# Event type 0 (EV_SYN)
# Event code 0 (SYN_REPORT)
# Event code 1 (SYN_CONFIG)
# Event code 2 (SYN_MT_REPORT)
# Event code 3 (SYN_DROPPED)
# Event code 4 ((null))
# Event code 5 ((null))
# Event code 6 ((null))
# Event code 7 ((null))
# Event code 8 ((null))
# Event code 9 ((null))
# Event code 10 ((null))
# Event code 11 ((null))
# Event code 12 ((null))
# Event code 13 ((null))
# Event code 14 ((null))
# Event type 1 (EV_KEY)
# Event code 272 (BTN_LEFT)
# Event code 273 (BTN_RIGHT)
# Event code 274 (BTN_MIDDLE)
# Event type 2 (EV_REL)
# Event code 0 (REL_X)
# Event code 1 (REL_Y)
# Event code 8 (REL_WHEEL)
# Event type 4 (EV_MSC)
# Event code 4 (MSC_SCAN)
# Properties:
The device name is the one (usually) set by the manufacturer and so are the vendor and product IDs. The bus is one of the "BUS_USB" and similar constants defined in /usr/include/linux/input.h. The version is often quite arbitrary, only a few devices have something meaningful here.

We also have a set of supported events, categorised by "event type" and "event code" (note how type and code are also part of the struct input_event). The type is a general category, and /usr/include/linux/input-event-codes.h defines quite a few of those. The most important types are EV_KEY (keys and buttons), EV_REL (relative axes) and EV_ABS (absolute axes). In the output above we can see that we have EV_KEY and EV_REL set.

As a subitem of each type we have the event code. The event codes for this device are self-explanatory: BTN_LEFT, BTN_RIGHT and BTN_MIDDLE are the left, right and middle button. The axes are a relative x axis, a relative y axis and a wheel axis (i.e. a mouse wheel). EV_MSC/MSC_SCAN is used for raw scancodes and you can usually ignore it. And finally we have the EV_SYN bits but let's ignore those, they are always set for all devices.

Note that an event code cannot be on its own, it must be a tuple of (type, code). For example, REL_X and ABS_X have the same numerical value and without the type you won't know which one is which.

That's pretty much it. A keyboard will have a lot of EV_KEY bits set and the EV_REL axes are obviously missing (but not always...). Instead of BTN_LEFT, a keyboard would have e.g. KEY_ESC, KEY_A, KEY_B, etc. 90% of device debugging is looking at the event codes and figuring out which ones are missing or shouldn't be there.

Exercise: You should now be able to read a evemu-record description from any mouse or keyboard device connected to your computer and understand what it means. This also applies to most special devices such as remotes - the only thing that changes are the names for the keys/buttons. Just run sudo evemu-describe and pick any device in the list.

The events from relative devices and keyboards

evdev is a serialised protocol. It sends a series of events and then a synchronisation event to notify us that the preceeding events all belong together. This synchronisation event is EV_SYN SYN_REPORT, is generated by the kernel, not the device and hence all EV_SYN codes are always available on all devices.

Let's have a look at a mouse movement. As explained above, half the line is machine-readable but we can ignore that bit and look at the human-readable output on the right.


E: 0.335996 0002 0000 0001 # EV_REL / REL_X 1
E: 0.335996 0002 0001 -002 # EV_REL / REL_Y -2
E: 0.335996 0000 0000 0000 # ------------ SYN_REPORT (0) ----------
This means that within one hardware event, we've moved 1 device unit to the right (x axis) and two device units up (y axis). Note how all events have the same timestamp (0.335996).

Let's have a look at a button press:


E: 0.656004 0004 0004 589825 # EV_MSC / MSC_SCAN 589825
E: 0.656004 0001 0110 0001 # EV_KEY / BTN_LEFT 1
E: 0.656004 0000 0000 0000 # ------------ SYN_REPORT (0) ----------
E: 0.727002 0004 0004 589825 # EV_MSC / MSC_SCAN 589825
E: 0.727002 0001 0110 0000 # EV_KEY / BTN_LEFT 0
E: 0.727002 0000 0000 0000 # ------------ SYN_REPORT (0) ----------
For button events, the value 1 signals button pressed, button 0 signals button released.

And key events look like this:


E: 0.000000 0004 0004 458792 # EV_MSC / MSC_SCAN 458792
E: 0.000000 0001 001c 0000 # EV_KEY / KEY_ENTER 0
E: 0.000000 0000 0000 0000 # ------------ SYN_REPORT (0) ----------
E: 0.560004 0004 0004 458976 # EV_MSC / MSC_SCAN 458976
E: 0.560004 0001 001d 0001 # EV_KEY / KEY_LEFTCTRL 1
E: 0.560004 0000 0000 0000 # ------------ SYN_REPORT (0) ----------
[....]
E: 1.172732 0001 001d 0002 # EV_KEY / KEY_LEFTCTRL 2
E: 1.172732 0000 0000 0001 # ------------ SYN_REPORT (1) ----------
E: 1.200004 0004 0004 458758 # EV_MSC / MSC_SCAN 458758
E: 1.200004 0001 002e 0001 # EV_KEY / KEY_C 1
E: 1.200004 0000 0000 0000 # ------------ SYN_REPORT (0) ----------
Mostly the same as button events. But wait, there is one difference: we have a value of 2 as well. For key events, a value 2 means "key repeat". If you're on the tty, then this is what generates repeat keys for you. In X and Wayland we ignore these repeat events and instead use XKB-based key repeat.

Now look at the keyboard events again and see if you can make sense of the sequence. We have an Enter release (but no press), then ctrl down (and repeat), followed by a 'c' press - but no release. The explanation is simple - as soon as I hit enter in the terminal, evemu-record started recording so it captured the enter release too. And it stopped recording as soon as ctrl+c was down because that's when it was cancelled by the terminal. One important takeaway here: the evdev protocol is not guaranteed to be balanced. You may see a release for a key you've never seen the press for, and you may be missing a release for a key/button you've seen the press for (this happens when you stop recording). Oh, and there's one danger: if you record your keyboard and you type your password, the keys will show up in the output. Security experts generally reocmmend not publishing event logs with your password in it.

Exercise: You should now be able to read a evemu-record events list from any mouse or keyboard device connected to your computer and understand the event sequence.This also applies to most special devices such as remotes - the only thing that changes are the names for the keys/buttons. Just run sudo evemu-record and pick any device listed.

Absolute devices

Things get a bit more complicated when we look at absolute input devices like a touchscreen or a touchpad. Yes, touchpads are absolute devices in hardware and the conversion to relative events is done in userspace by e.g. libinput. The output of my touchpad is below. Note that I've manually removed a few bits to make it easier to grasp, they will appear later in the multitouch discussion.


# Input device name: "SynPS/2 Synaptics TouchPad"
# Input device ID: bus 0x11 vendor 0x02 product 0x07 version 0x1b1
# Supported events:
# Event type 0 (EV_SYN)
# Event code 0 (SYN_REPORT)
# Event code 1 (SYN_CONFIG)
# Event code 2 (SYN_MT_REPORT)
# Event code 3 (SYN_DROPPED)
# Event code 4 ((null))
# Event code 5 ((null))
# Event code 6 ((null))
# Event code 7 ((null))
# Event code 8 ((null))
# Event code 9 ((null))
# Event code 10 ((null))
# Event code 11 ((null))
# Event code 12 ((null))
# Event code 13 ((null))
# Event code 14 ((null))
# Event type 1 (EV_KEY)
# Event code 272 (BTN_LEFT)
# Event code 325 (BTN_TOOL_FINGER)
# Event code 328 (BTN_TOOL_QUINTTAP)
# Event code 330 (BTN_TOUCH)
# Event code 333 (BTN_TOOL_DOUBLETAP)
# Event code 334 (BTN_TOOL_TRIPLETAP)
# Event code 335 (BTN_TOOL_QUADTAP)
# Event type 3 (EV_ABS)
# Event code 0 (ABS_X)
# Value 2919
# Min 1024
# Max 5112
# Fuzz 0
# Flat 0
# Resolution 42
# Event code 1 (ABS_Y)
# Value 3711
# Min 2024
# Max 4832
# Fuzz 0
# Flat 0
# Resolution 42
# Event code 24 (ABS_PRESSURE)
# Value 0
# Min 0
# Max 255
# Fuzz 0
# Flat 0
# Resolution 0
# Event code 28 (ABS_TOOL_WIDTH)
# Value 0
# Min 0
# Max 15
# Fuzz 0
# Flat 0
# Resolution 0
# Properties:
# Property type 0 (INPUT_PROP_POINTER)
# Property type 2 (INPUT_PROP_BUTTONPAD)
# Property type 4 (INPUT_PROP_TOPBUTTONPAD)
We have a BTN_LEFT again and a set of other buttons that I'll explain in a second. But first we look at the EV_ABS output. We have the same naming system as above. ABS_X and ABS_Y are the x and y axis on the device, ABS_PRESSURE is an (arbitrary) ranged pressure value.

Absolute axes have a bit more state than just a simple bit. Specifically, they have a minimum and maximum (not all hardware has the top-left sensor position on 0/0, it can be an arbitrary position, specified by the minimum). Notable here is that the axis ranges are simply the ones announced by the device - there is no guarantee that the values fall within this range and indeed a lot of touchpad devices tend to send values slightly outside that range. Fuzz and flat can be safely ignored, but resolution is interesting. It is given in units per millimeter and thus tells us the size of the device. in the above case: (5112 - 1024)/42 means the device is 97mm wide. The resolution is quite commonly wrong, a lot of axis overrides need the resolution changed to the correct value.

The axis description also has a current value listed. The kernel only sends events when the value changes, so even if the actual hardware keeps sending events, you may never see them in the output if the value remains the same. In other words, holding a finger perfectly still on a touchpad creates plenty of hardware events, but you won't see anything coming out of the event node.

Finally, we have properties on this device. These are used to indicate general information about the device that's not otherwise obvious. In this case INPUT_PROP_POINTER tells us that we need a pointer for this device (it is a touchpad after all, a touchscreen would instead have INPUT_PROP_DIRECT set). INPUT_PROP_BUTTONPAD means that this is a so-called clickpad, it does not have separate physical buttons but instead the whole touchpad clicks. Ignore INPUT_PROP_TOPBUTTONPAD because it only applies to the Lenovo *40 series of devices.

Ok, back to the buttons: aside from BTN_LEFT, we have BTN_TOUCH. This one signals that the user is touching the surface of the touchpad (with some in-kernel defined minimum pressure value). It's not just for finger-touches, it's also used for graphics tablet stylus touchpes (so really, it's more "contact" than "touch" but meh).

The BTN_TOOL_FINGER event tells us that a finger is in detectable range. This gives us two bits of information: first, we have a finger (a tablet would have e.g. BTN_TOOL_PEN) and second, we may have a finger in proximity without touching. On many touchpads, BTN_TOOL_FINGER and BTN_TOUCH come in the same event, but others can detect a finger hovering over the touchpad too (in which case you'd also hope for ABS_DISTANCE being available on the touchpad).

Finally, the BTN_TOOL_DOUBLETAP up to BTN_TOOL_QUINTTAP tell us whether the device can detect 2 through to 5 fingers on the touchpad. This doesn't actually track the fingers, it merely tells you "3 fingers down" in the case of BTN_TOOL_TRIPLETAP.

Exercise: Look at your touchpad's description and figure out if the size of the touchpad is correct based on the axis information [1]. Check how many fingers your touchpad can detect and whether it can do pressure or distance detection.

The events from absolute devices

Events from absolute axes are not really any different than events from relative devices which we already covered. The same type/code combination with a value and a timestamp, all framed by EV_SYN SYN_REPORT events. Here's an example of me touching the touchpad:


E: 0.000001 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 0.000001 0003 0000 3335 # EV_ABS / ABS_X 3335
E: 0.000001 0003 0001 3308 # EV_ABS / ABS_Y 3308
E: 0.000001 0003 0018 0069 # EV_ABS / ABS_PRESSURE 69
E: 0.000001 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 0.000001 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +0ms
E: 0.021751 0003 0018 0070 # EV_ABS / ABS_PRESSURE 70
E: 0.021751 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +21ms
E: 0.043908 0003 0000 3334 # EV_ABS / ABS_X 3334
E: 0.043908 0003 0001 3309 # EV_ABS / ABS_Y 3309
E: 0.043908 0003 0018 0065 # EV_ABS / ABS_PRESSURE 65
E: 0.043908 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +22ms
E: 0.052469 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 0.052469 0003 0018 0000 # EV_ABS / ABS_PRESSURE 0
E: 0.052469 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 0.052469 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +9ms
In the first event you see BTN_TOOL_FINGER and BTN_TOUCH set (this touchpad doesn't detect hovering fingers). An x/y coordinate pair and a pressure value. The pressure changes in the second event, the third event changes pressure and location. Finally, we have BTN_TOOL_FINGER and BTN_TOUCH released on finger up, and the pressure value goes back to 0. Notice how the second event didn't contain any x/y coordinates? As I said above, the kernel only sends updates on absolute axes when the value changed.

Ok, let's look at a three-finger tap (again, minus the ABS_MT_ bits):


E: 0.000001 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 0.000001 0003 0000 2149 # EV_ABS / ABS_X 2149
E: 0.000001 0003 0001 3747 # EV_ABS / ABS_Y 3747
E: 0.000001 0003 0018 0066 # EV_ABS / ABS_PRESSURE 66
E: 0.000001 0001 014e 0001 # EV_KEY / BTN_TOOL_TRIPLETAP 1
E: 0.000001 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +0ms
E: 0.034209 0003 0000 2148 # EV_ABS / ABS_X 2148
E: 0.034209 0003 0018 0064 # EV_ABS / ABS_PRESSURE 64
E: 0.034209 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +34ms
[...]
E: 0.138510 0003 0000 4286 # EV_ABS / ABS_X 4286
E: 0.138510 0003 0001 3350 # EV_ABS / ABS_Y 3350
E: 0.138510 0003 0018 0055 # EV_ABS / ABS_PRESSURE 55
E: 0.138510 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 0.138510 0001 014e 0000 # EV_KEY / BTN_TOOL_TRIPLETAP 0
E: 0.138510 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +23ms
E: 0.147834 0003 0000 4287 # EV_ABS / ABS_X 4287
E: 0.147834 0003 0001 3351 # EV_ABS / ABS_Y 3351
E: 0.147834 0003 0018 0037 # EV_ABS / ABS_PRESSURE 37
E: 0.147834 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +9ms
E: 0.157151 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 0.157151 0003 0018 0000 # EV_ABS / ABS_PRESSURE 0
E: 0.157151 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 0.157151 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +10ms
In the first event, the touchpad detected all three fingers at the same time. So get BTN_TOUCH, x/y/pressure and BTN_TOOL_TRIPLETAP set. Note that the various BTN_TOOL_* bits are mutually exclusive. BTN_TOOL_FINGER means "exactly 1 finger down" and you can't have exactly 1 finger down when you have three fingers down. In the second event x and pressure update (y has no event, it stayed the same).

In the event after the break, we switch from three fingers to one finger. BTN_TOOL_TRIPLETAP is released, BTN_TOOL_FINGER is set. That's very common. Humans aren't robots, you can't release all fingers at exactly the same time, so depending on the hardware scanout rate you have intermediate states where one finger has left already, others are still down. In this case I released two fingers between scanouts, one was still down. It's not uncommon to see a full cycle from BTN_TOOL_FINGER to BTN_TOOL_DOUBLETAP to BTN_TOOL_TRIPLETAP on finger down or the reverse on finger up.

Exercise: test out the pressure values on your touchpad and see how close you can get to the actual announced range. Check how accurate the multifinger detection is by tapping with two, three, four and five fingers. (In both cases, you'll likely find that it's very much hit and miss).

Multitouch and slots

Now we're at the most complicated topic regarding evdev devices. In the case of multitouch devices, we need to send multiple touches on the same axes. So we need an additional dimension and that is called multitouch slots (there is another, older multitouch protocol that doesn't use slots but it is so rare now that you don't need to bother).

First: all axes that are multitouch-capable are repeated as ABS_MT_foo axis. So if you have ABS_X, you also get ABS_MT_POSITION_X and both axes have the same axis ranges and resolutions. The reason here is backwards-compatibility: if a device only sends multitouch events, older programs only listening to the ABS_X etc. events won't work. Some axes may only be available for single-touch (ABS_MT_TOOL_WIDTH in this case).

Let's have a look at my touchpad, this time without the axes removed:


# Input device name: "SynPS/2 Synaptics TouchPad"
# Input device ID: bus 0x11 vendor 0x02 product 0x07 version 0x1b1
# Supported events:
# Event type 0 (EV_SYN)
# Event code 0 (SYN_REPORT)
# Event code 1 (SYN_CONFIG)
# Event code 2 (SYN_MT_REPORT)
# Event code 3 (SYN_DROPPED)
# Event code 4 ((null))
# Event code 5 ((null))
# Event code 6 ((null))
# Event code 7 ((null))
# Event code 8 ((null))
# Event code 9 ((null))
# Event code 10 ((null))
# Event code 11 ((null))
# Event code 12 ((null))
# Event code 13 ((null))
# Event code 14 ((null))
# Event type 1 (EV_KEY)
# Event code 272 (BTN_LEFT)
# Event code 325 (BTN_TOOL_FINGER)
# Event code 328 (BTN_TOOL_QUINTTAP)
# Event code 330 (BTN_TOUCH)
# Event code 333 (BTN_TOOL_DOUBLETAP)
# Event code 334 (BTN_TOOL_TRIPLETAP)
# Event code 335 (BTN_TOOL_QUADTAP)
# Event type 3 (EV_ABS)
# Event code 0 (ABS_X)
# Value 5112
# Min 1024
# Max 5112
# Fuzz 0
# Flat 0
# Resolution 41
# Event code 1 (ABS_Y)
# Value 2930
# Min 2024
# Max 4832
# Fuzz 0
# Flat 0
# Resolution 37
# Event code 24 (ABS_PRESSURE)
# Value 0
# Min 0
# Max 255
# Fuzz 0
# Flat 0
# Resolution 0
# Event code 28 (ABS_TOOL_WIDTH)
# Value 0
# Min 0
# Max 15
# Fuzz 0
# Flat 0
# Resolution 0
# Event code 47 (ABS_MT_SLOT)
# Value 0
# Min 0
# Max 1
# Fuzz 0
# Flat 0
# Resolution 0
# Event code 53 (ABS_MT_POSITION_X)
# Value 0
# Min 1024
# Max 5112
# Fuzz 8
# Flat 0
# Resolution 41
# Event code 54 (ABS_MT_POSITION_Y)
# Value 0
# Min 2024
# Max 4832
# Fuzz 8
# Flat 0
# Resolution 37
# Event code 57 (ABS_MT_TRACKING_ID)
# Value 0
# Min 0
# Max 65535
# Fuzz 0
# Flat 0
# Resolution 0
# Event code 58 (ABS_MT_PRESSURE)
# Value 0
# Min 0
# Max 255
# Fuzz 0
# Flat 0
# Resolution 0
# Properties:
# Property type 0 (INPUT_PROP_POINTER)
# Property type 2 (INPUT_PROP_BUTTONPAD)
# Property type 4 (INPUT_PROP_TOPBUTTONPAD)
We have an x and y position for multitouch as well as a pressure axis. There are also two special multitouch axes that aren't really axes. ABS_MT_SLOT and ABS_MT_TRACKING_ID. The former specifies which slot is currently active, the latter is used to track touch points.

Slots are a static property of a device. My touchpad, as you can see above ony supports 2 slots (min 0, max 1) and thus can track 2 fingers at a time. Whenever the first finger is set down it's coordinates will be tracked in slot 0, the second finger will be tracked in slot 1. When the finger in slot 0 is lifted, the second finger continues to be tracked in slot 1, and if a new finger is set down, it will be tracked in slot 0. Sounds more complicated than it is, think of it as an array of possible touchpoints.

The tracking ID is an incrementing number that lets us tell touch points apart and also tells us when a touch starts and when it ends. The two values are either -1 or a positive number. Any positive number means "new touch" and -1 means "touch ended". So when you put two fingers down and lift them again, you'll get a tracking ID of 1 in slot 0, a tracking ID of 2 in slot 1, then a tracking ID of -1 in both slots to signal they ended. The tracking ID value itself is meaningless, it simply increases as touches are created.

Let's look at a single tap:


E: 0.000001 0003 0039 0387 # EV_ABS / ABS_MT_TRACKING_ID 387
E: 0.000001 0003 0035 2560 # EV_ABS / ABS_MT_POSITION_X 2560
E: 0.000001 0003 0036 2905 # EV_ABS / ABS_MT_POSITION_Y 2905
E: 0.000001 0003 003a 0059 # EV_ABS / ABS_MT_PRESSURE 59
E: 0.000001 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 0.000001 0003 0000 2560 # EV_ABS / ABS_X 2560
E: 0.000001 0003 0001 2905 # EV_ABS / ABS_Y 2905
E: 0.000001 0003 0018 0059 # EV_ABS / ABS_PRESSURE 59
E: 0.000001 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 0.000001 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +0ms
E: 0.021690 0003 003a 0067 # EV_ABS / ABS_MT_PRESSURE 67
E: 0.021690 0003 0018 0067 # EV_ABS / ABS_PRESSURE 67
E: 0.021690 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +21ms
E: 0.033482 0003 003a 0068 # EV_ABS / ABS_MT_PRESSURE 68
E: 0.033482 0003 0018 0068 # EV_ABS / ABS_PRESSURE 68
E: 0.033482 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +12ms
E: 0.044268 0003 0035 2561 # EV_ABS / ABS_MT_POSITION_X 2561
E: 0.044268 0003 0000 2561 # EV_ABS / ABS_X 2561
E: 0.044268 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +11ms
E: 0.054093 0003 0035 2562 # EV_ABS / ABS_MT_POSITION_X 2562
E: 0.054093 0003 003a 0067 # EV_ABS / ABS_MT_PRESSURE 67
E: 0.054093 0003 0000 2562 # EV_ABS / ABS_X 2562
E: 0.054093 0003 0018 0067 # EV_ABS / ABS_PRESSURE 67
E: 0.054093 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +10ms
E: 0.064891 0003 0035 2569 # EV_ABS / ABS_MT_POSITION_X 2569
E: 0.064891 0003 0036 2903 # EV_ABS / ABS_MT_POSITION_Y 2903
E: 0.064891 0003 003a 0059 # EV_ABS / ABS_MT_PRESSURE 59
E: 0.064891 0003 0000 2569 # EV_ABS / ABS_X 2569
E: 0.064891 0003 0001 2903 # EV_ABS / ABS_Y 2903
E: 0.064891 0003 0018 0059 # EV_ABS / ABS_PRESSURE 59
E: 0.064891 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +10ms
E: 0.073634 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 0.073634 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 0.073634 0003 0018 0000 # EV_ABS / ABS_PRESSURE 0
E: 0.073634 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 0.073634 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +9ms
We have a tracking ID (387) signalling finger down, as well as a position plus pressure. then some updates and eventually a tracking ID of -1 (signalling finger up). Notice how there is no ABS_MT_SLOT here - the kernel buffers those too so while you stay in the same slot (0 in this case) you don't see any events for it. Also notice how you get both single-finger as well as multitouch in the same event stream. This is for backwards compatibility [2]

Ok, time for a two-finger tap:


E: 0.000001 0003 0039 0496 # EV_ABS / ABS_MT_TRACKING_ID 496
E: 0.000001 0003 0035 2609 # EV_ABS / ABS_MT_POSITION_X 2609
E: 0.000001 0003 0036 3791 # EV_ABS / ABS_MT_POSITION_Y 3791
E: 0.000001 0003 003a 0054 # EV_ABS / ABS_MT_PRESSURE 54
E: 0.000001 0003 002f 0001 # EV_ABS / ABS_MT_SLOT 1
E: 0.000001 0003 0039 0497 # EV_ABS / ABS_MT_TRACKING_ID 497
E: 0.000001 0003 0035 3012 # EV_ABS / ABS_MT_POSITION_X 3012
E: 0.000001 0003 0036 3088 # EV_ABS / ABS_MT_POSITION_Y 3088
E: 0.000001 0003 003a 0056 # EV_ABS / ABS_MT_PRESSURE 56
E: 0.000001 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 0.000001 0003 0000 2609 # EV_ABS / ABS_X 2609
E: 0.000001 0003 0001 3791 # EV_ABS / ABS_Y 3791
E: 0.000001 0003 0018 0054 # EV_ABS / ABS_PRESSURE 54
E: 0.000001 0001 014d 0001 # EV_KEY / BTN_TOOL_DOUBLETAP 1
E: 0.000001 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +0ms
E: 0.012909 0003 002f 0000 # EV_ABS / ABS_MT_SLOT 0
E: 0.012909 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 0.012909 0003 002f 0001 # EV_ABS / ABS_MT_SLOT 1
E: 0.012909 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 0.012909 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 0.012909 0003 0018 0000 # EV_ABS / ABS_PRESSURE 0
E: 0.012909 0001 014d 0000 # EV_KEY / BTN_TOOL_DOUBLETAP 0
E: 0.012909 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +12ms
This was a really quick two-finger tap that illustrates the tracking IDs nicely. In the first event we get a touch down, then an ABS_MT_SLOT event. This tells us that subsequent events belong to the other slot, so it's the other finger. There too we get a tracking ID + position. In the next event we get an ABS_MT_SLOT to switch back to slot 0. Tracking ID of -1 means that touch ended, and then we see the touch in slot 1 ended too.

Time for a two-finger scroll:


E: 0.000001 0003 0039 0557 # EV_ABS / ABS_MT_TRACKING_ID 557
E: 0.000001 0003 0035 2589 # EV_ABS / ABS_MT_POSITION_X 2589
E: 0.000001 0003 0036 3363 # EV_ABS / ABS_MT_POSITION_Y 3363
E: 0.000001 0003 003a 0048 # EV_ABS / ABS_MT_PRESSURE 48
E: 0.000001 0003 002f 0001 # EV_ABS / ABS_MT_SLOT 1
E: 0.000001 0003 0039 0558 # EV_ABS / ABS_MT_TRACKING_ID 558
E: 0.000001 0003 0035 3512 # EV_ABS / ABS_MT_POSITION_X 3512
E: 0.000001 0003 0036 3028 # EV_ABS / ABS_MT_POSITION_Y 3028
E: 0.000001 0003 003a 0044 # EV_ABS / ABS_MT_PRESSURE 44
E: 0.000001 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 0.000001 0003 0000 2589 # EV_ABS / ABS_X 2589
E: 0.000001 0003 0001 3363 # EV_ABS / ABS_Y 3363
E: 0.000001 0003 0018 0048 # EV_ABS / ABS_PRESSURE 48
E: 0.000001 0001 014d 0001 # EV_KEY / BTN_TOOL_DOUBLETAP 1
E: 0.000001 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +0ms
E: 0.027960 0003 002f 0000 # EV_ABS / ABS_MT_SLOT 0
E: 0.027960 0003 0035 2590 # EV_ABS / ABS_MT_POSITION_X 2590
E: 0.027960 0003 0036 3395 # EV_ABS / ABS_MT_POSITION_Y 3395
E: 0.027960 0003 003a 0046 # EV_ABS / ABS_MT_PRESSURE 46
E: 0.027960 0003 002f 0001 # EV_ABS / ABS_MT_SLOT 1
E: 0.027960 0003 0035 3511 # EV_ABS / ABS_MT_POSITION_X 3511
E: 0.027960 0003 0036 3052 # EV_ABS / ABS_MT_POSITION_Y 3052
E: 0.027960 0003 0000 2590 # EV_ABS / ABS_X 2590
E: 0.027960 0003 0001 3395 # EV_ABS / ABS_Y 3395
E: 0.027960 0003 0018 0046 # EV_ABS / ABS_PRESSURE 46
E: 0.027960 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +27ms
E: 0.051720 0003 002f 0000 # EV_ABS / ABS_MT_SLOT 0
E: 0.051720 0003 0035 2609 # EV_ABS / ABS_MT_POSITION_X 2609
E: 0.051720 0003 0036 3447 # EV_ABS / ABS_MT_POSITION_Y 3447
E: 0.051720 0003 002f 0001 # EV_ABS / ABS_MT_SLOT 1
E: 0.051720 0003 0036 3080 # EV_ABS / ABS_MT_POSITION_Y 3080
E: 0.051720 0003 0000 2609 # EV_ABS / ABS_X 2609
E: 0.051720 0003 0001 3447 # EV_ABS / ABS_Y 3447
E: 0.051720 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +24ms
[...]
E: 0.272034 0003 002f 0000 # EV_ABS / ABS_MT_SLOT 0
E: 0.272034 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 0.272034 0003 002f 0001 # EV_ABS / ABS_MT_SLOT 1
E: 0.272034 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 0.272034 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 0.272034 0003 0018 0000 # EV_ABS / ABS_PRESSURE 0
E: 0.272034 0001 014d 0000 # EV_KEY / BTN_TOOL_DOUBLETAP 0
E: 0.272034 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +30ms
Note that "scroll" is something handled in userspace, so what you see here is just a two-finger move. Everything in there i something we've already seen, but pay attention to the two middle events: as updates come in for each finger, the ABS_MT_SLOT changes before the upates are sent. The kernel filter for identical events is still in effect, so in the third event we don't get an update for the X position on slot 1. The filtering is per-touchpoint, so in this case this means that slot 1 position x is still on 3511, just as it was in the previous event.

That's all you have to remember, really. If you think of evdev as a serialised way of sending an array of touchpoints, with the slots as the indices then it should be fairly clear. The rest is then just about actually looking at the touch positions and making sense of them.

Exercise: do a pinch gesture on your touchpad. See if you can track the two fingers moving closer together. Then do the same but only move one finger. See how the non-moving finger gets less updates.

That's it. There are a few more details to evdev but much of that is just more event types and codes. The few details you really have to worry about when processing events are either documented in libevdev or abstracted away completely. The above should be enough to understand what your device does, and what goes wrong when your device isn't working. Good luck.

[1] If not, file a bug against systemd's hwdb and CC me so we can put corrections in
[2] We treat some MT-capable touchpads as single-touch devices in libinput because the MT data is garbage

September 18, 2016

Headed to LAS GNOME!

By the time this gets posted on the blog, I will be headed to LAS GNOME. I'm really looking forward to being there!

I'm on the schedule to talk about usability testing. Specifically, I'll discuss how you can do usability testing for your own open source software projects. Maybe you think usability testing is hard—it's not! Anyone can do usability testing! It only takes a little prep work and about five testers to get enough useful feedback that you can improve your interface.

As part of my presentation, I'll use our usability tests from this summer's GNOME usability tests as examples. Diana, Renata and Ciarrai did a great job on their usability testing.

These usability testing projects also demonstrate three different methods you can use to examine usability in software:

Ciarrai did a paper prototype test of the new GNOME Settings. A paper prototype is a useful test if you don't have the user interface nailed down yet. The paper prototype test allows you to examine how real people would respond to the interface while it's still mocked up on paper. If you have a demo version of the software, you can do a variation of this called an "animated prototype" that looks a lot like a traditional usability test.

Renata performed a traditional usability test of other areas of ongoing development in GNOME. This is the kind of test most people think of when they hear about usability testing. In a traditional usability test, you ask testers to perform various tasks ("scenario tasks") while you observe what they do and take notes of what they say or how they attempt to complete the tasks. This is a very powerful test that can provide great insights to how users approach your software.

Diana led a user experience (UX) test of users who used GNOME for the first time. User experience is technically different from usability. Where usability is about how easily real people can accomplish real tasks using the software, user experience focuses more on the emotional reaction these people have when using the software. Usability and user experience are often confused with each other, but they are separate concepts.

I hope to see you at the conference!
image: LAS GNOME

systemd.conf 2016 Workshop Tickets Available

Tickets for systemd 2016 Workshop day still available!

We still have a number of ticket for the workshop day of systemd.conf 2016 available. If you are a newcomer to systemd, and would like to learn about various systemd facilities, or if you already know your way around, but would like to know more: this is the best chance to do so. The workshop day is the 28th of September, one day before the main conference, at the betahaus in Berlin, Germany. The schedule for the day is available here. There are five interesting, extensive sessions, run by the systemd hackers themselves. Who better to learn systemd from, than the folks who wrote it?

Note that the workshop day and the main conference days require different tickets. (Also note: there are still a few tickets available for the main conference!).

Buy a ticket here.

See you in Berlin!

GNOME Games 3.22: the Giant Leap

I didn't blog about Games since quite some time and the app changed a lot since 3.18. 3.20 was quite a small update featurewise: it added support for MAME and Neo Geo Pocket games, added the About dialog, allowed l10n of the application, added a Preferences window listing the available plugins and fixed other small bugs, but this release mainly saw refactoring work with the introduction of the plugins system where plugins allow to list games: the Steam plugin lists Steam games and the SNES plugin lists SNES games.

So with 3.20, Games was ready to be improved upon and improvement there was! 3.22 is the first properly usable version of Games

The biggest change this cycle is the number of contributors to Games' codebase, first of all with two GSoC interns working on it: Megh Parikh and Ricard Gascons did a great job as I will detail it later. But Games didn't gain contributors only via GSoC: Bastien Nocera has been helping on the project since a year or so and got even more involved recently, and Mathieu Bridon implemented several new features and helped a lot working on Flatpak integration as well as on shipping the Libretro cores.

Supported Game Types

We disambiguated several games related MIME types in shared-mime-info:

  • SG-1000 and Game Gear games got disambiguated from the Master System ones;
  • Mega-CD, 32X and Sega Pico games got disambiguated from the Mega Drive ones;
  • Game Boy Color games got disambiguated from the Game Boy ones.

This disambiguation done, Games wouldn't be able to detect these games as it was only looking for Master System, Mega Drive and Game Boy games, hence we now suport them explicitly. Games also gained support for new systems, here are the newly supported systems in 3.22:

  • Atari 2600;
  • Atari 7800;
  • Game Boy Color;
  • Game Gear;
  • Mega-CD — a.k.a. Sega CD;
  • Mega-CD 32X — a.k.a. Sega CD 32X;
  • Mega Drive 32X — a.k.a. Genesis 32X, Super 32X and Mega 32X;
  • PC-Engine CD-ROM² and its variants — a.k.a. TurboGrafx-CD;
  • PlayStation;
  • Sega Pico — a.k.a. Kids Computer Pico;
  • SG-1000.

Keep in mind that what we mean by support is that Games can list the games for this system, it doesn't mean it can run them — this ability depends on other factors such as whether a Libretro core able to run the game is installed — nor that it will run properly — for example, games requiring a mouse aren't supported yet.

Covers and Icons

Batien Nocera wrote a Grilo plugin retrieving info from TheGamesDB.net and I made most game types use this in Games. The previously discussed new MIME types have been added to shared-mime-info to allow us to support more game types but also to discriminate properly the different types in this plugin: before that we had no proper way to know if a Game Boy game was a Game Boy one or a Game Boy Color one.

Games can automatically fetch covers from TheGamesDB.net.

Maybe TheGamesDB.net doesn't have a cover for your game, but that's not a problem: this website is crowdsourced, contribute a cover and it will appear in Games!

What if you simply don't like the cover the website returned for any reason: no problem, if you have a game located at /path/to/mario.nes, an image file will be used as the game's cover if it's named like:

  • /path/to/mario.*,
  • /path/to/cover.* or
  • /path/to/folder.*

where * is any extension.

If you have cover image files alongside your game files…

…Games will use them for the games' thumbnails.

Headers of Steam games are downloaded from the Steam store's website and used as the game's cover.

With pretty covers to show, we decided to double the size of the game thumbnails (from 128 pixels to 256 pixels) to better appreciate them! If your game still has no cover to display, it may have an icon: desktop and Steam games already displayed their icon, but now icons are also extracted from LÖVE packages and Nintendo DS games.

Fullscreen Support

I finally found some time to work on the fullscreen mode! It is available to Libretro based games: on the game display page at the top right corner you will find a Fullscreen button allowing you to switch to the fullscreen mode; in this mode the headerbar and the pointer will be hidden after 2 seconds of pointer inactivity, just move the pointer to reveal them.

You can toggle the fullscren mode by pressing Ctrl+F or F11, and you can escape it by pressing Escape; leaving the game will also quit the fullscreen mode.

Gamepads Support

Megh Parikh added support for gamepads to play Libretro based games; the gamepads are discovered with udev and are read with libevdev.

He implemented support for the format used by SDL2 to map the input events sent by the gamepad into meaningful gamepad events: with that, Games can know for any mapped gamepad that the Start button got pressed rather than the 10th button. Games comes with a large database of gamepad mappings.

Linux's input system has proper gamepad inputs (buttons, etc.), even though only a few gamepads send these proper events we should support them even if Games doesn't have a mapping for them: we already can know which button is which one! Hence I added support for these: to work with Games, your gamepad need to send proper gamepad events or to have a mapping available. If your gamepad doesn't work with the application, consider it a bug!

Games doesn't have a user interface to handle the gamepads — yet? — but it doesn't need it to be usable! Megh implemented an automatic way to assign a controller to a player, here is how it works:

  • when a gamepad is plugged in, it is assigned to the first player with no gamepad;
  • when a gamepad is plugged out, the player which had it have no gamepad instead and any other player keep its controller;
  • the keyboard is assigned to the first player with no controller after reassigning the gamepads.

If your gamepad doesn't work with games, consider it a bug too!

PlayStation Support

PlayStation support has been a big focus for Ricard Gascons and to a lesser extend for myself. Ricard added multi disc support for PlayStation games: if the game you are playing has multiple discs then the header bar will contain a button with a CD icon, pressing it will reveal a list of the discs of the game, selecting one will switch the disc in use for this game, allowing you to keep progressing almost seamlessly.

You can switch between the multiple discs of a PlayStation game.

Some discs have a title, if it's the case it will be displayed rather than Disc n as the disc's title.

If a PlayStation disc has a title, Games will display it.

The DualShock controller for the PlayStation which has been introduced after the launch of the console has two analog thumbsticks and several games take advantage of it. These controllers feature a button allowing to present the gamepad as a DualShock controller or as a classic controller, this was a workaround for compatibility purpose as earlier games wouldn't work with a DualShock. For gamepads to work seamlessly with any games in Games we needed to automatically select the correct gamepad type: if your game doesn't support DualShock, we present the gamepads as classic ones, otherwise we present them as DualShocks.

To achieve grouping several discs into a single game, knowing a disc's title and knowing the supported gamepad types, Games ship a database containing these informations so it can work out of the box; this also allow Games to display a good title for any known game .This database is built by dumping the PlayStation DataCenter website, if you find an oddity, it's either a bug in our dumper or in the website!

Pause on Focus-Out

You probably don't want to lose the control of the game because the window loses its focus and when playing you'll likely have the window focused, so I made Games pause a running game when the main window loses the focus and resume the game when it gains it back. If the window loses its focus to the Shell, the pause is delayed by half a second, allowing to pause when the shell takes the focus while avoiding annoying micropauses when a short notification appears on screen.

Inhibition

To avoid the screen to go black when playing a game, Mathieu added a screensaver inhibitor; and to avoid to loose a running game he also added a session inhibitor: when trying to close your session you'll be warned if a game is running.

Resume and Quit Dialogs

Unfortunately some integrated games can't be saved and resumed, hence quitting such a game implies you will lose your progress. To be sure you know that, I added a dialog letting you to quit the game and to lose your progress or to keep playing.

The dialog proposing you to resume the game or to start it over has been overhauled: it used to allow you to:

  • resume the game with a Resume button;
  • restart the game with a Main Menu button;
  • go back to the games list with a Cancel button.

This was confusing: Main Menu took you back to the game's title screen while many thought it moved you to the games list; also the Cancel button wasn't really useful as you could as well choose to resume the game and then quit it. So Mathieu refactored it by renaming the Main Menu button into Restart and by removing the Cancel button.

Mathieu then added a new dialog letting you to choose what to do in case resuming the game failed for any reason: you can reset the game with a Reset button or choose to do nothing and go back to the games list with a Cancel button.

Audio

There was an annoying bug which made the sound stop working after playing a game for some time, it was caused mainly by a poor usage of PulseAudio in retro-gtk, it has been fixed by using the PulseAudio Simple API instead. Another problem was that an error made any game run at 60 frames per second rather than the rate needed by the game's system. I fixed both problems into retro-gtk so sound and game speed should work as expected.

Running a Game Failed

When Games failed to run a game it used to display a message in an infobox at the top of the collection view, this didn't work well so I replaced this by the following page.

Distribution

Bastien and Mathieu worked a lot to make Games work better with Flatpak: they found missing functionalities in Flatpak which are now shipped, they made gamepads work in the sandbox, they helped making the nightly flatpak build, they added some Libretro cores to Games' nightly Flatpak… so many things I probably forgot some.

Speaking of Libretro cores, this is the biggest problem when distributing Games. We are currently relying on retro-plugins to distribute a curated set of Libretro cores but it doesn't work well:

  • it isn't very useful as it simply ships the content of other projects;
  • it limits Games to the cores shipped in it and there aren't many;
  • Games contains hardcoded information we need about these cores, which is terrible;
  • it gives us the burden to maintain this module when we have many more important things to work on.

retro-plugins was good when the project was young but now it needs a better way to ship Libretro cores. The libretro-super project seems to be the de facto standard way to install Libretro cores, it installs them in the $(libdir)/libretro directory with info files for each core. We started working on extending these info files to make them include the information we need: a way to pick the best core to run the games we want and whether the core supports resuming the games. We will help hardening this solution so we can deprecate retro-plugins and use this instead.

We started testing this solution in the Flatpak version of games: it doesn't depends on retro-plugins, instead we directly ship some Libretro cores with an extended info file.

Conclusion

Many other things happened, for example Games received many translations and I fixed some bugs in the PCSX-ReARMed Libretro core with the help of Alexis Puskarczyk.

Despite remaining rough edges and lacking features, I'm extremely proud of this release as it marks the first really usable version of Games!

September 17, 2016

Two Small Fundraisings – on gspell and LaTeXila

We live in a world where it’s increasingly possible to have a part-time job and being paid for other small tasks on the side; think about Uber or airbnb.

I have a half-time job, and I care about Free Software. So the natural thing to do for me is to find ways to be funded for the contributions I do.

That’s why I was really pleased to hear Alexander Larsson, at the end of his talk at GUADEC about Flatpak:


[…]
And also an interesting thing – I think actually super important – is payment. I want people to be able to pay for Free Software.

Which was met with applause. But unfortunately such support in Flatpak and GNOME Software are not going to happen anytime soon, maybe in a few years with some hope.

In the meantime, I’m launching two small fundraisings!

If this is successful, the idea is to add further milestones, after the work is done on the first one.

gspell

gspell is a library that I created last year to share the spell-checking code between gedit and LaTeXila. The code comes from the gedit spell plugin, as such there is only the support for GtkTextView. The goal of the fundraiser is to add support for GtkEntry, a single line text entry field.

Go to the gspell fundraising page if you’re interested!

LaTeXila

GTK+ 3.22, which will be released this Wednesday, will be the last GTK+ 3 stable version (see this announcement). After that, the deprecated functionality of GTK+ 3 will be removed. LaTeXila is not a new application, it is developed since 2009. A fundraising on a new piece of software can concentrate on features. For LaTeXila, what is more important is that it is well maintained, to be still relevant in the 2020’s. So the fundraiser is to make the code ready for GTK+ 4, at least as a next step.

Code maintenance is not really what we can call interesting, but it is useful. We can see this interesting/useful dichotomy quite often in the computer science world: for a researcher, is proof of correctness interesting? Yes. But in practice it is rarely applied. Is writing unit tests interesting? No, but it is very useful.

Go to the LaTeXila fundraising page if you’re convinced ;)

Layout APIs don’t have to be terrible – lessons from Bokeh

Our APIs for arranging elements on the screen are stuck in the stone age. Using these APIs in the simplest way results in an ugly layout. To achieve pretty layouts we deploy tricks that aren’t obvious to newcomers, though many of us have internalized them and don’t notice anymore.

If you ask a designer to arrange items on a page, by default they’re going to line shit up. (They’ll think a lot about exactly which things to align with which other things in order to communicate what’s related to what, and there may be some strategic non-alignment, but … alignment will be happening.)

Layout APIs aren’t designed to implement what graphic designers design.

In the print design tradition, designers don’t have to think about the window size changing or users choosing a larger font. Developers have to translate mockups to code in a way that keeps the design intent while allowing stuff to scale. Alignment of items will often be the most important aspect of the design to preserve.

When we aren’t working with a designer, lining stuff up is a good default anyway. It’ll look better than not. But typical layout APIs require extra work to get stuff aligned.

In this post I’ll talk about:

  • how we tried to improve this in the Bokeh project
  • three ideas that any UI toolkit could explore to escape the limitations of today’s layout APIs

I suspect there’s a large innovation space here that hasn’t been explored.

Bokeh layout

If you aren’t familiar with Bokeh, it’s a toolkit to create plots and data-centric applications or dashboards. Bokeh lets someone build a web app in plain Python without becoming a web developer. Many data scientists are Python developers but don’t keep up with the modern web stack (JS, HTTP, CSS). Web development is a full-time job in itself, and it’s a distraction.

We faced an issue that typical Bokeh data visualization apps didn’t look nice; after all, they were created by data scientists without design help. How could we make the easy approach a data scientist might choose look nice by default?

Bokeh users were placing their plots in rows and columns (also known to some as hboxes and vboxes). But if you had two plots in a column, the different label widths on the Y axes would keep the Y axes from aligning with one another, for example. If you stacked two rows into a column, the rows might not be the same total width, and even if each row had the same number of plots, the result wouldn’t be an aligned grid.

We asked designer Sara Schnadt to mock up some prototypical layouts for data visualization apps. She used rows and columns just as data scientists were doing, but she aligned a bunch of the elements.

Here’s the goal we arrived at: let the data scientist group plots into rows and columns, and then match widths/heights and align axes as a designer might.

That is, the input should be something like this with no additional hints or manual layout tweaks:

column(row(plot1, plot2), row(plot3, plot4))

Using that input alone, the output has to look good.

Existing solutions used in native toolkits and in CSS were not appropriate:

  • boxes and variations on them are simple but the results look bad without a lot of manual massaging;
  • grid/table systems require manually choosing the grid size and manually specifying coordinates to attach each element, which is too much work, and making changes later is a pain;
  • constraint systems are complicated to understand and horrible to debug;
  • fixed sizes and positions aren’t acceptable for most apps.

Here’s what we ended up doing. We converted the rows and columns into a constraint system (using the same Cassowary algorithm that’s made it from scwm to iOS); but for Bokeh, the constraint system is an internal implementation detail, so data scientists shouldn’t end up debugging it. And our constraints are about alignment.

Bryan van de Ven and I created an initial prototype of the algorithm, and Sarah Bird did 95% of the work fixing it and converting the concept into a reality. Bokeh uses Chris Colbert’s implementation of Cassowary for JavaScript.

Our prototype used wireframe dummy widgets. Here’s what happens when you arrange some dummy “plots” with a traditional box layout algorithm:

before

And here’s what happens when the same dummy widgets (plus I guess a couple more at the bottom) are arranged with the new algorithm:

after

The code for that prototype can be found here. After a ton of work by Sarah, you can find some real Bokeh code running at http://demo.bokehplots.com, and the source on GitHub.

There’s a lot more that Bokeh could do to be even smarter about layout, but this is a start.

Three ideas to explore further

In the spirit of “yes, and…” I’d love to see other toolkits (and Bokeh) take this further. Here are some ideas I think are useful.

1. Do layout globally, not recursively.

For implementation reasons, toolkits use recursive layout algorithms; each node in the widget tree is responsible for arranging its immediate children.

But often we want to align things that may be in different sub-branches. There are ways to do this, such as hacking in some fixed sizes, or adding hints (one such hint API is GtkSizeGroup). In Bokeh, we use the tree of rows and columns to infer constraints, but we pull everything up into a global toplevel constraint system. With global layout, constraints can span the entire tree.

2. Use constraints as implementation, but try to avoid them in the public API.

Cassowary is a clever algorithm, but not a friendly API in any way. Read these iOS docs; simple, right?

Bokeh takes rows and columns as input. It could probably allow you to provide additional hints, but manually providing constraints gets ugly quickly.

I initially tried to prototype the Bokeh layout algorithm without using a constraint solver; I think it’s possible to do, but the constraint solver approach is much, much simpler. As long as app developers aren’t exposed to debugging constraint systems, it’s a good route to take.

3. Align visual elements, not logical bounds of widgets.

For example:

  • even though a plot including its axes might be one widget, we want to consider the axes an element for alignment purposes
  • even though a widget such as a slider might have some whitespace around it, we want to consider the visible pixel bounds for alignment purposes

We could think of something like text baseline alignment as a special case of this idea.

Lots more to do

For me, layout remains an unsolved problem. I think it’s because we’re in a rut of old assumptions, such as recursive algorithms that use logical widget bounds without ever “peeking in” to the visual elements inside the widget. We’ve also failed to find the right role for constraint systems; we are trying to use them as the API itself, but in fact they are a powerful implementation technique that could support a lot of different higher-level layout APIs. We could do more to figure out what those APIs could be.

Historically, layout APIs have been implementation-driven; they didn’t start by thinking about “what graphic designers design,” or “what app developers would like to maintain,” they started with something like “how GUI toolkits work.” Rethinking these APIs in a more top-down, experience-oriented way could find quite a bit of room for improvement.

 

Happy Software Freedom Day!

Celebrate SFD with us on September 17, 2016!And today is the 13th edition of Software Freedom Day! We wish you all a great day talking to people and discovering (or making them discovery) the benefits and joys of running Free Software. As usual we have a map where you can find all the events in your area. Should you just discover about SFD today and want to organize an event it is never too late. While the date is global, each team has the freedom to run the event at a date that is convenient in their area. We (in Cambodia) are running our event on November 26 due to university schedule, other conferences and religious holidays conflicting.

So hopefully you’ll get hooked just like us and start a new journey into the world of learning, sharing and contributing to your needs!

Happy Software Freedom Day to all of us!

September 16, 2016

Builder Nightly Flatpak

First off, I’ll be in Portland at the first ever LAS giving demos and starting on Builder features for 3.24.

For a while now, you’ve been able to get Builder from the gnome-apps-nightly Flatpak repository. Until now, it had a few things that made it difficult to use. We care a whole lot about making our tooling available via Flatpak because it is going to allow us to get new code into users hands quicker, safer, and more stable.

So over the last couple of weeks I’ve dug in and really started polishing things up. A few patches in Flatpak, a few patches in Builder, and a few patches in Sysprof start getting us towards something refreshing.

Python Jedi should be working now. So you can autocomplete in Python (including GObject Introspection) to your hearts delight.

Jhbuild from within the Flatpak works quite well now. So if you have a jhbuild environment on your host, you can use the Flatpak nightly and still target your jhbuild setup.

One of the tricks to being a module maintainer is getting other people to do your work. Thankfully the magnificent Patrick Griffis came to the rescue and got polkit building inside of Flatpak. Combined with some additional Sysprof patches, we have a profiler that can run from Flatpak.

Another pain point was that the terminal was inside of a pid/mount/network namespace different than that of the host. This meant that /usr/lib was actually from the Flatpak runtime, not your system /usr/lib. This has been fixed using one of the new developer features in Flatpak.

Flatpak now supports executing programs on the host (a sandbox breakout) for applications that are marked as developer tools. For those of you building your own Flatpaks, this requires --allow=devel when running the flatpak build-finish command. Of course, one could expect UI/UX flows to make this known to the user so that it doesn’t get abused for nefarious purposes.

Now that we have access to execute a command on the host using the HostCommand method of the org.freedesktop.Flatpak.Development interface, we can piggy back to execute our shell.

The typical pty dance, performed in our program.

/* error handling excluded */
int master_fd = vte_pty_get_fd (pty);
grantpt (master_fd);
unlockpt (master_fd);
char *name = ptsname (master_fd);
int pty_fd = open (name, O_RDWR, 0);

Then when executing the HostCommand method we simply pass pty_fd as a mapping to stdin (0), stdout (1), and stderr (2).

On the Flatpak side, it will check if any of these file-descriptors are a tty (with the convenient isatty() function. If so, it performs the necessary ioctl() to make our spawned process the controller of the pty. Lovely!

So now we have a terminal, whose process is running on the host, using a pty from inside our Flatpak.

Endless and LAS GNOME

I’ve been spending the week in San Francisco where I’ve been going every day to the awesome Endless‘ office in SoMa.
It’s been really great to talk in person to all the people I usually have to ping on the internetz and experience a bit of the office life in San Francisco.

Endless' Office in San Francisco

Next Monday I am speaking at the Libre Application Summit GNOME in Portland about how we’re managing and delivering the applications to our Endless OS’s users. I am also very curious to check out the city of Portland as everybody tells me good things about it.
If you’re attending the event, come say hi!

September 14, 2016

Copyleft and data: databases as poor subject

tl;dr: Open licensing works when you strike a healthy balance between obligations and reuse. Data, and how it is used, is different from software in ways that change that balance, making reasonable compromises in software (like attribution) suddenly become insanely difficult barriers.

In my last post, I wrote about how database law is a poor platform to build a global public copyleft license on top of. Of course, whether you can have copyleft in data only matters if copyleft in data is a good idea. When we compare software (where copyleft has worked reasonably well) to databases, we’ll see that databases are different in ways that make even “minor” obligations like attribution much more onerous.

Card Puncher from the 1920 US Census.
Card Puncher from the 1920 US Census.

How works are combined

In software copyleft, the most common scenarios to evaluate are merging two large programs, or copying one small file into a much larger program. In this scenario, understanding how licenses work together is fairly straightforward: you have two licenses. If they can work together, great; if they can’t, then you don’t go forward, or, if it matters enough, you change the license on your own work to make it work.

In contrast, data is often combined in three ways that are significantly different than software:

  • Scale: Instead of a handful of projects, data is often combined from hundreds of sources, so doing a license conflicts analysis if any of those sources have conflicting obligations (like copyleft) is impractical. Peter Desmet did a great job of analyzing this in the context of an international bio-science dataset, which has 11,000+ data sources.
  • Boundaries: There are some cases where hundreds of pieces of software are combined (like operating systems and modern web services) but they have “natural” places to draw a boundary around the scope of the copyleft. Examples of this include the kernel-userspace boundary (useful when dealing with the GPL and Linux kernel), APIs (useful when dealing with the LGPL), or software-as-a-service (where no software is “distributed” in the classic sense at all). As a result, no one has to do much analysis of how those pieces fit together. In contrast, no natural “lines” have emerged around databases, so either you have copyleft that eats the entire combined dataset, or you have no copyleft. ODbL attempts to manage this with the concept of “independent” databases and produced works, but after this recent case I’m not sure even those tenuous attempts hold as a legal matter anymore.
  • Authorship: When you combine a handful of pieces of software, most of the time you also control the licensing of at least one of those pieces of software, and you can adjust the licensing of that piece as needed. (Widely-used exceptions to this rule, like OpenSSL, tend to be rare.) In other words, if you’re writing a Linux kernel driver, or a WordPress theme, you can choose the license to make sure it complies. Not necessarily the case in data combinations: if you’re making use of large public data sets, you’re often combining many other data sources where you aren’t the author. So if some of them have conflicting license obligations, you’re stuck.

How attribution is managed

Attribution in large software projects is painful enough that lawyers have written a lot on it, and open-source operating systems vendors have built somewhat elaborate systems to manage it. This isn’t just a problem for copyleft: it is also a problem for the supposedly easy case of attribution-only licenses.

Now, again, instead of dozens of authors, often employed by the same copyright-owner, imagine hundreds or thousands. And imagine that instead of combining these pieces in basically the same way each time you build the software, imagine that every time you have a different query, you have to provide different attribution data (because the relevant slices of data may have different sources or authors). That’s data!

The least-bad “solution” here is to (1) tag every field (not just data source) with licensing information, and (2) have data-reading software create new, accurate attribution information every time a new view into the data is created. (I actually know of at least one company that does this internally!) This is not impossible, but it is a big burden on data software developers, who must now include a lawyer in their product design team. Most of them will just go ahead and violate the licenses instead, pass the burden on to their users to figure out what the heck is going on, or both.

Who creates data

Most software is either under a very standard and well-understood open source license, or is produced by a single entity (or often even a single person!) that retains copyright and can adjust that license based on their needs. So if you find a piece of software that you’d like to use, you can either (1) just read their standard FOSS license, or (2) call them up and ask them to change it. (They might not change it, but at least they can if they want to.) This helps make copyleft problems manageable: if you find a true incompatibility, you can often ask the source of the problem to fix it, or fix it yourself (by changing the license on your software).

Data sources typically can’t solve problems by relicensing, because many of the most important data sources are not authored by a single company or single author. In particular:

  • Governments: Lots of data is produced by governments, where licensing changes can literally require an act of the legislature. So if you do anything that goes against their license, or two different governments release data under conflicting licenses, you can’t just call up their lawyers and ask for a change.
  • Community collaborations: The biggest open software relicensing that’s ever been done (Mozilla) required getting permission from a few thousand people. Successful online collaboration projects can have 1-2 orders of magnitude more contributors than that, making relicensing is hard. Wikidata solved this the right way: by going with CC0.

What is the bottom line?

Copyleft (and, to a lesser extent, attribution licenses) works when the obligations placed on a user are in balance with the benefits those users receive. If they aren’t in balance, the materials don’t get used. Ultimately, if the data does not get used, our egos feel good (we released this!) but no one benefits, and regardless of the license, no one gets attributed and no new material is released. Unfortunately, even minor requirements like attribution can throw the balance out of whack. So if we genuinely want to benefit the world with our data, we probably need to let it go.

So what to do?

So if data is legally hard to build a license for, and the nature of data makes copyleft (or even attribution!) hard, what to do? I’ll go into that in my next post.

September 13, 2016

Podcasts I've Been Listening To Lately

Podcasts

For someone who has run his own podcast for several years (albeit not generating a lot of content lately), it took me quite some time to actually start listening to podcasts myself. Ironic, I know, but I guess the main reason behind this was because I was always reading code at work and eventually, no matter how hard I tried, I just couldn't pay attention to what was being said! No matter how interesting the topic being discussed was or how engaging the hosts (or hosts) were, my brain would be so focused on reading code that everything else just turned into white noise.

Well, fast forward a couple of years and I still am reading code (though not as much as I used to due to a new role), and I still have a hard time listening to podcast while at work... so I decided to only listen to them when I was not working. Simple, right? But it took me a while to change that for some reason.

Anyhow, I now listen to podcasts while driving (which I don't really do a lot of since I work from home 99.99% of the time) or when I go for walks, and after a while I have started following a handful of them which are now part of my weekly routine:

  • All The Books which provide me with an up to date list of suggestions for what books to read next. They're pretty regular with their episodes, so I can always count on listening about new books pretty much every week.
  • Book Riot for another dose of more news about books!
  • Hack the Entrepreneur to keep up with people who are making something about what they are passionate about.
  • Wonderland Podcast which I only started listening to a few weeks back but it has turned into one of my favorite.
  • Science Vs another new addition to my list, with entertaining takes at interesting topics such as 'the G-spot', 'Fracking', 'Gun Control' and 'Organic Food'.

Today I was introduced to Invisibilia and though I only listened to the first 10 minutes (I was giving the link during working hours, so no go for me), I'm already very interested and will follow it.

I do have other podcasts that I am still subscribed to, but these listed here are the ones that I am still following every episode. Maybe if I had to drive to work every day or went for walks more often, maybe then I would listen to more podcasts? Trust me though, I rather continue listening to only a small set of them than drive to work every day. Don't get me wrong, I love going to work, but that's 2 hours/day of my life that I rather spend at home :)

September 12, 2016

Maps marching towards 3.22

Long time since the my last blog post, but here we go… 

So, I just rolled the 3.21.92 release of GNOME Maps. This is final beta release before the next stable (3.22.0).

The most noteworthy change will ofcourse be the new tile provider, replacing the discontinued MapQuest tiles, courtesy of Mapbox!
We have also backported this to prior stable versions to keep things working in current distribution releases, and for the future we will also have the ability to swich tile sources without patching release versions, as Maps now fetches a service definition file. And maybe (if time and effort permits) we might expand into the territory of client-side rendering of vector data, which opens up some possibilties, such as rendering various layers of interesting stuff such as a specific type of point-of-interests, like "show all restaurants in this area".

Another nice feature, thanks to Marius Stanciu's work in libchamlain, is that we can now render the map continously around the globe (at longitude 180°), thus we're no longer pretending there's an edge of the world, but rather aknowledge what Eratosthenes predicted around 200 BC :-)

Unfortunatly we will not see support for public transit routing for 3.22…
We still need somewhere and something to run our OpenTripPlanner instance on, and this summer getting basic tile service back on has ofcourse been prio one.

But stay tuned, and I will cook up a little status update of the stuff me and Andreas has been up to in this department too…

Feeds