Free download:

Software Wars, the Movie

Soundtrack for the book:


If you enjoyed the free download, a donation of the cost of a newspaper would be appreciated.



The best book explaining free market economics:

The best explanation of how we can build a space elevator in 10 years:


Book explaining a political solution to our economic problems:


1+ Year Running Arch Linux on a Lenovo Yoga 2

In October 2013, I bought a Lenovo Yoga 2 Pro:
Promotional picture of a Yoga 2 Pro.
After 5 years with a Thinkpad, I was ready to upgrade to a prettier model. I wrote a long, but still incomplete review, and it became the most popular article on my website. It has apparently become one of Lenovo’s best-selling models because I’ve seen advertisements for it during NFL football games.

So, I decided to write an update after long-term daily use. Things have gotten better, but numerous challenges remain, and there have been some regressions. If you read the Linux newswires, you might think the biggest remaining challenge holding back Linux is systemd. While the drama and arguments are interesting, it has been the least of my worries. My biggest daily frustration is the drivers.

What if it took an airline 1-2 years to return your lost luggage? Or, imagine Linux as a big estate, where the developers are the maintenance staff. Everyone is discussing their specific features, such as the design of the Italian ceramic tile in the 4th swimming pool, but there is no toilet paper in the guest bathroom. This is a known problem, but it sits with the other 2,736 active bugs and 402 regressions. The biggest Linux discussion is about Linus’s sarcasm, not whether there is anything lacking in the quality of the release process. The Linux kernel is already very high quality, but with thousands of active bugs, there are bound to be millions of unhappy users. My machine alone experienced 10 of them — I had 10 reasons to be unhappy.

You can’t just look at patches, you also need to look at bugs – the patches that are missing. The value of a bug list is that it helps you find the areas of the code that the programmers are ignoring, that need more resources.

I would suggest goals such as having all bugs resolved within 1-2 releases. Many sit around for 10+ months today. Not all bugs have to be fixed, but from going through the active list, most of them seem like they need to be, and a lot of them are scary looking.

Other than the hardware-specific issues, I’ve been amazed by how well Arch Linux works, given that it doesn’t have release cycles, or a big team with a lot of money supporting and marketing it. I’ve heard only 30 developers maintain the core Arch packages, with most of them having a full-time job doing something else! At the same time, it shouldn’t be a total surprise things work so well because free software doesn’t just fall off a turnip truck:

With notable exceptions and regressions, every free codebase is getting better every day.

I still run Debian on my server, but I think Arch is a great OS for the desktop where things are evolving so quickly, and each component has its own release cycle. A lot of average Linux users don’t talk much about Arch, but all the big software teams are aware because they find bugs months before the other distros, and have knowledgeable testers. Arch, because of its setup process and superb wiki, creates more competent users. Not everyone needs to know how to use the command line, but everyone reading this review should!

While it might seem scary to not have a huge full-time team behind an operating system, in truth, the bigger distributions also have more users and so that your particular bug isn’t likely to get much attention. Nearly every major free software codebase has thousands of active bugs. It can take years to get something fixed.

While things are getting better every day, you can still have risks of regressions, but you are not really stuck in Arch. You can always downgrade to a previous version of the software: “pacman -U pkgname-oldver.pkg.tar.gz”. The package manager will also automatically downgrade any components that depend on the newer package.

The install process that I wrote about in my first review was a little complicated, but it was also an interesting and enjoyable learning experience. In general, the only ongoing maintenance I now do is to run “pacman -Syu”. This downloads all the newest software and installs it. There is no new release to celebrate, you are always up to date. I expect to be able to run this installation for years without having to bother doing it again.

The only tricky thing I had to deal with was getting my Android phone connected. I’m not sure how it is handled on other distros because I never had this phone until I got Arch, but I can say it was a pain. The problem is that my LG G2 didn’t support the extremely popular USB mass storage protocol. Even the iPhone supports it! Instead they force you to use MTP, which is a crappy standard created by Microsoft. Samsung at least offers you a choice. Unfortunately, while there are multiple implementations of MTP on Linux, some didn’t work for my phone. Eventually I got it working by using the gvfs-mtp package.

Kernel

I’ve not yet had a problem with my machine not booting, but I did have a regression with my Intel wireless driver that was almost a catastrophe because a laptop without Internet is basically useless as a work machine. The wifi-menu command broke with my Intel card. It should bring up something like this:netctl

Instead, it just returned:

Scanning for networks… failed

No networks found

This is a command I ran every time I turned on the computer or wanted to switch to a new Internet hotspot. I never actually proved whether it was a kernel bug or a wifi-menu bug, but I suspect it was a quirk of the Intel driver, and this command wasn’t broken for all network cards for so many months. It would have been a huge problem to have no networking, except that the command “netctl start wlp1s0-MyHomeNetwork” worked, so even though scanning was broken, I could still start profiles.

As a side note, I should be using the GUI Network Manager:

It is the de-facto wireless GUI on Linux, but it was broken for my machine because it thought my wireless card was disabled. The kernel was giving out invalid rfkill information for this model. The Ideapad_laptop kernel module was returning invalid wireless data for this machine until 1 year after it was released. This is a few thousand lines of code that Lenovo should be helping to maintain, but does not. It is sort of amazing that a company with 54,000 employees can’t afford even one to help maintain even the most basic Linux support.

Meanwhile, my mouse is the most frustrating issue. I’ll talk more about it later, but the reason the official Linux driver is so buggy is because Synaptics wrote a driver, but never released it publicly. It is that sort of mentality that has been killing Linux on the desktop.

I’ve had a number of other random kernel issues. Resume has been flakey. It didn’t work at the beginning, and then it got better, but periodically it gets worse again. For a while, I never closed my screen because I didn’t trust it would come back. Sometimes, it would come back, but Gnome wouldn’t let me login!

For a while, the laptop speakers never worked after a reboot until I plugged something into the headphone jack, and then removed it. It was fine when I bought the machine, but broke for about 6 months. The sound’s maximum allowed volume was much too high initially, and sometimes the fader magically moves on startup, so I have to go into the options and re-set it.

Initially my machine was generating about 70 MB of kernel spew per day of spurious error messages. So I configured systemd to just write them all to RAM. This isn’t necessary anymore as the logs look better now. For example, the constant USB “errors” I wrote about in my first review have gone away.

Overheating

The Yoga blows hot air out of the bottom of the machine, compared to my old Thinkpad, which ventilated out of the sides. The downside of the new design is that you have to be careful what you place the computer on. One time I was building LibreOffice while it was on a blanket and it overheated and charred the bottom.

20150327_135649-2

Fortunately, it didn’t ruin any of the electronics. It would be interesting to know whether the Linux power management prevented the computer from dying, or whether I had pulled it away in time. However, I’m not going to do any more testing! When doing CPU-intensive work, I now place this laptop on a metal plate.

Graphics

I’ve been very happy with the 13-inch 3200×1800 screen. Eventually I was able to remove the “acpi_backlight=vendor” kernel hack I mentioned in my first review, and then the brightness keys worked.

The random screen dirt bugs were fixed by Intel a few months after my review. Sometimes I’d have up to 50 8×4 black rectangles randomly scattered all over my screen. I presume nearly everyone at Intel are running Windows because a number of bugs don’t get fixed until after they’ve shipped the hardware out to customers. This means the kernel developers need to balance their time between supporting the upcoming hardware, and making it actually work on hardware that customers already have.

Clearly they are not creating the hardware and the Linux drivers concurrently, in a holistic fashion. Part of the reason the drivers are buggy is because of issues in the hardware that weren’t found until after it was shipped. In one bug fix, the Intel driver developer wrote: “There seems to be no clear rationale for these flushes.”

