This feed omits posts by rms. Just 'cause.

Disclaimer: this is pending for v4.21 and thus not yet in any kernel release.

Most wheel mice have a physical feature to stop the wheel from spinning freely. That feature is called detents, notches, wheel clicks, stops, or something like that. On your average mouse that is 24 wheel clicks per full rotation, resulting in the wheel rotating by 15 degrees before its motion is arrested. On some other mice that angle is 18 degrees, so you get 20 clicks per full rotation.

Of course, the world wouldn't be complete without fancy hardware features. Over the last 10 or so years devices have added free-wheeling scroll wheels or scroll wheels without distinct stops. In many cases wheel behaviour can be configured on the device, e.g. with Logitech's HID++ protocol. A few weeks back, Harry Cutts from the chromium team sent patches to enable Logitech high-resolution wheel scrolling in the kernel. Succinctly, these patches added another axis next to the existing REL_WHEEL named REL_WHEEL_HI_RES. Where available, the latter axis would provide finer-grained scroll information than the click-by-click REL_WHEEL. At the same time I accidentally stumbled across the documentation for the HID Resolution Multiplier Feature. A few patch revisions later and we now have everything queued up for v4.21. Below is a summary of the new behaviour.

The kernel will continue to provide REL_WHEEL as axis for "wheel clicks", just as before. This axis provides the logical wheel clicks, (almost) nothing changes here. In addition, a REL_WHEEL_HI_RES axis is available which allows for finer-grained resolution. On this axis, the magic value 120 represents one logical traditional wheel click but a device may send a fraction of 120 for a smaller motion. Userspace can either accumulate the values until it hits a full 120 for one wheel click or it can scroll by a few pixels on each event for a smoother experience. The same principle is applied to REL_HWHEEL and REL_HWHEEL_HI_RES for horizontal scroll wheels (which these days is just tilting the wheel). The REL_WHEEL axis is now emulated by the kernel and simply sent out whenever we have accumulated 120.

Important to note: REL_WHEEL and REL_HWHEEL are now legacy axes and should be ignored by code handling the respective high-resolution version.

The magic value of 120 is taken directly from Windows. That value was chosen because it has a good number of integer factors, so dividing 120 by whatever multiplier the mouse uses gives you a integer fraction of 120. And because HW manufacturers want it to work on Windows, we can rely on them doing it right, provided we use the same approach.

There are two implementations that matter. Harry's patches enable the high-resolution scrolling on Logitech mice which seem to mostly have a multiplier of 8 (i.e. REL_WHEEL_HI_RES will send eight events with a value of 15 before REL_WHEEL sends 1 click). There are some interesting side-effects with e.g. the MX Anywhere 2S. In high-resolution mode with a multiplier of 8, a single wheel movement does not always give us 8 events, the firmware does its own magic here. So we have some emulation code in place with the goal of making the REL_WHEEL event happen on the mid-point of a wheel click motion. The exact point can shift a bit when the device sends 7 events instead of 8 so we have a few extra bits in place to reset after timeouts and direction changes to make sure the wheel behaviour is as consistent as possible.

The second implementation is for the generic HID protocol. This was all added for Windows Vista, so we're only about a decade behind here. Microsoft got the Resolution Multiplier feature into the official HID documentation (possibly in the hope that other HW manufacturers implement it which afaict didn't happen). This feature effectively provides a fixed value multiplier that the device applies in hardware when enabled. It's basically the same as the Logitech one except it's set through a HID feature instead of a vendor-specific protocol. On the devices tested so far (all Microsoft mice because no-one else seems to implement this) the multipliers vary a bit, ranging from 4 to 12. And the exact behaviour varies too. One mouse behaves correctly (Microsoft Comfort Optical Mouse 3000) and sends more events than before. Other mice just send the multiplied value instead of the normal value, so nothing really changes. And at least one mouse (Microsoft Sculpt Ergonomic) sends the tilt-wheel values more frequently and with a higher value. So instead of one event with value 1 every X ms, we now get an event with value 3 every X/4 ms. The mice tested do not drop events like the Logitech mice do, so we don't need fancy emulation code here. Either way, we map this into the 120 range correctly now, so userspace gets to benefit.

As mentioned above, the Resolution Multiplier HID feature was introduced for Windows Vista which is... not the most recent release. I have a strong suspicion that Microsoft dumped this feature as well, the most recent set of mice I have access to don't provide the feature anymore (they have vendor-private protocols that we don't know about instead). So the takeaway for all this is: if you have a Logitech mouse, you'll get higher-resolution scrolling on v4.21. If you have a Microsoft mouse a few years old, you may get high-resolution wheel scrolling if the device supports it. Any other vendor or a new Microsoft mouse, you don't get it.

Coincidentally, if you know anyone at Microsoft who can provide me with the specs for their custom protocol, I'd appreciate it. We'd love to have support for it both in libratbag and in the kernel. Or any other vendor, come to think of it.

Posted Wed Dec 12 04:27:00 2018 Tags:
And by "tube" I mean: I stepped out of my door and some idiot on a scooter rammed into me and went flying. He had been speeding down the sidewalk like a foot from the wall. As he lay sprawled in his yardsale and I tried to determine whether I was bleeding I said, "This is why I hate those things!"


Still lying on the ground, he said, "But it's not my fault!"

"Fuck you!" I explained. "You were going 20 miles an hour on the fucking sidewalk!"

This is when the guy at the glass shop started laughing. I guess you can't really say you were a part of San Francisco 2018 until a techbro on a scooter has slammed into you and then blamed you for it.

How to Recycle your E-scooter:

