Older blog entries for auspex (starting at number 45)

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.

Ich nien . . . uh, read German.

For years I've been amazed by the solution to the basic Gaussian integral. For most of the mathematical problems I've encountered, I've either had the insight to the solution myself, or had some idea how it was reached. (Mostly the latter, I'm sure.) But not so for the Gaussian integral. It is like a solution out of Looney Tunes; where Bugs Bunny reached into a portable "hole", Gauss reached into another dimension.

Some months ago, this started to really annoy me. The same day I decided I would endeavor to find some paper of Gauss explaining how he came to his solution, I was informed of the Gauss collection at NSU. This was entirely coincidental. I was speaking to a local high school teacher about my high school which is located on the campus of NSU. She'd days earlier learned of the Gauss collection there. Such good fortune! At the time, I already had a trip to there planned for my 10-year class reunion.

Now, I'm not going. While there are former classmates I'd like to see, there are none I'm going out of my way to see. The one I might travel for already told me she won't be there. The one I'd want a restraining order against probably will be going; damn ex-girlfriends.

But still, there's the Gauss collection. No matter what, that would be worth seeing. But I'd forgotten one thing, and the other day my father reminded me of it: I can't read German.

Confusion over Linux vs. GNU/Linux

The truth is that GNU is the kernel of the Emacs OS.

elanthis

(in re wishlist) A scary aspect of a GUI scripting language for GNOME is that it should work over the network. I wonder if that means an X dependency. *shudder*

If hacking the linker is required (I don't know that it is), then there's another benefit of the LinuxSTEP work. :-) As for "install" vs. "drop in place", the simple (so probably wrong) solution would be a daemon. Isn't what's needed really "drop in the right place"?

One thing that really worries me is that I don't see any communication between GNUStep/LinuxSTEP and freedesktop.org.

kz

Applying the CSS box model to Gtk sounds interesting. I suspect backward compatibility will be a large obstacle. The planned padding has not yet been added to GtkAlignment in CVS HEAD. I don't see or recall that adding it to GtkContainer was considered. You should perhaps bring this up soon on gtk-devel-list.

Pincushion

Being in what seems to be my worst episode of depression ever, and not having yet seen a doctor, and not taking any medication, I'm think that the neither of the antidepressants I'd been prescribed had any positive effect. Except for the side-effects, I'm almost exactly the same. "Almost" here is disturbing word; something is different, but I can't put my finger on it.

I'll probably see a doctor on Monday. I don't expect to be satisfied. I think satisfaction would require the opening scene of The Six Million Dollar Man - "We can rebuild him...." According to a PBS program, diagnostics are really good now with EEGs and NMRI.

The Six Million Dollar Man

Seems pretty cheap now. Doesn't the US military spend more than that on toilet seats?

NMRI

One of my professors had said that MRI is shortened from NMRI because people fear nuclear technology. That seems reasonable. Why worry a patient with images of Dr. Strangelove? However, someone else suggested a better and less cynical explanation. "En-Em-Ar" sounds a lot like "En-Em-Ah". I'd hate for the confusion to be resolved by coin toss.

What's with the randomness, dude?

My sleep schedule is . . . not. Being nocturnal or nearly so is normal for me. This week, I have no rhythm. I think anxiety about my sleep schedule is one of the reasons.

Sleep

Strange thing just occurred to me. I have two normal sleep schedules: asleep by about 10 PM or 4 AM, and awake 6 hrs. later. My abnormal schedule - the one that I fall into when depressed is to go to sleep at 10 AM. (It's after 2 PM now and I awoke last night at about 7 PM.) Er, maybe that's all stranger than what occurred to me.

36 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!