There are 4K videos on Youtube, but they are extremely jittery and suck all the CPU as the GPU is not being used. I don’t play many videogames, but it is a shame that the driver only supports OpenGL version 3.3, which was released in 2010, whereas the current standard is 4.4.

I installed Steam and played Portal 2 at ¼ resolution: 1600×900, and it looked great and didn’t stutter. I tried Blender and discovered that it can’t use Intel’s GPU for rendering. It took hours to render these 3200×1800 Arch wallpapers. Intel has implemented the OpenCL API for Linux, but the drivers use the CPU only. This is in the process of being fixed, but it still isn’t yet.

I had to double-check this fact because it made no sense to me that an API designed for GPUs would be implemented only on CPUs, but that is the current state in the Intel Linux world. People give Intel a lot of credit for doing well with graphics drivers, but a big part of that is that they look good only by comparing to AMD and NVidia, which have historically been terrible. You get the sense that Linux is publicly “supported” by Intel, but that the Linux laptop team is still a skunkworks project. I heard from an Intel employee 9 years ago that Linux had 1% of the investments that Windows had, and I suspect it is about the same today.

Mouse

The mouse was extremely annoying when I first got the computer. As I wrote in my initial review, I was briefly sorry I didn’t keep Windows around because it is hard to concentrate on an idea while having to also focus on the mouse.

The good news is that it is less flakey. It use to jump violently all over the screen while typing, but now it just hovers in small circles. Sometimes the mouse still disappears; I’ll want to move it a few inches, and it will instead end up on the edge of the screen, out of sight.

With the old Trackpad, it used to be okay to gently rest your finger on the left or right mouse button, while you moved the pointer with other other hand, but now you cannot! With the current Linux driver, when there is a finger in the “soft button” area, the driver currently ignores all touches and movements, not just those in the fake button area.

For now, I’ve retrained my muscle memory. I just hold my finger above the click area until I need to use it. It took several weeks to be able to do it without thinking. I’ve seen configurations that are supposed to work better for this trackpad, but there is no UI, so you can’t easily just try things and test. I created a petition a couple of months after my review to encourage Synaptics to improve the Linux mouse drivers. Even after a year of deliberating, they are still thinking about what to do. It is a shame a company with 500 employees can’t even decide to maintain a driver for their hardware, that is less than 10,000 lines, and is already mostly written.

Keyboard

I’ve gotten used to the keyboard, but it is still difficult in various ways. After a couple of weeks, my fingers adjusted to the swapped left Fn and Ctrl keys, but whenever I go back to another layout, I get frustrated again. I wish the keys could have a bit more depth to travel, and be curved, like their old keyboards, but it isn’t a huge problem. I don’t understand why a $1,000 laptop can’t have a quality keyboard. The computer is 1.5 centimeters thick. I’d be happy to allocate more space for a better keyboard and battery.

I’ve generally gotten used to the new locations on the keyboard, although I need to look down to find special keys (such as Page Up). There are various negative issues when they combined the Function keys and IBM’s other special buttons.

The first problem is that the special keys are not broken up into groups like they used to be. I used to know that the volume increase button was the last button in a special group. It was easy to find, and I wouldn’t accidentally press any other buttons. Now I either have to count over to the 4th button, or look at the keys, which often involves moving my fingers out of the way.

Some of the keys are overloaded such that the F4 button is mapped to close, so instead of having to hit Alt-F4 as I used to, I can just hit the F4 button. This is one example of saving a keystroke. But it is actually also a problem because the button is right next to the volume increase button, and so I’ve sometimes closed the application when I meant to make the song or video louder.

Most of the other special buttons I don’t use. One of the buttons turns off the screen backlight. Hitting that accidentally can be confusing and I can’t really imagine the use case for it. It is also more difficult now because some things like F5 and F11 which I use somewhat frequently, require two fingers. One other little issue I ran into is that the print screen key is right next to the backspace key and so I sometimes overshoot and press it instead. I have created 100s of screenshots over the year. I don’t think the classic Thinkpad keyboard was perfect, but it was definitely better.

HiDPI

The HiDPI support has improved, especially in Gnome, but it still has a long way to go when you consider the long tail of applications. Gnome since version 3.14 has fixed almost all of the HiDPI issues I wrote about in my first review. However, Gnome 3.16 still has a few problems:

The scrollbars in all Gtk2 apps are too narrow. You can manually tweak this by opening the file: usr/share/themes/Adwaita/gtk-2.0/gtkrc and doubling the ‘slider-width’ from 13 to 26. A bug was filed against Gnome, but nothing has been done yet.

There was a HiDPI regression in Gnome 3.16. The desktop icons are huge, as if the computer is to be used by a 5 year old. They looked fine in Gnome 3.10-3.14. Fortunately this can be fixed by the File – Preferences menu in the file manager, but it disrupted my existing desktop icon arrangement and I had to redo it.

I wish that Gnome 3.x had more themes, and allowed for multiple color schemes. I read a funny quote on Slashdot: “KDE looks like a widget factory exploded on your desktop. Of course, GNOME looks like they’re experiencing a widget shortage, perhaps due to a widget factory somewhere being out of production due to an explosion.”

I learned after my review that Firefox can enable HiDPI support if you set: layout.css.devPixelsPerPx to 2 in about:config. I still use the NoSquint plugin so I can tweak the text size of individual pages, but it is nice that websites look pretty good automatically, and this tweak also makes Firefox’s own UI elements larger and nicer, whereas the plugin doesn’t.

I did a couple weeks of coding to help LibreOffice 4.2.3 look better on HiDPI screens, and the work has continued since. You can read my writeups about it here: Part 1: Writing, Part 2: Shipping. There are numerous other important applications out that still need basic fixes in applications such as Gimp, Audacity, VLC, and Inkscape. A few programs like Blender allow you set the DPI of the UI so even though it doesn’t look good out of the box, you can quickly fix it. It is easy to fetch the DPI on Linux via “xrdb -query”. People with these screens, report issues in your favorite apps, or send patches! Scaling the toolbar buttons in LibreOffice was just a few lines of code and by itself made a huge difference. 16×16 icons look like dead bugs on my screen. A lot of applications are waiting until they port to Gtk3 to fix their HiDPI issues, but it isn’t necessary, nor sufficient!

Wear

The hard drive is doing fine, writing to each cell 10 times since my first review. At the current rate, the drive should last 300 years. According to their calculations, I’m writing on average 5 gigabytes a day. Most of my HD writes are for new software from Arch, but that has only averaged 1.7 gigabytes a week of uncompressed files. That is about 120 gigabytes, whereas I’ve supposedly written 2.5 Terabytes! Where the extra writes are coming from is a mystery, but not a big problem.

One of the reasons I wanted a new laptop was that the florescent bulb on my 2008 laptop was getting very dim. This LED is more efficient, and will last a long time without degrading.

The battery is doing fine and gives about 3.5 hours with moderate brightness. I wish I could set the maximum recharge to 90% which would make the battery last much longer. It is not good to have a battery fully charged for long periods of time. Furthermore, I almost never need that last 10%. Unfortunately, such advanced battery features are not yet enabled in Linux. Within a year or so I’ll have to buy a Torx T-5 screwdriver to open the machine up and replace the battery. Otherwise, I expect this laptop will last me 5 years. I wouldn’t even consider buying the new Yoga 3 Pro, as they took away all the function keys. There is even more unused space on the machine as it is now just a 5-row keyboard. The world of Idiocracy inches closer.

Conclusion

This machine overall works better than when I first got it, considering the software improvements. I hope things improve further in the next year, especially with regards to HiDPI.

