Older blog entries for auspex (starting at number 48)

My GUP to-do list

  • 1st decent draft of notification area guidelines (I have one in a HIG bug, but I need to go over it, comments made on it, and Mark's proposal that seems to have slipped from view.)
  • 2nd draft of Notification Area Preferences proposal
  • 2nd draft of window list proposal
  • 3rd draft of Find and Replace dialogs proposal
  • Draft power management control panel proposal (The one on Windows really sucks. It's something to avoid.)
  • Draft language/input/keyboard control panel proposal
  • Check the HIG bugs and maybe do something about them.
  • Maybe knock off a few UI reviews. Maybe my hair is short enough now so that I can't pull it all out. (Mumble something about not being able to grab a scrap from a garbage can and say, "No. Like this.")
  • Finally take the time to write the big frickin' huge document describing a complete user model for the GNOME which I could present in person on a napkin. (Curse the lack of "Oh, I get it!"-cues. Bemoan the state of the non-(but should be)-obvious)
  • Think of more things to put on this list to make the point that even though I suffer from recurrent major depression and, at the moment, post traumatic stress disorder, I am doing something other than complaining and cursing the broken 'B' key on my laptop.

Other software to-do's

  • Think of a better name than "WordSense" for my WordNet interface. (It's better than the first name: gwordnet)
  • Write libgwn so I don't have to depend on libwn
  • Just pick one of the possible APIs to the X-selection-based remote control, and finish the damn thing.
  • Figure out how to auto-tool-ize it so people don't whine about my handwritten Makefile
  • Release the damn thing this time
  • Curse more in code comments so I don't do it on to-do lists

Did I tell you so?

I've noted many times that an X client that tries to reparent the window of another X client without the assistance of the other client or the window manager is inherently flawed. X doesn't work that way.

This is why the KDE system tray protocol often failed outside of KDE. It depended on the window manager, but just how was not known to many. (With WM support, it worked fine. It's another question whether it should depend on the window manager.) GNOME's status dock (the old one) was an acknowledged hack that failed more frequently as window managers improved but without support for KDE's protocol.

The "swallowing" feature of the GNOME panel exhibited the same error. Perhaps because this was finally realized, the feature was removed. It has been resurrected as an applet, but it is still doomed.

Now, prompting this entry, Mozplugger has failed as I expected. Although it certainly tries harder than the old GNOME status dock or any "swallowing" for which I've read the code, it too is ultimately doomed. Moments ago, a GhostView window created from a process launched by Mozplugger appeared in the bottom right corner of my screen and stayed there.

I wonder who will get the first bug report. It belongs to Mozplugger, but I won't be filing it. There's no point to filing a bug against a program for the basic concept of the program, is there? I imagine there will be reports to every program possibly involved: browsers; the browser engine; the to-be-reparented programs; window managers; the GNOME panel; the GNOME window list; libwnck (these last three because a button for the window appears in the window list in the panel); and, of course, the culprit, Mozplugger. Despite this entry, fingers will be pointed and tongues will be forked.

Providence, I should say nothing more.

Interlude

Among other frustrations are the astonishing unresponsiveness of Mozilla's text area and the poor wrapping of Emacs.

Mozilla is so slow that I, a slow typer, can write an entire sentence before its first chraracter is displayed. I don't know why this is so; it appears to be unique to Mozilla. (I should perhaps say Epiphany instead of Mozilla, as that is what I use, but, as I recall, I did check the Mozilla browser too.)

I decided to use Emacs and then cut-and-paste to the webpage text area. This was fine until I reread what I'd written. Not wanting to insert unnecessary carriage returns, I'd typed long lines. (I wasn't writing email or code, after all.) If Emacs can wrap text at word boundaries without inserting characters, I've not found the setting to make it do so.

Having surveyed other text editors, I knew of none to my liking. GEdit would probably be fine for me if not for the inescapable document tab. It serves as a persitent reminder of other usability problems; with Emacs, which I've used for a while, the nagging errors are quieter because of familiarity. I wonder if abused spouses are also guilty of this error: if I'm going to use an unfamiliar text editor, there had better be no blatant prolems with it; better with errors is worse than worse with familiarity.

This interlude was written in a new editor. This editor is named "stupiditor" and may be downloaded from http://www.phys.lsu.edu/~merchan/stupiditor.c. (A command to compile it that works for me is at the top of the file.) Cursory use, or reading of the source code, should explain the name. I cannot and do not recommend using it for more than amusement. The command line syntax is: stupiditor regular file you can read and write. Actually, permissions are never checked, and errors resulting from are not reported. When you are done playing, you have two choices: save or lose your changes. If you close the window with your window manager and no errors occur, your changes will be saved. (Unless your window manager is so archaic that it uses XKillClient instead of sending a WM_DELETE_WINDOW message.) Any other program termination will lose changes.

Unfortunately, it is not as responsive as I hoped it would be.

Frustrated (cont.)

The X selection mechanism can be used for more than it is commonly used today. The most common use is for the user to "mark" some data and transfer it. Marking here include selection (for middle-button paste) and also the more widely known Cut and Copy commands. Along the same lines, some other uses have emerged:

  • At least some WindowMaker "squares" (I don't know what the correct name is) accept middle-button clicks as "paste" commands.
  • The Googlizer is a program that reads selected text and opens a Google query URL in a web browser.
  • The GNOME dictionary applet can lookup selected text.
The system is not without problems. The select-and-paste method, because it needs one clearly active selection, conflicts with the expectation of non-X users that there may be more than one visible selection. The cut/copy/paste method, while providing dynamic typing, does not provide persistence. Another program must be used to provide persistence. When there is a large amount of data or many forms which it may take, the bottleneck of a persistence-providing program is a nuisance. Motif UTM (the protocol, not the API) alleviates this, but it is poorly documented.

Another use of X selections is window manager control. Though it has long been documented, only recently did window managers other than MWM (and maybe DTWM) begin to implement it. There are only two documented suggestions for using it: explicitly, to get the version of the ICCCM with which the window manager complies; and implicitly, to switch window managers.

There is also a "workspace manager" and protocol which MWM recognizes, but I've found no documentation. Something like this for the window manager specification at freedesktop.org is being discussed.

One new use of selections is the XSETTINGS system. Unlike the previous selections, it stores data on the selection owner and clients are expected to monitor this window for changes. Here, using a selection ensures uniqueness to a screen and identifies the owner window. Uniqueness is important to avoid conflicting settings. Screen-specificity is important because settings, such as colors, on one screen may be inappropriate for another. Because XSETTINGS are available from on program for use by many others, it is better for all interested programs to monitor a particular window for changes. If this were implemented using the full selection mechanism:

  • Every interested client would have to either:
    • Periodically query the XSETTINGS program for changes, or
    • Register with the XSETTINGS program to be notified of changes.
  • The XSETTINGS program would have to notify every other program directly. If a registration system were used, then it would also have to watch for new and dropped registrations.
Programs watching for changes on a specified window is like registration, except that the programs register with the X server.

The system tray protocol is the last common use of the selection mechanism. Its accepted form uses a selection just to be unique, then batteries of ClientMessages for communication. The originally proposed protocol used selections for communication.

I don't feel like going on for now. Part III later.

"HIG"

HIG is an acronym for either Human Interface Guidelines or Human Interaction Guidelines. So, it's a noun. In the context of a particular environment, the name of the environment may be omitted. The GNOME HIG is simply "the HIG" if you're talking about GNOME.

The noun "HIG" has been verbified. (Or verbed? Or verbificated?). To HIGify [sic] is to make compliant with a HIG. This is a poor verbification; the -ify form would ordinarily make it mean "to make into a HIG". Now gerund and gerundive forms of the verbificative have appeared. Their usage, oddly enough, seems to have lost their connection to the original noun. Something HIGified is something made "cool", regardless of good taste, HIG-compliance, and probably a lick of sense.

I still like the name I once used for a shell script to build the GNOME HIG when we started working on it: higgy-piggy.

(If someone knows the proper names of the linguistic convolutions I've described, I'd like to know them too.)

SpamAssassin

I finally installed SpamAssassin and added procmailrc rules to use it. It is very slow, but I can imagine why. I had placed the SA rules at the beginning of my procmailrc, but this was not necessary. I have now moved them near the end of the file and I am much happier. Mail from known addresses is no longer checked, and those include a list of domains which go to /dev/null.

Magic!

After suspending and resuming my laptop, sound works! This is so bizarre. Something, I know not yet what nor do I much care, changed in some Debian ALSA packages. Sound quality is very poor and music skips on all sorts of events such as terminal output, focus changes, and rapidly moving the mouse. This used to just work.

Irrationality × Irrationality = Rationality ???

Lacking a good model, application features and options sets grow wildly. Lacking - well - a good model, GNOME usability work became option removal. Between these opposing forces, things have gotten a little bit better. It's a lot like chemotherapy, I suppose.

Frustrated

It is a trivial matter to write a "remote control" for one's X application. Consider a common problem: how to make the application unique to a display[1]. The most trivial solution causes the program to exit if another instance is running. This is the basic[2] code:

void
ensure_uniqueness (Display *display)
{
  Atom app_id;
  app_id = XInternAtom (display, "_MY_APP_ID", False);
  if (XGetSelectionOwner (display, app_id) == None) {
    Window app_window;
    app_window = XCreateSimpleWindow (display, DefaultRootWindow (display),
                                      0, 0, 1, 1, 0, 0, 0);
    XSetSelectionOwner (display, app_id, app_window, CurrentTime);
  } else {
    exit (EXIT_FAILURE);
  }
}

Just exiting will befuddle users, so it'd be good to do something visible. The most trivial visible thing is to present an error alert, but that's annoying and blockheaded. Suppose it suffices to present an existing program window to the user. Somehow the second instance (P2) must tell the first instance (P1), or the window manager (WM), to do this. Because P2 cannot get the correct window by itself, to tell the WM what to do it has to get the correct window from P1. It is simpler to tell P1 what to do and let it handle the rest. For P2, ensure_uniqueness() calls this instead of exit():

void
call_for_presentation (Display *display, Atom app_id)
{
  Atom   present_window;
  Window dummy_window;
  present_window = XInternAtom (display, "_MY_APP_PRESENT_WINDOW", False);
  dummy_window = XCreateSimpleWindow (display, DefaultRootWindow (display),
                                      0, 0, 1, 1, 0, 0, 0);
  XConvertSelection (display, app_id, present_window,
                     None, dummy_window, CurrentTime);
}
When P1 receives the SelectionRequest event, it will filter this ordinarily and on finding what has been requested it will present some window and send a SelectionNotify event to P2. This is using a side effect target and is described in section 2.6.3 of the ICCCM.

Just presenting an existing window will not suffice for most applications, though it's fine for simple utilities and control panels. Often an application will manipulate some document, so it will be useful for P2 to tell P1 to open a document.[3] This is basically passing a string, so command line arguments and more can be passed the same way. Again, a side effect target is used, but this time there is data in the property specified for XConvertSelection(). (This property was None in the previous code.)

void
call_for_open (Display *display, Atom app_id, const char *filename)
{
  Atom   _my_app_open;
  Window data_window;
  Atom   data_property;
  Atom   data_property_type;
  _my_app_open = XInternAtom (display, "_MY_APP_OPEN", False);
  data_window = XCreateSimpleWindow (display, DefaultRootWindow (display),
                                     0, 0, 1, 1, 0, 0, 0);
  data_property = XInternAtom (display, "_MY_APP_DATA", False);
  data_property_type = XA_STRING;
  XChangeProperty (display, data_window,
                   data_property, data_property_type, 8,
                   PropModeReplace,
                   filename, strlen(filename));
  XConvertSelection (display, app_id, _my_app_open,
                     data_property, data_window, CurrentTime);
}
Now when P1 recieves the SelectionRequest event, it will take the additional step of retrieving the data with XGetWindowProperty().

The entire remote control system can be built with one selection target and a string passed for interpretation. It could even return a result. I do not know if that would be better than using multiple side effect targets as commands.

What I've described thusfar is a remote control system for one program. It it allows one instance of an executable to control another. Both transmitter and receiver are in the same executable file, so there is little need for discovery, versioning, or even sensible names. However, if another version of the same program uses the same uniqueness atom, there could be problems. This makes the remote control less trivial.

Versioning is convenient because it allows for a simple check; even with a discovery method, it is worthwhile. One obvious way to handle it is by noting the version in the app id, but that would eliminate the benefits of uniqueness. Instead, it is better to provide a target which will return the version. The target VERSION, indicating an ICCCM version, is required of ICCCM-compliant window managers.[4] For a window manager to have a versioned remote control, it must use another target. For common remote control targets to be standardized for all apps, another target must be used, or window managers must be excepted.

The ICCCM-required target TARGETS provides a list of available targets. This is suitable for discovering whether a program has a particular remote control command, but not what it does or how. By always using a target that does not change with application versions, an application can provide a dictionary of its remote control commands.

Furthermore, if every application providing a remote control uses the same dictionary target, then it is possible to build a "universal" remote control.

More to come, including an explanation of the title.

Notes:

[1] Subdomains of uniqueness are possible, such as a particular screen of a display, or a particular host connected to that display. This method depends on the display and is not suitable for making the program unique to -say- a host. Other methods, such as special files, exist for that.

[2] The code ignores a lot. The created Window isn't returned in any way; though a later call to XGetSelectionOwner() might retrieve it. No events are handled. Using CurrentTime is wrong. Etc.

[3] There is a problem here in that P1 and P2 may be on different hosts without access to the same documents. The simple and incomplete solution is to use URIs like file://host/path/to/file to avoid false matches and fail when the file cannot be opened.

[4] This was a bad choice. The ICCCM version target should have been something like ICCCM_VERSION and the VERSION target left for application versions.

Eerie

I took a look at Slicker today. It reminded me of code I'd written in GNOME 1.x days. Screenshots are here. The last one was the initial mockup. I emphasize that there was code behind this because it seemed that few people grasped that part of it. Sadly, that code is all stale now; I'm not even sure where it is.

GNOME Wishlist - Old bugs

There are some bugs that haven't seen any attention in a while, and I fear they're going to slip through the cracks of another major release. These first few are Gtk+ bugs.

  • 53577, 53709 - These are keyboard navigation bug reports for GtkButton and subclasses. Each reports many bugs, and I'm most interested in seeing that pressing Enter performs the default action in a dialog; i.e., that it's the same as clicking OK. Per the GNOME HIG, a dialog is confirmed by pressing the Enter key and cancelled by pressing the Escape key. (Alternative actions - e.g., Don't Save in a Save-Before-Closing alert - don't have a special key.)

    I find this particularly interesting because bringing Gtk+ into compliance with the HIG can reduce the size of Gtk+. I don't know (yet) how many bytes will be removed or how much it will improve performance. I do not know of any use for a default action outside of confirming a dialog, so I think the mechanism for it can be limited to dialog confirmation. For GtkWidget, this saves 3 bits by eliminating the GTK_WIDGET_CAN_DEFAULT, GTK_WIDGET_HAS_DEFAULT, and GTK_WIDGET_RECEIVES_DEFAULT flags; however, these are in a bitfield of 16-bits. For GtkWindow this eliminates the checks for a default. These may be trivial changes, but almost every piece of a GNOME UI is a GtkWidget in a GtkWindow. I don't have or yet know how to use the tools to assess this.

    I'm concerned that there may be a non-trivial number of trivial points like this.

  • 61843 - GtkMenuBar has at least about 40 dead pixels per item by default. This depends on the size of the item and can be much more. The space is good for readability, but it should be usable to activate the item. (cf. Fitts's Law)
  • 65765 - Add an authentication icon to Gtk+'s stock icons. This is an easy one.
  • 68938 - Remove the separator from GtkDialog. This is just a minor nuisance, but it falls under the "redesign dialogs" category.
  • 70372 - One can not see the tooltip for any insensitive widget. This makes it hard to learn what a widget does or why it's insensitive. On the other hand, if a large section of a dialog is insensitive, having to navigate through it is a pain.
  • 73269 - There should be a separate report for this. The icons need to be removed from dialog buttons. This might be another redesign issue. GtkButton is a GtkBin subclass. (GtkBin is an abstract class for a container with only one child.) But there are only a few basic button types or button-like interface objects. Perhaps it would be better for GtkButton and other widgets to handle text and images directly instead of by packing them in.
  • 84188 - Another dialog redesign issue.
To be continued, perhaps later today.
7 May 2003 (updated 7 May 2003 at 16:55 UTC) »

RossBurton, indeed, gnome-games is a scary module. I was told on IRC that it changes hands frequently. I shouldn't have included refactoring on my list of special days without mentioning a frequency of those days or at least a context. For code like gnome-games, refactoring would consume so much time that every day would be a "special" day for it. For a stable project, I think it would be good to have a day out of the year to check the code against its external dependecies. For instance, GObject will soon have a new way to handle instance-private data, so stable code might switch to that instead of using *priv as is common now.

I sometimes forget the number of some bug that interests me and look at all the open bugs for a project. For some there are very old bug reports that are no longer relevant, yet the report stays open. There are also forgotten patches. A project maintainer could handle many of these in less than a day, but I suspect that few maintainers use the web interface to bugzilla unless they must. Bugzilla sends email for every change to a bug, so the amount of bug mail for a project is at least twice the number of reported bugs. This has to make maintainership daunting. Except for that someone may incorrectly resolve a bug, it would probably be better for maintainers to ignore bugzilla mail and instead periodically check the bug list via the web.

GNOME Wishlist (cont.)

It would be great if we could rely on GError for alerts. I would still like to see GtkMessageDialog scrapped in favor of simple HIG-compliant widgets. Maybe I spend today writing some.

UI Debugging with grep (cont.)

In a short while I found and made patches for more than 50 instances of the same bug. Earlier today, I decided to look at gnome-games. With apologies to the current maintainer, this module is a mess. It changes hands often, so perhaps it's amazing that it hasn't completely collapsed. I'm tempted to refactor the whole thing. Correcting the misplaced-Close error is simple enough, but removing the Yes/No errors is not. Doing so requires rewording dialogs and changing the response handling code.

Suddenly, I feared the worst. Perhaps in the sed-corrected code there was something weird. I just checked every file by eye and did indeed find weirdness. I'm glad that none of the weirdness will dramatically affect program execution. The weirdness is a matter of style. I found at least 3 different ways of doing the same thing (presenting an error alert) and sometimes more than one way within a single file.

It is at least good that in some programs there is a special function that wraps this so correcting code once corrects the UI in infinite instances.

...

...

I'm so tired I can barely keep my eyes open. There are many quick fixes that I'd like to do now, but weariness compels me to wait.

Notes to self:

  • Does anyone systematically approach programming?
  • Does anyone set aside a day to refactor, to fix bugs, to close bugs, to look for bugs?
  • Am I such a freak for that I would?

UI Debugging with grep

While looking for the protocol violation bug in the GNOME notification area, I spied a UI bug in an error alert. Suspicious, in part because I've seen this UI bug elsewhere, I looked for it in gnome-applets. This was fairly simple. The UI bug is using Close where OK should be used. For some unknown reason, it frequently appears in error alerts. These are often made with GtkMessageDialog, which takes at least one GtkButtonsType argument. GtkButtonsType is an enumeration with GTK_BUTTONS_CLOSE as one of the values. This does not appear in any other code.* By using grep -r GTK_BUTTONS_CLOSE gnome-applets/, I found 20 instances of this bug.** Correcting this bug is trivial.
for i in `grep -l -r GTK_BUTTONS_CLOSE gnome-applets/`; do `sed s/GTK_BUTTONS_CLOSE/GTK_BUTTONS_OK/g $i > $i.tmp`; mv $i.tmp $i; done
For the maintainer to just do that and commit is simpler than me doing that, making a patch file, and filing a bug report for each applet. (I'm going to try to file one for the entire module.)

* If it did, then the grep parameter -B5 could be used to check that GTK_BUTTONS_CLOSE appears as an argument to gtk_message_dialog_new().

** Some instance of GTK_BUTTONS_CLOSE are in another type of alert. That doesn't matter because only instant-apply property or preference windows are supposed to have Close buttons.

Programming is like . . . ?

MichaelCrawford, thanks for the German lesson. I too wonder what programming ability is most like. Neither language nor mathematical ability seems to correlate.

Of course, they both help. I almost switched my major to CS once. I was shocked to find all but one other student used a loop to compute the sum of a range of counting numbers. (I dropped most of my courses that semester, but sank too deep in depression without resigning. My university makes a big deal out of dropping every course, so that one sits on my record with an F or a D.)

Complexity

As I've been building GnomeChat regularly from CVS, I've been exposed to a complex (read: common) build system of late. This has revealed other systemic cracks.

More than a year after Debian should have had an XML catalog, it still does not. Fortunately, I found a script by jamesh that solves the problem for me. It seems the Debian process provides all the bureaucracy of the U.S. Government without the service. I really hate it and I'm switching to something else as soon as I feel ready to archive $HOME and install another OS.

There are so many things that are more complex than they need to be that I don't feel like ranting about them; it would take too long.

GNOME Wishlist (cont.)

A panel applet is the wrong UI for some (most?) of the things the standard panel applets do. The inclusion of battfink is one half-step towards fixing this. (Removing the battery monitor applet is the other half.) Some other things:

  • Use check menu items for the items on the panel which should appear only once.
  • Be reasonable about what should appear how many times. Most of the applets should only have one instance per display or screen.
  • Confine launchers to a special object on the panel. The ill-named "Quick Lounge" applet is along the correct lines.

The Abyss

When any problem could be fixed by fixing a lower-level problem, where does one begin? Not answering this, perhaps more than anything else, depresses me. Even when I decide to work on one problem, the deeper ones annoy me. When solving the chosen problem gets hard, the futility of doing so given the underlying problem weighs in. I'm thinking of problems like those in The UNIX-HATERS Handbook, and also a number of social problems.

Wanting to solve problems instead of wanting to get paid for solving problems is one of my problems. Though I've tutored a little in recent years, I haven't charged for it in more than 6 years.

That tray

Icons in the tray are supposed to be handled much like any other window. You set your hints, and then either you take what you're given or you go away. E.g.:

  • You ask for a 1x1 space. You get a 16x16. Scale up.
  • You ask for a 128x128 space. You get a 24x24. Scale down.
  • You ask for a 1x128 space. You get a 32x32.
    1. Adjust.
    2. Take a little bit of time to look at the platforms that has been using such a thing for a few years (Windows, MacOS) and see if you can get it to sink in that you should use something sqaure.
    3. Realize that if you don't use something square, your design is probably wrong.

Windows appearing outside of the tray have been reported. Since only the tray is supposed to map these window and only after they are embedded, someone is violating the spec. Is the tray mapping before embedding? Is an app attempting to map its tray icon? Dunno.

39 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!