Mixin Audit

There are many mixins in PLWM which should use a different paradigm.

Guidelines

Since I'm not ready to really summarize the guidelines for separating mixins from other patterns, here are a couple of quotes from the mailing list on the subject:

From Mike Meyer:

On Wed, 23 Apr 2008 16:21:05 -0400
"David Bronke" <whitelynx@gmail.com> wrote:

> I haven't given much though yet to what should actually be a mixin and what
> shouldn't, although that will be rather important to figure out too. If
> anyone has any input, please repond... I'd like to get an official design
> document for the classes in PLWM posted on the Trac wiki so we can start
> moving toward a more transparent architecture.

Ah yes, the "is-a" vs "has-a" question. A really fundamental question
in O-O design. All I have is the obvious guideline - if the map
between the two types isn't 1-1, then it can't be an is-a.

Part of the original intent was that mixins would be used to configure
the window manager, screens, clients, etc. This works when you're
changing properties that really are 1-1 with the object in
question. But when you start looking at some of the things that mix
in, it's not clear that's the case.

So the first question to ask is: Is there any benefit from having more
than one of mixin foo attached to a bar, or having multiple bar's
share a foo?

> Screen includes all of the ModeWindow mixins, which I personally think might
> be better off in a separate tree... use ModeWindow as a base class, and add
> all the ModeStatus classes as mixins to the ModeWindow.

I can see that. The mac has two things things that I'd be tempted to
implement via modewindow (I don't use it, so I'm not sure how far off
base this is): the menu bar and the dock. So having more than one per
screen makes sense.

For that matter, the mac also only has one of each of those: screens
beyond the first don't get a menu bar or dock. So having fewer than
one per screen also makes sense (This isn't true for all multi-screen
window managers, though).

> WindowManager includes all of the other ModeWindow* mixins, which also seem
> like they should just be added to a ModeWindow hierarchy. Font also seems a
> bit out of place here.