In spite of my problems, I’m very glad I don’t need to mess with the Windows or Mac world. They are more bloated, yet more constrained. The Linux desktop has plenty of workitems, but it advances everywhere. I’m surprised Arch is only the 9th most popular version of Linux on Distrowatch. However, if you add in Manjaro and Antergos, it would be #2. (I recommend people run Antergos rather than Manjaro, if they don’t want to install from the command line as it uses the official Arch repositories.)

I’m happy I’ve never had to mess with UEFI. I don’t feel like I’m missing any features compared to the old BIOS system. I hope it remains optional indefinitely but I somehow doubt it. Lenovo has no idea how many people are even using their legacy BIOS option, and I doubt it is a question they’d ever think to ask.

Once the hardware works, then we need the applications. Music and movie-making are a big priority in things that need to get better. I’ve heard that a number of the Ableton software engineers personally love Linux and they write a lot of their code in Python, but their software is released only on Windows and the Mac. I’d prefer if people were working together on free software for music creation, but in the meantime, running Ableton on Linux should be a better experience! The key to the Linux desktop’s success is lowering barriers.

Since Ableton already supports Windows and the Mac, supporting Linux isn’t technically very hard. Applications like Firefox, Chrome, LibreOffice, VLC, Audacity, Gimp, and many others are cross-platform. There are many challenges to Linux reaching beyond 1% on the desktop. I wrote a chapter about them in my book years ago, and there are new ones since. Fortunately, it generally gets better, if not always in the places that need it most.

It is amazing how Linux is doing very well, given how so much of it is underfunded. The UK government has given hundreds of millions of dollars to Microsoft for Office alone, and yet the foundation behind LibreOffice has total of a $225,000 budget. Hopefully along with the UK government’s decision to standardize on ODF, it will also include investments in free software to support their needs. The proprietary world continues to suck up huge amounts of money which is effectively starving Linux.

Shipping the LibreOffice HiDPI Patches, or How I Learned to Love Heartbleed

I wrote my story about getting some HiDPI patches into LibreOffice, but it was an unfinished one because while the code had gotten accepted into the main Master branch, there was a lot remaining. It hadn’t shipped, I’d only tested it on Gnome and KDE, it hadn’t been tried on Windows, and didn’t work on the Mac. Worst of all, because it missed the December 20 cutoff date for 4.2.0, it was on the default next release train for 4.3.0 in late July.

LibreOffice has a two-part release process. You are encouraged to submit code into the main tree where it can sit for up to 6 months. Twice per year, it is branched and shipped. In between these major releases, every month or so, a minor release is made containing high priority fixes. Meanwhile most of the development team moves ahead adding features and cleanup for the upcoming release.

The code was too late for 4.2.0, and so it wasn’t getting much feedback. Very few people run the daily builds, with all the releases and release-candidates to test. A friendly chap named Darcy from Australia showed up on the QA alias, built LibreOffice on his Fedora 20 laptop, and verified that it worked, but that was it. The only way to get this code tested was to get it out there.

I had also decided to stop working after the second batch. I had improved the most noticeable parts of the product, but I was also steadily making more potential problems for myself. Software isn’t just about code, it is about standing behind your work. I could prove most of my changes were fine, but I was changing places where I didn’t always understand what was going on around. I could justify my fixes, but not the code around it.

Even though LibreOffice is built by a community where other people can fix your bugs, other people can also find your bugs. If your code is causing problems, and no one has time to look into it, it can be reverted. The work is interesting, but I was just a motivated user with some free time during the Christmas holiday. I wanted to reserve time to deal with the inevitable complaints.

In spite of the lack of feedback, since it makes a visual and usability difference, why wait? More computers with these beautiful screens are coming out every day. A very high-resolution screen is the best reason to buy a new laptop. There should be a free software experience that we can enjoy looking at. LibreOffice has plenty of ways to improve, but it can look good in the meanwhile.

Sidebar

The Sidebar was one of the areas I had kept putting off and almost didn’t work on. It is about 70,000 lines of new code providing an alternate UI, and I wanted to focus on the existing one first. I have been using this codebase for almost 10 years and had never missed it. The code was also written by someone from IBM, and so I couldn’t trust that anyone in LibreOffice would be able to help me.

I also hoped that maybe the Apache team would notice bug reports and fix the Sidebar themselves. LibreOffice grabs fixes from Apache on a daily basis. Only about half the changes are useful because in many cases LibreOffice has already done the work, but any pieces of value are ported over, and just a small part of LibreOffice’s churn of the their thousands of improvements per release.

I considered sending an email to the Apache OpenOffice alias asking if they were aware of the problem, and whether they were planning to work on it. It is more efficient to coordinate efforts and not have multiple people re-learning each other’s work. It took me hours to fix problems that could have been fixed over lunch by the person who wrote the code. However, while LibreOffice is taking patches from Apache OpenOffice, the groups are generally not actively planning work, and so asking for HiDPI support for the Sidebar would have been a breach of protocol.

In addition, the codebases are diverging so fixes might not be usable. Apache OpenOffice doesn’t have the OutputDevice::DPIScaleFactor API, so the patches wouldn’t have been directly usable. I didn’t try Apache OpenOffice on Linux, but I did try it on Windows 8.1 and sidebar bitmaps looked doubled. However, Windows 8.1 might have been artificially scaling the entire Apache OpenOffice UI because the text was a blurry mess compared to LibreOffice:
OOLO2
So I could imagine that fixing the Sidebar for LibreOffice would not be a high priority for Apache.

While I personally don’t care about the Sidebar, it is now turned on by default for Impress. I knew that the more places I fixed, the stronger argument I would have to convince people to get the improvements out there. I realized I just needed to motivate myself to learn the code. So while I was in rural northern Michigan with my family over the holiday, there were some quiet nights, and I dug in and learned the Sidebar well enough to fix the major issues. It was the same process and techniques I had used for the other parts of the code. As per usual, finding the correct place to put in a fix was the hardest part.

I’m glad I worked on it because not only did it make the Sidebar fit in visually with the other improvements, it fixed a crashing bug. LibreOffice’s Sidebar is better than OpenOffice’s in that it has dynamic layout when docked. However, the bigger buttons created something wider than the maximum width allowed. With the sidebar starting in an invalid state, the product would still work, but if you tried to resize it with the mouse, you could sometimes get LibreOffice to hang. If you push software beyond its limits, bad things can happen.

I don’t even remember clearly how I found the place to fix, but by just reading enough code, I found the routine SidebarController::RestrictWidth.

@@ -1109,7 +1112,8 @@ void SidebarController::RestrictWidth (sal_Int32 nWidth)
const sal_uInt16 nSetId (pSplitWindow->GetSet(nId));
	pSplitWindow->SetItemSizeRange(nSetId,
- 	Range(TabBar::GetDefaultWidth() + nWidth, gnMaximumSidebarWidth));
+ 	Range(TabBar::GetDefaultWidth() * mpTabBar->GetDPIScaleFactor() + nWidth,
+ 	gnMaximumSidebarWidth * mpTabBar->GetDPIScaleFactor()));
	}
}

Getting on the 4.2.3 release train

Since it was a batch of new code to a stable branch, the LibreOffice Engineering Steering Committee had a discussion about it in one of their weekly meetings:

* HiDPI patches for 4.2.x? (Kendy)
    + LibreOffice does not look good on HiDPI screens at all - close to unusable
    + proposal to merge the HiDPI work to 4.2.x as a late feature
        + I would split the work into 'safe' and 'need real review' parts & push to a branch
        + can I get ESC approval / 3 independent reviews for that ?
    + is it a feature or a bug-fix ? (Michael)
        + most of the pieces going in enclosed in an if (hidpi) ...
            + checking that everything in the right if.
        + less safe part is checking / setting that flag; a small VCL piece.
    + Michael / Caolán signed up to review as/when there is a branch.

