blob: 8249b95d555b5f4b06d95ec0bbfecefd14f97249 [file] [log] [blame]
// 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:
// 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();
// 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 positioned 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 regular Chrome 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,
// Toplevel windows, along with their transient windows.
LAYER_TOPLEVEL_WINDOW,
// Snapshot windows, along with their input windows.
LAYER_SNAPSHOT_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,
};
// 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.
// Its shadow will be stacked at the bottom of the layer so as to not appear
// above the windows' siblings. Returns false if the X request fails.
bool StackWindowAtTopOfLayer(Window* win, Layer 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). Returns
// false if the X request fails.
bool 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. As in StackWindowAtTopOfLayer(), the window's shadow
// will be stacked at the bottom of |layer|. Make sure that |sibling| is
// in |layer| -- things will get confusing otherwise.
bool StackWindowRelativeToOtherWindow(
Window* win, Window* sibling, bool above, Layer layer);
// Stack a compositor actor above or below another actor.
void StackActorRelativeToOtherActor(
Compositor::Actor* actor, Compositor::Actor* sibling, bool above);
// 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_