This one seems to violate the 1-1 nature required. You can have more
than one screen (even though we don't support it very well), so you
can presumably have more than one modewindow, even though you only
have one window manager.

From Peter Liljenberg:

I won't try to comment everything said about the mixins, rather add
another viewpoint on how to cut them.  Any class that is currently a
mixin, but doesn't add any public methods to be used by other classes,
shouldn't be a mixin.  XorOutlineClient and ModeWindow are proper
mixins in this case, while BorderClient, ModeWindowACPI etc isn't.

The client non-mixins can easily be rewritten into a event handler for
AddClient which instantiates an object whose self.client points to the
actual client object.
The WM mixins are true singletons, while the screen mixins are
singletons as far as each screen is concerned (what is the pattern for
that?).

There would need to be some hooks for registering the event handlers
and creating the singletonish objects, similar to the __wm_init__ etc
of today.  This would best be solved by replacing them with some
better named methods in Screen and WindowManager which are overriden
by MyScreen and MyWM.

/Peter

Classes

Mixin Class (current design) Class to use with (current design) 1-to-1? Adds public methods? Needed actions
border.BorderClient Client ? ?
focus.JumpstartClient Client ? ?
focus.FocusClient Client ? ?
misc.InitialKeepOnScreenClient Client ? ?
misc.InhibitMozillaPopups Client ? ?
modestatus.ModeFocusedTitleClient Client ? ?
outline.XorOutlineClient Client ? ?
outline.WindowOutlineClient Client ? ?
panes.panesClient Client ? ?
views.ViewedClient Client ? ?
color.Color Screen ? ?
keys.KeyGrabber Screen ? ?
modestatus.ModeStatus Screen ? ?
modestatus.ModeFocusedTitleScreen Screen ? ?
modestatus.ModeMoveResize Screen ? ?
modewindow.ModeWindowScreen Screen ? ?
panes.panesScreen Screen ? ?
views.ViewHandler Screen ? ?
views.XMW_ViewHandler Screen ? ?
focus.PointToFocus WindowManager ? ?
focus.FocusHandler WindowManager ? ?
inspect.InspectServer WindowManager ? ?
mw_mixer.Mixer WindowManager No ? Use with new ModeWindow class instead, as a child.
mw_acpi.ModeWindowACPI WindowManager No ? Use with new ModeWindow class instead, as a child.
mw_apm.ModeWindowAPM WindowManager No ? Use with new ModeWindow class instead, as a child.
mw_biff.ModeWindowBiff WindowManager No ? Use with new ModeWindow class instead, as a child.
mw_biff.ThreadedModeWindowBiff WindowManager No ? Use with new ModeWindow class instead, as a child.
mw_clock.ModeWindowClock WindowManager No ? Use with new ModeWindow class instead, as a child.
mw_gmail.ModeWindowGmail WindowManager No ? Use with new ModeWindow class instead, as a child.
mw_load.ModeWindowLoad WindowManager No ? Use with new ModeWindow class instead, as a child.
mw_watchfiles.ModeWindowWatchFiles WindowManager No ? Use with new ModeWindow class instead, as a child.
mw_xmms.ModeWindowXMMS WindowManager No ? Use with new ModeWindow class instead, as a child.
mw_xmms2.ModeWindowXMMS2 WindowManager No ? Use with new ModeWindow class instead, as a child.
panes.panesManager WindowManager ? ?

Original Design

  • Client
    • border.BorderClient
    • focus.JumpstartClient
    • focus.FocusClient
    • misc.InitialKeepOnScreenClient
    • misc.InhibitMozillaPopups
    • modestatus.ModeFocusedTitleClient
    • outline.XorOutlineClient
    • outline.WindowOutlineClient
    • panes.panesClient
    • views.ViewedClient
  • Screen
    • color.Color
    • keys.KeyGrabber
    • modestatus.ModeStatus
    • modestatus.ModeFocusedTitleScreen
    • modestatus.ModeMoveResize
    • modewindow.ModeWindowScreen
    • panes.panesScreen
    • views.ViewHandler
    • views.XMW_ViewHandler
  • WindowManager
    • focus.PointToFocus
    • focus.FocusHandler
    • inspect.InspectServer
    • mw_mixer.Mixer
    • mw_acpi.ModeWindowACPI
    • mw_apm.ModeWindowAPM
    • mw_biff.ModeWindowBiff
    • mw_biff.ThreadedModeWindowBiff
    • mw_clock.ModeWindowClock
    • mw_gmail.ModeWindowGmail
    • mw_load.ModeWindowLoad
    • mw_watchfiles.ModeWindowWatchFiles
    • mw_xmms.ModeWindowXMMS
    • mw_xmms2.ModeWindowXMMS2
    • panes.panesManager

New Design

NOTE: Added classes are designated by bold formatting; classes which have moved to a different tree are designated by italics; classes which still need to be looked at are designated by monospace formatting.

  • Client
    • border.BorderClient
    • focus.JumpstartClient
    • focus.FocusClient
    • misc.InitialKeepOnScreenClient
    • misc.InhibitMozillaPopups
    • modestatus.ModeFocusedTitleClient
    • outline.XorOutlineClient
    • outline.WindowOutlineClient
    • panes.panesClient
    • views.ViewedClient
  • Screen
    • color.Color
    • keys.KeyGrabber
    • modestatus.ModeStatus
    • modestatus.ModeFocusedTitleScreen - Shouldn't this be in the ModeWindow tree?
    • modestatus.ModeMoveResize
    • modewindow.ModeWindowScreen - Is this necessary when using a separate ModeWindow class? Maybe to provide an add_modewindow() method...
    • panes.panesScreen
    • views.ViewHandler
    • views.XMW_ViewHandler
  • WindowManager
    • focus.PointToFocus
    • focus.FocusHandler
    • inspect.InspectServer
    • panes.panesManager
  • ModeWindow
    • mw_mixer.Mixer
    • mw_acpi.ModeWindowACPI
    • mw_apm.ModeWindowAPM
    • mw_biff.ModeWindowBiff
    • mw_biff.ThreadedModeWindowBiff
    • mw_clock.ModeWindowClock
    • mw_gmail.ModeWindowGmail
    • mw_load.ModeWindowLoad
    • mw_watchfiles.ModeWindowWatchFiles
    • mw_xmms.ModeWindowXMMS
    • mw_xmms2.ModeWindowXMMS2