| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "ash/display/display_controller.h" | 5 #include "ash/display/display_controller.h" | 
| 6 | 6 | 
| 7 #include <algorithm> | 7 #include <algorithm> | 
| 8 | 8 | 
| 9 #include "ash/ash_switches.h" | 9 #include "ash/ash_switches.h" | 
| 10 #include "ash/display/display_manager.h" | 10 #include "ash/display/display_manager.h" | 
| 11 #include "ash/root_window_controller.h" | 11 #include "ash/root_window_controller.h" | 
| 12 #include "ash/screen_ash.h" | 12 #include "ash/screen_ash.h" | 
| 13 #include "ash/shell.h" | 13 #include "ash/shell.h" | 
| 14 #include "ash/wm/coordinate_conversion.h" | 14 #include "ash/wm/coordinate_conversion.h" | 
| 15 #include "ash/wm/property_util.h" | 15 #include "ash/wm/property_util.h" | 
| 16 #include "ash/wm/window_util.h" | 16 #include "ash/wm/window_util.h" | 
| 17 #include "base/command_line.h" | 17 #include "base/command_line.h" | 
| 18 #include "base/json/json_value_converter.h" | 18 #include "base/json/json_value_converter.h" | 
| 19 #include "base/string_piece.h" | 19 #include "base/string_piece.h" | 
| 20 #include "base/stringprintf.h" | 20 #include "base/stringprintf.h" | 
| 21 #include "base/values.h" | 21 #include "base/values.h" | 
| 22 #include "ui/aura/client/screen_position_client.h" | 22 #include "ui/aura/client/screen_position_client.h" | 
| 23 #include "ui/aura/env.h" | 23 #include "ui/aura/env.h" | 
| 24 #include "ui/aura/root_window.h" | 24 #include "ui/aura/root_window.h" | 
| 25 #include "ui/aura/window.h" | 25 #include "ui/aura/window.h" | 
|  | 26 #include "ui/aura/window_property.h" | 
| 26 #include "ui/compositor/dip_util.h" | 27 #include "ui/compositor/dip_util.h" | 
| 27 #include "ui/gfx/display.h" | 28 #include "ui/gfx/display.h" | 
| 28 #include "ui/gfx/screen.h" | 29 #include "ui/gfx/screen.h" | 
| 29 | 30 | 
| 30 #if defined(OS_CHROMEOS) | 31 #if defined(OS_CHROMEOS) | 
| 31 #include "ash/display/output_configurator_animation.h" | 32 #include "ash/display/output_configurator_animation.h" | 
| 32 #include "base/chromeos/chromeos_version.h" | 33 #include "base/chromeos/chromeos_version.h" | 
| 33 #include "base/string_number_conversions.h" | 34 #include "base/string_number_conversions.h" | 
| 34 #include "base/time.h" | 35 #include "base/time.h" | 
| 35 #include "chromeos/display/output_configurator.h" | 36 #include "chromeos/display/output_configurator.h" | 
| 36 #include "ui/base/x/x11_util.h" | 37 #include "ui/base/x/x11_util.h" | 
| 37 #endif  // defined(OS_CHROMEOS) | 38 #endif  // defined(OS_CHROMEOS) | 
| 38 | 39 | 
|  | 40 DECLARE_WINDOW_PROPERTY_TYPE(ash::internal::DisplayInfo::Rotation); | 
| 39 | 41 | 
| 40 namespace ash { | 42 namespace ash { | 
| 41 namespace { | 43 namespace { | 
| 42 | 44 | 
|  | 45 DEFINE_WINDOW_PROPERTY_KEY(internal::DisplayInfo::Rotation, kRotationKey, | 
|  | 46                            internal::DisplayInfo::Rotate0); | 
|  | 47 | 
| 43 // Primary display stored in global object as it can be | 48 // Primary display stored in global object as it can be | 
| 44 // accessed after Shell is deleted. A separate display instance is created | 49 // accessed after Shell is deleted. A separate display instance is created | 
| 45 // during the shutdown instead of always keeping two display instances | 50 // during the shutdown instead of always keeping two display instances | 
| 46 // (one here and another one in display_manager) in sync, which is error prone. | 51 // (one here and another one in display_manager) in sync, which is error prone. | 
| 47 int64 primary_display_id = gfx::Display::kInvalidDisplayID; | 52 int64 primary_display_id = gfx::Display::kInvalidDisplayID; | 
| 48 gfx::Display* primary_display_for_shutdown = NULL; | 53 gfx::Display* primary_display_for_shutdown = NULL; | 
| 49 // Keeps the number of displays during the shutdown after | 54 // Keeps the number of displays during the shutdown after | 
| 50 // ash::Shell:: is deleted. | 55 // ash::Shell:: is deleted. | 
| 51 int num_displays_for_shutdown = -1; | 56 int num_displays_for_shutdown = -1; | 
| 52 | 57 | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 98     case DisplayLayout::LEFT: | 103     case DisplayLayout::LEFT: | 
| 99       return std::string("left"); | 104       return std::string("left"); | 
| 100   } | 105   } | 
| 101   return std::string("unknown"); | 106   return std::string("unknown"); | 
| 102 } | 107 } | 
| 103 | 108 | 
| 104 internal::DisplayManager* GetDisplayManager() { | 109 internal::DisplayManager* GetDisplayManager() { | 
| 105   return Shell::GetInstance()->display_manager(); | 110   return Shell::GetInstance()->display_manager(); | 
| 106 } | 111 } | 
| 107 | 112 | 
|  | 113 void RotateRootWindow(aura::RootWindow* root_window, | 
|  | 114                       const gfx::Display& display, | 
|  | 115                       const internal::DisplayInfo& info) { | 
|  | 116   // TODO(oshima): Add animation. (crossfade+rotation, or just cross-fade) | 
|  | 117   if (info.rotation() == root_window->GetProperty(kRotationKey)) | 
|  | 118     return; | 
|  | 119   root_window->SetProperty(kRotationKey, info.rotation()); | 
|  | 120   gfx::Transform rotate; | 
|  | 121   switch (info.rotation()) { | 
|  | 122     case internal::DisplayInfo::Rotate0: | 
|  | 123       break; | 
|  | 124     case internal::DisplayInfo::Rotate90: | 
|  | 125       rotate.Translate(display.bounds().height(), 0); | 
|  | 126       rotate.Rotate(90); | 
|  | 127       break; | 
|  | 128     case internal::DisplayInfo::Rotate270: | 
|  | 129       rotate.Translate(0, display.bounds().width()); | 
|  | 130       rotate.Rotate(270); | 
|  | 131       break; | 
|  | 132     case internal::DisplayInfo::Rotate180: | 
|  | 133       rotate.Translate(display.bounds().width(), display.bounds().height()); | 
|  | 134       rotate.Rotate(180); | 
|  | 135       break; | 
|  | 136   } | 
|  | 137   root_window->SetTransform(rotate); | 
|  | 138 } | 
|  | 139 | 
| 108 void SetDisplayPropertiesOnHostWindow(aura::RootWindow* root, | 140 void SetDisplayPropertiesOnHostWindow(aura::RootWindow* root, | 
| 109                                       const gfx::Display& display) { | 141                                       const gfx::Display& display) { | 
| 110 #if defined(OS_CHROMEOS) | 142 #if defined(OS_CHROMEOS) | 
| 111   // Native window property (Atom in X11) that specifies the display's | 143   // Native window property (Atom in X11) that specifies the display's | 
| 112   // rotation and scale factor.  They are read and used by | 144   // rotation and scale factor.  They are read and used by | 
| 113   // touchpad/mouse driver directly on X (contact adlr@ for more | 145   // touchpad/mouse driver directly on X (contact adlr@ for more | 
| 114   // details on touchpad/mouse driver side). The value of the rotation | 146   // details on touchpad/mouse driver side). The value of the rotation | 
| 115   // is one of 0 (normal), 1 (90 degrees clockwise), 2 (180 degree) or | 147   // is one of 0 (normal), 1 (90 degrees clockwise), 2 (180 degree) or | 
| 116   // 3 (270 degrees clockwise).  The value of the scale factor is in | 148   // 3 (270 degrees clockwise).  The value of the scale factor is in | 
| 117   // percent (100, 140, 200 etc). | 149   // percent (100, 140, 200 etc). | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 130     if (rotation < 0 || rotation > 3) | 162     if (rotation < 0 || rotation > 3) | 
| 131       rotation = 0; | 163       rotation = 0; | 
| 132   } | 164   } | 
| 133   gfx::AcceleratedWidget xwindow = root->GetAcceleratedWidget(); | 165   gfx::AcceleratedWidget xwindow = root->GetAcceleratedWidget(); | 
| 134   ui::SetIntProperty(xwindow, kRotationProp, kCARDINAL, rotation); | 166   ui::SetIntProperty(xwindow, kRotationProp, kCARDINAL, rotation); | 
| 135   ui::SetIntProperty(xwindow, | 167   ui::SetIntProperty(xwindow, | 
| 136                      kScaleFactorProp, | 168                      kScaleFactorProp, | 
| 137                      kCARDINAL, | 169                      kCARDINAL, | 
| 138                      100 * display.device_scale_factor()); | 170                      100 * display.device_scale_factor()); | 
| 139 #endif | 171 #endif | 
|  | 172   RotateRootWindow(root, display, GetDisplayManager()->GetDisplayInfo(display)); | 
| 140 } | 173 } | 
| 141 | 174 | 
| 142 }  // namespace | 175 }  // namespace | 
| 143 | 176 | 
| 144 //////////////////////////////////////////////////////////////////////////////// | 177 //////////////////////////////////////////////////////////////////////////////// | 
| 145 // DisplayLayout | 178 // DisplayLayout | 
| 146 | 179 | 
| 147 DisplayLayout::DisplayLayout() | 180 DisplayLayout::DisplayLayout() | 
| 148     : position(RIGHT), | 181     : position(RIGHT), | 
| 149       offset(0) {} | 182       offset(0) {} | 
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 230 bool DisplayController::DisplayChangeLimiter::IsThrottled() const { | 263 bool DisplayController::DisplayChangeLimiter::IsThrottled() const { | 
| 231   return base::Time::Now() < throttle_timeout_; | 264   return base::Time::Now() < throttle_timeout_; | 
| 232 } | 265 } | 
| 233 | 266 | 
| 234 //////////////////////////////////////////////////////////////////////////////// | 267 //////////////////////////////////////////////////////////////////////////////// | 
| 235 // DisplayController | 268 // DisplayController | 
| 236 | 269 | 
| 237 DisplayController::DisplayController() | 270 DisplayController::DisplayController() | 
| 238     : desired_primary_display_id_(gfx::Display::kInvalidDisplayID), | 271     : desired_primary_display_id_(gfx::Display::kInvalidDisplayID), | 
| 239       primary_root_window_for_replace_(NULL) { | 272       primary_root_window_for_replace_(NULL) { | 
|  | 273   CommandLine* command_line = CommandLine::ForCurrentProcess(); | 
| 240 #if defined(OS_CHROMEOS) | 274 #if defined(OS_CHROMEOS) | 
| 241   CommandLine* command_line = CommandLine::ForCurrentProcess(); |  | 
| 242   if (!command_line->HasSwitch(switches::kAshDisableDisplayChangeLimiter) && | 275   if (!command_line->HasSwitch(switches::kAshDisableDisplayChangeLimiter) && | 
| 243       base::chromeos::IsRunningOnChromeOS()) | 276       base::chromeos::IsRunningOnChromeOS()) | 
| 244     limiter_.reset(new DisplayChangeLimiter); | 277     limiter_.reset(new DisplayChangeLimiter); | 
| 245 #endif | 278 #endif | 
|  | 279   if (command_line->HasSwitch(switches::kAshSecondaryDisplayLayout)) { | 
|  | 280     std::string value = command_line->GetSwitchValueASCII( | 
|  | 281         switches::kAshSecondaryDisplayLayout); | 
|  | 282     char layout; | 
|  | 283     int offset = 0; | 
|  | 284     if (sscanf(value.c_str(), "%c,%d", &layout, &offset) == 2) { | 
|  | 285       if (layout == 't') | 
|  | 286         default_display_layout_.position = DisplayLayout::TOP; | 
|  | 287       else if (layout == 'b') | 
|  | 288         default_display_layout_.position = DisplayLayout::BOTTOM; | 
|  | 289       else if (layout == 'r') | 
|  | 290         default_display_layout_.position = DisplayLayout::RIGHT; | 
|  | 291       else if (layout == 'l') | 
|  | 292         default_display_layout_.position = DisplayLayout::LEFT; | 
|  | 293       default_display_layout_.offset = offset; | 
|  | 294     } | 
|  | 295   } | 
| 246   // Reset primary display to make sure that tests don't use | 296   // Reset primary display to make sure that tests don't use | 
| 247   // stale display info from previous tests. | 297   // stale display info from previous tests. | 
| 248   primary_display_id = gfx::Display::kInvalidDisplayID; | 298   primary_display_id = gfx::Display::kInvalidDisplayID; | 
| 249   delete primary_display_for_shutdown; | 299   delete primary_display_for_shutdown; | 
| 250   primary_display_for_shutdown = NULL; | 300   primary_display_for_shutdown = NULL; | 
| 251   num_displays_for_shutdown = -1; | 301   num_displays_for_shutdown = -1; | 
| 252 | 302 | 
| 253   Shell::GetScreen()->AddObserver(this); | 303   Shell::GetScreen()->AddObserver(this); | 
| 254 } | 304 } | 
| 255 | 305 | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 305 | 355 | 
| 306 void DisplayController::InitSecondaryDisplays() { | 356 void DisplayController::InitSecondaryDisplays() { | 
| 307   internal::DisplayManager* display_manager = GetDisplayManager(); | 357   internal::DisplayManager* display_manager = GetDisplayManager(); | 
| 308   for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { | 358   for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { | 
| 309     const gfx::Display* display = display_manager->GetDisplayAt(i); | 359     const gfx::Display* display = display_manager->GetDisplayAt(i); | 
| 310     if (primary_display_id != display->id()) { | 360     if (primary_display_id != display->id()) { | 
| 311       aura::RootWindow* root = AddRootWindowForDisplay(*display); | 361       aura::RootWindow* root = AddRootWindowForDisplay(*display); | 
| 312       Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root); | 362       Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root); | 
| 313     } | 363     } | 
| 314   } | 364   } | 
| 315   CommandLine* command_line = CommandLine::ForCurrentProcess(); |  | 
| 316   if (command_line->HasSwitch(switches::kAshSecondaryDisplayLayout)) { |  | 
| 317     std::string value = command_line->GetSwitchValueASCII( |  | 
| 318         switches::kAshSecondaryDisplayLayout); |  | 
| 319     char layout; |  | 
| 320     int offset; |  | 
| 321     if (sscanf(value.c_str(), "%c,%d", &layout, &offset) == 2) { |  | 
| 322       if (layout == 't') |  | 
| 323         default_display_layout_.position = DisplayLayout::TOP; |  | 
| 324       else if (layout == 'b') |  | 
| 325         default_display_layout_.position = DisplayLayout::BOTTOM; |  | 
| 326       else if (layout == 'r') |  | 
| 327         default_display_layout_.position = DisplayLayout::RIGHT; |  | 
| 328       else if (layout == 'l') |  | 
| 329         default_display_layout_.position = DisplayLayout::LEFT; |  | 
| 330       default_display_layout_.offset = offset; |  | 
| 331     } |  | 
| 332   } |  | 
| 333   UpdateDisplayBoundsForLayout(); | 365   UpdateDisplayBoundsForLayout(); | 
| 334 } | 366 } | 
| 335 | 367 | 
| 336 void DisplayController::AddObserver(Observer* observer) { | 368 void DisplayController::AddObserver(Observer* observer) { | 
| 337   observers_.AddObserver(observer); | 369   observers_.AddObserver(observer); | 
| 338 } | 370 } | 
| 339 | 371 | 
| 340 void DisplayController::RemoveObserver(Observer* observer) { | 372 void DisplayController::RemoveObserver(Observer* observer) { | 
| 341   observers_.RemoveObserver(observer); | 373   observers_.RemoveObserver(observer); | 
| 342 } | 374 } | 
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 601 gfx::Display* DisplayController::GetSecondaryDisplay() { | 633 gfx::Display* DisplayController::GetSecondaryDisplay() { | 
| 602   internal::DisplayManager* display_manager = GetDisplayManager(); | 634   internal::DisplayManager* display_manager = GetDisplayManager(); | 
| 603   CHECK_EQ(2U, display_manager->GetNumDisplays()); | 635   CHECK_EQ(2U, display_manager->GetNumDisplays()); | 
| 604   return display_manager->GetDisplayAt(0)->id() == primary_display_id ? | 636   return display_manager->GetDisplayAt(0)->id() == primary_display_id ? | 
| 605       display_manager->GetDisplayAt(1) : display_manager->GetDisplayAt(0); | 637       display_manager->GetDisplayAt(1) : display_manager->GetDisplayAt(0); | 
| 606 } | 638 } | 
| 607 | 639 | 
| 608 void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) { | 640 void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) { | 
| 609   if (limiter_.get()) | 641   if (limiter_.get()) | 
| 610     limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs); | 642     limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs); | 
| 611   DCHECK(!GetDisplayManager()->GetDisplayInfo(display). | 643   const internal::DisplayInfo& display_info = | 
| 612          bounds_in_pixel().IsEmpty()); | 644       GetDisplayManager()->GetDisplayInfo(display); | 
|  | 645   DCHECK(!display_info.bounds_in_pixel().IsEmpty()); | 
| 613 | 646 | 
| 614   NotifyDisplayConfigurationChanging(); | 647   NotifyDisplayConfigurationChanging(); | 
| 615   UpdateDisplayBoundsForLayout(); | 648   UpdateDisplayBoundsForLayout(); | 
| 616   aura::RootWindow* root = root_windows_[display.id()]; | 649   aura::RootWindow* root = root_windows_[display.id()]; | 
|  | 650   root->SetHostBoundsAndInsets(display_info.bounds_in_pixel(), | 
|  | 651                                display_info.GetOverscanInsetsInPixel()); | 
| 617   SetDisplayPropertiesOnHostWindow(root, display); | 652   SetDisplayPropertiesOnHostWindow(root, display); | 
| 618   root->SetHostBounds( |  | 
| 619       GetDisplayManager()->GetDisplayInfo(display).bounds_in_pixel()); |  | 
| 620 } | 653 } | 
| 621 | 654 | 
| 622 void DisplayController::OnDisplayAdded(const gfx::Display& display) { | 655 void DisplayController::OnDisplayAdded(const gfx::Display& display) { | 
| 623   if (limiter_.get()) | 656   if (limiter_.get()) | 
| 624     limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs); | 657     limiter_->SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs); | 
| 625 | 658 | 
| 626   NotifyDisplayConfigurationChanging(); | 659   NotifyDisplayConfigurationChanging(); | 
| 627   if (primary_root_window_for_replace_) { | 660   if (primary_root_window_for_replace_) { | 
| 628     DCHECK(root_windows_.empty()); | 661     DCHECK(root_windows_.empty()); | 
| 629     primary_display_id = display.id(); | 662     primary_display_id = display.id(); | 
| 630     root_windows_[display.id()] = primary_root_window_for_replace_; | 663     root_windows_[display.id()] = primary_root_window_for_replace_; | 
| 631     primary_root_window_for_replace_->SetProperty( | 664     primary_root_window_for_replace_->SetProperty( | 
| 632         internal::kDisplayIdKey, display.id()); | 665         internal::kDisplayIdKey, display.id()); | 
| 633     primary_root_window_for_replace_ = NULL; | 666     primary_root_window_for_replace_ = NULL; | 
| 634     UpdateDisplayBoundsForLayout(); | 667     UpdateDisplayBoundsForLayout(); | 
| 635     root_windows_[display.id()]->SetHostBounds( | 668     const internal::DisplayInfo& display_info = | 
| 636         GetDisplayManager()->GetDisplayInfo(display).bounds_in_pixel()); | 669         GetDisplayManager()->GetDisplayInfo(display); | 
|  | 670     root_windows_[display.id()]->SetHostBoundsAndInsets( | 
|  | 671         display_info.bounds_in_pixel(), | 
|  | 672         display_info.GetOverscanInsetsInPixel()); | 
| 637   } else { | 673   } else { | 
| 638     DCHECK(!root_windows_.empty()); | 674     DCHECK(!root_windows_.empty()); | 
| 639     aura::RootWindow* root = AddRootWindowForDisplay(display); | 675     aura::RootWindow* root = AddRootWindowForDisplay(display); | 
| 640     UpdateDisplayBoundsForLayout(); | 676     UpdateDisplayBoundsForLayout(); | 
| 641     if (desired_primary_display_id_ == display.id()) | 677     if (desired_primary_display_id_ == display.id()) | 
| 642       SetPrimaryDisplay(display); | 678       SetPrimaryDisplay(display); | 
| 643     Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root); | 679     Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root); | 
| 644   } | 680   } | 
| 645 } | 681 } | 
| 646 | 682 | 
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 766     const DisplayLayout& layout, | 802     const DisplayLayout& layout, | 
| 767     bool override) { | 803     bool override) { | 
| 768   DisplayIdPair pair; | 804   DisplayIdPair pair; | 
| 769   pair.first = id1; | 805   pair.first = id1; | 
| 770   pair.second = id2; | 806   pair.second = id2; | 
| 771   if (override || paired_layouts_.find(pair) == paired_layouts_.end()) | 807   if (override || paired_layouts_.find(pair) == paired_layouts_.end()) | 
| 772     paired_layouts_[pair] = layout; | 808     paired_layouts_[pair] = layout; | 
| 773 } | 809 } | 
| 774 | 810 | 
| 775 }  // namespace ash | 811 }  // namespace ash | 
| OLD | NEW | 
|---|