### 10.2 Minor Mode Scopes ¶

Minor modes can be scoped to different objects in a rather arbitrary manner. These scopes are defined by the macro `DEFINE-MINOR-MODE-SCOPE`. Because minor modes are implemented as mixins, the object returned by a scopes current object function must be a class instance.

Macro: define-minor-mode-scope (designator class &optional filter-type) &body retrieve-current-object ¶

  Default Values:

        filter-type  nil

  Define a minor mode scope for use with DEFINE-MINOR-MODE. This generates a call to ADD-MINOR-MODE-SCOPE which is evaluated when compiled, loaded, or executed. DESIGNATOR should be a keyword and TYPE should denote a class, while FILTER-TYPE should denote a general type. RETRIEVE-CURRENT-OBJECT should be a thunk body which returns the current object for this scope.

Macro: define-descended-minor-mode-scope designator parent &key class filter-type retrieve-current-object ¶

  Default Values:

        class                    nil
        filter-type              nil
        retrieve-current-object  nil

  Define a descended scope which inherits the parents type and functions unless provided.

Function: add-minor-mode-scope designator type current-object-thunk &optional filter-type ¶

  Default Values:

        filter-type  nil

  Add a list of the TYPE, CURRENT-OBJECT-THUNK, and ALL-OBJECTS-THUNK, under DESIGNATOR in the minor mode scope hash table.

When a minor mode is defined its scope is looked up and validated by the function `VALIDATE-SCOPE`. This function takes a scope and a list of superclasses, and ensures that the scope can descend from the superclasses scopes. This restricts the valid scopes to ensure that a minor mode scoped to `:GROUP` cant be a subclass of a minor mode scoped to `:WINDOW`, for example. However there is a way to override this by explicitly stating that two otherwise incompatible scopes are compatible. This is done by defining methods for the generic function `VALIDATE-SUPERSCOPE` which specialize upon the scope designators. Such methods should return at least one value, indicating if the superscope is a valid parent of the scope. If multiple values are returned, the second value must indicate whether the superscope is an invalid parent of the scope. For example:

    (defmethod stumpwm:validate-superscope ((c (eql :id1)) (p (eql :id2)))
      "Explicitly allow id1 to descend from id2"
      (values t nil))

    (defmethod stumpwm:validate-superscope ((c (eql :id3)) (p (eql :id4)))
      "Explicitly prevent id3 from descending from id4"
      (values nil t))

When defining and using scopes the type specifier is important; it is used to determine what minor modes should be mixed into an object when it is created. For this reason it is important when defining a minor mode or minor mode scope to understand the type hierarchy. It may also be in the programmers best interests to define an accompanying type.

Below is an example of a minor mode scope definition that descends from the `:WINDOW` scope, and is restricted to only firefox windows. This would be used to implement a minor mode that only gets mixed in to firefox windows, for example to implement key rebinding.

    (defun %firefox-window-p (w)
      (and (typep w 'window)
           (string-equal (window-class window) "Firefox")))

    (define-descended-minor-mode-scope :firefox-window :window
      :filter-type (satisfies %firefox-window-p))

The following scopes are predefined:

- Designator: `:UNSCOPED`, type: `T` Current object: return the global unscoped object.
- Designator: `:SCREEN`, type: `SCREEN` Current object: return the current screen.
- Designator: `:GROUP`, type: `GROUP` Current object: return the current group.
- Designator: `:TILE-GROUP`, type: `TILE-GROUP` Current object: return the current group.
- Designator: `:DYNAMIC-GROUP`, type: `DYNAMIC-GROUP` Current object: return the current group.
- Designator: `:FLOAT-GROUP`, type: `FLOAT-GROUP` Current object: return the current group.
- Designator: `:TILING-NON-DYNAMIC-GROUP`, type: `TILE-GROUP` Current object: return the current group when it is a non-dynamic tiling group.
- Designator: `:HEAD`, type: `HEAD` Current object: return the current head.
- Designator: `:FRAME`, type: `FRAME` Current object: return the current frame when in a tiling group.
- Designator: `:FRAME-EXCLUDING-HEAD`, type: `ONLY-FRAME-NO-HEADS` Descends from minor mode scope `:FRAME`.
- Designator: `:WINDOW`, type: `WINDOW`

  Current object: return the current window.
  All objects: collect every window from every group in the current screen.

- Designator: `:TILE-WINDOW`, type: `TILE-WINDOW`

  Current object: return the current window.
  All objects: collect every window from every tiling group, filtering all floating windows.

- Designator: `:FLOAT-WINDOW`, type: `FLOAT-WINDOW`

  Current object: return the current window.
  All objects: colelct every window from every group, filtering all non floating windows.