Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ui / display / chromeos / x11 / native_display_event_dispatcher_x11.cc
1 // Copyright 2014 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 "base/time/default_tick_clock.h"
6 #include "ui/display/chromeos/x11/native_display_event_dispatcher_x11.h"
7 #include "ui/display/chromeos/x11/display_mode_x11.h"
8 #include "ui/display/chromeos/x11/display_snapshot_x11.h"
9 #include "ui/events/platform/platform_event_source.h"
10
11 #include <X11/extensions/Xrandr.h>
12
13 namespace ui {
14
15 // static
16 const int NativeDisplayEventDispatcherX11::kUseCacheAfterStartupMs = 7000;
17
18 NativeDisplayEventDispatcherX11::NativeDisplayEventDispatcherX11(
19     NativeDisplayDelegateX11::HelperDelegate* delegate,
20     int xrandr_event_base)
21     : delegate_(delegate),
22       xrandr_event_base_(xrandr_event_base),
23       tick_clock_(new base::DefaultTickClock) {
24   startup_time_ = tick_clock_->NowTicks();
25 }
26
27 NativeDisplayEventDispatcherX11::~NativeDisplayEventDispatcherX11() {}
28
29 bool NativeDisplayEventDispatcherX11::CanDispatchEvent(
30     const PlatformEvent& event) {
31   return (event->type - xrandr_event_base_ == RRScreenChangeNotify) ||
32          (event->type - xrandr_event_base_ == RRNotify);
33 }
34
35 uint32_t NativeDisplayEventDispatcherX11::DispatchEvent(
36     const PlatformEvent& event) {
37   if (event->type - xrandr_event_base_ == RRScreenChangeNotify) {
38     VLOG(1) << "Received RRScreenChangeNotify event";
39     delegate_->UpdateXRandRConfiguration(event);
40     return ui::POST_DISPATCH_PERFORM_DEFAULT;
41   }
42
43   // Bail out early for everything except RRNotify_OutputChange events
44   // about an output getting connected or disconnected.
45   if (event->type - xrandr_event_base_ != RRNotify)
46     return ui::POST_DISPATCH_PERFORM_DEFAULT;
47   const XRRNotifyEvent* notify_event = reinterpret_cast<XRRNotifyEvent*>(event);
48   if (notify_event->subtype != RRNotify_OutputChange)
49     return ui::POST_DISPATCH_PERFORM_DEFAULT;
50   const XRROutputChangeNotifyEvent* output_change_event =
51       reinterpret_cast<XRROutputChangeNotifyEvent*>(event);
52   const int action = output_change_event->connection;
53   if (action != RR_Connected && action != RR_Disconnected)
54     return ui::POST_DISPATCH_PERFORM_DEFAULT;
55
56   const bool connected = (action == RR_Connected);
57   VLOG(1) << "Received RRNotify_OutputChange event:"
58           << " output=" << output_change_event->output
59           << " crtc=" << output_change_event->crtc
60           << " mode=" << output_change_event->mode
61           << " action=" << (connected ? "connected" : "disconnected");
62
63   bool check_cache = (tick_clock_->NowTicks() - startup_time_)
64                          .InMilliseconds() <= kUseCacheAfterStartupMs;
65
66   if (check_cache) {
67     bool found_changed_output = false;
68     const std::vector<DisplaySnapshot*>& cached_outputs =
69         delegate_->GetCachedDisplays();
70     for (std::vector<DisplaySnapshot*>::const_iterator it =
71              cached_outputs.begin();
72          it != cached_outputs.end();
73          ++it) {
74       const DisplaySnapshotX11* x11_output =
75           static_cast<const DisplaySnapshotX11*>(*it);
76       const DisplayModeX11* x11_mode =
77           static_cast<const DisplayModeX11*>(x11_output->current_mode());
78
79       if (x11_output->output() == output_change_event->output) {
80         if (connected && x11_output->crtc() == output_change_event->crtc &&
81             x11_mode->mode_id() == output_change_event->mode) {
82           VLOG(1) << "Ignoring event describing already-cached state";
83           return POST_DISPATCH_PERFORM_DEFAULT;
84         }
85         found_changed_output = true;
86         break;
87       }
88     }
89
90     if (!connected && !found_changed_output) {
91       VLOG(1) << "Ignoring event describing already-disconnected output";
92       return ui::POST_DISPATCH_PERFORM_DEFAULT;
93     }
94   }
95
96   delegate_->NotifyDisplayObservers();
97
98   return ui::POST_DISPATCH_PERFORM_DEFAULT;
99 }
100
101 void NativeDisplayEventDispatcherX11::SetTickClockForTest(
102     scoped_ptr<base::TickClock> tick_clock) {
103   tick_clock_ = tick_clock.Pass();
104   startup_time_ = tick_clock_->NowTicks();
105 }
106
107 }  // namespace ui