| // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef WINDOW_MANAGER_STACKING_MANAGER_H_ |
| #define WINDOW_MANAGER_STACKING_MANAGER_H_ |
| |
| #include <map> |
| #include <tr1/memory> |
| |
| #include <gtest/gtest_prod.h> // for FRIEND_TEST() macro |
| |
| #include "window_manager/compositor/compositor.h" |
| #include "window_manager/x11/x_types.h" |
| |
| namespace window_manager { |
| |
| class AtomCache; |
| class Window; |
| class XConnection; |
| |
| // Used to stack X11 client windows and compositor actors. StackingManager |
| // creates a window and an actor to use as reference points for each |
| // logical stacking layer and provides methods to move windows and actors |
| // between layers. |
| class StackingManager { |
| public: |
| // Layers into which windows can be stacked, in top-to-bottom order. |
| // Layers above LAYER_TOP_CLIENT_WINDOW don't have X windows, since we want |
| // them to always appear above client windows. |
| enum Layer { |
| // Debugging objects that should be stacked above everything else. |
| LAYER_DEBUGGING = 0, |
| |
| // Snapshots of the screen animated while locking or shutting down. |
| LAYER_SCREEN_LOCKER_SNAPSHOT, |
| |
| // Actors belonging to client windows are initially stacked at this layer. |
| // They shouldn't be raised above it (but note that an override-redirect |
| // window can stack itself above this layer's X window -- the layers above |
| // this one have no X windows, so their actors should always be stacked |
| // above client windows' actors). |
| LAYER_TOP_CLIENT_WINDOW, |
| |
| // Chrome screen locker window. |
| LAYER_SCREEN_LOCKER, |
| |
| // A fullscreen window (maybe a browser window; maybe a panel content |
| // window). |
| LAYER_FULLSCREEN_WINDOW, |
| |
| // A panel as it's being dragged. This is a separate layer so that the |
| // panel's shadow will be cast over stationary panels. |
| LAYER_DRAGGED_PANEL, |
| |
| // A transient window belonging to the currently-active toplevel |
| // window. Transients are stacked here when in active mode so that |
| // they'll obscure panels. (In overview mode, they're stacked directly |
| // above their owners.) |
| LAYER_ACTIVE_TRANSIENT_WINDOW, |
| |
| // Panel bar's input windows. |
| LAYER_PANEL_BAR_INPUT_WINDOW, |
| |
| // A stationary, packed (that is, in the main group on the right) panel |
| // in the panel bar. |
| LAYER_PACKED_PANEL_IN_BAR, |
| |
| // A stationary, floating ("independently positioned") panel in the |
| // panel bar. |
| LAYER_FLOATING_PANEL_IN_BAR, |
| |
| // A stationary panel in a panel dock. |
| LAYER_PACKED_PANEL_IN_DOCK, |
| |
| // Panel docks along the sides of the screen (specifically, their |
| // backgrounds). |
| LAYER_PANEL_DOCK, |
| |
| // The currently active (i.e. stacked-on-top) browser window. |
| LAYER_ACTIVE_BROWSER_WINDOW, |
| |
| // An inactive browser window. |
| LAYER_INACTIVE_BROWSER_WINDOW, |
| |
| // "Other" non-login windows (e.g. transient dialogs) managed by |
| // LoginController. |
| LAYER_LOGIN_OTHER_WINDOW, |
| |
| // Chrome login windows used by LoginController. |
| LAYER_LOGIN_WINDOW, |
| |
| // The background image. |
| LAYER_BACKGROUND, |
| |
| kNumLayers, |
| }; |
| |
| // Policies for stacking something relative to a supplied sibling. |
| enum SiblingPolicy { |
| // Stack the object directly above the sibling. |
| ABOVE_SIBLING = 0, |
| |
| // Stack the object directly below the sibling. |
| BELOW_SIBLING, |
| }; |
| |
| // Policies for stacking a window's shadow. |
| enum ShadowPolicy { |
| // Stack the shadow at the bottom of layer specified by the |shadow_layer| |
| // parameter. This can be useful for preventing a window's shadow from |
| // falling on its siblings -- imagine the case of two panels in the same |
| // layer that are located a pixel apart. |
| SHADOW_AT_BOTTOM_OF_SHADOW_LAYER = 0, |
| |
| // Stack the shadow directly below |win|'s actor. |
| SHADOW_DIRECTLY_BELOW_ACTOR, |
| }; |
| |
| // The layer reference points will be created at the top of the current stack |
| // of X windows (for LAYER_TOP_CLIENT_WINDOW and below) and children of the |
| // default compositor stage. |
| StackingManager(XConnection* xconn, |
| Compositor* compositor, |
| AtomCache* atom_cache); |
| ~StackingManager(); |
| |
| // Is the passed-in X window one of our internal windows? |
| bool IsInternalWindow(XWindow xid) { |
| return (xid_to_layer_.find(xid) != xid_to_layer_.end()); |
| } |
| |
| // Stack a window (both its X window and its compositor actor) at the top |
| // of the passed-in layer, which must be LAYER_TOP_CLIENT_WINDOW or below. |
| // |shadow_layer| is only honored if |shadow_policy| is |
| // SHADOW_AT_BOTTOM_OF_SHADOW_LAYER. |
| void StackWindowAtTopOfLayer( |
| Window* win, |
| Layer layer, |
| ShadowPolicy shadow_policy, |
| Layer shadow_layer); |
| |
| // Stack an X window at the top of the passed-in layer, which must be |
| // LAYER_TOP_CLIENT_WINDOW or below. This is useful for X windows that don't |
| // have Window objects associated with them (e.g. input windows). |
| void StackXidAtTopOfLayer(XWindow xid, Layer layer); |
| |
| // Stack a compositor actor at the top of the passed-in layer. |
| void StackActorAtTopOfLayer(Compositor::Actor* actor, Layer layer); |
| |
| // Stack a window's client and composited windows directly above or below |
| // another window. |
| void StackWindowRelativeToOtherWindow( |
| Window* win, |
| Window* sibling, |
| SiblingPolicy sibling_policy, |
| ShadowPolicy shadow_policy, |
| Layer shadow_layer); |
| |
| // Stack a compositor actor above or below another actor. |
| void StackActorRelativeToOtherActor( |
| Compositor::Actor* actor, |
| Compositor::Actor* sibling, |
| SiblingPolicy sibling_policy); |
| |
| // If |xid| is being used as a layer's stacking reference point, return |
| // the actor corresponding to the layer. Returns NULL otherwise. |
| Compositor::Actor* GetActorIfLayerXid(XWindow xid); |
| |
| private: |
| friend class BasicWindowManagerTest; // uses Get*ForLayer() |
| FRIEND_TEST(LayoutManagerTest, InitialWindowStacking); // uses |layer_to_*| |
| FRIEND_TEST(WindowManagerTest, StackOverrideRedirectWindowsAboveLayers); |
| |
| // Get a layer's name. |
| static const char* LayerToName(Layer layer); |
| |
| // Get the actor or XID for a particular layer. These crash if the layer |
| // is invalid. |
| Compositor::Actor* GetActorForLayer(Layer layer); |
| XWindow GetXidForLayer(Layer layer); |
| |
| XConnection* xconn_; // not owned |
| |
| // Maps from layers to the corresponding X or Compositor reference points. |
| // The reference points are stacked at the top of their corresponding |
| // layer (in other words, the Stack*AtTopOfLayer() methods will stack |
| // windows and actors directly beneath the corresponding reference |
| // points). |
| std::map<Layer, XWindow> layer_to_xid_; |
| std::map<Layer, std::tr1::shared_ptr<Compositor::Actor> > |
| layer_to_actor_; |
| |
| // Map we can use for quick lookup of whether an X window belongs to us, |
| // and to find the layer corresponding to an X window. |
| std::map<XWindow, Layer> xid_to_layer_; |
| }; |
| |
| } // namespace window_manager |
| |
| #endif // WINDOW_MANAGER_STACKING_MANAGER_H_ |