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