| 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 "chromeos/display/output_configurator.h" | 5 #include "chromeos/display/output_configurator.h" |
| 6 | 6 |
| 7 #include <X11/Xlib.h> | 7 #include <X11/Xlib.h> |
| 8 #include <X11/extensions/dpms.h> | 8 #include <X11/extensions/dpms.h> |
| 9 #include <X11/extensions/Xrandr.h> | 9 #include <X11/extensions/Xrandr.h> |
| 10 | 10 |
| 11 // Xlib defines Status as int which causes our include of dbus/bus.h to fail | 11 // Xlib defines Status as int which causes our include of dbus/bus.h to fail |
| 12 // when it tries to name an enum Status. Thus, we need to undefine it (note | 12 // when it tries to name an enum Status. Thus, we need to undefine it (note |
| 13 // that this will cause a problem if code needs to use the Status type). | 13 // that this will cause a problem if code needs to use the Status type). |
| 14 // RootWindow causes similar problems in that there is a Chromium type with that | 14 // RootWindow causes similar problems in that there is a Chromium type with that |
| 15 // name. | 15 // name. |
| 16 #undef Status | 16 #undef Status |
| 17 #undef RootWindow | 17 #undef RootWindow |
| 18 | 18 |
| 19 #include "base/bind.h" |
| 19 #include "base/chromeos/chromeos_version.h" | 20 #include "base/chromeos/chromeos_version.h" |
| 20 #include "base/logging.h" | 21 #include "base/logging.h" |
| 21 #include "base/message_pump_aurax11.h" | 22 #include "base/message_pump_aurax11.h" |
| 22 #include "base/metrics/histogram.h" | 23 #include "base/metrics/histogram.h" |
| 23 #include "base/perftimer.h" | 24 #include "base/perftimer.h" |
| 24 #include "chromeos/dbus/dbus_thread_manager.h" | 25 #include "chromeos/dbus/dbus_thread_manager.h" |
| 25 #include "dbus/bus.h" | 26 #include "dbus/bus.h" |
| 26 #include "dbus/exported_object.h" | 27 #include "dbus/exported_object.h" |
| 27 #include "dbus/message.h" | 28 #include "dbus/message.h" |
| 28 #include "dbus/object_path.h" | 29 #include "dbus/object_path.h" |
| (...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 } | 750 } |
| 750 return success; | 751 return success; |
| 751 } | 752 } |
| 752 | 753 |
| 753 bool OutputConfigurator::SetDisplayMode(State new_state) { | 754 bool OutputConfigurator::SetDisplayMode(State new_state) { |
| 754 if (output_state_ == STATE_INVALID || | 755 if (output_state_ == STATE_INVALID || |
| 755 output_state_ == STATE_HEADLESS || | 756 output_state_ == STATE_HEADLESS || |
| 756 output_state_ == STATE_SINGLE) | 757 output_state_ == STATE_SINGLE) |
| 757 return false; | 758 return false; |
| 758 | 759 |
| 759 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); | 760 if (animation_delegate_.get()) { |
| 760 CHECK(display != NULL); | 761 animation_delegate_->WillDisplayModeChange( |
| 761 XGrabServer(display); | 762 base::Bind(&OutputConfigurator::SetDisplayModeInternal, |
| 762 Window window = DefaultRootWindow(display); | 763 base::Unretained(this), new_state)); |
| 763 XRRScreenResources* screen = XRRGetScreenResources(display, window); | 764 } else { |
| 764 CHECK(screen != NULL); | 765 SetDisplayModeInternal(new_state); |
| 765 | 766 } |
| 766 UpdateCacheAndXrandrToState(display, | |
| 767 screen, | |
| 768 window, | |
| 769 new_state); | |
| 770 XRRFreeScreenResources(screen); | |
| 771 XUngrabServer(display); | |
| 772 return true; | 767 return true; |
| 773 } | 768 } |
| 774 | 769 |
| 775 bool OutputConfigurator::Dispatch(const base::NativeEvent& event) { | 770 bool OutputConfigurator::Dispatch(const base::NativeEvent& event) { |
| 776 // Ignore this event if the Xrandr extension isn't supported. | 771 // Ignore this event if the Xrandr extension isn't supported. |
| 777 if (is_running_on_chrome_os_ && | 772 if (is_running_on_chrome_os_ && |
| 778 (event->type - xrandr_event_base_ == RRNotify)) { | 773 (event->type - xrandr_event_base_ == RRNotify)) { |
| 779 XEvent* xevent = static_cast<XEvent*>(event); | 774 XEvent* xevent = static_cast<XEvent*>(event); |
| 780 XRRNotifyEvent* notify_event = | 775 XRRNotifyEvent* notify_event = |
| 781 reinterpret_cast<XRRNotifyEvent*>(xevent); | 776 reinterpret_cast<XRRNotifyEvent*>(xevent); |
| 782 if (notify_event->subtype == RRNotify_OutputChange) { | 777 if (notify_event->subtype == RRNotify_OutputChange) { |
| 783 XRROutputChangeNotifyEvent* output_change_event = | 778 XRROutputChangeNotifyEvent* output_change_event = |
| 784 reinterpret_cast<XRROutputChangeNotifyEvent*>(xevent); | 779 reinterpret_cast<XRROutputChangeNotifyEvent*>(xevent); |
| 785 if ((output_change_event->connection == RR_Connected) || | 780 if ((output_change_event->connection == RR_Connected) || |
| 786 (output_change_event->connection == RR_Disconnected)) { | 781 (output_change_event->connection == RR_Disconnected)) { |
| 787 RecacheAndUseDefaultState(); | 782 RecacheAndUseDefaultState(); |
| 788 CheckIsProjectingAndNotify(); | 783 CheckIsProjectingAndNotify(); |
| 789 } | 784 } |
| 790 // Ignore the case of RR_UnkownConnection. | 785 // Ignore the case of RR_UnkownConnection. |
| 791 } | 786 } |
| 792 } | 787 } |
| 793 return true; | 788 return true; |
| 794 } | 789 } |
| 795 | 790 |
| 791 void OutputConfigurator::SetDisplayModeInternal(State new_state) { |
| 792 // We should have this guard both in SetDisplayMode and SetDisplayModeInternal |
| 793 // because |output_state_| may change during the animation. |
| 794 if (output_state_ == STATE_INVALID || |
| 795 output_state_ == STATE_HEADLESS || |
| 796 output_state_ == STATE_SINGLE) { |
| 797 if (animation_delegate_.get()) { |
| 798 MessageLoop::current()->PostTask( |
| 799 FROM_HERE, base::Bind(&AnimationDelegate::OnDisplayModeChanged, |
| 800 base::Unretained(animation_delegate_.get()))); |
| 801 } |
| 802 return; |
| 803 } |
| 804 |
| 805 Display* display = base::MessagePumpAuraX11::GetDefaultXDisplay(); |
| 806 CHECK(display != NULL); |
| 807 XGrabServer(display); |
| 808 Window window = DefaultRootWindow(display); |
| 809 XRRScreenResources* screen = XRRGetScreenResources(display, window); |
| 810 CHECK(screen != NULL); |
| 811 |
| 812 UpdateCacheAndXrandrToState(display, |
| 813 screen, |
| 814 window, |
| 815 new_state); |
| 816 XRRFreeScreenResources(screen); |
| 817 XUngrabServer(display); |
| 818 if (animation_delegate_.get()) { |
| 819 MessageLoop::current()->PostTask( |
| 820 FROM_HERE, base::Bind(&AnimationDelegate::OnDisplayModeChanged, |
| 821 base::Unretained(animation_delegate_.get()))); |
| 822 } |
| 823 } |
| 824 |
| 796 void OutputConfigurator::CheckIsProjectingAndNotify() { | 825 void OutputConfigurator::CheckIsProjectingAndNotify() { |
| 797 // Determine if there is an "internal" output and how many outputs are | 826 // Determine if there is an "internal" output and how many outputs are |
| 798 // connected. | 827 // connected. |
| 799 bool has_internal_output = false; | 828 bool has_internal_output = false; |
| 800 int connected_output_count = 0; | 829 int connected_output_count = 0; |
| 801 for (int i = 0; i < output_count_; ++i) { | 830 for (int i = 0; i < output_count_; ++i) { |
| 802 if (output_cache_[i].is_connected) { | 831 if (output_cache_[i].is_connected) { |
| 803 connected_output_count += 1; | 832 connected_output_count += 1; |
| 804 has_internal_output |= output_cache_[i].is_internal; | 833 has_internal_output |= output_cache_[i].is_internal; |
| 805 } | 834 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 818 power_manager::kSetIsProjectingMethod); | 847 power_manager::kSetIsProjectingMethod); |
| 819 dbus::MessageWriter writer(&method_call); | 848 dbus::MessageWriter writer(&method_call); |
| 820 writer.AppendBool(is_projecting); | 849 writer.AppendBool(is_projecting); |
| 821 power_manager_proxy->CallMethod( | 850 power_manager_proxy->CallMethod( |
| 822 &method_call, | 851 &method_call, |
| 823 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | 852 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| 824 dbus::ObjectProxy::EmptyResponseCallback()); | 853 dbus::ObjectProxy::EmptyResponseCallback()); |
| 825 } | 854 } |
| 826 | 855 |
| 827 } // namespace chromeos | 856 } // namespace chromeos |
| OLD | NEW |