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
