// 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/focus_manager.h"

#include <utility>

#include "window_manager/window.h"
#include "window_manager/window_manager.h"
#include "window_manager/x11/x_connection.h"

using std::make_pair;
using std::map;
using std::set;

namespace window_manager {

FocusManager::FocusManager(WindowManager* wm)
    : wm_(wm),
      focused_win_(NULL),
      last_focus_timestamp_(0) {
  DCHECK(wm_);
}

FocusManager::~FocusManager() {
}

void FocusManager::FocusWindow(Window* win, XTime timestamp) {
  if (win == focused_win_)
    return;

  if (timestamp < last_focus_timestamp_) {
    DLOG(INFO) << "Timestamp for focusing " << (win ? win->xid_str() : "root")
               << " (" << timestamp << ") precedes the last timestamp "
               << "used for focusing (" << last_focus_timestamp_ << "); "
               << "reusing the last timestamp instead";
    timestamp = last_focus_timestamp_;
  } else {
    last_focus_timestamp_ = timestamp;
  }

  if (focused_win_ && click_to_focus_windows_.count(focused_win_))
    AddButtonGrabs(focused_win_);

  focused_win_ = win;
  if (focused_win_) {
    focused_win_->TakeFocus(timestamp);
    if (click_to_focus_windows_.count(focused_win_))
      RemoveButtonGrabs(focused_win_);
  } else {
    wm_->xconn()->FocusWindow(wm_->xconn()->GetRootWindow(), timestamp);
  }

  wm_->SetActiveWindowProperty(focused_win_ ? focused_win_->xid() : 0);

  for (set<FocusChangeListener*>::const_iterator it =
         focus_change_listeners_.begin();
       it != focus_change_listeners_.end(); ++it) {
    (*it)->HandleFocusChange();
  }
}

void FocusManager::UseClickToFocusForWindow(Window* win,
                                            ClickToFocusPolicy policy) {
  DCHECK(win);
  map<Window*, ClickToFocusPolicy>::iterator it =
      click_to_focus_windows_.find(win);
  if (it != click_to_focus_windows_.end()) {
    it->second = policy;
  } else {
    click_to_focus_windows_.insert(make_pair(win, policy));
    if (focused_win_ != win)
      AddButtonGrabs(win);
  }
}

void FocusManager::HandleWindowUnmap(Window* win) {
  DCHECK(win);
  map<Window*, ClickToFocusPolicy>::iterator it =
      click_to_focus_windows_.find(win);
  if (it != click_to_focus_windows_.end()) {
    RemoveButtonGrabs(win);
    click_to_focus_windows_.erase(it);
  }

  if (focused_win_ == win)
    FocusWindow(NULL, wm_->GetCurrentTimeFromServer());
}

void FocusManager::HandleButtonPressInWindow(Window* win, XTime timestamp) {
  DCHECK(win);
  map<Window*, ClickToFocusPolicy>::iterator it =
      click_to_focus_windows_.find(win);
  if (it != click_to_focus_windows_.end()) {
    const bool replay_events =
        it->second == PASS_CLICKS_THROUGH &&
        (!focused_win_ || !focused_win_->wm_state_modal());
    wm_->xconn()->UngrabPointer(replay_events, timestamp);
  }
}

void FocusManager::RegisterFocusChangeListener(
    FocusChangeListener* listener) {
  DCHECK(listener);
  bool added = focus_change_listeners_.insert(listener).second;
  DCHECK(added) << "Listener " << listener << " was already registered";
}

void FocusManager::UnregisterFocusChangeListener(
    FocusChangeListener* listener) {
  int num_removed = focus_change_listeners_.erase(listener);
  DCHECK_EQ(num_removed, 1) << "Listener " << listener << " wasn't registered";
}

void FocusManager::AddButtonGrabs(Window* win) {
  DCHECK(win);
  win->AddButtonGrab(1);
  win->AddButtonGrab(2);
  win->AddButtonGrab(3);
}

void FocusManager::RemoveButtonGrabs(Window* win) {
  DCHECK(win);
  win->RemoveButtonGrab(1);
  win->RemoveButtonGrab(2);
  win->RemoveButtonGrab(3);
}

}  // namespace window_manager
