blob: 39c375a8dc4d64bd5c6a6f0f920deb9ed7886ee2 [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.
#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