// 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.

#include "window_manager/window.h"

#include <algorithm>

#include <gflags/gflags.h>

#include "base/logging.h"
#include "base/string_util.h"
#include "cros/chromeos_wm_ipc_enums.h"
#include "window_manager/atom_cache.h"
#include "window_manager/compositor/animation.h"
#include "window_manager/focus_manager.h"
#include "window_manager/geometry.h"
#include "window_manager/shadow.h"
#include "window_manager/stacking_manager.h"
#include "window_manager/util.h"
#include "window_manager/window_manager.h"
#include "window_manager/x11/x_connection.h"

using std::map;
using std::max;
using std::min;
using std::set;
using std::string;
using std::tr1::shared_ptr;
using std::vector;
using window_manager::util::GetCurrentTimeSec;
using window_manager::util::XidStr;

DEFINE_bool(load_window_shapes, false,
            "Should we use the Shape extension to load shaped windows' "
            "bounding regions?  The compositing code doesn't currently support "
            "using these regions to mask windows, and we favor RGBA windows "
            "instead.");

namespace window_manager {

// We could technically just move windows to (XConnection::kMaxPosition,
// XConnection::kMaxPosition) to keep them offscreen (X11 appears to allow
// window contents to go beyond the 2**15 limit; it's just the origin that needs
// to fall within it), but GTK sometimes arranges override-redirect windows
// relative to offscreen windows, and it happily overflows the limit in this
// case, ending up with negative coordinates.
const int Window::kOffscreenX = (XConnection::kMaxPosition + 1) / 2;
const int Window::kOffscreenY = (XConnection::kMaxPosition + 1) / 2;

const int Window::kVideoMinWidth = 300;
const int Window::kVideoMinHeight = 225;
const int Window::kVideoMinFramerate = 15;

// Maximum size of |damage_debug_actors_|.  This is effectively the maximum
// number of damage events that we'll show onscreen at once for this window.
static const size_t kMaxDamageDebugActors = 8;

// Color for damage actors.
static const char kDamageDebugColor[] = "#d60";

// Starting opacity for damage actors.
static const double kDamageDebugOpacity = 0.25;

// Duration in milliseconds over which a damage actor's opacity fades to 0.
static const int kDamageDebugFadeMs = 200;

Window::Window(WindowManager* wm,
               XWindow xid,
               bool override_redirect,
               const XConnection::WindowGeometry& geometry)
    : xid_(xid),
      xid_str_(XidStr(xid_)),
      wm_(wm),
      actor_(wm_->compositor()->CreateTexturePixmap()),
      transient_for_xid_(None),
      override_redirect_(override_redirect),
      mapped_(false),
      shaped_(false),
      type_(chromeos::WM_IPC_WINDOW_UNKNOWN),
      visibility_(VISIBILITY_UNSET),
      update_client_position_for_moves_(true),
      client_bounds_(geometry.bounds),
      client_depth_(geometry.depth),
      client_opacity_(1.0),
      composited_shown_(false),
      composited_origin_(geometry.bounds.position()),
      composited_scale_x_(1.0),
      composited_scale_y_(1.0),
      composited_opacity_(1.0),
      shadow_opacity_(1.0),
      supports_wm_take_focus_(false),
      supports_wm_delete_window_(false),
      supports_wm_ping_(false),
      wm_state_fullscreen_(false),
      wm_state_maximized_horz_(false),
      wm_state_maximized_vert_(false),
      wm_state_modal_(false),
      wm_hint_urgent_(false),
      damage_(0),
      pixmap_(0),
      need_to_update_actor_position_(false),
      need_to_reset_pixmap_(false),
      wm_sync_request_alarm_(0),
      current_wm_sync_num_(0),
      client_has_redrawn_after_last_resize_(true),
      updates_frozen_(false),
      client_pid_(-1),
      num_video_damage_events_(0),
      video_damage_start_time_(-1) {
  DCHECK(xid_);
  DLOG(INFO) << "Constructing object to track "
             << (override_redirect_ ? "override-redirect " : "")
             << "window " << xid_str_ << " at " << geometry.bounds;

  // Listen for property and shape changes on this window.
  wm_->xconn()->SelectInputOnWindow(xid_, PropertyChangeMask, true);
  wm_->xconn()->SelectShapeEventsOnWindow(xid_);

  // If the window has a border, remove it -- borders make things more
  // confusing (we'd need to include the border when telling the compositor
  // the window's position, but it's not included when telling X to resize
  // the window, etc.).
  if (!override_redirect_ && geometry.border_width > 0)
    wm_->xconn()->SetWindowBorderWidth(xid_, 0);

  damage_ = wm_->xconn()->CreateDamage(
      xid_, XConnection::DAMAGE_REPORT_LEVEL_BOUNDING_BOX);

  actor_->Move(composited_x(), composited_y(), 0);
  actor_->Hide();
  // TODO(derat): Move this stuff to WindowManager::TrackWindow() instead.
  wm_->stage()->AddActor(actor_.get());
  if (!override_redirect_) {
    wm_->stacking_manager()->StackWindowAtTopOfLayer(
        this,
        StackingManager::LAYER_TOP_CLIENT_WINDOW,
        StackingManager::SHADOW_DIRECTLY_BELOW_ACTOR,
        StackingManager::LAYER_TOP_CLIENT_WINDOW);
  } else {
    wm_->stacking_manager()->StackActorAtTopOfLayer(
        actor_.get(),
        StackingManager::LAYER_TOP_CLIENT_WINDOW);
  }

  // Various properties could've been set on this window after it was
  // created but before we selected PropertyChangeMask, so we need to query
  // them here.
  FetchAndApplyTitle();
  FetchAndApplyWindowType();
  FetchAndApplyShape();
  FetchAndApplyWindowOpacity();
  FetchAndApplySizeHints();
  FetchAndApplyWmProtocols();
  FetchAndApplyWmState();
  FetchAndApplyChromeState();
  FetchAndApplyChromeStatusBounds();
  FetchAndApplyTransientHint();
  FetchAndApplyWmHints();
  FetchAndApplyWmWindowType();
  FetchAndApplyWmClientMachine();
  FetchAndApplyWmPid();
  FetchAndApplyChromeFreezeUpdates();
}

Window::~Window() {
  if (damage_)
    wm_->xconn()->DestroyDamage(damage_);
  if (pixmap_)
    wm_->xconn()->FreePixmap(pixmap_);
  DestroyWmSyncRequestAlarm();
}

bool Window::IsFocused() const {
  return wm_->focus_manager()->focused_win() == this;
}

void Window::FetchAndApplyTitle() {
  DCHECK(xid_);
  DCHECK(actor_.get());

  title_.clear();
  wm_->xconn()->GetStringProperty(
      xid_, wm_->GetXAtom(ATOM_NET_WM_NAME), &title_);

  if (title_.empty())
    actor_->SetName(string("window ") + xid_str_);
  else
    actor_->SetName(string("window '") + title_ + "' (" + xid_str_ + ")");
}

bool Window::FetchAndApplySizeHints() {
  DCHECK(xid_);
  if (!wm_->xconn()->GetSizeHintsForWindow(xid_, &size_hints_))
    return false;

  const XConnection::SizeHints& h = size_hints_;
  DLOG(INFO) << "Got size hints for " << xid_str_ << ":"
             << " size=" << h.size
             << " min_size=" << h.min_size
             << " max_size=" << h.max_size
             << " inc=" << h.size_increment
             << " min_aspect=" << h.min_aspect_ratio
             << " max_aspect=" << h.max_aspect_ratio
             << " base=" << h.base_size;

  // If windows are override-redirect or have already been mapped, they
  // should just make/request any desired changes directly.  Also ignore
  // position, aspect ratio, etc. hints for now.
  if (!mapped_ && !override_redirect_ &&
      (size_hints_.size.width > 0 && size_hints_.size.height > 0)) {
    Resize(size_hints_.size, GRAVITY_NORTHWEST);
  }

  return true;
}

bool Window::FetchAndApplyTransientHint() {
  DCHECK(xid_);
  XWindow prev_transient_for_xid = transient_for_xid_;
  if (!wm_->xconn()->GetTransientHintForWindow(xid_, &transient_for_xid_))
    return false;
  if (transient_for_xid_ != prev_transient_for_xid) {
    DLOG(INFO) << "Window " << xid_str_ << " is transient for "
               << XidStr(transient_for_xid_);
  }
  return true;
}

bool Window::FetchAndApplyWindowType() {
  DCHECK(xid_);
  bool result = wm_->wm_ipc()->GetWindowType(xid_, &type_, &type_params_);
  DLOG(INFO) << "Window " << xid_str_ << " has type " << type_
             << " (" << type_str() << ")";
  return result;
}

void Window::FetchAndApplyWindowOpacity() {
  DCHECK(xid_);
  static const uint32 kMaxOpacity = 0xffffffffU;

  uint32 opacity = kMaxOpacity;
  wm_->xconn()->GetIntProperty(
      xid_,
      wm_->GetXAtom(ATOM_NET_WM_WINDOW_OPACITY),
      reinterpret_cast<int32*>(&opacity));
  client_opacity_ = (opacity == kMaxOpacity) ?
      1.0 : static_cast<double>(opacity) / kMaxOpacity;

  // TODO: It'd be nicer if we didn't interrupt any in-progress opacity
  // animations.
  SetCompositedOpacity(composited_opacity_, 0);
}

void Window::FetchAndApplyWmHints() {
  DCHECK(xid_);
  vector<int> wm_hints;
  if (!wm_->xconn()->GetIntArrayProperty(
          xid_, wm_->GetXAtom(ATOM_WM_HINTS), &wm_hints)) {
    return;
  }

  const uint32_t flags = wm_hints[0];
  wm_hint_urgent_ = flags & (1L << 8);  // XUrgencyHint from Xutil.h
}

void Window::FetchAndApplyWmProtocols() {
  DCHECK(xid_);
  supports_wm_take_focus_ = false;
  supports_wm_delete_window_ = false;
  supports_wm_ping_ = false;
  bool supports_wm_sync_request = false;

  vector<int> wm_protocols;
  if (!wm_->xconn()->GetIntArrayProperty(
          xid_, wm_->GetXAtom(ATOM_WM_PROTOCOLS), &wm_protocols)) {
    return;
  }

  const XAtom wm_take_focus = wm_->GetXAtom(ATOM_WM_TAKE_FOCUS);
  const XAtom wm_delete_window = wm_->GetXAtom(ATOM_WM_DELETE_WINDOW);
  const XAtom wm_ping = wm_->GetXAtom(ATOM_NET_WM_PING);
  const XAtom wm_sync_request = wm_->GetXAtom(ATOM_NET_WM_SYNC_REQUEST);
  for (vector<int>::const_iterator it = wm_protocols.begin();
       it != wm_protocols.end(); ++it) {
    if (static_cast<XAtom>(*it) == wm_take_focus) {
      DLOG(INFO) << "Window " << xid_str_ << " supports WM_TAKE_FOCUS";
      supports_wm_take_focus_ = true;
    } else if (static_cast<XAtom>(*it) == wm_delete_window) {
      DLOG(INFO) << "Window " << xid_str_ << " supports WM_DELETE_WINDOW";
      supports_wm_delete_window_ = true;
    } else if (static_cast<XAtom>(*it) == wm_ping) {
      DLOG(INFO) << "Window " << xid_str_ << " supports _NET_WM_PING";
      supports_wm_ping_ = true;
    } else if (static_cast<XAtom>(*it) == wm_sync_request) {
      DLOG(INFO) << "Window " << xid_str_ << " supports _NET_WM_SYNC_REQUEST";
      supports_wm_sync_request = true;
    }
  }

  // Don't check the property again if we already have a counter.
  if (supports_wm_sync_request && !wm_sync_request_alarm_) {
    if (!FetchAndApplyWmSyncRequestCounterProperty())
      supports_wm_sync_request = false;
  }

  if (!supports_wm_sync_request && wm_sync_request_alarm_)
    DestroyWmSyncRequestAlarm();
}

bool Window::FetchAndApplyWmSyncRequestCounterProperty() {
  DCHECK(!wm_sync_request_alarm_);

  int counter = 0;
  if (!wm_->xconn()->GetIntProperty(
          xid_, wm_->GetXAtom(ATOM_NET_WM_SYNC_REQUEST_COUNTER), &counter)) {
    LOG(WARNING) << "Didn't find a _NET_WM_SYNC_REQUEST_COUNTER property on "
                 << "window " << xid_str_;
    return false;
  }

  XID counter_xid = static_cast<XID>(counter);
  current_wm_sync_num_ = 10;  // arbitrary, but not the default of 0
  wm_->xconn()->SetSyncCounter(counter_xid, current_wm_sync_num_);
  wm_sync_request_alarm_ = wm_->xconn()->CreateSyncCounterAlarm(
      counter_xid, current_wm_sync_num_ + 1);
  if (!wm_sync_request_alarm_)
    return false;
  wm_->RegisterSyncAlarm(wm_sync_request_alarm_, this);

  DLOG(INFO) << "Created sync alarm " << XidStr(wm_sync_request_alarm_)
             << " on counter " << XidStr(counter_xid) << " for window "
             << xid_str_;
  return true;
}

void Window::FetchAndApplyWmState() {
  DCHECK(xid_);
  wm_state_fullscreen_ = false;
  wm_state_maximized_horz_ = false;
  wm_state_maximized_vert_ = false;
  wm_state_modal_ = false;

  vector<int> state_atoms;
  if (!wm_->xconn()->GetIntArrayProperty(
          xid_, wm_->GetXAtom(ATOM_NET_WM_STATE), &state_atoms)) {
    return;
  }

  XAtom fullscreen_atom = wm_->GetXAtom(ATOM_NET_WM_STATE_FULLSCREEN);
  XAtom max_horz_atom = wm_->GetXAtom(ATOM_NET_WM_STATE_MAXIMIZED_HORZ);
  XAtom max_vert_atom = wm_->GetXAtom(ATOM_NET_WM_STATE_MAXIMIZED_VERT);
  XAtom modal_atom = wm_->GetXAtom(ATOM_NET_WM_STATE_MODAL);
  for (vector<int>::const_iterator it = state_atoms.begin();
       it != state_atoms.end(); ++it) {
    XAtom atom = static_cast<XAtom>(*it);
    if (atom == fullscreen_atom)
      wm_state_fullscreen_ = true;
    if (atom == max_horz_atom)
      wm_state_maximized_horz_ = true;
    if (atom == max_vert_atom)
      wm_state_maximized_vert_ = true;
    else if (atom == modal_atom)
      wm_state_modal_ = true;
  }

  DLOG(INFO) << "Fetched _NET_WM_STATE for " << xid_str_ << ":"
             << " fullscreen=" << wm_state_fullscreen_
             << " maximized_horz=" << wm_state_maximized_horz_
             << " maximized_vert=" << wm_state_maximized_vert_
             << " modal=" << wm_state_modal_;
}

void Window::FetchAndApplyWmWindowType() {
  DCHECK(xid_);
  wm_window_type_xatoms_.clear();

  vector<int> window_type_ints;
  if (!wm_->xconn()->GetIntArrayProperty(
          xid_, wm_->GetXAtom(ATOM_NET_WM_WINDOW_TYPE), &window_type_ints)) {
    return;
  }

  for (vector<int>::const_iterator it = window_type_ints.begin();
       it != window_type_ints.end(); ++it) {
    wm_window_type_xatoms_.push_back(static_cast<XAtom>(*it));
  }
}

void Window::FetchAndApplyChromeState() {
  DCHECK(xid_);
  XAtom state_xatom = wm_->GetXAtom(ATOM_CHROME_STATE);
  chrome_state_xatoms_.clear();
  vector<int> state_xatoms;
  if (!wm_->xconn()->GetIntArrayProperty(xid_, state_xatom, &state_xatoms))
    return;

  string debug_str;
  for (vector<int>::const_iterator it = state_xatoms.begin();
       it != state_xatoms.end(); ++it) {
    chrome_state_xatoms_.insert(static_cast<XAtom>(*it));
    if (!debug_str.empty())
      debug_str += " ";
    debug_str += wm_->GetXAtomName(static_cast<XAtom>(*it));
  }
  DLOG(INFO) << "Fetched " << wm_->GetXAtomName(state_xatom) << " for "
             << xid_str_ << ": " << debug_str;
}

void Window::FetchAndApplyChromeStatusBounds() {
  DCHECK(xid_);
  status_bounds_.reset(0, 0, 0, 0);
  vector<int> values;
  if (!wm_->xconn()->GetIntArrayProperty(
          xid_, wm_->GetXAtom(ATOM_CHROME_STATUS_BOUNDS), &values)) {
    return;
  }

  if (values.size() != 4) {
    LOG(WARNING) << "Got status bounds property for " << xid_str_ << " with "
                 << values.size() << " value(s) (expected 4)";
    return;
  }

  status_bounds_.reset(values[0], values[1], values[2], values[3]);
  DLOG(INFO) << "Fetched status bounds " << status_bounds_ << " for "
             << xid_str_;
}

void Window::FetchAndApplyWmClientMachine() {
  DCHECK(xid_);
  client_hostname_.clear();
  wm_->xconn()->GetStringProperty(
      xid_, wm_->GetXAtom(ATOM_WM_CLIENT_MACHINE), &client_hostname_);
  if (!client_hostname_.empty()) {
    DLOG(INFO) << "Client owning window " << xid_str_ << " is running on "
               << "host \"" << client_hostname_ << "\"";
  }
}

void Window::FetchAndApplyWmPid() {
  DCHECK(xid_);
  client_pid_ = -1;
  wm_->xconn()->GetIntProperty(
      xid_, wm_->GetXAtom(ATOM_NET_WM_PID), &client_pid_);
  DLOG(INFO) << "Client owning window " << xid_str_ << " has PID "
             << client_pid_;
}

void Window::FetchAndApplyChromeFreezeUpdates() {
  DCHECK(xid_);
  int dummy_value = 0;
  bool property_exists =
      wm_->xconn()->GetIntProperty(
          xid_, wm_->GetXAtom(ATOM_CHROME_FREEZE_UPDATES), &dummy_value);
  HandleFreezeUpdatesPropertyChange(property_exists);
}

void Window::FetchAndApplyShape() {
  DCHECK(xid_);
  DCHECK(actor_.get());
  shaped_ = false;

  // We don't grab the server around these two requests, so it's possible
  // that a shaped window will have become unshaped between them and we'll
  // think that the window is shaped but get back an unshaped region.  This
  // should be okay; we should get another ShapeNotify event for the window
  // becoming unshaped and clear the useless mask then.
  if (wm_->xconn()->IsWindowShaped(xid_)) {
    shaped_ = true;

    if (FLAGS_load_window_shapes) {
      ByteMap bytemap(client_size());
      if (wm_->xconn()->GetWindowBoundingRegion(xid_, &bytemap)) {
        DLOG(INFO) << "Got shape for " << xid_str_;
        actor_->SetAlphaMask(
            bytemap.bytes(), bytemap.size().width, bytemap.size().height);
      } else {
        shaped_ = false;
      }
    }
  }

  if (FLAGS_load_window_shapes && !shaped_)
    actor_->ClearAlphaMask();

  UpdateShadowVisibility();
}

bool Window::FetchMapState() {
  DCHECK(xid_);
  XConnection::WindowAttributes attr;
  if (!wm_->xconn()->GetWindowAttributes(xid_, &attr))
    return false;
  return (attr.map_state != XConnection::WindowAttributes::MAP_STATE_UNMAPPED);
}

void Window::ParseWmStateMessage(const long data[5],
                                 map<XAtom, bool>* states_out) const {
  DCHECK(xid_);
  DCHECK(states_out);
  states_out->clear();

  XAtom fullscreen_atom = wm_->GetXAtom(ATOM_NET_WM_STATE_FULLSCREEN);
  if (static_cast<XAtom>(data[1]) == fullscreen_atom ||
      static_cast<XAtom>(data[2]) == fullscreen_atom) {
    bool value = wm_state_fullscreen_;
    SetWmStateInternal(data[0], &value);
    (*states_out)[fullscreen_atom] = value;
  }
  XAtom modal_atom = wm_->GetXAtom(ATOM_NET_WM_STATE_MODAL);
  if (static_cast<XAtom>(data[1]) == modal_atom ||
      static_cast<XAtom>(data[2]) == modal_atom) {
    bool value = wm_state_modal_;
    SetWmStateInternal(data[0], &value);
    (*states_out)[modal_atom] = value;
  }

  // We don't let clients toggle their maximized state currently.
}

bool Window::ChangeWmState(const map<XAtom, bool>& states) {
  DCHECK(xid_);
  for (map<XAtom, bool>::const_iterator it = states.begin();
       it != states.end(); ++it) {
    XAtom xatom = it->first;
    int action = it->second;  // 0 is remove, 1 is add

    if (xatom == wm_->GetXAtom(ATOM_NET_WM_STATE_FULLSCREEN))
      SetWmStateInternal(action, &wm_state_fullscreen_);
    else if (xatom == wm_->GetXAtom(ATOM_NET_WM_STATE_MAXIMIZED_HORZ))
      SetWmStateInternal(action, &wm_state_maximized_horz_);
    else if (xatom == wm_->GetXAtom(ATOM_NET_WM_STATE_MAXIMIZED_VERT))
      SetWmStateInternal(action, &wm_state_maximized_vert_);
    else if (xatom == wm_->GetXAtom(ATOM_NET_WM_STATE_MODAL))
      SetWmStateInternal(action, &wm_state_modal_);
    else
      LOG(ERROR) << "Unsupported _NET_WM_STATE " << xatom
                 << " for " << xid_str_;
  }
  return UpdateWmStateProperty();
}

bool Window::ChangeChromeState(const map<XAtom, bool>& states) {
  DCHECK(xid_);
  for (map<XAtom, bool>::const_iterator it = states.begin();
       it != states.end(); ++it) {
    if (it->second)
      chrome_state_xatoms_.insert(it->first);
    else
      chrome_state_xatoms_.erase(it->first);
  }
  return UpdateChromeStateProperty();
}

bool Window::TakeFocus(XTime timestamp) {
  DLOG(INFO) << "Focusing " << xid_str_ << " using time " << timestamp;
  DCHECK(xid_);
  if (supports_wm_take_focus_) {
    long data[5];
    memset(data, 0, sizeof(data));
    data[0] = wm_->GetXAtom(ATOM_WM_TAKE_FOCUS);
    data[1] = timestamp;
    if (!wm_->xconn()->SendClientMessageEvent(
             xid_, xid_, wm_->GetXAtom(ATOM_WM_PROTOCOLS), data, 0)) {
      return false;
    }
  } else {
    if (!wm_->xconn()->FocusWindow(xid_, timestamp))
      return false;
  }
  return true;
}

bool Window::SendDeleteRequest(XTime timestamp) {
  DLOG(INFO) << "Maybe asking " << xid_str_ << " to delete itself with time "
             << timestamp;

  DCHECK(xid_);
  if (!supports_wm_delete_window_)
    return false;

  DCHECK(!override_redirect_)
      << "Attempted to send delete request to override-redirect window "
      << xid_str_;

  long data[5];
  memset(data, 0, sizeof(data));
  data[0] = wm_->GetXAtom(ATOM_WM_DELETE_WINDOW);
  data[1] = timestamp;
  return wm_->xconn()->SendClientMessageEvent(
            xid_, xid_, wm_->GetXAtom(ATOM_WM_PROTOCOLS), data, 0);
}

bool Window::SendPing(XTime timestamp) {
  DCHECK(xid_);
  if (!supports_wm_ping_)
    return false;

  long data[5];
  memset(data, 0, sizeof(data));
  data[0] = wm_->GetXAtom(ATOM_NET_WM_PING);
  data[1] = timestamp;
  data[2] = xid_;
  return wm_->xconn()->SendClientMessageEvent(
            xid_, xid_, wm_->GetXAtom(ATOM_WM_PROTOCOLS), data, 0);
}

bool Window::AddButtonGrab(int button) {
  DLOG(INFO) << "Adding button grab for " << button << " on " << xid_str_;
  DCHECK(xid_);
  return wm_->xconn()->AddButtonGrabOnWindow(
      xid_, button, ButtonPressMask, true);  // synchronous=true
}

bool Window::RemoveButtonGrab(int button) {
  DLOG(INFO) << "Removing button grab for " << button << " on " << xid_str_;
  DCHECK(xid_);
  return wm_->xconn()->RemoveButtonGrabOnWindow(xid_, button);
}

void Window::GetMaxSize(const Size& desired_size, Size* size_out) const {
  CHECK(!desired_size.empty());
  Size capped_size = desired_size;

  if (size_hints_.max_size.width > 0)
    capped_size.width = min(size_hints_.max_size.width, capped_size.width);
  if (size_hints_.min_size.width > 0)
    capped_size.width = max(size_hints_.min_size.width, capped_size.width);

  if (size_hints_.max_size.height > 0)
    capped_size.height = min(size_hints_.max_size.height, capped_size.height);
  if (size_hints_.min_size.height > 0)
    capped_size.height = max(size_hints_.min_size.height, capped_size.height);

  if (size_hints_.size_increment.width > 0) {
    const int base_width =
        (size_hints_.base_size.width > 0) ? size_hints_.base_size.width :
        (size_hints_.min_size.width > 0) ? size_hints_.min_size.width :
        0;
    size_out->width = base_width +
        ((capped_size.width - base_width) / size_hints_.size_increment.width) *
        size_hints_.size_increment.width;
  } else {
    size_out->width = capped_size.width;
  }

  if (size_hints_.size_increment.height > 0) {
    const int base_height =
        (size_hints_.base_size.height > 0) ? size_hints_.base_size.height :
        (size_hints_.min_size.height > 0) ? size_hints_.min_size.height :
        0;
    size_out->height = base_height +
        ((capped_size.height - base_height) /
         size_hints_.size_increment.height) *
        size_hints_.size_increment.height;
  } else {
    size_out->height = capped_size.height;
  }

  DLOG(INFO) << "Max size for " << xid_str_ << " is " << *size_out
             << " (desired was " << desired_size << ")";
}

bool Window::MapClient() {
  DLOG(INFO) << "Mapping " << xid_str_;
  DCHECK(xid_);
  if (!wm_->xconn()->MapWindow(xid_))
    return false;
  return true;
}

bool Window::UnmapClient() {
  DLOG(INFO) << "Unmapping " << xid_str_;
  DCHECK(xid_);
  if (!wm_->xconn()->UnmapWindow(xid_))
    return false;
  return true;
}

void Window::SetVisibility(Visibility visibility) {
  DCHECK_NE(visibility, VISIBILITY_UNSET) << " xid=" << xid_str_;
  if (visibility == visibility_)
    return;

  visibility_ = visibility;

  DCHECK(actor_.get());
  switch (visibility) {
    case VISIBILITY_SHOWN:  // fallthrough
    case VISIBILITY_SHOWN_NO_INPUT:
      actor_->Show();
      if (damage_debug_group_.get())
        damage_debug_group_->Show();
      break;
    case VISIBILITY_HIDDEN:
      actor_->Hide();
      if (damage_debug_group_.get())
        damage_debug_group_->Hide();
      break;
    default:
      NOTREACHED() << "Unknown visibility setting " << visibility;
  }
  UpdateShadowVisibility();
  UpdateClientWindowPosition();
}

void Window::SetUpdateClientPositionForMoves(bool update) {
  DCHECK_NE(visibility_, VISIBILITY_UNSET) << " xid=" << xid_str_;
  if (update_client_position_for_moves_ == update)
    return;
  update_client_position_for_moves_ = update;
  if (update_client_position_for_moves_)
    UpdateClientWindowPosition();
}

void Window::SetBounds(const Rect& bounds, int anim_ms) {
  DLOG(INFO) << "Setting " << xid_str_ << "'s bounds to " << bounds
             << " over " << anim_ms << " ms";
  DCHECK_NE(visibility_, VISIBILITY_UNSET);
  DCHECK(!override_redirect_);

  if (bounds.size() != client_size())
    SendWmSyncRequestMessage();

  Rect new_client_bounds(
      x_window_should_be_onscreen() ?
          bounds.position() :
          Point(kOffscreenX, kOffscreenY),
      bounds.size());
  if (new_client_bounds != client_bounds_) {
    wm_->xconn()->ConfigureWindow(xid_, new_client_bounds);
    client_bounds_ = new_client_bounds;
  }

  if (bounds.position() != composited_origin_)
    MoveCompositedInternal(bounds.position(), MOVE_DIMENSIONS_X_AND_Y, anim_ms);
}

void Window::Move(const Point& origin, int anim_ms) {
  DCHECK_NE(visibility_, VISIBILITY_UNSET) << " xid=" << xid_str_;
  MoveCompositedInternal(origin, MOVE_DIMENSIONS_X_AND_Y, anim_ms);
  if (update_client_position_for_moves_)
    UpdateClientWindowPosition();
}

void Window::MoveX(int x, int anim_ms) {
  DCHECK_NE(visibility_, VISIBILITY_UNSET) << " xid=" << xid_str_;
  MoveCompositedInternal(Point(x, 0), MOVE_DIMENSIONS_X_ONLY, anim_ms);
  if (update_client_position_for_moves_)
    UpdateClientWindowPosition();
}

void Window::MoveY(int y, int anim_ms) {
  DCHECK_NE(visibility_, VISIBILITY_UNSET) << " xid=" << xid_str_;
  MoveCompositedInternal(Point(0, y), MOVE_DIMENSIONS_Y_ONLY, anim_ms);
  if (update_client_position_for_moves_)
    UpdateClientWindowPosition();
}

bool Window::MoveClient(int x, int y) {
  DCHECK_EQ(visibility_, VISIBILITY_UNSET) << " xid=" << xid_str_;
  return MoveClientInternal(Point(x, y));
}

bool Window::MoveClientOffscreen() {
  return MoveClient(kOffscreenX, kOffscreenY);
}

bool Window::MoveClientToComposited() {
  return MoveClient(composited_x(), composited_y());
}

bool Window::CenterClientOverWindow(Window* win) {
  CHECK(win);
  int center_x = win->client_x() + 0.5 * win->client_width();
  int center_y = win->client_y() + 0.5 * win->client_height();
  return MoveClient(center_x - 0.5 * client_width(),
                    center_y - 0.5 * client_height());
}

bool Window::Resize(const Size& new_size, Gravity gravity) {
  DCHECK(xid_);
  DCHECK(!override_redirect_)
      << "Attempted to resize override-redirect window " << xid_str_;

  // Bail out early if this is a no-op.  (No-op resizes won't generate
  // ConfigureNotify events, which means that the client won't know to
  // redraw and update the _NET_WM_SYNC_REQUEST counter.)
  if (new_size == client_size())
    return true;

  DLOG(INFO) << "Resizing " << xid_str_ << "'s client window to " << new_size;
  SendWmSyncRequestMessage();

  if (visibility_ != VISIBILITY_UNSET) {
    Point new_composited_origin = composited_origin_;
    new_composited_origin.x -=
        (gravity == GRAVITY_NORTHEAST || gravity == GRAVITY_SOUTHEAST) ?
        new_size.width - client_width() : 0;
    new_composited_origin.y -=
        (gravity == GRAVITY_SOUTHWEST || gravity == GRAVITY_SOUTHEAST) ?
        new_size.height - client_height() : 0;

    if (!wm_->xconn()->ResizeWindow(xid_, new_size))
      return false;
    client_bounds_.resize(new_size, GRAVITY_NORTHWEST);

    if (new_composited_origin != composited_origin_) {
      MoveCompositedInternal(new_composited_origin, MOVE_DIMENSIONS_X_AND_Y, 0);
      if (update_client_position_for_moves_)
        UpdateClientWindowPosition();
    }
  } else {
    // TODO(derat): Remove this once the legacy interface that separates
    // management of the composited and client windows is gone.
    int dx = (gravity == GRAVITY_NORTHEAST || gravity == GRAVITY_SOUTHEAST) ?
        new_size.width - client_width() : 0;
    int dy = (gravity == GRAVITY_SOUTHWEST || gravity == GRAVITY_SOUTHEAST) ?
        new_size.height - client_height() : 0;

    if (dx || dy) {
      // If we need to move the window as well due to gravity, do it all in
      // one ConfigureWindow request to the server.
      if (!wm_->xconn()->ConfigureWindow(
              xid_, Rect(Point(client_x() - dx, client_y() - dy), new_size))) {
        return false;
      }
      client_bounds_.move(client_x() - dx, client_y() - dy);
      composited_origin_.x -= dx * composited_scale_x_;
      composited_origin_.y -= dy * composited_scale_y_;
      need_to_update_actor_position_ = true;
    } else  {
      if (!wm_->xconn()->ResizeWindow(xid_, new_size))
        return false;
    }
    client_bounds_.resize(new_size, GRAVITY_NORTHWEST);
  }

  return true;
}

bool Window::StackClientAbove(XWindow sibling_xid) {
  DCHECK(xid_);
  CHECK(sibling_xid != None);
  bool result = wm_->xconn()->StackWindow(xid_, sibling_xid, true);
  return result;
}

bool Window::StackClientBelow(XWindow sibling_xid) {
  DCHECK(xid_);
  CHECK(sibling_xid != None);
  bool result = wm_->xconn()->StackWindow(xid_, sibling_xid, false);
  return result;
}

void Window::MoveComposited(int x, int y, int anim_ms) {
  DCHECK_EQ(visibility_, VISIBILITY_UNSET) << " xid=" << xid_str_;
  MoveCompositedInternal(Point(x, y), MOVE_DIMENSIONS_X_AND_Y, anim_ms);
}

void Window::MoveCompositedX(int x, int anim_ms) {
  DCHECK_EQ(visibility_, VISIBILITY_UNSET) << " xid=" << xid_str_;
  MoveCompositedInternal(Point(x, 0), MOVE_DIMENSIONS_X_ONLY, anim_ms);
}

void Window::MoveCompositedY(int y, int anim_ms) {
  DCHECK_EQ(visibility_, VISIBILITY_UNSET) << " xid=" << xid_str_;
  MoveCompositedInternal(Point(0, y), MOVE_DIMENSIONS_Y_ONLY, anim_ms);
}

void Window::MoveCompositedToClient() {
  MoveComposited(client_x(), client_y(), 0);
}

void Window::ShowComposited() {
  DLOG(INFO) << "Showing " << xid_str_ << "'s composited window";
  DCHECK(actor_.get());
  DCHECK_EQ(visibility_, VISIBILITY_UNSET) << " xid=" << xid_str_;
  actor_->Show();
  composited_shown_ = true;
  UpdateShadowVisibility();
  if (damage_debug_group_.get())
    damage_debug_group_->Show();
}

void Window::HideComposited() {
  DLOG(INFO) << "Hiding " << xid_str_ << "'s composited window";
  DCHECK(actor_.get());
  DCHECK_EQ(visibility_, VISIBILITY_UNSET) << " xid=" << xid_str_;
  actor_->Hide();
  composited_shown_ = false;
  UpdateShadowVisibility();
  if (damage_debug_group_.get())
    damage_debug_group_->Hide();
}

void Window::SetCompositedOpacity(double opacity, int anim_ms) {
  composited_opacity_ = opacity;
  DLOG(INFO) << "Setting " << xid_str_ << "'s composited window opacity to "
             << opacity << " (combined is " << combined_opacity() << ") over "
             << anim_ms << " ms";
  DCHECK(actor_.get());

  actor_->SetOpacity(combined_opacity(), anim_ms);
  if (shadow_.get())
    shadow_->SetOpacity(combined_opacity() * shadow_opacity_, anim_ms);

  // If the window became completely transparent (or was and now isn't), we may
  // need to move the client window offscreen or back onscreen.
  if (visibility_ != VISIBILITY_UNSET)
    UpdateClientWindowPosition();

  if (damage_debug_group_.get())
    damage_debug_group_->SetOpacity(combined_opacity(), anim_ms);
}

void Window::ScaleComposited(double scale_x, double scale_y, int anim_ms) {
  DLOG(INFO) << "Scaling " << xid_str_ << "'s composited window by ("
             << scale_x << ", " << scale_y << ") over " << anim_ms << " ms";
  DCHECK(actor_.get());
  DCHECK_GE(composited_scale_x_, 0.0);
  DCHECK_GE(composited_scale_y_, 0.0);
  composited_scale_x_ = scale_x;
  composited_scale_y_ = scale_y;

  actor_->Scale(scale_x, scale_y, anim_ms);
  if (shadow_.get())
    shadow_->Resize(scale_x * client_width(), scale_y * client_height(),
                    anim_ms);

  // When the window's scale changes, we may need to move the client window
  // offscreen or back onscreen.
  if (visibility_ != VISIBILITY_UNSET)
    UpdateClientWindowPosition();

  if (damage_debug_group_.get())
    damage_debug_group_->Scale(scale_x, scale_y, anim_ms);
}

AnimationPair* Window::CreateMoveCompositedAnimation() {
  DCHECK(actor_.get());
  return actor_->CreateMoveAnimation();
}

void Window::SetMoveCompositedAnimation(AnimationPair* animations) {
  DCHECK(animations);
  DCHECK(actor_.get());
  composited_origin_.reset(
      animations->first_animation().GetEndValue(),
      animations->second_animation().GetEndValue());
  DLOG(INFO) << "Setting custom animation to eventually move " << xid_str_
             << "'s composited window to (" << composited_x() << "x"
             << composited_y() << ")";
  actor_->SetMoveAnimation(animations);

  // Make sure that the client window is in the right position.
  if (visibility_ != VISIBILITY_UNSET)
    UpdateClientWindowPosition();

  if (shadow_.get())
    shadow_->Move(composited_x(), composited_y(), 0);
  if (damage_debug_group_.get())
    damage_debug_group_->Move(composited_x(), composited_y(), 0);
}

AnimationPair* Window::CreateScaleCompositedAnimation() {
  DCHECK(actor_.get());
  return actor_->CreateScaleAnimation();
}

void Window::SetScaleCompositedAnimation(AnimationPair* animations) {
  DCHECK(animations);
  DCHECK(actor_.get());
  composited_scale_x_ = animations->first_animation().GetEndValue();
  composited_scale_y_ = animations->second_animation().GetEndValue();
  actor_->SetScaleAnimation(animations);
}

void Window::HandleMapRequested() {
  DCHECK(xid_);
  DCHECK(!override_redirect_)
      << "Got map request for override-redirect window " << xid_str_;

  // Tell the client to notify us after it's repainted in response to the
  // next ConfigureNotify that it receives, and then send a synthetic
  // ConfigureNotify event to the window.  This lets us avoid compositing
  // new windows until the client has painted them.
  if (wm_sync_request_alarm_) {
    SendWmSyncRequestMessage();
    SendSyntheticConfigureNotify();
  }
}

void Window::HandleMapNotify() {
  DCHECK(xid_);
  if (mapped_)
    return;

  mapped_ = true;
  need_to_reset_pixmap_ = true;

  // If we're still waiting for the client to redraw the window (probably in
  // response to the _NET_WM_SYNC_REQUEST message that we sent in
  // HandleMapRequested() or due to the client setting _CHROME_FREEZE_UPDATES
  // before mapping), then hold off on fetching the pixmap.  This makes us not
  // composite new windows until clients have painted them.
  if (able_to_reset_pixmap())
    ResetPixmap();

  if (override_redirect_)
    SetVisibility(VISIBILITY_SHOWN);
}

void Window::HandleUnmapNotify() {
  DCHECK(xid_);
  mapped_ = false;

  if (override_redirect_)
    SetVisibility(VISIBILITY_HIDDEN);

  // We could potentially show a window onscreen even after it's been
  // unmapped, so we avoid hiding the shadow here.
}

void Window::HandleRedirect() {
  if (!mapped_)
    return;

  need_to_reset_pixmap_ = true;
  ResetPixmap();

  // If the window is in the middle of an animation (sliding offscreen),
  // its client position is already updated to the final position, and its
  // composited position is one frame into the animation because we've
  // already updated the coordinates prior to calling this method. However,
  // the content of the root window has not yet repainted, so using the
  // coordinates of the root window (0, 0)-(width, height) for the copying
  // will work while the coordinates of the window will not.
  wm_->xconn()->CopyArea(wm_->root(),
                         pixmap_,
                         Point(0, 0),  // src
                         Point(0, 0),  // dest
                         Size(wm_->width(), wm_->height()));
}

void Window::HandleConfigureNotify(const Rect& bounds, XWindow above_xid) {
  DCHECK(actor_.get());
  const bool size_changed = actor_->GetBounds().size() != bounds.size();
  // Hold off on grabbing the window's contents if we haven't received
  // notification that the client has drawn to the new pixmap yet.
  if (size_changed) {
    need_to_reset_pixmap_ = true;
    if (able_to_reset_pixmap())
      ResetPixmap();
  }

  // If this is an override-redirect window (i.e. we didn't initiate the change
  // ourselves), save the updated bounds and make sure that the actor is in the
  // right place.
  if (override_redirect_) {
    client_bounds_ = bounds;
    MoveCompositedInternal(bounds.position(), MOVE_DIMENSIONS_X_AND_Y, 0);

    // When we see a stacking change, we attempt to restack our actor
    // correspondingly.  If we don't have an actor for the X window directly
    // under us, we walk down the stack until we find one.
    while (above_xid) {
      Window* above_win = wm_->GetWindow(above_xid);
      Compositor::Actor* above_actor =
          above_win ?
          above_win->GetTopActor() :
          wm_->stacking_manager()->GetActorIfLayerXid(above_xid);

      if (above_actor) {
        DLOG(INFO) << "Stacking override-redirect window " << xid_str_
                   << "'s actor above window " << XidStr(above_xid) << "'s";
        StackCompositedAbove(above_actor, NULL, false);
        break;
      }
      const XWindow* above_ptr = wm_->stacked_xids().GetUnder(above_xid);
      above_xid = above_ptr ? *above_ptr : 0;
    }
  }
}

void Window::HandleDamageNotify(const Rect& bounding_box) {
  DCHECK(actor_.get());
  wm_->xconn()->ClearDamage(damage_);
  actor_->UpdateTexture();
  actor_->MergeDamagedRegion(bounding_box);

  if (wm_->damage_debugging_enabled())
    UpdateDamageDebugging(bounding_box);

  // Check if this update could indicate that a video is playing.
  if (!IsClientWindowOffscreen() &&
      bounding_box.width >= kVideoMinWidth &&
      bounding_box.height >= kVideoMinHeight) {
    const time_t now = GetCurrentTimeSec();
    if (now != video_damage_start_time_) {
      video_damage_start_time_ = now;
      num_video_damage_events_ = 0;
    }
    num_video_damage_events_++;
    if (num_video_damage_events_ == kVideoMinFramerate)
      wm_->SetVideoTimeProperty(now);
  }
}

void Window::HandleFreezeUpdatesPropertyChange(bool frozen) {
  if (frozen == updates_frozen_)
    return;

  DLOG(INFO) << "Updates are " << (frozen ? "" : "un") << "frozen on window "
             << xid_str_;
  updates_frozen_ = frozen;

  if (need_to_reset_pixmap_ && able_to_reset_pixmap())
    ResetPixmap();
}

DestroyedWindow* Window::HandleDestroyNotify() {
  DCHECK(xid_);
  DCHECK(actor_.get());
  DestroyedWindow* destroyed_win =
      new DestroyedWindow(
          wm_, xid_, actor_.release(), shadow_.release(), pixmap_);
  pixmap_ = 0;
  xid_ = 0;
  return destroyed_win;
}

void Window::SetShadowType(Shadow::Type type) {
  DCHECK(actor_.get());

  shadow_.reset(Shadow::Create(wm_->compositor(), type));
  shadow_->group()->SetName("shadow group for window " + xid_str_);
  wm_->stage()->AddActor(shadow_->group());
  shadow_->group()->Lower(actor_.get());
  shadow_->Move(composited_x(), composited_y(), 0);
  shadow_->SetOpacity(combined_opacity() * shadow_opacity_, 0);
  shadow_->Resize(composited_scale_x_ * actor_->GetWidth(),
                  composited_scale_y_ * actor_->GetHeight(), 0);
  UpdateShadowVisibility();
}

void Window::DisableShadow() {
  shadow_.reset(NULL);
}

void Window::SetShadowOpacity(double opacity, int anim_ms) {
  DLOG(INFO) << "Setting " << xid_str_ << "'s shadow opacity to " << opacity
             << " over " << anim_ms << " ms";
  shadow_opacity_ = opacity;
  if (shadow_.get())
    shadow_->SetOpacity(combined_opacity() * shadow_opacity_, anim_ms);
}

void Window::StackCompositedAbove(Compositor::Actor* actor,
                                  Compositor::Actor* shadow_actor,
                                  bool stack_above_shadow_actor) {
  DCHECK(actor_.get());
  if (actor)
    actor_->Raise(actor);
  if (shadow_.get()) {
    if (!shadow_actor || !stack_above_shadow_actor) {
      shadow_->group()->Lower(shadow_actor ? shadow_actor : actor_.get());
    } else {
      shadow_->group()->Raise(shadow_actor);
    }
  }
  if (damage_debug_group_.get())
    damage_debug_group_->Raise(actor_.get());
}

void Window::StackCompositedBelow(Compositor::Actor* actor,
                                  Compositor::Actor* shadow_actor,
                                  bool stack_above_shadow_actor) {
  DCHECK(actor_.get());
  if (actor)
    actor_->Lower(actor);
  if (shadow_.get()) {
    if (!shadow_actor || !stack_above_shadow_actor) {
      shadow_->group()->Lower(shadow_actor ? shadow_actor : actor_.get());
    } else {
      shadow_->group()->Raise(shadow_actor);
    }
  }
  if (damage_debug_group_.get())
    damage_debug_group_->Raise(actor_.get());
}

Compositor::Actor* Window::GetTopActor() {
  DCHECK(actor_.get());
  return damage_debug_group_.get() ?
      static_cast<Compositor::Actor*>(damage_debug_group_.get()) :
      static_cast<Compositor::Actor*>(actor_.get());
}

Compositor::Actor* Window::GetBottomActor() {
  DCHECK(actor_.get());
  return (shadow_.get() ? shadow_->group() : actor_.get());
}

void Window::CopyClientBoundsToRect(Rect* rect) const {
  DCHECK(rect);
  *rect = client_bounds_;
}

void Window::HandleSyncAlarmNotify(XID alarm_id, int64_t value) {
  if (alarm_id != wm_sync_request_alarm_) {
    LOG(WARNING) << "Window " << xid_str_ << " got sync alarm notify for "
                 << " unknown alarm " << XidStr(alarm_id);
    return;
  }

  DLOG(INFO) << "Window " << xid_str_ << " handling sync alarm notify with "
             << "value " << value << " (current sync num is "
             << current_wm_sync_num_ << ")";
  if (value != current_wm_sync_num_ || client_has_redrawn_after_last_resize_)
    return;

  client_has_redrawn_after_last_resize_ = true;
  if (able_to_reset_pixmap())
    ResetPixmap();
}

void Window::SendSyntheticConfigureNotify() {
  const XWindow* xid_under_us_ptr = wm_->stacked_xids().GetUnder(xid_);
  const XWindow xid_under_us = xid_under_us_ptr ? *xid_under_us_ptr : 0;
  DLOG(INFO) << "Sending synthetic configure notify for " << xid_str_ << ": "
             << client_bounds_ << ", above " << XidStr(xid_under_us);
  wm_->xconn()->SendConfigureNotifyEvent(
      xid_,
      client_bounds_,
      0,  // border_width
      xid_under_us,
      false);  // override_redirect
}

bool Window::IsClientWindowOffscreen() const {
  return (client_x() >= wm_->width() || client_x() + client_width() < 0 ||
          client_y() >= wm_->height() || client_y() + client_height() < 0);
}

void Window::SetWmStateInternal(int action, bool* value) const {
  switch (action) {
    case 0:  // _NET_WM_STATE_REMOVE
      *value = false;
      break;
    case 1:  // _NET_WM_STATE_ADD
      *value = true;
      break;
    case 2:  // _NET_WM_STATE_TOGGLE
      *value = !(*value);
      break;
    default:
      LOG(WARNING) << "Got _NET_WM_STATE message for " << xid_str_
                   << " with invalid action " << action;
  }
}

bool Window::MoveClientInternal(const Point& origin) {
  DLOG(INFO) << "Moving " << xid_str_ << "'s client window to " << origin;
  DCHECK(xid_);
  DCHECK(!override_redirect_)
      << "Attempted to move override-redirect window " << xid_str_;
  if (!wm_->xconn()->MoveWindow(xid_, origin))
    return false;
  client_bounds_.move(origin);
  return true;
}

void Window::MoveCompositedInternal(const Point& origin,
                                    MoveDimensions dimensions,
                                    int anim_ms) {
  switch (dimensions) {
    case MOVE_DIMENSIONS_X_AND_Y:
      DLOG(INFO) << "Setting " << xid_str_ << "'s composited position to "
                 << origin;
      composited_origin_ = origin;
      break;
    case MOVE_DIMENSIONS_X_ONLY:
      DLOG(INFO) << "Setting " << xid_str_ << "'s composited X position to "
                 << origin.x;
      composited_origin_.x = origin.x;
      break;
    case MOVE_DIMENSIONS_Y_ONLY:
      DLOG(INFO) << "Setting " << xid_str_ << "'s composited Y position to "
                 << origin.y;
      composited_origin_.y = origin.y;
      break;
    default:
      NOTREACHED() << "Unknown move dimensions " << dimensions;
  }

  DCHECK(actor_.get());
  if (actor_->GetBounds().size() == client_bounds_.size() || !pixmap_) {
    UpdateActorPosition(dimensions, anim_ms);
    need_to_update_actor_position_ = false;
  } else {
    need_to_update_actor_position_ = true;
  }
}

void Window::UpdateClientWindowPosition() {
  DCHECK_NE(visibility_, VISIBILITY_UNSET) << " xid=" << xid_str_;
  if (override_redirect_)
    return;

  Point new_origin =
      x_window_should_be_onscreen() ?
      composited_origin_ :
      Point(kOffscreenX, kOffscreenY);
  if (new_origin != client_origin())
    MoveClientInternal(new_origin);
}

void Window::UpdateActorPosition(MoveDimensions dimensions, int anim_ms) {
  DCHECK(actor_.get());

  switch (dimensions) {
    case MOVE_DIMENSIONS_X_AND_Y:
      actor_->Move(composited_origin_.x, composited_origin_.y, anim_ms);
      if (shadow_.get())
        shadow_->Move(composited_origin_.x, composited_origin_.y, anim_ms);
      break;
    case MOVE_DIMENSIONS_X_ONLY:
      actor_->MoveX(composited_origin_.x, anim_ms);
      if (shadow_.get())
        shadow_->MoveX(composited_origin_.x, anim_ms);
      break;
    case MOVE_DIMENSIONS_Y_ONLY:
      actor_->MoveY(composited_origin_.y, anim_ms);
      if (shadow_.get())
        shadow_->MoveY(composited_origin_.y, anim_ms);
      break;
    default:
      NOTREACHED() << "Unknown move dimensions " << dimensions;
  }

  if (damage_debug_group_.get())
    damage_debug_group_->Move(
        composited_origin_.x, composited_origin_.y, anim_ms);
}

void Window::ResetPixmap() {
  DCHECK(xid_);
  DCHECK(actor_.get());
  if (!mapped_)
    return;

  XID old_pixmap = pixmap_;
  pixmap_ = wm_->xconn()->GetCompositingPixmapForWindow(xid_);
  DLOG(INFO) << "Fetched pixmap " << XidStr(pixmap_) << " for " << xid_str_;

  actor_->SetPixmap(pixmap_);
  if (shadow_.get()) {
    shadow_->Resize(composited_scale_x_ * actor_->GetWidth(),
                    composited_scale_y_ * actor_->GetHeight(),
                    0);  // anim_ms
  }

  if (need_to_update_actor_position_ &&
      actor_->GetBounds().size() == client_bounds_.size()) {
    UpdateActorPosition(MOVE_DIMENSIONS_X_AND_Y, 0);
    need_to_update_actor_position_ = false;
  }

  if (old_pixmap) {
    wm_->xconn()->FreePixmap(old_pixmap);
  } else {
    // If we didn't have a pixmap already, then we're showing the window for
    // the first time and may need to show the shadow as well.
    UpdateShadowVisibility();
  }

  need_to_reset_pixmap_ = false;
  wm_->HandleWindowPixmapFetch(this);
}

bool Window::UpdateWmStateProperty() {
  DCHECK(xid_);
  vector<int> values;
  if (wm_state_fullscreen_)
    values.push_back(wm_->GetXAtom(ATOM_NET_WM_STATE_FULLSCREEN));
  if (wm_state_maximized_horz_)
    values.push_back(wm_->GetXAtom(ATOM_NET_WM_STATE_MAXIMIZED_HORZ));
  if (wm_state_maximized_vert_)
    values.push_back(wm_->GetXAtom(ATOM_NET_WM_STATE_MAXIMIZED_VERT));
  if (wm_state_modal_)
    values.push_back(wm_->GetXAtom(ATOM_NET_WM_STATE_MODAL));

  DLOG(INFO) << "Updating _NET_WM_STATE for " << xid_str_ << ":"
             << " fullscreen=" << wm_state_fullscreen_
             << " maximized_horz=" << wm_state_maximized_horz_
             << " maximized_vert=" << wm_state_maximized_vert_
             << " modal=" << wm_state_modal_;
  XAtom wm_state_atom = wm_->GetXAtom(ATOM_NET_WM_STATE);
  if (!values.empty()) {
    return wm_->xconn()->SetIntArrayProperty(
        xid_, wm_state_atom, wm_->GetXAtom(ATOM_ATOM), values);
  } else {
    return wm_->xconn()->DeletePropertyIfExists(xid_, wm_state_atom);
  }
}

bool Window::UpdateChromeStateProperty() {
  DCHECK(xid_);
  vector<int> values;
  for (set<XAtom>::const_iterator it = chrome_state_xatoms_.begin();
       it != chrome_state_xatoms_.end(); ++it) {
    values.push_back(static_cast<int>(*it));
  }

  XAtom state_xatom = wm_->GetXAtom(ATOM_CHROME_STATE);
  if (!values.empty()) {
    return wm_->xconn()->SetIntArrayProperty(
        xid_, state_xatom, wm_->GetXAtom(ATOM_ATOM), values);
  } else {
    return wm_->xconn()->DeletePropertyIfExists(xid_, state_xatom);
  }
}

void Window::DestroyWmSyncRequestAlarm() {
  if (!wm_sync_request_alarm_)
    return;
  wm_->xconn()->DestroySyncCounterAlarm(wm_sync_request_alarm_);
  wm_->UnregisterSyncAlarm(wm_sync_request_alarm_);
  wm_sync_request_alarm_ = 0;
  client_has_redrawn_after_last_resize_ = true;
}

void Window::UpdateShadowVisibility() {
  // If nobody requested that this window have a shadow, |shadow_| will just
  // be NULL.
  if (!shadow_.get())
    return;

  // Even if it was requested, there may be other reasons not to show it
  // (maybe the window isn't mapped yet, or it's shaped, or it's hidden).
  const bool should_show = pixmap_ && !shaped_ && actor_is_shown();

  if (!shadow_->is_shown() && should_show)
    shadow_->Show();
  else if (shadow_->is_shown() && !should_show)
    shadow_->Hide();
}

void Window::SendWmSyncRequestMessage() {
  if (!wm_sync_request_alarm_)
    return;

  current_wm_sync_num_++;

  long data[5];
  memset(data, 0, sizeof(data));
  data[0] = wm_->GetXAtom(ATOM_NET_WM_SYNC_REQUEST);
  data[1] = wm_->GetCurrentTimeFromServer();
  data[2] = current_wm_sync_num_ & 0xffffffff;
  data[3] = (current_wm_sync_num_ >> 32) & 0xffffffff;
  DLOG(INFO) << "Asking " << xid_str_ << " to notify us after it's redrawn "
             << "using sync num " << current_wm_sync_num_;
  wm_->xconn()->SendClientMessageEvent(
      xid_, xid_, wm_->GetXAtom(ATOM_WM_PROTOCOLS), data, 0);
  client_has_redrawn_after_last_resize_ = false;
}

void Window::UpdateDamageDebugging(const Rect& bounding_box) {
  // If we don't have a group for transforming all of the actors at once,
  // initialize one.
  if (!damage_debug_group_.get()) {
    damage_debug_group_.reset(wm_->compositor()->CreateGroup());
    damage_debug_group_->SetName("damage debug group for window " + xid_str_);
    damage_debug_group_->Move(composited_x(), composited_y(), 0);
    damage_debug_group_->Scale(composited_scale_x_, composited_scale_y_, 0);
    damage_debug_group_->SetOpacity(combined_opacity(), 0);
    if (actor_is_shown())
      damage_debug_group_->Show();
    else
      damage_debug_group_->Hide();

    wm_->stage()->AddActor(damage_debug_group_.get());
    damage_debug_group_->Raise(actor_.get());
  }

  // Create a new actor if we're not yet at the limit; recycle the oldest one
  // otherwise.
  shared_ptr<Compositor::ColoredBoxActor> debug_actor;
  if (damage_debug_actors_.size() < kMaxDamageDebugActors) {
    debug_actor.reset(
        wm_->compositor()->CreateColoredBox(
            bounding_box.width, bounding_box.height,
            Compositor::Color(kDamageDebugColor)));
    debug_actor->SetName("damage debug actor");
    damage_debug_group_->AddActor(debug_actor.get());
    debug_actor->Show();
  } else {
    debug_actor = damage_debug_actors_[0];
    damage_debug_actors_.pop_front();
  }
  damage_debug_actors_.push_back(debug_actor);

  debug_actor->Move(bounding_box.x, bounding_box.y, 0);
  debug_actor->SetSize(bounding_box.width, bounding_box.height);
  debug_actor->SetOpacity(kDamageDebugOpacity, 0);
  debug_actor->SetOpacity(0.0, kDamageDebugFadeMs);
}


DestroyedWindow::DestroyedWindow(WindowManager* wm,
                                 XWindow xid,
                                 Compositor::TexturePixmapActor* actor,
                                 Shadow* shadow,
                                 XID pixmap)
    : wm_(wm),
      actor_(actor),
      shadow_(shadow),
      pixmap_(pixmap) {
  DCHECK(wm);
  DCHECK(actor);
  actor_->SetName(string("destroyed window ") + XidStr(xid));
}

DestroyedWindow::~DestroyedWindow() {
  if (pixmap_)
    wm_->xconn()->FreePixmap(pixmap_);
}

}  // namespace window_manager
