1// Copyright 2013 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/extensions/api/system_display/display_info_provider.h"
6
7#include <windows.h>
8
9#include "base/strings/utf_string_conversions.h"
10#include "ui/base/win/dpi.h"
11#include "ui/gfx/display.h"
12#include "ui/gfx/size.h"
13
14namespace extensions {
15
16using api::system_display::Bounds;
17using api::system_display::DisplayUnitInfo;
18
19namespace {
20
21BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor,
22                                  HDC hdc,
23                                  LPRECT rect,
24                                  LPARAM data) {
25  DisplayInfo* display_info =
26      reinterpret_cast<DisplayInfo*>(data);
27  DCHECK(display_info);
28
29  linked_ptr<DisplayUnitInfo> unit(new DisplayUnitInfo);
30
31  MONITORINFOEX monitor_info;
32  ZeroMemory(&monitor_info, sizeof(MONITORINFOEX));
33  monitor_info.cbSize = sizeof(monitor_info);
34  GetMonitorInfo(monitor, &monitor_info);
35
36  DISPLAY_DEVICE device;
37  device.cb = sizeof(device);
38  if (!EnumDisplayDevices(monitor_info.szDevice, 0, &device, 0))
39    return FALSE;
40
41  gfx::Display display(0, gfx::Rect(monitor_info.rcMonitor));
42  display.set_work_area(gfx::Rect(monitor_info.rcWork));
43
44  gfx::Size dpi(ui::GetDPI());
45  unit->id = WideToUTF8(device.DeviceID);
46  unit->name = WideToUTF8(device.DeviceString);
47  unit->is_primary = monitor_info.dwFlags & MONITORINFOF_PRIMARY ? true : false;
48
49  // TODO(hongbo): Figure out how to determine whether the display monitor is
50  // internal or not.
51  unit->is_internal = false;
52  unit->is_enabled = device.StateFlags & DISPLAY_DEVICE_ACTIVE ? true : false;
53  unit->dpi_x = dpi.width();
54  unit->dpi_y = dpi.height();
55  unit->bounds.left = display.bounds().x();
56  unit->bounds.top = display.bounds().y();
57  unit->bounds.width = display.bounds().width();
58  unit->bounds.height = display.bounds().height();
59  unit->work_area.left = display.work_area().x();
60  unit->work_area.top = display.work_area().y();
61  unit->work_area.width = display.work_area().width();
62  unit->work_area.height = display.work_area().height();
63  display_info->push_back(unit);
64
65  return TRUE;
66}
67
68}  // namespace
69
70void DisplayInfoProvider::RequestInfo(const RequestInfoCallback& callback) {
71  // Redirect the request to a worker pool thread.
72  StartQueryInfo(callback);
73}
74
75void DisplayInfoProvider::SetInfo(
76    const std::string& display_id,
77    const api::system_display::DisplayProperties& info,
78    const SetInfoCallback& callback) {
79  base::MessageLoopProxy::current()->PostTask(
80      FROM_HERE,
81      base::Bind(callback, false, "Not implemented"));
82}
83
84bool DisplayInfoProvider::QueryInfo() {
85  info_.clear();
86
87  if (EnumDisplayMonitors(NULL, NULL, EnumMonitorCallback,
88        reinterpret_cast<LPARAM>(&info_)))
89    return true;
90  return false;
91}
92
93}  // namespace extensions
94