The city and the e-scooter companies have been working very hard to find a solution to the e-scooter problem, and in response to public demand, they have placed escooter docking stations all over the city for your convenience. When you see an e-scooter on the sidewalk, calmly walk up to it, pick it up, and place it on the nearest docking station, also known as a 'scootypods' (they're still focus grouping that title).

If a docking station does not have the recycling symbol on it, simply slot the scooter through the top of the docking station as pictured. [...]

When you're done riding an escooter, always remember to D.U.M.P

  • Don't panic
  • Understand that you are part of the problem
  • Mobilize your legs
  • Place escooter in the trash

Previously, previously, previously, previously, previously.

Posted Tue Dec 11 19:45:03 2018 Tags:
And by "tube" I mean: I stepped out of my door and some idiot on a scooter rammed into me and went flying. He had been speeding down the sidewalk like a foot from the wall. As he lay sprawled in his yardsale and I tried to determine whether I was bleeding I said, "This is why I hate those things!"


Still lying on the ground, he said, "But it's not my fault!"

"Fuck you!" I explained. "You were going 20 miles an hour on the fucking sidewalk!"

This is when the guy at the glass shop started laughing. I guess you can't really say you were a part of San Francisco 2018 until a techbro on a scooter has slammed into you and then blamed you for it.

How to Recycle your E-scooter:

The city and the e-scooter companies have been working very hard to find a solution to the e-scooter problem, and in response to public demand, they have placed escooter docking stations all over the city for your convenience. When you see an e-scooter on the sidewalk, calmly walk up to it, pick it up, and place it on the nearest docking station, also known as a 'scootypods' (they're still focus grouping that title).

If a docking station does not have the recycling symbol on it, simply slot the scooter through the top of the docking station as pictured. [...]

When you're done riding an escooter, always remember to D.U.M.P

  • Don't panic
  • Understand that you are part of the problem
  • Mobilize your legs
  • Place escooter in the trash

Previously, previously, previously, previously, previously.

Posted Tue Dec 11 19:45:03 2018 Tags:

This time we're digging into HID - Human Interface Devices and more specifically the protocol your mouse, touchpad, joystick, keyboard, etc. use to talk to your computer.

Remember the good old days where you had to install a custom driver for every input device? Remember when PS/2 (the protocol) had to be extended to accommodate for mouse wheels, and then again for five button mice. And you had to select the right protocol to make it work. Yeah, me neither, I tend to suppress those memories because the world is awful enough as it is.

As users we generally like devices to work out of the box. Hardware manufacturers generally like to add bits and bobs because otherwise who would buy that new device when last year's device looks identical. This difference in needs can only be solved by one superhero: Committee-man, with the superpower to survive endless meetings and get RFCs approved.

Many many moons ago, when USB itself was in its infancy, Committee man and his sidekick Caffeine boy got the USB consortium agree on a standard for input devices that is so self-descriptive that operating systems (Win95!) can write one driver that can handle this year's device, and next year's, and so on. No need to install extra drivers, your device will just work out of the box. And so HID was born. This may only an approximate summary of history.

Originally HID was designed to work over USB. But just like Shrek the technology world is obsessed with layers so these days HID works over different transport layers. HID over USB is what your mouse uses, HID over i2c may be what your touchpad uses. HID works over Bluetooth and it's celebrity-diet version BLE. Somewhere, someone out there is very slowly moving a mouse pointer by sending HID over carrier pigeons just to prove a point. Because there's always that one guy.

HID is incredibly simple in that the static description of the device can just be bytes burnt into the ROM like the Australian sun into unprepared English backpackers. And the event frames are often an identical series of bytes where every bit is filled in by the firmware according to the axis/buttons/etc.

HID is incredibly complicated because parsing it is a stack-based mental overload. Each individual protocol item is simple but getting it right and all into your head is tricky. Luckily, I'm here for you to make this simpler to understand or, failing that, at least more entertaining.

As said above, the purpose of HID is to make devices describe themselves in a generic manner so that you can have a single driver handle any input device. The idea is that the host parses that standard protocol and knows exactly how the device will behave. This has worked out great, we only have around 200 files dealing with vendor- and hardware-specific HID quirks as of v4.20.

HID messages are Reports. And to know what a Report means and how to interpret it, you need a Report Descriptor. That Report Descriptor is static and contains a series of bytes detailing "what" and "where", i.e. what a sequence of bits represents and where to find those bits in the Report. So let's try and parse one of Report Descriptors, let's say for a fictional mouse with a few buttons. How exciting, we're at the forefront of innovation here.

The Report Descriptor consists of a bunch of Items. A parser reads the next Item, processes the information within and moves on. Items are small (1 byte header, 0-4 bytes payload) and generally only apply exactly one tiny little bit of information. You need to accumulate several items to build up enough information to actually know what's happening.

The "what" question of the Report Descriptor is answered with the so-called Usage. This could be something simple like X or Y (0x30 and 0x31) or something more esoteric like System Menu Exit (0x88). A Usage is 16 bits but all Usages are grouped into so-called Usage Pages. A Usage Page too is a 16 bit value and together they form the 32-bit value that tells us what the device can do. Examples:


0001 0031 # Generic Desktop, Y
0001 0088 # Generic Desktop, System Menu Exit
0003 0005 # VR Controls, Head Tracker
0003 0006 # VR Controls, Head Mounted Display
0004 0031 # Keyboard, Keyboard \ and |
Note how the Usage in the last item is the same as the first one, without the Usage Page you will mix things up. It helps if you always think of as the Usage as a 32-bit number. For your kids' bed-time story time, here are the HID Usage Tables from 2004 and the approved HID Usage Table Review Requests of the last decade. Because nothing puts them to sleep quicker than droning on about hex numbers associated with remote control buttons.

To successfully interpret a Report from the device, you need to know which bits have which Usage associated with them. So let's go back to our innovative mouse. We would want a report descriptor with 6 items like this:


Usage Page (Generic Desktop)
Usage (X)
Report Size (16)
Usage Page (Generic Desktop)
Usage (Y)
Report Size (16)
This basically tells the host: X and Y both have 16 bits. So if we get a 4-byte Report from the device, we know two bytes are for X, two for Y.

HID was invented when a time when bits were more expensive than printer ink, so we can't afford to waste any bits (still the case because who would want to spend an extra penny on more ROM). HID makes use of so-called Global items, once those are set their value applies to all following items until changed. Usage Page and Report Size are such Global items, so the above report descriptor is really implemented like this:


Usage Page (Generic Desktop)
Usage (X)
Usage (Y)
Report Count (2)
Report Size (16)
Input (Data,Var,Rel)
The Report Count just tells us that 2 fields of the current Report Size are coming up. We have two usages, two fields, and 16 bits each so we know what to do. The Input item is sort-of the marker for the end of the stack, it basically tells us "process what you've seen so far", together with a few flags. Rel in this case means that the Usages are relative. Oh, and Input means that this is data from device to host. Output would be data from host to device, e.g. to set LEDs on a keyboard. There's also Feature which indicates configurable items.

Buttons on a device are generally just numbered so it'd be monumental 16-bits-at-a-time waste to have HID send Usage (Button1), Usage (Button2), etc. for every button on the device. HID instead provides a Usage Minimum and Usage Maximumto sequentially order them. This looks like this:


Usage Page (Button)
Usage Minimum (1)
Usage Maximum (5)
Report Count (5)
Report Size (1)
Input (Data,Var,Abs)
So we have 5 buttons here and each button has one bit. Note how the buttons are Abs because a button state is not a relative value, it's either down or up. HID is quite intolerant to Schrödinger's thought experiments.

Let's put the two things together and we have an almost-correct Report descriptor:


Usage Page (Button)
Usage Minimum (1)
Usage Maximum (5)
Report Count (5)
Report Size (1)
Input (Data,Var,Abs)

Report Size (3)
Report Count (1)
Input (Cnst,Arr,Abs)

Usage Page (Generic Desktop)
Usage (X)
Usage (Y)
Report Count (2)
Report Size (16)
Input (Data,Var,Rel)
New here is Cnst. This signals that the bits have a constant value, thus don't need a Usage and basically don't matter (haha. yeah, right. in theory). Linux does indeed ignore those. Cnst is used for padding to align on byte boundaries - 5 bits for buttons plus 3 bits padding make 8 bits. Which makes one byte as everyone agrees except for granddad over there in the corner. I don't know how he got in.

Were we to get a 5-byte Report from the device, we'd parse it approximately like this:


button_state = byte[0] & 0x1f
x = bytes[1] | (byte[2] << 8)
y = bytes[3] | (byte[4] << 8)
Hooray, we're almost ready. Except not. We may need more info to correctly interpret the data within those reports.

The Logical Minimum and Logical Maximum specify the value range of the actual data. We need this to tell us whether the data is signed and what the allowable range is. Together with the Physical Minimumand the Physical Maximum they specify what the values really mean. In the simple case:


Usage Page (Generic Desktop)
Usage (X)
Usage (Y)
Report Count (2)
Report Size (16)
Logical Minimum (-32767)
Logical Maximum (32767)
Input (Data,Var,Rel)
This just means our x/y data is signed. Easy. But consider this combination:

...
Logical Minimum (0)
Logical Maximum (1)
Physical Minimum (1)
Physical Maximum (12)
This means that if the bit is 0, the effective value is 1. If the bit is 1, the effective value is 12.

Note that the above is one report only. Devices may have multiple Reports, indicated by the Report ID. So our Report Descriptor may look like this:


Report ID (01)
Usage Page (Button)
Usage Minimum (1)
Usage Maximum (5)
Report Count (5)
Report Size (1)
Input (Data,Var,Abs)
Report Size (3)
Report Count (1)
Input (Cnst,Arr,Abs)

Report ID (02)
Usage Page (Generic Desktop)
Usage (X)
Usage (Y)
Report Count (2)
Report Size (16)
Input (Data,Var,Rel)
If we were to get a Report now, we need to check byte 0 for the Report ID so we know what this is. i.e. our single-use hard-coded parser would look like this:

if byte[0] == 0x01:
button_state = byte[1] & 0x1f
else if byte[0] == 0x02:
x = bytes[2] | (byte[3] << 8)
y = bytes[4] | (byte[5] << 8)
A device may use multiple Reports if the hardware doesn't gather all data within the same hardware bits. Now, you may ask: if I get fifteen reports, how should I know what belongs together? Good question, and lucky for you the HID designers are miles ahead of you. Report IDs are grouped into Collections.

Collections can have multiple types. An Application Collectiondescribes a set of inputs that make sense as a whole. Usually, every Report Descriptor must define at least one Application Collection but you may have two or more. For example, a a keyboard with integrated trackpoint should and/or would use two. This is how the kernel knows it needs to create two separate event nodes for the device. Application Collections have a few reserved Usages that indicate to the host what type of device this is. These are e.g. Mouse, Joystick, Consumer Control. If you ever wondered why you have a device named like "Logitech G500s Laser Gaming Mouse Consumer Control" this is the kernel simply appending the Application Collection's Usage to the device name.

A Physical Collection indicates that the data is collected at one physical point though what a point is is a bit blurry. Theoretical physicists will disagree but a point can be "a mouse". So it's quite common for all reports on a mouse to be wrapped in one Physical Collections. If you have a device with two sets of sensors, you'd have two collections to illustrate which ones go together. Physical Collections also have reserved Usages like Pointer or Head Tracker.

Finally, a Logical Collection just indicates that some bits of data belong together, whatever that means. The HID spec uses the example of buffer length field and buffer data but it's also common for all inputs from a mouse to be grouped together. A quick check of my mice here shows that Logitech doesn't wrap the data into a Logical Collection but Microsoft's firmware does. Because where would we be if we all did the same thing...

Anyway. Now that we know about collections, let's look at a whole report descriptor as seen in the wild:


Usage Page (Generic Desktop)
Usage (Mouse)
Collection (Application)
Usage Page (Generic Desktop)
Usage (Mouse)
Collection (Logical)
Report ID (26)
Usage (Pointer)
Collection (Physical)
Usage Page (Button)
Usage Minimum (1)
Usage Maximum (5)
Report Count (5)
Report Size (1)
Logical Minimum (0)
Logical Maximum (1)
Input (Data,Var,Abs)
Report Size (3)
Report Count (1)
Input (Cnst,Arr,Abs)
Usage Page (Generic Desktop)
Usage (X)
Usage (Y)
Report Count (2)
Report Size (16)
Logical Minimum (-32767)
Logical Maximum (32767)
Input (Data,Var,Rel)
Usage (Wheel)
Physical Minimum (0)
Physical Maximum (0)
Report Count (1)
Report Size (16)
Logical Minimum (-32767)
Logical Maximum (32767)
Input (Data,Var,Rel)
End Collection
End Collection
End Collection
We have one Application Collection (Generic Desktop, Mouse) that contains one Logical Collection (Generic Desktop, Mouse). That contains one Physical Collection (Generic Desktop, Pointer). Our actual Report (and we have only one but it has the decimal ID 26) has 5 buttons, two 16-bit axes (x and y) and finally another 16 bit axis for the Wheel. This device will thus send 8-byte reports and our parser will do:

if byte[0] != 0x1a: # it's decimal in the above descriptor
error, should be 26
button_state = byte[1] & 0x1f
x = byte[2] | (byte[3] << 8)
y = byte[4] | (byte[5] << 8)
wheel = byte[6] | (byte[7] << 8)
That's it. Now, obviously, you can't write a parser for every HID descriptor out there so your actual parsing code needs to be generic. The Linux kernel does exactly that and so does everything else that needs to parse HID. There's a huge variety in devices out there, all with HID descriptors that may or may not be correct. As with so much in life, correct HID implementations are often defined by "whatever Windows accepts" so if you like playing catch, Linux development is for you.

Oh, in case you just got a bit too optimistic about the state of the world: HID allows for vendor-defined usages. Which does exactly what you'd think it does, it hides vendor-specific protocol inside what should be a generic protocol. There are devices with hidden report IDs that you can only unlock by sending the right magic sequence to the report and/or by defeating the boss on Level 4. Usually those devices present themselves as basic/normal devices over HID but if you know the magic sequence you get to use *gasp* all buttons. Or access the device-specific configuration features. Logitech's HID++ is just one example here but at least that's one where we have most of the specs available.

The above describes how to parse the HID report descriptor and interpret the reports. But what happens once you have a HID report correctly parsed? In the case of the Linux kernel, once the report descriptor is parsed evdev nodes are created (one per Application Collection, more or less). As the Reports come in, they are mapped to evdev codes and the data appears on the evdev node. That's where userspace like libinput can pick it up. That bit is actually quite simple (mostly anyway).

The above output was generated with the tools from the hid-tools repository. Go forth and hid-record.

Posted Tue Dec 11 05:56:00 2018 Tags:

From a book I've been reading:

    Power is certainly important, particularly in dictatorships, in places where constitutions, laws, unwritten rules, traditions and understandings don't count. But in a healthy democracy, power is a surprisingly limited element. And the unwritten conventions, understandings, forms of respect for how things are done, for how citizens relate to government and to each other, are surprisingly important. Why? Because if democracy is only power, then what we are left with is a system of deep distrust. Why? Because if only power matters - even if it is the result of an election - then the government feels that it has a mandate to do whatever it wants, that the law is there principally to serve power. If democracy is only about winning power and using it, then it has been deformed into a denial of society and of the idea of responsible citizenship.

    And that is the increasingly common characteristic of government, even in democracies. Only power matters. This is partly the outcome of government being de-intellectualized. Elections are now thought to be unsuitable moments for real debates over ideas. In between these elections the focus is on administrative problems - legalistic, managerial undertakings. In this case, real debates over ideas are unnecessary because the decision about power was taken on election night. There is nothing, therefore, to debate. Worse still, the efficient putting in place of programs to be administered can only be made inefficient by debate.

    And so we are witnessing a growth in the Napoleonic or Mussolinian corporatist idea that when citizens vote in an election, it is actually an all-purpose referendum or plebiscite. It is then the winner's job to get on with running things. First win an election, then administer as you wish. Omnibus bills are one of the ways you can speed things up; they are a great way to convert the deeply inefficient process of democracy, with all its thinking, debating and complex differences of opinion, into a sort of shop-floor system of utilitarian efficiency. Therefore, once elected, a government has broad, unlimited permission.

    [...]

    In any case, today's plebiscitary approach is both populist and anti-democratic. What it amounts to is this: We won the election. We have power. It is now a matter of administrative efficiency. We can do what we want.

        - John Ralson Saul, The Comeback, 2014

This finally put into words a concept I've been struggling with for a long time: the idea that ethics and responsibility come with (should come with) political power, and how they seem to be on the decline lately.

For example, I recently learned, to my horror, about the concept of a Frankenstein Veto, where in some U.S. states, the governor can just delete words (eg. "not") from a bill passed by the legislature, producing and then approving a bill with a completely different meaning than was intended.

The exact legal machinations of this are beside the point. The point is, politicians increasingly feel that they "first win an election, then administer as you wish." That almost sounds logical, so why does it feel so wrong?

Because it is wrong. The job of an elected official isn't to do whatever they want. It's to figure out what the people want (or need), and to deliver that, in accordance with principles and ethics. This is a surprisingly selfless expectation: sometimes the right thing to do is the opposite of what you want to do. And it can be hard to figure out what's right, which is why we have debates, and why we listen to our opponents in those debates, even when we have a majority and they're "merely" the opposition.

Even direct polling on issues doesn't always work, because sometimes issues are too subtle for the population to simply vote yes or no; that's why we elect representatives who will presumably do their homework, consult the right people, and figure out the right, complex answer. At least one thing is clear: if the legislature vigorously debates an issue and decides one thing, a governor passing a law that does the opposite - or even rejecting the one that was so carefully produced - is just not right.

I've been struck many times by the way the U.S. system of political "checks and balances" treats politicians like children: none of them can be trusted, so we must restrict them at every opportunity. The underlying assumption is that they will all operate without honour. As most of us eventually learn in our human relationships, if you treat people as children - or worse, as actively malicious adults - then they will tend to meet your expectations. The great irony is that in countries with less of a focus on checking "power" (such as Canada), politicians seem to abuse their power less often and less dramatically.

The above quote made me think that maybe the secret recipe is some combination of traditions, conventions, understanding, and respect. Maybe those are more effective balances to power than any system designed to simply neutralize it. And maybe this was obvious to the people who designed it, and we've forgotten, long ago.

Posted Sun Dec 9 12:14:41 2018 Tags:
Here's a video of the program, running in an emulator, and synchronized with the album. "Press any key at start of music":

This video shows the whole process of booting it up, along with more detail than you probably need to know about cassette tape audio fidelity:


In 1983, Pete Shelley's album XL•1 included as its final track a program for the Sinclair ZX Spectrum 8-bit home computer. To play it, you had to first copy the track from the vinyl record to cassette, wait several minutes for the computer to read the cassette, and then press the any key once you dropped the needle on the first track! Lyrics and visualizations ensued.

Here's the programmer's story: Joey Headen:

In late 1982 Pete had ordered a Sinclair Spectrum by mail order, and one of the first BASIC programs he wrote put up the lyrics to one of his songs prompted by key presses. [...] I spent most of Christmas 1982 learning machine code and disassembling the Spectrum ROM.

I didn't have an assembler for the Spectrum, I don't even know if one was available then, so all the code had to be converted into its hex equivalent and typed into the program. All the jumps and calls to subroutines had to be hand calculated as well! When the machine crashed it had to be restarted and the cassette tape program reloaded, usually taking at least 5 minutes. [...]

With only a few days before the album had to be finished, Pete still had two songs to complete, one of which only had a title. We had to wait for the songs to be completed, type in the lyrics off scraps of paper, and then synchronize the lyrics to the music. [...]

Once the album was finished and mixed we had to do the final version of the timing for the lyrics. This involved adding in the timings between each track on the final master version of the album. It was at this point that we noticed that there was as much as 5 seconds difference (over a 20-minute side of the album) between different one-inch tape machines in the studio. The implication of this was that home turntables and tape machines could get horribly out of synch with the program unless they had some sort of variable speed control. One solution to this problem would be to add speed control keys to the program, but it was too late to add any more code. [...]

Our work wasn't quite finished yet, as we had to cut the album. To our knowledge nobody had put a program on a 12-inch disc before, so we were breaking new ground. After the last music track of side 2 there was a locking groove to prevent the code from blasting through someone's speakers.

The only way to play the code was to physically lift the needle onto the last track. We cut one master disc and tested it on a Spectrum but it didn't work, so we had to reset some of the levels and try again. Luckily the second master disc worked fine and it could go to the pressing plant.

Previously, previously, previously, previously, previously, previously, previously, previously.

Posted Sat Dec 8 19:37:35 2018 Tags:
In case there was any lingering doubt about the scooter business model:

  1. Dump electronic junk onto the street;
  2. Abandon it and walk away as soon as any unit stops generating money;
  3. Shift the cost of collection, storage, and disposal onto the taxpayers.

I told you so!

These scooters were standard, off-the-shelf electric scooters made in China, loaded up with battery packs, motors, and a 'brain box' that has a GPS unit, a cellular modem, and a few more electronics that turn this dumb electric scooter into something you can ride via an app. Dropping electronic waste on cities around the country was not looked upon kindly by these municipalities, and right now there are hundreds of Bird and Lime scooters in towing yards, just waiting to be auctioned off to the highest bidder. [...]

Right now, humanbeing21 is in contact with a towing company that has well over a hundred Bird scooters on their lot, each accruing daily storage fees. Since these scooters only cost about $400 new, we're probably well past the time when it makes sense for Bird to pay to get them out of storage. This means they'll probably be heading for an auction where anyone can pick them up -- all of them -- for a hundred bucks or so.

Previously, previously, previously, previously, previously.

Posted Sat Dec 8 07:57:15 2018 Tags:
Because we live in the Stupidest Timeline, Mozilla find themselves needing to point out that MICROS~1 leaving the web browser market is bad for the web.

Stupidest. Stupidest, stupidest, stupidest timeline.

Mozilla Blog: Goodbye, EdgeHTML:

Microsoft is officially giving up on an independent shared platform for the internet. By adopting Chromium, Microsoft hands over control of even more of online life to Google. [...]

From a business point of view Microsoft's decision may well make sense. Google is so close to almost complete control of the infrastructure of our online lives that it may not be profitable to continue to fight this. [...] From a social, civic and individual empowerment perspective ceding control of fundamental online infrastructure to a single company is terrible. This is why Mozilla exists. We compete with Google not because it's a good business opportunity. We compete with Google because the health of the internet and online life depend on competition and choice. They depend on consumers being able to decide we want something better and to take action.

So that "this is why Mozilla exists" sentiment is great and all, but....

Remember back in the 90s when Gates was claiming that Internet Explorer was an inseparable part of the Windows operating system, and then someone asked him a question he couldn't answer: "Which part of Windows is Internet Explorer for Mac"?

Well, what part of "the health of the internet and online life depend on competition and choice" is served by Mozilla's partnership with vertically integrated, predatory multinational monopolists like Live Nation? Or by implementing DRM?

Previously, previously, previously, previously, previously.

Posted Sat Dec 8 02:49:47 2018 Tags:
I know that eel, bro:

It took several emails and phone calls before the decision was made to grab the eel and try pulling it out.

"There was only maybe two inches of the eel actually still sticking out of the nose, so it was very much akin to the magician's trick when they're pulling out the handkerchiefs and they keep coming and coming and coming," he said.

After less than a minute of tugging, a two-and-a-half-foot dead eel emerged from the seal's nostril.

Since then, Littnan said there have been at least three or four reported cases, and the most recent occurred this fall. In all the cases, the eels were removed successfully and the seals are "doing great," he said. None of the eels, however, survived. [...]

If monk seals could understand humans, Littnan said he has a message for them: "I would gently plead for them to stop."

Previously, previously, previously, previously, previously, previously, previously.

Posted Fri Dec 7 21:18:42 2018 Tags:

Orbital was the first band that I saw in San Francisco. It was 1990 and I crossed the bridge from Berkeley to see them at some club called The Bridge. I don't remember who the opener was -- maybe it was Consolidated? Someone like that -- but I was standing at the back by the sound booth when Orbital began, and they performed from the sound booth, so suddenly I was I the "front row", leaning into the window and watching these two nerdy bald guys with headlights on their glasses turn knobs and punch arcane numbers into the keypads of a really impressive stack of 1U rack-mount devices.

So then years later, I'm leaning against the Trocadero bar, probably at Death Guild, and I'm telling someone the Orbital story. "Yeah, I don't know where that club was... I hadn't lived here long...", I said. "There was a stage over there, and the bar was over there, and stairs were over there, and HEY WAIT A MINUTE it was this building!"

So it turns out that the Trocadero, which has been named that since the 70s, was renamed to "The Bridge" for like, six months in the middle of its 30 year history. Weird.

And then suddenly:

It's 1995. I'm seeing Hackers, for the first time, in the theatre. The opening song is Halcyon + On + On. I think, "Ok, Orbital, cool! A little old school. But I see what you're doing here. I'll allow it."

Anyway, if you see your mom this weekend, be sure and tell her...

Posted Fri Dec 7 11:06:02 2018 Tags:

.NET Foundation Changes

Today we announced a major change to the .NET Foundation, in which we fundamentally changed the way that the foundation operates. The new foundation draws inspiration from the Gnome Foundation and the F# Foundation.

We are making the following changes:

  • The Board of Directors of the Foundation will now be elected by the .NET Foundation membership, and they will be in charge of steering the direction of the foundation. The Board of Directors will be elected annually via direct vote from the members of the Foundation, with just one permanent member from Microsoft.

  • Anyone contributing to projects in the .NET Foundation can become a voting member of the Foundation. The main benefit is that you get to vote for who should represent you in the board of directors. To become a member, we will judge contributions to the projects in the foundation, which can either be code contributions, documentation, evangelism or other activities that advance .NET and its ecosystem.

  • Membership fee: we are adding a membership fee that will give the .NET Foundation independence from Microsoft when it comes to how it chooses to promote .NET and the ecosystem around it. We realize that not everyone can pay this fee, so this fee can be waived. But those that contribute to the Foundation will help us fund activities that will expand .NET.

  • We intend to have elections every year, so individuals will campaign on what they intend to bring to the board.

  • There is a limit in the number of members on the board representing a single company, which prevents the board from being stacked up by contributors for a single company, and will encourage our community to vote for board members with diverse backgrounds, strengthening the views of the board.

  • Companies do not vote. The only way to vote is for contributors to the .NET ecosystem, which could be affiliated with a company to vote, but the companies themselves have no vote. Our corporate sponsors are sponsors that care as much as we care as the growth and health of our ecosystem.

These changes are very close to my heart and took a lot of work to make them happen and make sure that Microsoft the company was comfortable with giving up the control over the .NET Foundation.

I want to thank Jon Galloway, the Executive Director of the current .NET Foundation to help make this a reality.

Going from the idea to the execution took a long time. Martin Woodward did some of the early foot work to get various people at Microsoft comfortable with the idea. Then Jon took over, and had to continue this process to get everyone on board and get everyone to accept that our little baby was ready to graduate, go to college and start its own independent life.

I want to thank my peers in the board of directors that supported this move, Scott Hunter, Oren Novotny, Rachel Reese as well as the entire supporting crew that helped us make this happen, Beth Massi, Jay Schmelzer and the various heroes in the Microsoft legal department that crossed all the t’s and dotted all the i’s.

See you on the campaign trail!

Posted Tue Dec 4 17:25:08 2018 Tags:
Andy Ternay:

Pretty much says everything that needs to be said about Facebook.

Previously, previously, previously, previously, previously, previously, previously, previously, previously.

Posted Tue Dec 4 03:55:20 2018 Tags:
Upcoming events of note:

Tue, Dec 04:   Astronomy on Tap @ DNA Lounge
Wed, Dec 05:   Skating Polly @ DNA Lounge
Sat, Dec 15:   Haerts, Vicereine @ Rickshaw
Sat, Dec 29:   Missing Persons, Annabella, Gene Loves Jezebel, Trans X @ Great Northern
Thu, Jan 24:   Midi Matilda @ Rickshaw Stop
Fri, Jan 25+26:   Edwardian Ball @ Regency
Sat, Jan 26:   Turbo Drive: Danger @ DNA Lounge
Fri, Feb 01:   Chicane @ Mezzanine
Fri, Feb 01:   Turbo Drive: Tonebox, Lucy in Disguise @ DNA Lounge
Thu, Feb 07:   Drama @ Rickshaw Stop
Mon, Feb 11:   Le Butcherettes @ Bottom of the Hill

What have you got?

Posted Tue Dec 4 03:42:26 2018 Tags:

Last week while reviewing a patch I read that some gaming keyboards have two modes - keyboard mode and gaming mode. When in gaming mode, the keys send out pre-recorded macros when pressed. Presumably (I am not a gamer) this is to record keyboard shortcuts to have quicker access to various functionalities. The macros are stored in the hardware and are thus relatively independent of the host system. Pprovided you have access to the custom protocol, which you probably don't when you're on Linux. But I digress.

I reckoned this could be done in software and work with any 5 dollar USB keyboard. A few hours later, I have this working now: ggkbdd. It sits directly above the kernel and waits for key events. Once the 'mode key' is hit, the keyboard will send pre-configured key sequences for the respective keys. Hitting the mode key again (or ESC) switches back to normal mode.

There's a lot of functionality that is missing such as integration with the desktop (probably via DBus), better security (dropping privs, masking the fd to avoid accidental key logging), better system integration (request fds from logind, possibly through the compositor). And error handling, etc. I think the total time on this spent is somewhere between 3 and 4h, and that includes the time to write this blog post and debug the systemd unit autostartup. There are likely other projects that solve it the same way, or at least in a similar manner. I didn't check.

This was done as proof-of-concept and

  • I don't know if it's useful and if so, what the use-cases are
  • I don't know if I will have any time to fix things on this
  • I don't know if other (better developed) projects already occupy that space
In the grand glorious future and provided this is indeed something generally useful, this would need compositor integration. Not sure we'll ever get to that point. Meanwhile, consider this a code drop for a proof-of-concept and expect that you'll have to fix any bugs yourself.
Posted Mon Dec 3 05:43:00 2018 Tags:
DNA Lounge update, wherein it's almost Skating Polly time, and Chicago takes a stand.
Posted Sun Dec 2 20:07:10 2018 Tags:

A while ago I was discussing hiring plans with a co-founder of a recently-funded startup. Their story was something like this:

"The company is growing very fast and we now have about a dozen people. We have tight deadlines, and none of the founders has much experience in project management or people management. So, we're trying to hire an experienced project manager and an experienced engineering lead / people manager."

This course of action is pretty common. It also always makes me nervous, but I haven't thought much about it until now. This discussion finally forced me to clarify my thoughts on the subject.

First of all, I asked the co-founder what their role is. The answer was a good one, albeit vague, as startup roles always are: "I don't really know. It's frustrating that I never know. But I do know my job is whatever it takes to make the company successful."

Well, what are the most important problems that the other co-founders aren't solving? The answer came quickly: "We don't have a clear idea of our project schedule. And nobody is managing interpersonal, cultural, social issues. There are lots of other problems, but people are handling those." So those were the top two. Nobody was managing those, and it was getting serious.

This reminded me of some advice I must have heard somewhere, but no longer remember where: Don't delegate the most important thing. Or maybe it was a 1980's management book: Don't outsource your core competency.1

This advice is counterintuitive. At first glance it sounds like it should be intuitive, but once you think about it, it's not. The most important thing - whatever it is! - needs to be done well. Shouldn't we hire the best person possible to handle it? And isn't it vanishingly unlikely that the person already works here?

You're right! In an ideal world, you would get the best, most motivated, most passionate project manager in the world to manage your project. And the best, most motivated, most empathetic, most wise people manager to manage your people. But the real world is rarely ideal. You are unlikely to find the best person in the world on short notice. You probably can't afford to pay them what they deserve. In a wide world where they have their choice of exciting projects, they (statistically) probably don't care enough about your project anyway. And because they're so good, they're probably accustomed to leading huge teams with huge problems that need huge solutions.

In short, you aren't likely to hire the ideal person. You can probably hire a pretty good person. Or you might get unlucky and hire a terribly mismatched person.

That variability is a huge problem. Even if the average person you could hire might be better than you, the standard deviation is very high. It's essentially a random chance, a lottery ticket. Do you want to buy a lottery ticket for the (self-selected) most important thing in your entire domain, whatever it is?

The alternative is to find a person with less specific expertise, but who can understand the company vision, connect with everyone on the team personally, be highly invested in the shared outcome (not just personal gain), and be so passionate about the project that they'd be willing to step aside if they can someday find someone who is a better fit. As a bonus, this person already works at your company: it's you.

Relatively speaking, it's actually pretty easy to learn project management and scheduling or people management. It takes time and effort, but not much more, to become passably decent at either one. Whereas you can't buy shared vision, personal knowledge, shared motivation, or humility, for any amount of money.

Once the schedule or the management of small teams is no longer your most critical problem, then delegate those. Better still, by then you will know how to do the jobs, so you will be very good at interviewing your replacement.

Footnotes

1 "Core competencies" is one of those once-useful terms that has been badly diluted through overuse. It mostly just means "things that uniquely make you special compared to your competitors." If you're a software company, that's probably your software.2 So buy some commodity package (or service) to do your accounting, which doesn't differentiate you, and hire people to write your software, which does.

2 Even at a software company, sometimes your software is crappy and your customer service or sales organizations are your real advantage. Confusion about this has led to horrible strategic blunders. IBM's core competency, for example, clearly is not software.

Posted Fri Nov 30 21:20:48 2018 Tags:
I regularly receive questions from students in the field of computer science looking for career advice.

Here's an answer I wrote to one of them. It's not comprehensive or anything, but I thought people might find it interesting.

[A question about whether to choose a 9-5 job or be an entrepreneur]

The question about "9-5" vs. "entrepreneur" is a complex one -- not everybody can be a successful entrepreneur (who would do the work? :-) and not everybody has the temperament for it. For me personally it was never an option -- there are vast parts of management and entrepreneurship that I wouldn't enjoy doing, such as hiring (I hate interviewing and am bad at it) and firing (too emotionally draining -- even just giving negative feedback is hard for me). Pitching ideas to investors is another thing that I'd rather do without.

If any of that resonates with you, you may be better off not opting for entrepreneurship -- the kind of 9-5 software development jobs I have had are actually (mostly) very rewarding: I get to write software that gets used by hundreds or thousands of other developers (or millions in the case of Python), and those other developers in turn use my software to produce product that get uses by hundreds of thousands or, indeed hundreds of millions of users. Not every 9-5 job is the same! For me personally, I don't like the product stuff (since usually that means it's products I have no interest in using myself), but "your mileage may vary" (as they say in the US). Just try to do better than an entry-level web development job;  that particular field (editing HTML and CSS) is likely to be automated away, and would feel repetitive to me.

[A question about whether AI would make human software developers redundant (not about what I think of the field of AI as a career choice)]

Regarding AI, I'm not worried at all. The field is focused on automating boring, repetitive tasks like driving a car or recognizing faces, which humans can learn to do easily but find boring if they have to do it all the time. The field of software engineering (which includes the field of AI) is never boring, since as soon as a task is repetitive, you automate it, and you start solving new problems.
Posted Mon Nov 26 17:13:00 2018 Tags:

I recently decided to switch my laptop from a Macbook to a Chromebook, partly because Apple's keyboards are so terrible lately, and partly because ChromeOS is suddenly useful now that they invented Crostini.

(Some people ask why I, a person who actually knows how to use Linux and has debugged wifi drivers and XF86Config files, would want to use a locked-down desktop Linux variant instead of just installing Debian or something. And I do install Debian, on desktop hardware. But on a laptop, hardware support is paramount: external monitors (eg. for presentations), bluetooth audio (for music while travelling), long battery life, and rapid, non-crashy suspend/resume, are all really important to me. ChromeOS actually does all that stuff reliably nowadays, because they design the OS and the hardware at the same time. Debian can't compete with that.)

One showstopper for me when I'm trying to do software development, however, is having a proper window manager, which is to say, one that I can run without resorting to a mouse or touchpad. Because I am old and crusty and unreasonably opinionated, the one I want to run is ion1. I had it working on MacOS, but I wanted it on ChromeOS.

Now, modern ChromeOS uses Wayland as its display manager, not X11, which is of some concern becuse ion1 stopped evolving more than a decade ago (which is how I like it) and therefore only understands X11. Also, ChromeOS provides a Wayland compositor and doesn't let you replace it from Crostini, even though they do let you securely launch Wayland and X11 windows from Crostini (which is pretty cool).

Do we give up? No! The "obvious" "solution" is Xnest, an "X proxy" from before the dawn of time, which puts all your windows inside one big window. So I created one big full-screen Xnest window (managed by Wayland), and then ran ion1 and a bunch of rxvt terminals inside.

This actually worked almost right, except: ion1 doesn't support these fancypants client-rendered fonts. No. It's old and crusty, like me. It expects the X server to render its fonts. And unfortunately, ChromeOS contains only about four fonts in its X server, all of which are hopelessly microscopic on the 200dpi screen in my Chromebook. Oops.

Luckily, about 11 years ago, slightly after the dawn of time, someone else didn't like some Xnest limitations and made Xephyr, which apparently is more of a framebuffer and less of a proxy, the upshot of which is that it renders its own "server side" fonts (which from Wayland's point of view are on the client side, but from ion1's point of view are definitely on the server side). As a bonus, thanks to xrandr, it understands the idea of having its window resized, so I can use the handy ChromeOS "full screen" key and have it do something nice. Or drag it to an external monitor and get decent results.

I didn't try to do anything with 3D, but nominally Xephyr can do that too. But Crostini supposedly can't. I don't know and I don't really care, I'm just trying to run some terminals here.

Xephyr and its DPI calculation

One weird problem I've had with Xephyr is that whatever it's doing to calculate "dots per inch" (as reported by xdpyinfo) is completely insane. It starts off with a value that is definitely not the same as its host display, and then if you resize the window, it just changes the value and gets more and more confused. This is bad for people who want to specify their font size in points so that fonts will be roughly the same size no matter what size the display is.

As far as I can tell, this is just a bug in Xephyr. But if anybody knows what's going on or (especially) how to fix it, I'd love to know. Meanwhile, I learned to specify my font sizes in pixels instead of points.

Cut and paste

An even more annoying problem, which deserves its own section, is the question of how to deal with cut-and-paste between my Xephyr+ion1+rxvt session and the toplevel Wayland session. This is needed for two reasons:

  1. I want to copy URLs and text between my web browser and my terminals.

  2. I want to be able to run multiple Xephyr sessions and share text between them.

By default, Xephyr appears to have no clipboard sync at all between its internal clipboard and its host server's clipboard. That's no fun. (To their credit, ChromeOS does seem to manage to sync the clipboard between Wayland and its toplevel XWayland session, which is essential if we want anything to work. It's just Xnest and Xephyr that break the chain.)

Now, there are a few things you should know about X11 clipboards. The canonical explanation is jwz's X Selections, Cut Buffers, and Kill Rings, which is quite excellent and gives some background on how it's not the X11 clipboard that's crazy, it's all the apps using it.

So anyway, with that background in mind, all we need to do is magically keep the clipboard in sync between :0 (the toplevel XWayland server, which is synced with Wayland and Chrome), and :1 (inside my Xephyr server), and ideally :2 .. :n (inside other nested Xephyr servers). How hard can it be?

Well, apparently it can be hard. The best answers I could find on the Internet (which I won't link to, because they suck) are:

  1. Run a script that uses xclip to periodically grab the clipboard content from each server. If one server has different clipboard content than the currently-expected content, then copy it to the other server. This method has a few problems: first, you have to choose a periodicity for the sync process, which is inevitably either annoyingly long or battery-killingly short. Second, the "content based" sync decision is rather error prone and results in potentially unstable race conditions, especially with multi-way sync. And third, typical implementations are a little too pushy about copying the clipboard data to all screens: jwz's article talks about this problem in refence to the "X cut buffer" support before the new-style support was added. If you highlight/copy text frequently or in large volumes, it's pretty wasteful to copy it to other screens before it's needed for pasting.

  2. Run synergy, a tool that lets you seamlessly extend your mouse/keyboard/clipboard across multiple displays on multiple computers. This was very tempting, despite being severe overkill (I don't want to extend my mouse and keyboard, just my clipboard). Unfortunately, it didn't work. It almost worked. But it didn't.

Luckily(?) for you, I spent quite some time diagnosing why synergy didn't work for me in my use case. The symptom was that it would sync the clipboard in only one direction (say A->B), and only the first time I copied something. If I copied another thing on A, the clipboard on B would not be updated. To make it update, I had to copy something on B (which always fails to sync to A), and then copy something on A (which would work).

How hard can it be? I thought to myself, again, foolishly, and decided to read the source code.

Now, the synergy source code is actually pretty good. It has a nice abstraction layer for the various clipboard types in X, MacOS, and Windows. It's pretty easy to follow. It has a bit too few debug trace messages, but okay, those are easy enough to add as we go.

Unfortunately, synergy's clipboard support has two fatal design flaws:

  1. Like the periodic xclip case above, it grabs a copy of clipboard data right away when the clipboard ownership changes. It's better than a naive xclip script, because it actually gets a notification when the clipboard ownership changes, rather than polling periodically. Unfortunately, those notifications are also its downfall. See, in X11, there is only a clipboard notification when the clipboard owner changes, not when the content changes. If I copy text from rxvt, it will grab the clipboard. Synergy will notice this and read the clipboard. But if I then copy different text in rxvt, the owner doesn't change, so there is no notification, so Synergy doesn't re-copy it. That explains why it only worked the first time. (It also explains why copying on B and then on A causes it to work again exactly once: the clipboard ownership changes.) (This bug may not be visible on all terminals. If rxvt would give up the clipboard, then take it back, every time I made a copy, it would work around this problem.) (I think VNC's clipboard sync has/had the same problem.)

  2. Synergy, because it's mostly a keyboard/mouse sharing app, maintains the concept of a "current screen." That is, it watches which screen currently has the mouse pointer, and only replicates the clipboard to that screen. This is a performance optimization: since it (like the poorly designed "x cut buffer" mentioned by jwz) takes a copy every time the clipboard changes, it doesn't want to replicate this to screens where you're not using it. Unfortunately, since my screens are nested, I had to disable the keyboard/mouse sharing feature, which also leaves the "current screen" incorrect exactly half the time, which is why the clipboard fails to replicate from B->A and only works from A->B.

I was willing to try to fix some minor clipboard bugs in synergy, but I gave up when I realized this design (grab and replicate the content as soon as clipboard owner changes) was never going to work well with rxvt. That's when I gave up and decided to write my own trivial clipboard syncing tool, based on all the otherwise-useless trivia I had acquired while investigating the above.

The result is xclipsync, and, other than omitting non-text clipboard formats, I think I did it right.

  1. It starts up by taking ownership of the clipboard on display A.
  2. When it loses clipboard ownership on A, it takes ownership of the clipboard on display B.
  3. When it loses clipboard ownership on B, it goes back to step 1.
  4. When it receives a request for clipboard contents (which should be someone requesting a paste), it then reads the clipboard content from the display that it doesn't currently own, and forwards it along.

And that's it!

This avoids the problem of a single owner changing their clipboard content (since it grabs content only on demand). It doesn't do extra work if you copy content without pasting. It actually does nothing at all if you do a lot of work on one display: it loses the clipboard content on that display, which means it does nothing at all until you use the clipboard on the other display. It doesn't ever poll anything, so there are no arbitrary delays or race conditions.

And best of all, this algorithm works even for multi-way sync. You can run parallel instances of xclipsync between any two displays, and as long as you don't create any bridging loops, it will do the right thing across all of them. That is, exactly one display will "own" the clipboard, and all the other ones will copy from it. This works because every time you copy something from a new display, exactly one xclipsync instance will lose ownership, which causes it to assert ownership on exactly one display. If another xclipsync is syncing with that display, it will then lose ownership, and assert ownership on exactly one other display, and so on. As long as there are no loops, this process will terminate, and it'll do so very efficiently.

Things that could be better

There's no particular reason xclipsync can't support non-plaintext clip formats. I just didn't implement it, because I didn't need anything but text, since my Xephyr session is just terminals anyway.

xclipsync currently uses tcl/tk to take clipboard ownership (yes!). This would have been unnecessary if xclip had just one more feature: the ability to run a command at paste time, rather than always reading clipboard content from stdin at startup time. Then xclipsync would have been just a couple of (foregrounded) alternating xclip calls in a loop.

Xephyr probably should just implement this exact clipboard syncing protocol internally.

Note that it appears ChromeOS+Wayland is actually implementing some other kind of clipboard sync between Wayland and the toplevel XWayland server. When xclipsync tries to take ownership of the XWayland clipboard, it immediately experiences one "paste" operation and then loses ownership. This might be related to WAyland's inter-process security isolation features. In any case, xclipsync reacts as usual (giving clipboard ownership to XWayland and proxying requests to XWayland from other displays that want to paste) and all is well.

I really wish Alt-Tab would work even when the Xephyr instance is fullscreened in ChromeOS. I understand why they want to let me capture Alt-Tab in my full-screen X apps, but also... I don't want to.

The marketing-driven "Assistant key" on the Pixelbook is a user-hostile disaster in its current form. On the other hand, if they would let me remap it to, say, Meta, it would instantly redeem itself.

Posted Sat Nov 24 13:56:30 2018 Tags:

I have until now avoided making a public statement about my views on the various interrelated issues regarding the GNU Kind Communication Guidelines that came up over the last month. However, given increasing interest in our community on these issues, and the repeated inquiries that I received privately from major contributors in our community, I now must state my views publicly. I don't have much desire to debate these topics in public, nor do I think such is particularly useful, but I've been asked frequently about these GNU policy statements. I feel, if for no other reason than efficiency, that I should share them in one place publicly for easy reference:

  • I think the GNU Kind Communication Guidelines, as a stand-alone document, are useful suggestions and helpful to the GNU project and would be helpful, if adopted, for any software freedom project.
  • However, I think that the GNU Kind Communication Guidelines standing alone are inadequate for a project of GNU's size and number of contributors to address the stated problems. Traditional Codes of Conduct, particularly those that offer mechanisms for complaint resolution when bad behavior occurs, are necessary in Free Software projects of GNU's size. Codes of Conduct are the best mechanism known today in our community to ensure welcoming environments for those who might be targeted by inappropriate and unprofessional behavior.
  • I therefore disagree with the meta-material stated in the announcement of these Communication Guidelines. First, I disagree with the decision to reject any Code of Conduct for the GNU project. Second, I believe that diversity is an important goal for advancing software freedom and human equality generally. I am a supporter of Outreachy and work hard to help it succeed as part of my day job. I have publicly supported affirmative action since the early 1990s, and continue to support it. I agree with “making diversity a goal”; Richard Stallman (RMS), speaking on behalf of GNU, states that perse disagrees with “making diversity a goal”.
  • I also disagree with encouraging GNU project contributors to ignore the request of non-binary-gender individuals who ask for the pronouns they/them, as stated in RMS' personal essay linked to from the GNU Kind Communication Guidelines. My position is that refusing to use the pronouns people ask for is the same unkindness as refusing to call transgender people by a name that is not their legal name when they request it. I don't think the grammatical argument that “pronouns are different from proper nouns” is compelling enough to warrant unwelcoming behavior toward these individuals. The words people use matter. RMS has insisted for years that people make a clear distinction between open source and free software — for good reason —. I believe that how we say things makes a political statement in itself.
  • Related to the last point, I am concerned with the conflating of GNU project views with RMS' personal views. RMS seems to have decided unilaterally that GNU would take a position that requests for use of they/them pronouns need not be honored. I think it is essential that RMS keeps per personal views separate from official GNU policy; I have said so many times to the FSF Board of Directors in various contexts. It was a surprise to me that RMS' personal view on this issue was referenced as part of GNU project guidelines.
  • I think the GNU Kindness Communication Guidelines should apply to all communication from the project, including GNU manuals themselves, and I also believe the glibc abort() joke should be removed. I don't believe free speech of anyone is impacted if a Free Software project forbids certain types of off-topic communication in its official channels. Everyone can have their own website and blog to express their personal views; they don't need to do so through project channels.

I have been encouraged many times this year by various prominent community members to resign from the FSF's Board of Directors (sometimes over these issues, and sometimes over other, similar issues). I have also received many private communications from other prominent community members (including some GNU contributors) expressing similar concerns to the above, but these individuals noted that they feel much better about the FSF and its shepherding of the GNU project because I'm on the FSF Board of Directors, even though I clearly pointed out to them that my views on these matters will not necessarily become GNU and/or FSF policy. The argument that many have made to me is that it's valuable to have dissenting opinions in the leadership on these issues, even if those dissenting opinions do not become FSF and/or GNU policy.

I am swayed by the latter argument, and I have decided to continue as an FSF Director indefinitely (assuming the other Directors wish me to continue). However, these recent public positions are far enough out of alignment with my own views that I feel it necessary to exercise my own free speech rights here on my personal blog and state my disagreement with them. I will continue to urge the FSF and GNU to change and/or clarify these positions. (I also sent this blog post privately to the FSF Directors 8 days before I posted it, and had also discussed these concerns in detail with RMS for a month before posting this.)

Governing well means working (and finding common ground) with those you disagree. We oscillate a bit too much in software freedom communities: either we air every last disagreement no matter how minor, or (perhaps as an over-correction to the former) we seek to represent a seemingly perfect consensus even when one isn't present. I try to avoid both extremes; so this is the first time in my many years on the FSF Board of Directors where I've publicly disagreed with an FSF or GNU project policy. FSF and GNU primarily fight for one principle: equal software freedom for all users and developers. On other topics, there can easily exist disagreement, and working through those disagreements together, in my opinion, usually make the community stronger.

As always, this is my personal blog, and nothing here necessarily reflects the official views of any organization with which I am affiliated, including not only the Free Software Foundation and GNU, but also Software Freedom Conservancy.

Posted Thu Nov 22 08:09:00 2018 Tags: