Home | History | Annotate | Download | only in tabs
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/ui/tabs/dock_info.h"
      6 
      7 #include <stdlib.h>
      8 
      9 #include "base/logging.h"
     10 
     11 namespace {
     12 
     13 // Distance in pixels between the hotspot and when the hint should be shown.
     14 const int kHotSpotDeltaX = 120;
     15 const int kHotSpotDeltaY = 120;
     16 
     17 // Size of the popup window.
     18 const int kPopupWidth = 70;
     19 const int kPopupHeight = 70;
     20 
     21 }  // namespace
     22 
     23 // static
     24 bool DockInfo::IsCloseToPoint(const gfx::Point& screen_loc,
     25                               int x,
     26                               int y,
     27                               bool* in_enable_area) {
     28   int delta_x = abs(x - screen_loc.x());
     29   int delta_y = abs(y - screen_loc.y());
     30   *in_enable_area = (delta_x < kPopupWidth / 2 && delta_y < kPopupHeight / 2);
     31   return *in_enable_area || (delta_x < kHotSpotDeltaX &&
     32                              delta_y < kHotSpotDeltaY);
     33 }
     34 
     35 // static
     36 bool DockInfo::IsCloseToMonitorPoint(const gfx::Point& screen_loc,
     37                                      int x,
     38                                      int y,
     39                                      DockInfo::Type type,
     40                                      bool* in_enable_area) {
     41   // Because the monitor relative positions are aligned with the edge of the
     42   // monitor these need to be handled differently.
     43   int delta_x = abs(x - screen_loc.x());
     44   int delta_y = abs(y - screen_loc.y());
     45 
     46   int enable_delta_x = kPopupWidth / 2;
     47   int enable_delta_y = kPopupHeight / 2;
     48   int hot_spot_delta_x = kHotSpotDeltaX;
     49   int hot_spot_delta_y = kHotSpotDeltaY;
     50 
     51   switch (type) {
     52     case DockInfo::LEFT_HALF:
     53     case DockInfo::RIGHT_HALF:
     54       enable_delta_x += enable_delta_x;
     55       hot_spot_delta_x += hot_spot_delta_x;
     56       break;
     57 
     58 
     59     case DockInfo::MAXIMIZE: {
     60       // Make the maximize height smaller than the tab height to avoid showing
     61       // the dock indicator when close to maximized browser.
     62       hot_spot_delta_y = GetHotSpotDeltaY();
     63       enable_delta_y = hot_spot_delta_y / 2;
     64       break;
     65     }
     66     case DockInfo::BOTTOM_HALF:
     67       enable_delta_y += enable_delta_y;
     68       hot_spot_delta_y += hot_spot_delta_y;
     69       break;
     70 
     71     default:
     72       NOTREACHED();
     73       return false;
     74   }
     75   *in_enable_area = (delta_x < enable_delta_x && delta_y < enable_delta_y);
     76   bool result = (*in_enable_area || (delta_x < hot_spot_delta_x &&
     77                                      delta_y < hot_spot_delta_y));
     78   if (type != DockInfo::MAXIMIZE)
     79     return result;
     80 
     81   // Make the hot spot/enable spot for maximized windows the whole top of the
     82   // monitor.
     83   int max_delta_y = abs(screen_loc.y() - y);
     84   *in_enable_area = (*in_enable_area || (max_delta_y < enable_delta_y));
     85   return *in_enable_area || (max_delta_y < hot_spot_delta_y);
     86 }
     87 
     88 // static
     89 int DockInfo::popup_width() {
     90   return kPopupWidth;
     91 }
     92 
     93 // static
     94 int DockInfo::popup_height() {
     95   return kPopupHeight;
     96 }
     97 
     98 bool DockInfo::IsValidForPoint(const gfx::Point& screen_point) {
     99   if (type_ == NONE)
    100     return false;
    101 
    102   if (window_) {
    103     return IsCloseToPoint(screen_point, hot_spot_.x(), hot_spot_.y(),
    104                           &in_enable_area_);
    105   }
    106 
    107   return monitor_bounds_.Contains(screen_point) &&
    108           IsCloseToMonitorPoint(screen_point, hot_spot_.x(),
    109                                 hot_spot_.y(), type_, &in_enable_area_);
    110 }
    111 
    112 bool DockInfo::GetNewWindowBounds(gfx::Rect* new_window_bounds,
    113                                   bool* maximize_new_window) const {
    114   if (type_ == NONE || !in_enable_area_)
    115     return false;
    116 
    117   gfx::Rect window_bounds;
    118   if (window_ && !GetWindowBounds(&window_bounds))
    119     return false;
    120 
    121   int half_m_width = (monitor_bounds_.right() - monitor_bounds_.x()) / 2;
    122   int half_m_height = (monitor_bounds_.bottom() - monitor_bounds_.y()) / 2;
    123 
    124   *maximize_new_window = false;
    125 
    126   switch (type_) {
    127     case LEFT_OF_WINDOW:
    128       new_window_bounds->SetRect(monitor_bounds_.x(), window_bounds.y(),
    129                                  half_m_width, window_bounds.height());
    130       break;
    131 
    132     case RIGHT_OF_WINDOW:
    133       new_window_bounds->SetRect(monitor_bounds_.x() + half_m_width,
    134                                  window_bounds.y(), half_m_width,
    135                                  window_bounds.height());
    136       break;
    137 
    138     case TOP_OF_WINDOW:
    139       new_window_bounds->SetRect(window_bounds.x(), monitor_bounds_.y(),
    140                                  window_bounds.width(), half_m_height);
    141       break;
    142 
    143     case BOTTOM_OF_WINDOW:
    144       new_window_bounds->SetRect(window_bounds.x(),
    145                                  monitor_bounds_.y() + half_m_height,
    146                                  window_bounds.width(), half_m_height);
    147       break;
    148 
    149     case LEFT_HALF:
    150       new_window_bounds->SetRect(monitor_bounds_.x(), monitor_bounds_.y(),
    151                                  half_m_width, monitor_bounds_.height());
    152       break;
    153 
    154     case RIGHT_HALF:
    155       new_window_bounds->SetRect(monitor_bounds_.right() - half_m_width,
    156           monitor_bounds_.y(), half_m_width, monitor_bounds_.height());
    157       break;
    158 
    159     case BOTTOM_HALF:
    160       new_window_bounds->SetRect(monitor_bounds_.x(),
    161                                  monitor_bounds_.y() + half_m_height,
    162                                  monitor_bounds_.width(), half_m_height);
    163       break;
    164 
    165     case MAXIMIZE:
    166       *maximize_new_window = true;
    167       break;
    168 
    169     default:
    170       NOTREACHED();
    171   }
    172   return true;
    173 }
    174 
    175 void DockInfo::AdjustOtherWindowBounds() const {
    176   if (!in_enable_area_)
    177     return;
    178 
    179   gfx::Rect window_bounds;
    180   if (!window_ || !GetWindowBounds(&window_bounds))
    181     return;
    182 
    183   gfx::Rect other_window_bounds;
    184   int half_m_width = (monitor_bounds_.right() - monitor_bounds_.x()) / 2;
    185   int half_m_height = (monitor_bounds_.bottom() - monitor_bounds_.y()) / 2;
    186 
    187   switch (type_) {
    188     case LEFT_OF_WINDOW:
    189       other_window_bounds.SetRect(monitor_bounds_.x() + half_m_width,
    190                                   window_bounds.y(), half_m_width,
    191                                   window_bounds.height());
    192       break;
    193 
    194     case RIGHT_OF_WINDOW:
    195       other_window_bounds.SetRect(monitor_bounds_.x(), window_bounds.y(),
    196                                   half_m_width, window_bounds.height());
    197       break;
    198 
    199     case TOP_OF_WINDOW:
    200       other_window_bounds.SetRect(window_bounds.x(),
    201                                   monitor_bounds_.y() + half_m_height,
    202                                   window_bounds.width(), half_m_height);
    203       break;
    204 
    205     case BOTTOM_OF_WINDOW:
    206       other_window_bounds.SetRect(window_bounds.x(), monitor_bounds_.y(),
    207                                   window_bounds.width(), half_m_height);
    208       break;
    209 
    210     default:
    211       return;
    212   }
    213 
    214   SizeOtherWindowTo(other_window_bounds);
    215 }
    216 
    217 gfx::Rect DockInfo::GetPopupRect() const {
    218   int x = hot_spot_.x() - popup_width() / 2;
    219   int y = hot_spot_.y() - popup_height() / 2;
    220   switch (type_) {
    221     case LEFT_OF_WINDOW:
    222     case RIGHT_OF_WINDOW:
    223     case TOP_OF_WINDOW:
    224     case BOTTOM_OF_WINDOW: {
    225       // Constrain the popup to the monitor's bounds.
    226       gfx::Rect ideal_bounds(x, y, popup_width(), popup_height());
    227       ideal_bounds.AdjustToFit(monitor_bounds_);
    228       return ideal_bounds;
    229     }
    230     case DockInfo::MAXIMIZE:
    231       y += popup_height() / 2;
    232       break;
    233     case DockInfo::LEFT_HALF:
    234       x += popup_width() / 2;
    235       break;
    236     case DockInfo::RIGHT_HALF:
    237       x -= popup_width() / 2;
    238       break;
    239     case DockInfo::BOTTOM_HALF:
    240       y -= popup_height() / 2;
    241       break;
    242 
    243     default:
    244       NOTREACHED();
    245   }
    246   return gfx::Rect(x, y, popup_width(), popup_height());
    247 }
    248 
    249 bool DockInfo::CheckMonitorPoint(const gfx::Point& screen_loc,
    250                                  int x,
    251                                  int y,
    252                                  Type type) {
    253   if (IsCloseToMonitorPoint(screen_loc, x, y, type, &in_enable_area_)) {
    254     hot_spot_.SetPoint(x, y);
    255     type_ = type;
    256     return true;
    257   }
    258   return false;
    259 }
    260