Aqua toplevels

Musings by JH (2005-07-27) about how to rewrite the Tk toplevel handling on Mac OS X Aqua, focusing on full native control. When making comments, leave your name and a rough date to improve responses.

We need to move away from MacWindowStyle, and indeed from all pre-Appearance Manager window creation and usage. I would recommend wm attributes handling that controls the class and styling of the window (among other things). This basically proposes a significant rewrite of macosx/tkMacOSXWm.c.


Window Class and Style

wm attributes $toplevel -class takes one of:

  • alert moveableAlert modal moveableModal floating help document sheet toolbar plain altPlain drawer

The style bits (see "Carbon: Window Manager Reference" [L1 ]) are trickier. Should we allow for a list of allowed bits (eg, {collapseBox resizable}) with possible ! prefix notation for not-bits, or list out all bits as options to attributes?

  • some combination of closeBox, horizontalZoom, verticalZoom, collapseBox, resizable, sideTitlebar, metal, ...

Note that whatever we allow the user to manage, there will be Tk underneath needing to check, verify and possibly change for compatibility with classic code constructs like wm transient. I recommend removing any references to the older style (e.g., documentProc).


wm transient and wm overrideredirect

Currently an overrideredirect window (one where the progra should control all geometry and visibility) is simply created as a plainDBox, and a transient window did the same - no titlebar or anything. This is simply wrong for transient windows, but what is right? Also, the confluence of various settings need to be aware of each other to operate together (e.g., overrideredirect and transient together, as a standard combobox popdown would use).

On Windows, tkWinWm.c has an UpdateWrapper call that handles many things about the outer toplevel that may change. This is in part for correct menu handling and embedding, but is also critical for ensuring that the numerous attribute variants are all managed together correctly. We will need something like this in tkMacOSXWm.c as well. As much as possible, we need to allow the modification of a toplevel's attributes without having to recreate it. OS X does impose some limitations on us for this (like changing classes), but it also has some routines to assist in this (eg, GetAvailableWindowAttributes and ChangeWindowAttributes).

But what type should a transient window be? Jim Ingham proposed using floatZoomGrowProc [L2 ] at one point. The interesting thing about floating class windows is that they all exist in an app layer that floats them above document class windows of the app, and they are all withdrawn/deiconifying by the OS when you switch app contexts. This may well be an appropriate translation for transient windows on OS X, but there is also the possibility of simply grouping windows into a layer [L3 ] using functions like SetWindowGroup and ChangeWindowGroupAttributes. The latter will be necessary for proper support of sheets and drawers in any case.

An issue with floating class windows is that if you were to want a dropdown (like a combobox), then that must be also of floating class, or a modal class, otherwise it will remain behind the floating window.


sheets and drawers

These are window classes that can be created, but proper handling for them does not yet exist in Tk. They require the layer handling mentioned above. It is possible that if the right set of existing Tk commands are used (with proposed wm attributes changes), then this could be handled in the proposed UpdateWrapper. For example

 set t .t
 toplevel $t
 wm withdraw $t
 wm attributes $t -class sheet ; # add possible style bits
 wm transient $t .
 wm deiconify $t

The deiconify $t would force the mapping. UpdateWrapper would see that we have a transient window of class sheet, which means do the layer/group management attaching it to its parent. Drawers would operate in a similar way.


toolbar button

I have enabled the toplevel style bit that will place the toolbar button (the right-hand-side button that shows/hides toolbar-style controls in a topleve). However, there are events that go along with this that are not yet handled. I imagine the proper way to do this is to generate an <<AquaToolbutton>> (maybe without 'Aqua'?) event that users can handle to do what they want.


Comments here ...

Alastair Davies 2005-07-28: from the point-of-view of porting an application to MacOS X from Windows and Linux, the main problem was undoubtedly the inconsistent display of "wm transient" windows. For better or worse (and I think it's obviously not an ideal name) this is the usual way to create a dialog on both Windows and Linux; the fact that it does not produce something looking like a dialog on Aqua meant frequent resort to the MacWindowStyle command. In other words, the problem was not lack of native control, but that the code bulged with platform-specific tests. As I understand it, the proposal does address this issue properly, and goes beyond it to expose additional functionality in an Aqua-specific manner. Hopefully, therefore, this proposal delivers us the best of both worlds. Incidentally, one other point I'd love to see addressed in changes to tkMacOSXWm.c would be to include a patch to fix Bug #1073456 (TkAqua: no zoom support) [L4 ].

NEM 2005-09-22: A few quick comments as bullets:

  • (Superficial) Is there a possible confusion between [toplevel -class ...] and [wm attributes -class ...]?
  • I don't know the best way to handle style bits. Using separate options feels right as an interface, but is the list of attributes reasonably stable?
  • floatZoomGrowProc is a good style for transient windows, IIRC.
  • How do we expose additional drawer functionality. e.g. hiding/showing the drawer -- is that just withdraw/deiconify? (I guess that would seem natural). You can also specify a preferred side for the drawer (left,right,bottom). I'd say that is a low-priority option, though (the default, IIRC, is left or right depending on which has most space available, which is probably the Right Thing for most uses).

Now just got to fix my Mac up...