Once they gave their support, Kendy prepared for the patches for review.

Working with free software can be fun, but it can also be upsetting because problems can show up at any time. I was happy to see Kendy’s mail to the alias asking for review of the Gerrit patches, but not for very long because Norbert Thiebaud objected to them for the Mac. So after a flurry of emails over 3 days, we eventually got that resolved with another patch. So within a few days after that, the patches got reviewed and into the build for 4.2.3-rc1.

Windows

I was happy to see my efforts finally get into RC build, but I wasn’t happy for very long because this screenshot with clipped toolbar buttons showed up in my inbox:

This was upsetting for several reasons. The first is that it could have been found on master months before. Instead, it showed up on a day when I had my own things to work on. But instead of being able to focus on my tasks, I kept thinking about the toolbars, and what was I going to do about it?

I had been wondering for months what would happen when this code was tried on Windows. LibreOffice is created primarily by Linux developers, but Windows is the most popular OS for their users. My machine shipped with Windows but I had wiped it within a few hours and so couldn’t try it. I had used Windows for 15 years, but the last time was 9 years ago and I had no plans to go back.

I had envisioned various possibilities for what might happen on Windows, but cut-off toolbar buttons was not one of them. I also didn’t understand the toolbar layout code. I had written a toolbar manager before and didn’t want to volunteer any of my life on that boring problem.

However, I felt bad and that I should at least put some effort into trying to fix the problem. So that evening, I decided to just read through the toolbar code from beginning to end and see if I found anything obviously wrong. You don’t have to be very clever to notice a bloody knife at a murder scene.

And so I read through toolbox.cxx, including the toolbar layout code, and didn’t notice anything that stood out. So I next went to toolbox2.cxx. About halfway down, I found something suspicious:

/*static*/ Size
ToolBox::GetDefaultImageSize(bool bLarge)
{
    const long TB_SMALLIMAGESIZE = 16;
    if (!bLarge) {
        return Size(TB_SMALLIMAGESIZE, TB_SMALLIMAGESIZE);
    }

    OUString iconTheme = Application::GetSettings().GetStyleSettings().DetermineIconTheme();
    return vcl::IconThemeInfo::SizeByThemeName(iconTheme);
}

That 16 was a sign of a place that needed doubling. I didn’t yet know who used that function and whether it would make a difference, but opengrok helped me and found that it was called by the main toolbar layout routine.

So I made a change:

1738     // set defaults if image or text is needed but empty
1739     nDefWidth       = GetDefaultImageSize().Width() * GetDPIScaleFactor();
1740     nDefHeight      = GetDefaultImageSize().Height() * GetDPIScaleFactor();

However, I couldn’t tell whether it would fix the problem. The comment above the code, while happily in English, explained it was relevant only for empty toolbars. This was not a case I care about.

So I changed the code, and hoped the comment was wrong, but didn’t understand what the implication was. It was a change I would try if I had a Windows box. It requires much less mental effort to test a change than to manually prove what happens in a big function. As long as you can test something, you can postpone the necessity of full understanding.

Here is the main toolbar layout routine. I’ve highlighted in red all the references to the variable I changed.

