// Copyright (c) 2011 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/panels/panel_manager.h"

#include <utility>

#include "base/logging.h"
#include "cros/chromeos_wm_ipc_enums.h"
#include "window_manager/atom_cache.h"
#include "window_manager/event_consumer_registrar.h"
#include "window_manager/motion_event_coalescer.h"
#include "window_manager/panels/panel.h"
#include "window_manager/panels/panel_bar.h"
#include "window_manager/panels/panel_dock.h"
#include "window_manager/panels/panel_container.h"
#include "window_manager/stacking_manager.h"
#include "window_manager/window.h"
#include "window_manager/window_manager.h"

using std::make_pair;
using std::map;
using std::pair;
using std::set;
using std::tr1::shared_ptr;
using std::vector;
using window_manager::util::FindWithDefault;
using window_manager::util::XidStr;

namespace window_manager {

// Frequency with which we should update the position of dragged panels.
static const int kDraggedPanelUpdateMs = 25;

// How long should the animation when detaching panels from containers take?
static const int kDetachPanelAnimMs = 100;

// Chosen because 1280 - 256 = 1024.
const int PanelManager::kPanelDockWidth = 256;

PanelManager::PanelManager(WindowManager* wm)
    : wm_(wm),
      dragged_panel_(NULL),
      fullscreen_panel_(NULL),
      dragged_panel_event_coalescer_(
          new MotionEventCoalescer(
              wm_->event_loop(),
              NewPermanentCallback(
                  this, &PanelManager::HandlePeriodicPanelDragMotion),
              kDraggedPanelUpdateMs)),
      panel_bar_(new PanelBar(this)),
      left_panel_dock_(
          new PanelDock(this, PanelDock::DOCK_TYPE_LEFT, kPanelDockWidth)),
      right_panel_dock_(
          new PanelDock(this, PanelDock::DOCK_TYPE_RIGHT, kPanelDockWidth)),
      saw_map_request_(false),
      event_consumer_registrar_(new EventConsumerRegistrar(wm_, this)) {
  event_consumer_registrar_->RegisterForChromeMessages(
      chromeos::WM_IPC_MESSAGE_WM_SET_PANEL_STATE);
  event_consumer_registrar_->RegisterForChromeMessages(
      chromeos::WM_IPC_MESSAGE_WM_NOTIFY_PANEL_DRAGGED);
  event_consumer_registrar_->RegisterForChromeMessages(
      chromeos::WM_IPC_MESSAGE_WM_NOTIFY_PANEL_DRAG_COMPLETE);

  wm_->focus_manager()->RegisterFocusChangeListener(this);

  RegisterContainer(panel_bar_.get());
  RegisterContainer(left_panel_dock_.get());
  RegisterContainer(right_panel_dock_.get());
}

PanelManager::~PanelManager() {
  wm_->focus_manager()->UnregisterFocusChangeListener(this);
  dragged_panel_ = NULL;
}

bool PanelManager::IsInputWindow(XWindow xid) {
  return container_input_xids_.count(xid) || panel_input_xids_.count(xid);
}

void PanelManager::HandleScreenResize() {
  for (vector<PanelContainer*>::iterator it = containers_.begin();
       it != containers_.end(); ++it) {
    (*it)->HandleScreenResize();
  }
  for (PanelMap::iterator it = panels_.begin(); it != panels_.end(); ++it)
    it->second->HandleScreenResize();
}

bool PanelManager::HandleWindowMapRequest(Window* win) {
  saw_map_request_ = true;

  if (win->type() != chromeos::WM_IPC_WINDOW_CHROME_PANEL_CONTENT &&
      win->type() != chromeos::WM_IPC_WINDOW_CHROME_PANEL_TITLEBAR &&
      (!win->transient_for_xid() || !GetPanelByXid(win->transient_for_xid())))
    return false;

  DoInitialSetupForWindow(win);
  return true;
}

void PanelManager::HandleWindowMap(Window* win) {
  if (win->override_redirect())
    return;

  if (win->type() != chromeos::WM_IPC_WINDOW_CHROME_PANEL_CONTENT &&
      win->type() != chromeos::WM_IPC_WINDOW_CHROME_PANEL_TITLEBAR) {
    // The only non-panel windows that we'll handle are transients
    // belonging to panels.
    if (!win->transient_for_xid())
      return;

    Panel* owner_panel = GetPanelByXid(win->transient_for_xid());
    if (!owner_panel) {
      // Maybe its owner is itself a transient for a panel.
      Window* owner_win = wm_->GetWindow(win->transient_for_xid());
      if (owner_win)
        owner_panel = GetPanelOwningTransientWindow(*owner_win);
    }
    if (owner_panel) {
      transient_xids_to_owners_[win->xid()] = owner_panel;
      owner_panel->HandleTransientWindowMap(win);
      if (!win->is_rgba())
        win->SetShadowType(Shadow::TYPE_RECTANGULAR);
    }
    return;
  }

  // Handle initial setup for existing windows for which we never saw a map
  // request event.
  if (!saw_map_request_)
    DoInitialSetupForWindow(win);

  switch (win->type()) {
    case chromeos::WM_IPC_WINDOW_CHROME_PANEL_TITLEBAR:
      // Don't do anything with panel titlebars when they're first
      // mapped; we'll handle them after we see the corresponding content
      // window.
      break;

    case chromeos::WM_IPC_WINDOW_CHROME_PANEL_CONTENT: {
      // Resize the titlebar to match the content window's current width.
      // There's a small chance that we'll constrain the content size in the
      // Panel c'tor, but this lets us get the titlebar to the right size
      // before we make both windows visible in the common case.
      if (!win->type_params().empty()) {
        Window* titlebar_win = wm_->GetWindow(win->type_params().at(0));
        if (titlebar_win) {
          titlebar_win->Resize(
              Size(win->client_width(), titlebar_win->client_height()),
              GRAVITY_NORTHWEST);
        }
      }

      if (win->has_initial_pixmap()) {
        HandleContentWindowInitialPixmapFetch(win);
      } else {
        // If we don't have the window's pixmap yet, defer creating the Panel
        // object and register to get notified after the pixmap is loaded.
        event_consumer_registrar_->RegisterForWindowEvents(win->xid());
        content_xids_without_initial_pixmaps_.insert(win->xid());
      }
      break;
    }

    default:
      NOTREACHED() << "Unhandled window type " << win->type();
  }
}

void PanelManager::HandleWindowUnmap(Window* win) {
  if (win->override_redirect())
    return;

  set<XWindow>::iterator content_it =
      content_xids_without_initial_pixmaps_.find(win->xid());
  if (content_it != content_xids_without_initial_pixmaps_.end()) {
    event_consumer_registrar_->UnregisterForWindowEvents(win->xid());
    content_xids_without_initial_pixmaps_.erase(content_it);
  }

  Panel* owner_panel = GetPanelOwningTransientWindow(*win);
  if (owner_panel) {
    transient_xids_to_owners_.erase(win->xid());
    owner_panel->HandleTransientWindowUnmap(win);
    return;
  }

  Panel* panel = GetPanelByWindow(*win);
  if (!panel)
    return;

  PanelContainer* container = GetContainerForPanel(*panel);
  if (container)
    RemovePanelFromContainer(panel, container);
  if (panel == dragged_panel_)
    HandlePanelDragComplete(panel, true);  // removed=true
  if (panel == fullscreen_panel_)
    fullscreen_panel_ = NULL;

  // If the panel was focused, assign the focus to another panel, or
  // failing that, let the window manager decide what to do with it.
  if (panel->is_focused()) {
    XTime timestamp = wm()->GetCurrentTimeFromServer();
    if (!TakeFocus(timestamp))
      wm_->TakeFocus(timestamp);
  }

  vector<XWindow> input_windows;
  panel->GetInputWindows(&input_windows);
  for (vector<XWindow>::const_iterator it = input_windows.begin();
       it != input_windows.end(); ++it) {
    CHECK(panel_input_xids_.erase(*it) == 1);
  }

  // Clean up any references to this panel in the transient window map.
  vector<XWindow> orphaned_transient_xids;
  for (map<XWindow, Panel*>::const_iterator it =
         transient_xids_to_owners_.begin();
       it != transient_xids_to_owners_.end(); ++it) {
    if (it->second == panel)
      orphaned_transient_xids.push_back(it->first);
  }
  for (vector<XWindow>::const_iterator it = orphaned_transient_xids.begin();
       it != orphaned_transient_xids.end(); ++it) {
    CHECK(transient_xids_to_owners_.erase(*it) == 1);
  }

  CHECK(panels_by_titlebar_xid_.erase(panel->titlebar_xid()) == 1);
  CHECK(panels_.erase(panel->content_xid()) == 1);
}

void PanelManager::HandleWindowPixmapFetch(Window* win) {
  set<XWindow>::iterator it =
      content_xids_without_initial_pixmaps_.find(win->xid());
  if (it != content_xids_without_initial_pixmaps_.end()) {
    event_consumer_registrar_->UnregisterForWindowEvents(win->xid());
    content_xids_without_initial_pixmaps_.erase(it);
    HandleContentWindowInitialPixmapFetch(win);
  }
}

void PanelManager::HandleWindowConfigureRequest(Window* win,
                                                const Rect& requested_bounds) {
  if (Panel* owner_panel = GetPanelOwningTransientWindow(*win)) {
    owner_panel->HandleTransientWindowConfigureRequest(win, requested_bounds);
    return;
  }

  Panel* panel = GetPanelByWindow(*win);
  if (!panel)
    return;

  if (win != panel->content_win()) {
    LOG(WARNING) << "Ignoring request to configure non-content window "
                 << win->xid_str() << " for panel " << panel->xid_str();
    return;
  }
  PanelContainer* container = GetContainerForPanel(*panel);
  if (!container) {
    LOG(WARNING) << "Ignoring request to configure panel " << panel->xid_str()
                 << " while it's not in a container";
    return;
  }
  if (panel->is_being_resized_by_user()) {
    LOG(WARNING) << "Ignoring request to configure panel " << panel->xid_str()
                 << " while it's being manually resized";
    win->SendSyntheticConfigureNotify();
    return;
  }

  if (requested_bounds.size() != panel->content_size())
    container->HandlePanelResizeRequest(panel, requested_bounds.size());
  else
    win->SendSyntheticConfigureNotify();
}

void PanelManager::HandleButtonPress(XWindow xid,
                                     const Point& relative_pos,
                                     const Point& absolute_pos,
                                     int button,
                                     XTime timestamp) {
  // If this is a container's input window, notify the container.
  PanelContainer* container = GetContainerOwningInputWindow(xid);
  if (container) {
    container->HandleInputWindowButtonPress(
        xid, relative_pos, absolute_pos, button, timestamp);
    return;
  }

  // If this is a panel's input window, notify the panel.
  Panel* panel = GetPanelOwningInputWindow(xid);
  if (panel) {
    panel->HandleInputWindowButtonPress(xid, relative_pos, button, timestamp);
    return;
  }

  Window* win = wm_->GetWindow(xid);
  if (!win)
    return;

  // If it's a panel's content window, notify the panel's container.
  panel = GetPanelByWindow(*win);
  if (panel) {
    container = GetContainerForPanel(*panel);
    if (container)
      container->HandlePanelButtonPress(panel, button, timestamp);
    return;
  }

  panel = GetPanelOwningTransientWindow(*win);
  if (panel) {
    panel->HandleTransientWindowButtonPress(win, button, timestamp);
    return;
  }
}

void PanelManager::HandleButtonRelease(XWindow xid,
                                       const Point& relative_pos,
                                       const Point& absolute_pos,
                                       int button,
                                       XTime timestamp) {
  // We only care if button releases happened in container or panel input
  // windows -- there's no current need to notify containers about button
  // releases in their panels.
  PanelContainer* container = GetContainerOwningInputWindow(xid);
  if (container) {
    container->HandleInputWindowButtonRelease(
        xid, relative_pos, absolute_pos, button, timestamp);
    return;
  }

  Panel* panel = GetPanelOwningInputWindow(xid);
  if (panel) {
    panel->HandleInputWindowButtonRelease(xid, relative_pos, button, timestamp);
    return;
  }
}

void PanelManager::HandlePointerEnter(XWindow xid,
                                      const Point& relative_pos,
                                      const Point& absolute_pos,
                                      XTime timestamp) {
  PanelContainer* container = GetContainerOwningInputWindow(xid);
  if (container) {
    container->HandleInputWindowPointerEnter(
        xid, relative_pos, absolute_pos, timestamp);
    return;
  }

  // If it's a panel's titlebar window, notify the panel's container.
  Window* win = wm_->GetWindow(xid);
  if (win) {
    Panel* panel = GetPanelByWindow(*win);
    if (panel) {
      container = GetContainerForPanel(*panel);
      if (container && xid == panel->titlebar_xid())
        container->HandlePanelTitlebarPointerEnter(panel, timestamp);
      return;
    }
  }
}

void PanelManager::HandlePointerLeave(XWindow xid,
                                      const Point& relative_pos,
                                      const Point& absolute_pos,
                                      XTime timestamp) {
  PanelContainer* container = GetContainerOwningInputWindow(xid);
  if (container)
    container->HandleInputWindowPointerLeave(
        xid, relative_pos, absolute_pos, timestamp);
}

void PanelManager::HandlePointerMotion(XWindow xid,
                                       const Point& relative_pos,
                                       const Point& absolute_pos,
                                       XTime timestamp) {
  Panel* panel = GetPanelOwningInputWindow(xid);
  if (panel)
    panel->HandleInputWindowPointerMotion(xid, relative_pos);
}

void PanelManager::HandleChromeMessage(const WmIpc::Message& msg) {
  switch (msg.type()) {
    case chromeos::WM_IPC_MESSAGE_WM_SET_PANEL_STATE: {
      XWindow xid = msg.param(0);
      Panel* panel = GetPanelByXid(xid);
      if (!panel) {
        LOG(WARNING) << "Ignoring WM_SET_PANEL_STATE message for non-panel "
                     << "window " << XidStr(xid);
        return;
      }
      PanelContainer* container = GetContainerForPanel(*panel);
      if (container)
        container->HandleSetPanelStateMessage(panel, msg.param(1));
      break;
    }
    case chromeos::WM_IPC_MESSAGE_WM_NOTIFY_PANEL_DRAGGED: {
      XWindow xid = msg.param(0);
      Panel* panel = GetPanelByXid(xid);
      if (!panel) {
        LOG(WARNING) << "Ignoring WM_NOTIFY_PANEL_DRAGGED message for "
                     << "non-panel window " << XidStr(xid);
        return;
      }
      if (dragged_panel_ && panel != dragged_panel_)
        HandlePanelDragComplete(dragged_panel_, false);  // removed=false
      if (panel != dragged_panel_) {
        dragged_panel_ = panel;
        panel->HandleDragStart();
      }
      if (!dragged_panel_event_coalescer_->IsRunning())
        dragged_panel_event_coalescer_->Start();
      // We want the right edge of the panel, but pre-IPC-version-1 Chrome
      // sends us the left edge of the titlebar instead.
      Point drag_pos(
          (wm()->wm_ipc_version() >= 1) ?
            msg.param(1) : msg.param(1) + panel->titlebar_width(),
          msg.param(2));
      dragged_panel_event_coalescer_->StorePosition(drag_pos);
      break;
    }
    case chromeos::WM_IPC_MESSAGE_WM_NOTIFY_PANEL_DRAG_COMPLETE: {
      XWindow xid = msg.param(0);
      Panel* panel = GetPanelByXid(xid);
      if (!panel) {
        LOG(WARNING) << "Ignoring WM_NOTIFY_PANEL_DRAG_COMPLETE message for "
                     << "non-panel window " << XidStr(xid);
        return;
      }
      HandlePanelDragComplete(panel, false);  // removed=false
      break;
    }
    default:
      return;
  }
}

void PanelManager::HandleClientMessage(XWindow xid,
                                       XAtom message_type,
                                       const long data[5]) {
  Window* win = wm_->GetWindow(xid);
  if (!win)
    return;

  if (Panel* owner_panel = GetPanelOwningTransientWindow(*win)) {
    owner_panel->HandleTransientWindowClientMessage(win, message_type, data);
    return;
  }

  Panel* panel = GetPanelByXid(xid);
  if (!panel)
    return;

  if (message_type == wm_->GetXAtom(ATOM_NET_ACTIVE_WINDOW)) {
    DLOG(INFO) << "Got _NET_ACTIVE_WINDOW request to focus " << XidStr(xid)
               << " (requestor says its currently-active window is "
               << XidStr(data[2]) << "; real active window is "
               << XidStr(wm_->active_window_xid()) << ")";
    if (PanelContainer* container = GetContainerForPanel(*panel))
      container->HandleFocusPanelMessage(panel, data[1]);
  } else if (message_type == wm_->GetXAtom(ATOM_NET_WM_STATE)) {
    if (panel->content_xid() == xid) {
      map<XAtom, bool> states;
      panel->content_win()->ParseWmStateMessage(data, &states);
      map<XAtom, bool>::const_iterator it =
          states.find(wm_->GetXAtom(ATOM_NET_WM_STATE_FULLSCREEN));
      if (it != states.end()) {
        bool fullscreen = it->second;
        DLOG(INFO) << "Panel " << panel->xid_str() << " "
                   << (fullscreen ? "set" : "unset") << " its fullscreen hint";
        if (fullscreen)
          MakePanelFullscreen(panel);
        else
          RestoreFullscreenPanel(panel);
      }
    }
  }
}

void PanelManager::HandleWindowPropertyChange(XWindow xid, XAtom xatom) {
  Window* win = wm_->GetWindowOrDie(xid);
  Panel* panel = GetPanelByWindow(*win);
  DCHECK(panel) << "Got property change for non-panel window " << XidStr(xid);
  if (!panel || panel->content_win() != win)
    return;

  if (xatom == wm_->GetXAtom(ATOM_WM_HINTS)) {
    if (win->wm_hint_urgent() != panel->is_urgent()) {
      panel->set_is_urgent(win->wm_hint_urgent());
      PanelContainer* container = GetContainerForPanel(*panel);
      if (container)
        container->HandlePanelUrgencyChange(panel);
    }
  } else if (xatom == wm_->GetXAtom(ATOM_WM_NORMAL_HINTS)) {
    if (win == panel->content_win())
      panel->HandleContentWindowSizeHintsChange();
  } else {
    LOG(DFATAL) << "Got unexpected property " << wm_->GetXAtomName(xatom)
                << " (" << XidStr(xatom) << ") change for " << win->xid_str();
  }
}

void PanelManager::HandleFocusChange() {
  // If a fullscreen panel loses the focus, un-fullscreen it.
  if (fullscreen_panel_ && !fullscreen_panel_->is_focused())
    RestoreFullscreenPanel(fullscreen_panel_);
}

void PanelManager::RegisterAreaChangeListener(
    PanelManagerAreaChangeListener* listener) {
  DCHECK(listener);
  bool added = area_change_listeners_.insert(listener).second;
  DCHECK(added) << "Listener " << listener << " was already registered";
}

void PanelManager::UnregisterAreaChangeListener(
    PanelManagerAreaChangeListener* listener) {
  int num_removed = area_change_listeners_.erase(listener);
  DCHECK_EQ(num_removed, 1) << "Listener " << listener << " wasn't registered";
}

void PanelManager::GetArea(int* left_width, int* right_width) const {
  DCHECK(left_width);
  DCHECK(right_width);
  *left_width =
      left_panel_dock_->is_visible() ? left_panel_dock_->width() : 0;
  *right_width =
      right_panel_dock_->is_visible() ? right_panel_dock_->width() : 0;
}

void PanelManager::HandlePanelResizeByUser(Panel* panel) {
  DCHECK(panel);
  if (PanelContainer* container = GetContainerForPanel(*panel))
    container->HandlePanelResizeByUser(panel);
}

void PanelManager::HandleDockVisibilityChange(PanelDock* dock) {
  for (set<PanelManagerAreaChangeListener*>::const_iterator it =
           area_change_listeners_.begin();
       it != area_change_listeners_.end(); ++it) {
    (*it)->HandlePanelManagerAreaChange();
  }
}

bool PanelManager::TakeFocus(XTime timestamp) {
  return panel_bar_->TakeFocus(timestamp) ||
         left_panel_dock_->TakeFocus(timestamp) ||
         right_panel_dock_->TakeFocus(timestamp);
}

Panel* PanelManager::GetPanelByXid(XWindow xid) {
  Window* win = wm_->GetWindow(xid);
  if (!win)
    return NULL;
  return GetPanelByWindow(*win);
}

Panel* PanelManager::GetPanelByWindow(const Window& win) {
  shared_ptr<Panel> panel = FindWithDefault(
      panels_, win.xid(), shared_ptr<Panel>());
  if (panel.get())
    return panel.get();

  return FindWithDefault(
      panels_by_titlebar_xid_, win.xid(), static_cast<Panel*>(NULL));
}

Panel* PanelManager::GetPanelOwningTransientWindow(const Window& win) {
  return FindWithDefault(transient_xids_to_owners_,
                         win.xid(),
                         static_cast<Panel*>(NULL));
}

Panel* PanelManager::GetPanelOwningInputWindow(XWindow xid) {
  return FindWithDefault(panel_input_xids_, xid, static_cast<Panel*>(NULL));
}

PanelContainer* PanelManager::GetContainerOwningInputWindow(XWindow xid) {
  return FindWithDefault(
      container_input_xids_, xid, static_cast<PanelContainer*>(NULL));
}

void PanelManager::RegisterContainer(PanelContainer* container) {
  vector<XWindow> input_xids;
  container->GetInputWindows(&input_xids);
  for (vector<XWindow>::const_iterator it = input_xids.begin();
       it != input_xids.end(); ++it) {
    DLOG(INFO) << "Registering input window " << XidStr(*it)
               << " for container " << container;
    CHECK(container_input_xids_.insert(make_pair(*it, container)).second);
  }
  containers_.push_back(container);
}

void PanelManager::DoInitialSetupForWindow(Window* win) {
  win->SetVisibility(Window::VISIBILITY_HIDDEN);
}

void PanelManager::HandleContentWindowInitialPixmapFetch(Window* win) {
  if (win->type_params().empty()) {
    LOG(WARNING) << "Panel " << win->xid_str() << " is missing type "
                 << "parameter for titlebar window";
    return;
  }
  Window* titlebar_win = wm_->GetWindow(win->type_params().at(0));
  if (!titlebar_win) {
    LOG(WARNING) << "Unable to find titlebar "
                 << XidStr(win->type_params()[0])
                 << " for panel " << win->xid_str();
    return;
  }

  // TODO(derat): Make the second param required after Chrome has been
  // updated.
  bool expanded = win->type_params().size() >= 2 ?
      win->type_params().at(1) : false;
  DLOG(INFO) << "Adding " << (expanded ? "expanded" : "collapsed")
             << " panel with content window " << win->xid_str()
             << " and titlebar window " << titlebar_win->xid_str();

  shared_ptr<Panel> panel(new Panel(this, win, titlebar_win, expanded));
  panel->SetTitlebarWidth(panel->content_width());

  vector<XWindow> input_windows;
  panel->GetInputWindows(&input_windows);
  for (vector<XWindow>::const_iterator it = input_windows.begin();
       it != input_windows.end(); ++it) {
    CHECK(panel_input_xids_.insert(make_pair(*it, panel.get())).second);
  }

  CHECK(panels_.insert(make_pair(win->xid(), panel)).second);
  CHECK(panels_by_titlebar_xid_.insert(
          make_pair(titlebar_win->xid(), panel.get())).second);

  AddPanelToContainer(panel.get(),
                      panel_bar_.get(),
                      PanelContainer::PANEL_SOURCE_NEW);

  if (win->wm_state_fullscreen())
    MakePanelFullscreen(panel.get());
}

void PanelManager::HandlePeriodicPanelDragMotion() {
  DCHECK(dragged_panel_);
  if (!dragged_panel_)
    return;

  const Point pos = dragged_panel_event_coalescer_->position();

  bool container_handled_drag = false;
  bool panel_was_detached = false;
  PanelContainer* container = GetContainerForPanel(*dragged_panel_);
  if (container) {
    if (container->HandleNotifyPanelDraggedMessage(dragged_panel_, pos)) {
      container_handled_drag = true;
    } else {
      DLOG(INFO) << "Container " << container << " told us to detach panel "
                 << dragged_panel_->xid_str() << " at " << pos;
      RemovePanelFromContainer(dragged_panel_, container);
      panel_was_detached = true;
    }
  }

  if (!container_handled_drag) {
    if (panel_was_detached) {
      dragged_panel_->SetTitlebarWidth(dragged_panel_->content_width());
      dragged_panel_->StackAtTopOfLayer(StackingManager::LAYER_DRAGGED_PANEL);
    }

    // Offer the panel to all of the containers.  If we find one that wants
    // it, attach it; otherwise we just move the panel to the dragged location.
    bool panel_was_reattached = false;
    for (vector<PanelContainer*>::iterator it = containers_.begin();
         it != containers_.end(); ++it) {
      if ((*it)->ShouldAddDraggedPanel(dragged_panel_, pos)) {
        DLOG(INFO) << "Container " << *it << " told us to attach panel "
                   << dragged_panel_->xid_str() << " at " << pos;
        AddPanelToContainer(dragged_panel_,
                            *it,
                            PanelContainer::PANEL_SOURCE_DRAGGED);
        CHECK((*it)->HandleNotifyPanelDraggedMessage(dragged_panel_, pos));
        panel_was_reattached = true;
        break;
      }
    }
    if (!panel_was_reattached) {
      dragged_panel_->Move(pos, panel_was_detached ? kDetachPanelAnimMs : 0);
    }
  }
}

void PanelManager::HandlePanelDragComplete(Panel* panel, bool removed) {
  DCHECK(panel);
  DCHECK(dragged_panel_ == panel);
  if (dragged_panel_ != panel)
    return;

  panel->HandleDragEnd();

  if (dragged_panel_event_coalescer_->IsRunning())
    dragged_panel_event_coalescer_->Stop();
  dragged_panel_ = NULL;

  if (!removed) {
    PanelContainer* container = GetContainerForPanel(*panel);
    if (container) {
      container->HandleNotifyPanelDragCompleteMessage(panel);
    } else {
      DLOG(INFO) << "Attaching dropped panel " << panel->xid_str()
                 << " to panel bar";
      AddPanelToContainer(panel,
                          panel_bar_.get(),
                          PanelContainer::PANEL_SOURCE_DROPPED);
    }
  }
}

void PanelManager::AddPanelToContainer(Panel* panel,
                                       PanelContainer* container,
                                       PanelContainer::PanelSource source) {
  DCHECK(GetContainerForPanel(*panel) == NULL);
  CHECK(containers_by_panel_.insert(make_pair(panel, container)).second);
  container->AddPanel(panel, source);
}

void PanelManager::RemovePanelFromContainer(Panel* panel,
                                            PanelContainer* container) {
  DCHECK(GetContainerForPanel(*panel) == container);
  CHECK(containers_by_panel_.erase(panel) == static_cast<size_t>(1));
  container->RemovePanel(panel);
  panel->SetResizable(false);
  panel->SetShadowOpacity(1.0, kDetachPanelAnimMs);
  panel->SetExpandedState(true);
}

void PanelManager::MakePanelFullscreen(Panel* panel) {
  DCHECK(panel);
  if (panel->is_fullscreen()) {
    LOG(WARNING) << "Ignoring request to fullscreen already-fullscreen "
                 << "panel " << panel->xid_str();
    return;
  }

  // If there's already another fullscreen panel, unfullscreen it.
  if (fullscreen_panel_)
    RestoreFullscreenPanel(fullscreen_panel_);
  DCHECK(!fullscreen_panel_);

  panel->SetFullscreenState(true);
  fullscreen_panel_ = panel;
}

void PanelManager::RestoreFullscreenPanel(Panel* panel) {
  DCHECK(panel);
  if (!panel->is_fullscreen()) {
    LOG(WARNING) << "Ignoring request to restore non-fullscreen panel "
                 << panel->xid_str();
    return;
  }

  panel->SetFullscreenState(false);
  if (fullscreen_panel_ == panel)
    fullscreen_panel_ = NULL;
}

}  // namespace window_manager