bool ToolBox::ImplCalcItem()
{

    // recalc required ?
    if ( !mbCalc )
        return false;

    ImplDisableFlatButtons();

    long            nDefWidth;
    long            nDefHeight;
    long            nMaxWidth = 0;
    long            nMaxHeight = 0;
    long            nMinWidth   = 6;
    long            nMinHeight  = 6;
    long            nDropDownArrowWidth = TB_DROPDOWNARROWWIDTH;

    // set defaults if image or text is needed but empty
    nDefWidth       = GetDefaultImageSize().Width() * GetDPIScaleFactor();
    nDefHeight      = GetDefaultImageSize().Height() * GetDPIScaleFactor();

    mnWinHeight = 0;
    // determine minimum size necessary in NWF
    {
        Rectangle aRect( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
        Rectangle aReg( aRect );
        ImplControlValue aVal;
        Rectangle aNativeBounds, aNativeContent;
        if( IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
        {
            if( GetNativeControlRegion( CTRL_TOOLBAR, PART_BUTTON,
                                        aReg,
                                        CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
                                        aVal, OUString(),
                                        aNativeBounds, aNativeContent ) )
            {
                aRect = aNativeBounds;
                if( aRect.GetWidth() > nMinWidth )
                    nMinWidth = aRect.GetWidth();
                if( aRect.GetHeight() > nMinHeight )
                    nMinHeight = aRect.GetHeight();
                if( nDropDownArrowWidth < nMinWidth )
                    nDropDownArrowWidth = nMinWidth;
                if( nMinWidth > mpData->mnMenuButtonWidth )
                    mpData->mnMenuButtonWidth = nMinWidth;
                else if( nMinWidth < TB_MENUBUTTON_SIZE )
                    mpData->mnMenuButtonWidth = TB_MENUBUTTON_SIZE;
            }
        }

        // also calculate the area for comboboxes, drop down list boxes and spinfields
        // as these are often inserted into toolboxes; set mnWinHeight to the
        // greater of those values to prevent toolbar flickering (#i103385#)
        aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
        aReg = aRect;
        if( GetNativeControlRegion( CTRL_COMBOBOX, PART_ENTIRE_CONTROL,
                                    aReg,
                                    CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
                                    aVal, OUString(),
                                    aNativeBounds, aNativeContent ) )
        {
            aRect = aNativeBounds;
            if( aRect.GetHeight() > mnWinHeight )
                mnWinHeight = aRect.GetHeight();
        }
        aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
        aReg = aRect;
        if( GetNativeControlRegion( CTRL_LISTBOX, PART_ENTIRE_CONTROL,
                                    aReg,
                                    CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
                                    aVal, OUString(),
                                    aNativeBounds, aNativeContent ) )
        {
            aRect = aNativeBounds;
            if( aRect.GetHeight() > mnWinHeight )
                mnWinHeight = aRect.GetHeight();
        }
        aRect = Rectangle( Point( 0, 0 ), Size( nMinWidth, nMinHeight ) );
        aReg = aRect;
        if( GetNativeControlRegion( CTRL_SPINBOX, PART_ENTIRE_CONTROL,
                                    aReg,
                                    CTRL_STATE_ENABLED | CTRL_STATE_ROLLOVER,
                                    aVal, OUString(),
                                    aNativeBounds, aNativeContent ) )
        {
            aRect = aNativeBounds;
            if( aRect.GetHeight() > mnWinHeight )
                mnWinHeight = aRect.GetHeight();
        }
    }

    if ( ! mpData->m_aItems.empty() )
    {
        std::vector< ImplToolItem >::iterator it = mpData->m_aItems.begin();
        while ( it != mpData->m_aItems.end() )
        {
            bool bImage;
            bool bText;

	     // indicates if text will definitely be drawn, influences dropdown pos
            it->mbVisibleText = false;

            if ( it->meType == TOOLBOXITEM_BUTTON )
            {
                // check if image and/or text exists
                if ( !(it->maImage) )
                    bImage = false;
                else
                    bImage = true;
                if ( it->maText.isEmpty() )
                    bText = false;
                else
                    bText = true;
		 // default to toolbox setting
                ButtonType tmpButtonType = determineButtonType( &(*it), meButtonType ); 
                if ( bImage || bText )
                {

                    it->mbEmptyBtn = false;

                    if ( tmpButtonType == BUTTON_SYMBOL )
                    {
                        // we're drawing images only
                        if ( bImage || !bText )
                        {
                            it->maItemSize = it->maImage.GetSizePixel();
                        }
                        else
                        {
                            it->maItemSize = Size( GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET,
                                                   GetTextHeight() );
                            it->mbVisibleText = true;
                        }
                    }
                    else if ( tmpButtonType == BUTTON_TEXT )
                    {
                        // we're drawing text only
                        if ( bText || !bImage )
                        {
                            it->maItemSize = Size( GetCtrlTextWidth( it->maText )+TB_TEXTOFFSET,
                                                   GetTextHeight() );
                            it->mbVisibleText = true;
                        }
                        else
                        {
                            it->maItemSize = it->maImage.GetSizePixel();
                        }
                    }
                    else
                    {
                        // we're drawing images and text
                        it->maItemSize.Width() = bText ? GetCtrlTextWidth(it->maText)+TB_TEXTOFFSET:0;
                        it->maItemSize.Height() = bText ? GetTextHeight() : 0;

                        // leave space between image and text
                        if( bText )
                            it->maItemSize.Width() += TB_IMAGETEXTOFFSET;

                        // image and text side by side
                        it->maItemSize.Width() += it->maImage.GetSizePixel().Width();
                        if ( it->maImage.GetSizePixel().Height() > it->maItemSize.Height() )
                            it->maItemSize.Height() = it->maImage.GetSizePixel().Height();

                        it->mbVisibleText = bText;
                    }
                }
                else
                {   // no image and no text
                    it->maItemSize = Size( nDefWidth, nDefHeight );
                    it->mbEmptyBtn = true;
                }

                // save the content size
                it->maContentSize = it->maItemSize;

                // if required, take window height into consideration
                if ( it->mpWindow )
                {
                    long nHeight = it->mpWindow->GetSizePixel().Height();
                    if ( nHeight > mnWinHeight )
                        mnWinHeight = nHeight;
                }

                // add in drop down arrow
                if( it->mnBits & TIB_DROPDOWN )
                {
                    it->maItemSize.Width() += nDropDownArrowWidth;
                    it->mnDropDownArrowWidth = nDropDownArrowWidth;
                }

                // text items will be rotated in vertical mode
                // -> swap width and height
                if( it->mbVisibleText && !mbHorz )
                {
                    long tmp = it->maItemSize.Width();
                    it->maItemSize.Width() = it->maItemSize.Height();
                    it->maItemSize.Height() = tmp;

                    tmp = it->maContentSize.Width();
                    it->maContentSize.Width() = it->maContentSize.Height();
                    it->maContentSize.Height() = tmp;
                }
            }
            else if ( it->meType == TOOLBOXITEM_SPACE )
            {
                it->maItemSize = Size( nDefWidth, nDefHeight );
                it->maContentSize = it->maItemSize;
            }

            if ( it->meType == TOOLBOXITEM_BUTTON || it->meType == TOOLBOXITEM_SPACE )
            {
                // add borders
                ImplAddButtonBorder( it->maItemSize.Width(), it->maItemSize.Height(),
					mpData->mbNativeButtons );

                if( it->meType == TOOLBOXITEM_BUTTON )
                {
                    long nMinW = std::max(nMinWidth, it->maMinimalItemSize.Width());
                    long nMinH = std::max(nMinHeight, it->maMinimalItemSize.Height());

                    long nGrowContentWidth = 0;
                    long nGrowContentHeight = 0;

                    if( it->maItemSize.Width() < nMinW )
                    {
                        nGrowContentWidth = nMinW - it->maItemSize.Width();
                        it->maItemSize.Width() = nMinW;
                    }
                    if( it->maItemSize.Height() < nMinH )
                    {
                        nGrowContentHeight = nMinH - it->maItemSize.Height();
                        it->maItemSize.Height() = nMinH;
                    }

                    // grow the content size by the additional available space
                    it->maContentSize.Width() += nGrowContentWidth;
                    it->maContentSize.Height() += nGrowContentHeight;
                }

                // keep track of max item size
                if ( it->maItemSize.Width() > nMaxWidth )
                    nMaxWidth = it->maItemSize.Width();
                if ( it->maItemSize.Height() > nMaxHeight )
                    nMaxHeight = it->maItemSize.Height();
            }

            ++it;
        }
    }
    else
    {
        nMaxWidth  = nDefWidth;
        nMaxHeight = nDefHeight;

        ImplAddButtonBorder( nMaxWidth, nMaxHeight, mpData->mbNativeButtons );
    }

    if( !ImplIsFloatingMode() && GetToolboxButtonSize() != TOOLBOX_BUTTONSIZE_DONTCARE )
    {
        // make sure all vertical toolbars have the same width and horizontal have the same height
        // this depends on the used button sizes
        // as this is used for alignement of multiple toolbars
        // it is only required for docked toolbars

        long nFixedWidth = nDefWidth+nDropDownArrowWidth;
        long nFixedHeight = nDefHeight;
        ImplAddButtonBorder( nFixedWidth, nFixedHeight, mpData->mbNativeButtons );

        if( mbHorz )
            nMaxHeight = nFixedHeight;
        else
            nMaxWidth = nFixedWidth;
    }

    mbCalc = false;
    mbFormat = true;

    // do we have to recalc the sizes ?
    if ( (nMaxWidth != mnMaxItemWidth) || (nMaxHeight != mnMaxItemHeight) )
    {
        mnMaxItemWidth  = nMaxWidth;
        mnMaxItemHeight = nMaxHeight;

        return true;
    }
    else
        return false;
}

So I looked through the code, but didn’t understand it and didn’t want to. However, it was easy to see the change was reasonable and helpful in some cases. So I submitted it to Gerrit to see if it could get it reviewed and approved. If I can sneak it into a daily build, then maybe I could convince someone to try it out. So I submitted and waited for input. 3 days later, Caolán McNamara of Red Hat reviewed and accepted the patch. In fact, Caolán appears to be an email alias that 3 developers are attached to. I think Arch is a better distro for me than Fedora, but I am very grateful for the useful investments that Red Hat is making.

Once my patch got into the daily builds, I emailed the tester asking he could try one out, but he replied that he didn’t have time. So I was stuck and frustrated again. I couldn’t know if the change fixed the bug, which made me uncomfortable to ask for a patch to be triple-reviewed and back-ported. Blind-fixes to stable branches are generally not a good way to work.

I also didn’t know how to submit changes to anything other than the master branch. The LibreOffice wiki is great for new developers, but didn’t cover that specific topic. So I decided to ask Caolán if he could submit them to Gerrit to get them in before the 4.2.3 release. Caolán did that and even sent me the Git incantations so I can do it in the future.

With some reviews from Norbert and Miklos Vajna, the patch got into the 4.2.3 branch. So I was very happy, but not for very long. Because I soon noticed that the final 4.2.3 RC build had already been made. You can still push changes to the Git branch, but it doesn’t matter, the digital equivalent of air guitar. It is possible to mark bugs as release critical and delay the release, but this didn’t meet the bar. I should just have been happy that the issue was likely now fixed, but instead I was upset that after all my stress it had missed the train by a few hours.

However, the Heartbleed bug and a few other important ones showed up, and so another RC was made. I’m probably the only person on the Internet, other than the NSA, who was happy for Heartbleed.

KDE Regression

Just as LibreOffice 4.2.3 was shipping, another bug showed up from a KDE Ubuntu user:

Someone with a 1920×1080 15.6” monitor was seeing the HiDPI mode kick in. This is a bad bug because it is a regression. The goal of the feature is to improve the experience for HiDPI users, not break it for everyone else. Degrading a product for other people is the fastest way to get your code reverted.

This would have been stressful for me, but several weeks earlier I had studied the Linux DPI detection code and multi-monitor support. Since I knew exactly what 4.2.3 was doing here, I didn’t worry about being able to quickly solve the problem. I just needed to figure out what data LibreOffice was getting from the OS. You can stare at code as much as you want, but if you depend on hardware-specific information, you can’t prove it correct until you test on other computers.

I had taken the time to learn the code because I submitted a patch to LibreOffice for 4.3 that simplifies it to only fetch from xrdb and never bother to fetch from X Windows. I found the information unreliable for my laptop. On my machine, X tells me it is 96 DPI on a 33” by 18” monitor. It is pretty impressive to squeeze all that into a 13.3” screen. The patch to ignore X isn’t in 4.2.x, but that wasn’t a problem because the hard part is understanding the code. The tester was very helpful in quickly giving me the information I needed.

The problem is simple to describe. The monitor was 141 DPI, but X said it was 139×144. Of course it is crazy with bad data of different DPI values in the X and Y direction, but that was irrelevant here. The issue was that LibreOffice’s doubling kicked in at 144 DPI in the Y direction:

mnDPIScaleFactor = std::max((sal_Int32)1, (mpWindowImpl->mpFrameData->mnDPIY + 48) / 96);

144 + 48 == 192 / 96 == 2

I could think of several fixes, but I wasn’t sure what was best, so I decided to ask Kendy who had written that line of code. Within a few days, he submitted an improvement that will not cause this new mode to kick in until at least 168 DPI. That fixes the problem for this machine, and hopefully others. So with these fixes, things are in decent shape. The next issue is Unity, which is currently broken.

Unity

While LibreOffice can look good with Gnome, KDE, and Xfce, I hadn’t tried Unity. It is difficult to get it running on Arch because it has patches to a lot of key components they’ve not convinced upstreams to accept. And so I’d have to replace a lot of system packages, and I didn’t want to deal that risk for my personal laptop.

Unity isn’t even the only environment Ubuntu supports, but it is their premier one and so I had been curious. The Unity team had done a bunch of HiDPI work for version 8, and so I hoped it would work. Ubuntu 14.04 is shipping 4.2.3 with the LibreOffice icons prominently placed on the dock.

After hearing nothing for months, I tried out a live USB image of the final Ubuntu 14.04. Unfortunately, I discovered that even though they based some of their work on the Gnome 3.10 design, they didn’t fix the xrdb values. I could also find no way to force apps to be 192 DPI, as the other environments enable. Apparently there are new Unity APIs.

I wish Unity would fix their xrdb values. I don’t know where the Unity documentation is or how to write Ubuntu-specific code on LibreOffice. I recommended to Ubuntu’s developer, Bjoern Michaelson, to requisition a new machine. For now, it doesn’t work on Unity and the fix is unknown.

The end, for now

This story ends, but there is plenty more that can be done. It would be great to have higher-resolution toolbar bitmaps, but it isn’t high priority because only a few are pixelated. The Mac is still broken. It appears that the OS doesn’t work in pixels on retina displays. Good luck fixing that.

The splash screen is a little embarrassing, but is is only visible for a moment. I found the relevant code in splashx.c, but didn’t find an easy fix because this early code apparently can’t use the BitmapEx class with its scaling routines. In fact, it often draws bitmaps pixel by pixel. Maybe someone can just make a bigger splash screen and fix the progress control.

The status bar still needs to be improved. The bitmaps look fine but because the layout is done in pixels and stored in an XML file, there is no way currently to make it be different widths for normal and HiDPI screens.

The hyperlink dialog box has a few problems:

HyperlinkLO423

The Insert-special characters dialog needs to be taller by default. The letters are all much too small. I had spent some time looking through the code but never managed to find the place to make a fix. Fortunately, the dialog box is resizable so this isn’t a big problem.

It also needs testing on Windows 7, although from my casual re-reading of the MSDN documentation, it should work.

The underline wave character property isn’t scaling yet. I didn’t bother with that because it is very little used compared to mis-spellings, and is a more complicated codepath.

The line styles toolbar dropdown preview draws lines too thin. I looked around the code, but it was very voluminous. Kohei Yoshida spent a couple of weeks re-working it recently so I’m hoping when he gets a new laptop, he’ll quickly notice and be able to fix it.

It doesn’t appear that multiple monitors of different resolutions is handled properly in LibreOffice. Fixing that could be tricky. So the work continues!

LibreOffice HiDPI Patches

I bought a HiDPI laptop in October 2013 to replace my 5-year old Thinkpad. Between the 5.7 million pixels, and the bright LED backlight replacing my dying and dim fluorescent bulb, it makes the daily computing experience much easier on the eyes. I’d put up with a lot for this screen. It turns out I have to compared to my old Thinkpad, as there is an incompatible and inferior keyboard layout, the Synaptics mouse drivers are flakey, it is difficult to replace the battery or hard drive, etc.

I run Arch with Gnome 3.10 in Classic Mode. Gnome is the only DE that recognizes the high-res screen out of the box and picks a good font size. It has specific bugs I described in my review of the laptop, but it generally looks fine albeit bland and crippled. Firefox needs the No-Squint plugin, but then the web looks acceptable. The next most noticeable problem for me was LibreOffice. The text and dialogs looked beautiful:

The text looked like a magazine, but the bitmaps were far too small, and there were other problems. LibreOffice offers 16×16 or 24×24 toolbar icons today, but the small ones looked like dead bugs on the screen, and even the large ones required concentration to recognize. One day, rich 48×48 toolbar bitmaps can be created, but in the meanwhile, you can double them to look reasonable and be easy to click on. Given that LibreOffice has hundreds of bitmaps, this temporary solution could be useful for a while.

In addition to the toolbars, the status bar controls, the navigator, the sidebar, and various dialog boxes had tiny bitmaps. One of the most annoying problems was that the spelling underline was so thin you didn’t notice it while casually looking at the screen. And so you had to stare carefully to see the lines, which imprinted them causing remnants when you shut your eyes. It was maddening!

And so I thought: perhaps some volunteer developer in LibreOffice could be given new hardware by The Document Foundation to work on this problem. The Gnome 3.10 HiDPI work happened because of a computer donation and perhaps it could happen here. And so I wrote an email to their discuss alias asking if there was interest but I received no public response.

Apparently, everyone is so busy delivering a new product, fostering a young community, paying down technical debt, making it run on Android, improving import and export, rewriting the Calc engine, removing Java, etc., that no one has time to make it look good on these beautiful screens. There is a lot happening without any rich benefactor anymore, and a split community. If you think LibreOffice is amazing, just imagine what it would be if IBM gave them $10M / year, and the trademark, and didn’t seduce away naïve volunteers and donations. (I believe if IBM were to ask Watson whether it should end the fork, the AI would recommend it. Watson is only being applied to customer problems instead of their own. One could spend a lot of time correcting the inaccurate FUD written on the AOO dev alias. Imagine we lived in a society that celebrated divorce instead of marriage.)

I considered setting up a bounty on a website, but I decided to next see if I could find someone in the community with expertise who could be persuaded to work on this issue. It seemed that fixing the toolbars would be a great first step and I felt I’d be happy with that one improvement.

So I next emailed Michael Meeks and asked if he knew anyone who might have a few extra hours. I was put in contact with Andrzej Hunt, who eventually wrote a patch to double the toolbar bitmaps. But I felt that the spelling underline was the next highest priority issue. I decided to go through the codebase, and see if I could find the place that should be fixed. If I thought I could do it, I would buy an external SSD to build and do some experiments.

My first stop was opengrok.libreoffice.org. It is a simple and fast way to search through the codebase. This is one of best tools LibreOffice has setup since they started. Even when you have the code on your local machine, it is better to use their smarter system. The Opengrok source is color-coded and everything is clickable to take you to the definition and references of classes and functions.

I don’t remember exactly how many searches it took, but eventually I found the code to draw “wave lines”. If I had known that term in advance it would have been faster, but I always thought of them as squiggly underlines and that term brought up nothing. Eventually I found interesting routines such as DrawText, ImplDrawTextLine, ImplDrawWaveLine, DrawWavePixel, DrawWaveLine, etc. One usually reads code for understanding, but at first, I was just trying to figure out if the code I was looking at was relevant.

LibreOffice draws wavy underlines as a font property and as part of spelling / grammar errors, and for other reasons, so I had to read through the code, understand who called who, etc. Eventually, I discovered that DrawWaveLine was the function I wanted. It was called from the end of the main routine DrawText, which called lcl_DrawLineForWrongListData, which went through the grammar and spelling error list and called DrawWaveLine for every problem area. And in that routine, I found a strong clue:

5302 if ( nStyle == WAVE_NORMAL )
5303 {
5304     nWaveHeight = 3;

I knew the spelling underline was 3 pixels tall, so at that point I knew my search had ended. I decided to spend money on an external SSD so I could download the code, build it, and make changes.

The wiki is superb and the build process is ridiculously easy. Here are the commands I ran after installing the build dependencies:

$ git clone git://anongit.freedesktop.org/libreoffice/core libreoffice
$ cd libreoffice
$ ./autogen.sh --enable-dbgutil --without-java --without-help --without-myspell-dicts
$ make (wait two hours)
$ instdir/program/soffice --writer

With those few steps, I could then run LibreOffice and try things. After a few builds, I found what looked best. Here is the first diff I sent to the dev alias:

diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx
index f3f5a77..6e142fd 100644
--- a/vcl/source/gdi/outdev3.cxx
+++ b/vcl/source/gdi/outdev3.cxx
@@ -5301,9 +5301,12 @@ void OutputDevice::DrawWaveLine( const Point&
rStartPos, const Point& rEndPos,
long nWaveHeight;
if ( nStyle == WAVE_NORMAL )
{
-        nWaveHeight = 3;
+        nWaveHeight = 5;
nStartY++;
nEndY++;
+
+        nStartY++; //Shift down additional pixel for hidpi screens
+                   //TODO: Probably should be done above, before rotation happens
}
else if( nStyle == WAVE_SMALL )
{
@@ -5320,7 +5323,7 @@ void OutputDevice::DrawWaveLine( const Point& rStartPos, const Point& rEndPos, nWaveHeight = pFontEntry->maMetric.mnWUnderlineSize;


ImplDrawWaveLine( nStartX, nStartY, 0, 0,
-                 nEndX-nStartX, nWaveHeight, 1,
+                 nEndX-nStartX, nWaveHeight, 2,
nOrientation, GetLineColor() );

Note this code couldn’t possibly get checked into LibreOffice as-is because it changes the behavior for all screens, but it allowed me to test. Eventually what is needed is a way to know when to use the different values but there was no easy way to get that information. And so Michael Meeks introduced me to Kendy (Jan Holesovsky) who added a member to the low-level OutDev class containing the DPIScaleFactor. In principle, that information is based on the DPI of the screen / window, but sometimes the OS just returns 96 for compatibility reasons and therefore may need additional logic based on the system font size.

With the toolbar and spelling underlines looking great, it made the remaining problems more noticeable, and motivated me to keep going. I decided to next look at the status bar. The first control was zoom, the one I use the most. Eventually, I found the class: SvxZoomSliderControl. In this case, I was able to just read through the 400 lines until I saw the problem areas. For starters, it had hard-coded the bitmap size via #defines, so even if you plugged in a bigger bitmap, it would have mis-behaved. And so I first fixed the control to work based on the bitmap size, and made it draw bigger if necessary. The change was quite simple. From there, I went to the other status bar controls, the navigator, and various other places, and have so far submitted a first and second round of fixes.

The process was straightforward. First I’d find a problem visual area I wanted to work on, and then I’d trace through the code in opengrok till I found the right place, make a change, and see how it looked. I saw plenty of code I didn’t understand, but my changes were mostly simple and safe. A couple of times I had to first put in printf diagnostics to understand what was going on at runtime because there is no supported IDE with debugging, auto-complete, etc.

Sometimes hours of searches turned up nothing! I felt like Indiana Jones digging in the desert. After lots of sweating and effort, you find things, but it can take time to figure out if an artifact is valuable, how it fits with other pieces, etc.

The hardest piece of code to find was the black triangle in the toolbar font color dropdown, and many other places. I eventually resorted to commenting out drawing logic that looked like it might be handling it. At one point, random controls all over the product weren’t visible anymore, but the dropdown indicators were still there. It was the Terminator of Triangles. The LibreOffice codebase is overall very reasonable compared to Microsoft Office, but it does have a lot of widget logic because it tries to draw native visuals in a cross-platform way.

I emailed the dev alias and heard nothing. That wasn’t a surprise because the people who wrote the toolbar code are long gone. This happens more often in the proprietary world. Eventually I gave up and decided to work on the toolbar double-arrows which show up when some of the buttons don’t fit. That routine I found quickly by reading the code that laid out toolbars, figured out how it represented the situation of controls not having enough room, and then found the drawing routine which looked at that data.

And so I changed the arrow code, and started a build. While waiting, I decided have a look around, and found that triangle drawing code was the next function in the file. I about pooped my pants. I had spent at least 4 hours looking for it.

Reading through the code to find the right place to make the change took an unknown amount of time. Once the right place was found, the diff was mechanical, but usually there was something interesting about each case. Once you find the right function, the rest is usually easy, assuming what you want is possible via existing primitives. So far I’ve spent about 40 hours, working a few hours per session, and have fixed the most noticeable places in the product including the Sidebar.

Complexity and community

HiDPI is quite far from finished, in spite of the many changes I’ve made. Most of the code I’ve worked on will eventually be replaced! We shouldn’t be doubling bitmaps, we should have better ones. The toolbar dropdown triangle logic should eventually be replaced with code which calls into the toolkit / OS so it also looks more native. That is a better fix, but also bigger and riskier, and could have implications for toolbar layout. And I have no idea how to do that. I’m much better at telling LibreOffice to double integers and bitmaps.

There are more issues, but also more and more people who will want LibreOffice (and other apps) to work well on their new screen. I’ve been updating a wiki page as I go along and it also lists some of the remaining places. One isolated fix is the tab-drawing (and hit-testing) code in the ruler. The drawing logic starts on line 874.

On the Mac, someone needs to turn off the compatibility mode and see what happens. In my old life, I would have expensed a Macbook Retina to test it myself, but for now LibreOffice needs to find someone else to carry the work further.

This feature did not make it into LibreOffice 4.2.0, so it won’t get any of the automatic publicity that would come with that process, but I believe it can get into 4.2.1 and be announced then. LibreOffice make a minor release every month, and Arch automatically grabs them within a day or 2, so it means I’ve only got to wait an extra 32 days. That I could write some code in late December and get it on my machine in early March is quick turnaround compared to the proprietary world.

If I were an undergraduate in college, I’d take a bug somewhere in free software and work on it. LibreOffice is one of the most needed and relatively easy to get into. You have to look pretty hard to find ways to improve the Linux kernel, but with LibreOffice, that is not the case. A number of the things I worked on in school were writing toy programs. It made it easier to grade the assignments, but the code wasn’t realistic or useful to anyone. There also wasn’t as much great free software out there to learn from or contribute to. I joined Microsoft to learn more about programming because I knew there was a lot more to it than the toys I was making. LibreOffice is a very rich program to fully understand, but you don’t need to know very much to be productive. Most diffs are 5 to 50 lines.

One of the ongoing challenges for LibreOffice is to remove as much extra complexity as possible. It has already paid down a large amount of technical debt in the makefiles and other places, but this process will continue for a long time. I think that parts of Base should be re-written in Python, and the VCL replaced with WxWidgets or Qt, but these are very large tasks no one is working on, and therefore just pipe dreams. The good news is that they can be done incrementally. Porting the status bar to another toolkit could be done in a summer by a college student. The toolbar would be a bigger challenge that could take two summers. There is little work happening in VCL or the Writer layout engine. One of the downsides of the Symphony / Apache Sidebar is that it gave LibreOffice a new UI, but not a simpler and better way of building pretty UIs.

I received excellent “customer service” from Kendy along the way. The LibreOffice community is great and patches from first-timers get accepted all the time. So while we wait for IBM to change course, LibreOffice can keep doing the best that it can. LibreOffice has 100 dev contributors per month. Even if people show up to fix one real bug, it collectively adds up.

I plan on doing more, but first I want to help in the process of releasing the code already checked in. I wrote about some of the remaining issues in the wiki, but people might find others. For example, the first batch I submitted changes the width of the SvxPosSizeControl for normal and high-res screens. It is broken on current builds as the text doesn’t fit, and the bitmaps drew on top:

The status bar is one of the few places in LibreOffice that does layout based on pixels, and the resource XML files are not a place you can currently change at runtime.

A competitive office suite is critical to the success of a free desktop. There are billions of Office files out there and people who haven’t even heard of the best free alternative. LibreOffice is an extremely rich codebase, but it is more underfunded for its needs than the kernel, Firefox, systemd, etc. If someone can understand my diffs, they can contribute some code to LibreOffice. I note that the author of the article saying that LibreOffice is “ridiculously easy to build” never actually submitted a patch! People can contribute out of duty or selfishness like me, but it is best to find an isolated area or an issue they care about. There are plenty of Easy Hacks and bugs to read through, and various ongoing projects such as dialog format conversion.

I wrote this before LibreOffice released the patches. Part 2, of how it went during the ship process, is here.

Response from Synaptics regarding Linux drivers

Here is the mail I received this afternoon from Synaptics regarding the petition:

The open source Linux kernel currently has a PS2 touchpad driver from the third party open source community which was not developed, reviewed, or tested by Synaptics.  Based on industry and customer pull, we do not support PS2 interfaces for Linux as it is not a strategic fit for our roadmap or support model. In general, the trend in the PC industry is HID/I2C, for which we do offer driver support.  Our intent is to submit our HID/I2C driver to Kernel.org as time, resource allocation and customer project prioritization allow.

Best Regards,

Nick

———–

Here is what I sent in response:

It would be great if you were to get working on submitting a driver to the kernel. People will help you find bugs in the code as part of this process, and improve it in ways you hadn’t considered. It occurred to me over Thanksgiving after your last email that writing a Linux driver but not freely releasing is like cooking that big meal and not eating it. Proprietary software was one of the big mistakes of the baby boomer generation.

I will pass this information along to the petitioners with some questions / comments. When you make something public, I hope you make a public announcement as well because it will be read more than your average one. People care about companies that share their values. Here is a video of Steam’s recent announcements regarding Linux that I thought you might appreciate: http://www.youtube.com/watch?v=g8PMUvuHK4g

Unfortunately, I’m not knowledgeable about the benefit of supporting the PS2 interface vs HID/I2C. However, I can say that not every trend in the industry is a good one. IPv6 is a trend that still hasn’t arrived. I think UEFI as implemented is of dubious benefit. Can you please explain in more detail why HID/I2C is better? I may do some more research on this topic and ask other people, but I can say that the existing venerable standard has gotten us a long way including multi-touch and gestures. So I wouldn’t recommend supporting only the new trends which are sometimes fads. The Linux kernel supports 60 file systems. Can you consider to support the extremely popular as well as the latest?

When you think about getting code into the kernel, I want to emphasize making good default configuration values. You didn’t mention that aspect so I raise it again in hopes of a response. I’m sure your driver will have interesting knobs people will want to tweak, but you are the best people to know what they should be by default for your devices. So can you please commit to providing a great out of the box experience by including tested and tuned configuration data along with code?

2. Getting 10,000 lines of code into the kernel could take a year. For example, it took quite some time for Google’s wakelocks code to make it upstream. In that case, there were big disagreements about the design which may or may not apply to your code, but unforeseen things like that do happen. Also, your lawyers end up taking time and I’m sure your kernel developers are already busy and possibly understaffed. As this is your first big contribution it will take even longer.

So in addition to the question of whether supporting only one standard is good enough, there is a question of timeframe. That is why I created the #2 item. I realize you didn’t write or review any of the existing code. However, because you hadn’t released any code publicly in the past other people have written it for your customers. The kernel is filled with code written by other people but this module has your name on it and is depended on by millions of people.

Here is the key point. By fixing that code, you will help many customers today. A 10 line fix to a driver would quickly be accepted and deployed to millions within a few weeks and the entire community within 6 months. It would possibly be backported to older releases as as your hardware is so popular and important.

I read a line that a good way to judge an airline is by what happens *after* they lose your luggage. If they were to tell you that yes, they’ve lost your luggage, but they are implementing a new baggage tracking system that will give it to you in a year, you might not be so happy with that answer.

I believe if you were to ask your Linux customers whether they would want you to fix 20-30 bugs in the existing already-upstreamed code or work on some big chunk of new code whose date for delivery is very uncertain, they would want you to fix the existing code first. So this strategy is faster for us and cheaper for you and could even be a useful learning process on the way to the HID/I2C utopia. Once all your customers are no longer frustrated you can run the process for your new driver at your leisure. So can you re-consider your priorities in light of the situation that currently exists?

3. Also, you didn’t mention the #3 issue about providing a UI to configure your devices. Can you please think holistically about the end-user experience and realize that as your hardware gets more sophisticated, a UI to configure the device becomes more necesssary? You could provide a good value for palm detection by default, but a UI allows me to test and change it if the default did not work for my situation. It is quite difficult to tweak a knob without a UI.

In this code as well, people will help you here, by for example suggesting gestures to be added or turned off by default. By not working on freely-available configuration code, you are missing feedback loops everyone will benefit from. It is overall easier to write UI code on Linux versus Windows. There are more Environments / toolkits, but only 3 are used by 90% of users, and the code will be debugged for you, compiled, deployed and translated for you, etc. You don’t need to start from scratch as these environments have code, but it just needs to be improved. Can you please reconsider this end-to-end aspect as well?  It is also easier to find people qualified to write UI code versus drivers and I think most people would judge this to be more important than a HID/I2C driver.

Thanks again for your mail. I hope you will consider these issues and respond soon. It is great to hear of a new path, but I can recommend you verify it is what your customers actually want as opposed to what some people say they ought to want. I will post a request for feedback on your ideas, but these are my initial thoughts.

——

Please post your thoughts about this, preferably on the petition page.

Arch Linux HiDPI wallpapers

Here are a couple 3200×1800 wallpapers I rendered in Blender using the new Cycles engine based on a file I found.

Default:

Change to glass material:

Enjoy!!