Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: ui/base/x/x11_util.cc

Issue 10826198: Use persistent ID/names for displays. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: kInvalidID -> kInvalidDisplayID since Mac #define "kInvalidID"... Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/base/x/x11_util.h ('k') | ui/gfx/display.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 // This file defines utility functions for X11 (Linux only). This code has been 5 // This file defines utility functions for X11 (Linux only). This code has been
6 // ported from XCB since we can't use XCB on Ubuntu while its 32-bit support 6 // ported from XCB since we can't use XCB on Ubuntu while its 32-bit support
7 // remains woefully incomplete. 7 // remains woefully incomplete.
8 8
9 #include "ui/base/x/x11_util.h" 9 #include "ui/base/x/x11_util.h"
10 10
11 #include <ctype.h>
11 #include <sys/ipc.h> 12 #include <sys/ipc.h>
12 #include <sys/shm.h> 13 #include <sys/shm.h>
13 14
14 #include <list> 15 #include <list>
15 #include <map> 16 #include <map>
16 #include <vector> 17 #include <vector>
17 18
19 #include <X11/extensions/Xrandr.h>
20 #include <X11/extensions/randr.h>
21
18 #include "base/bind.h" 22 #include "base/bind.h"
19 #include "base/command_line.h" 23 #include "base/command_line.h"
20 #include "base/logging.h" 24 #include "base/logging.h"
21 #include "base/memory/scoped_ptr.h" 25 #include "base/memory/scoped_ptr.h"
22 #include "base/memory/singleton.h" 26 #include "base/memory/singleton.h"
23 #include "base/message_loop.h" 27 #include "base/message_loop.h"
24 #include "base/string_number_conversions.h" 28 #include "base/string_number_conversions.h"
25 #include "base/string_util.h" 29 #include "base/string_util.h"
26 #include "base/stringprintf.h" 30 #include "base/stringprintf.h"
31 #include "base/sys_byteorder.h"
27 #include "base/threading/thread.h" 32 #include "base/threading/thread.h"
28 #include "ui/base/keycodes/keyboard_code_conversion_x.h" 33 #include "ui/base/keycodes/keyboard_code_conversion_x.h"
29 #include "ui/base/x/x11_util_internal.h" 34 #include "ui/base/x/x11_util_internal.h"
30 #include "ui/gfx/rect.h" 35 #include "ui/gfx/rect.h"
31 #include "ui/gfx/size.h" 36 #include "ui/gfx/size.h"
32 37
33 #if defined(OS_FREEBSD) 38 #if defined(OS_FREEBSD)
34 #include <sys/sysctl.h> 39 #include <sys/sysctl.h>
35 #include <sys/types.h> 40 #include <sys/types.h>
36 #endif 41 #endif
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 } 300 }
296 301
297 ~XButtonMap() {} 302 ~XButtonMap() {}
298 303
299 unsigned char map_[256]; 304 unsigned char map_[256];
300 int count_; 305 int count_;
301 306
302 DISALLOW_COPY_AND_ASSIGN(XButtonMap); 307 DISALLOW_COPY_AND_ASSIGN(XButtonMap);
303 }; 308 };
304 309
310 bool IsRandRAvailable() {
311 static bool is_randr_available = false;
312 static bool is_randr_availability_cached = false;
313 if (is_randr_availability_cached)
314 return is_randr_available;
315
316 int randr_version_major = 0;
317 int randr_version_minor = 0;
318 is_randr_available = XRRQueryVersion(
319 GetXDisplay(), &randr_version_major, &randr_version_minor);
320 is_randr_availability_cached = true;
321 return is_randr_available;
322 }
323
305 } // namespace 324 } // namespace
306 325
307 bool XDisplayExists() { 326 bool XDisplayExists() {
308 return (GetXDisplay() != NULL); 327 return (GetXDisplay() != NULL);
309 } 328 }
310 329
311 Display* GetXDisplay() { 330 Display* GetXDisplay() {
312 return base::MessagePumpForUI::GetDefaultXDisplay(); 331 return base::MessagePumpForUI::GetDefaultXDisplay();
313 } 332 }
314 333
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after
980 } 999 }
981 1000
982 void FreePicture(Display* display, XID picture) { 1001 void FreePicture(Display* display, XID picture) {
983 XRenderFreePicture(display, picture); 1002 XRenderFreePicture(display, picture);
984 } 1003 }
985 1004
986 void FreePixmap(Display* display, XID pixmap) { 1005 void FreePixmap(Display* display, XID pixmap) {
987 XFreePixmap(display, pixmap); 1006 XFreePixmap(display, pixmap);
988 } 1007 }
989 1008
1009 bool GetOutputDeviceHandles(std::vector<XID>* outputs) {
1010 DCHECK(outputs);
1011 outputs->clear();
1012
1013 if (!IsRandRAvailable())
1014 return false;
1015
1016 Display* display = GetXDisplay();
1017
1018 Window root_window = DefaultRootWindow(display);
1019 XRRScreenResources* screen_resources =
1020 XRRGetScreenResources(display, root_window);
1021 for (int i = 0; i < screen_resources->noutput; ++i)
1022 outputs->push_back(screen_resources->outputs[i]);
1023 XRRFreeScreenResources(screen_resources);
1024 return true;
1025 }
1026
1027 bool GetOutputDeviceData(XID output,
1028 uint16* manufacturer_id,
1029 uint32* serial_number,
1030 std::string* human_readable_name) {
1031 if (!IsRandRAvailable())
1032 return false;
1033
1034 static Atom edid_property = GetAtom(RR_PROPERTY_RANDR_EDID);
1035
1036 Display* display = GetXDisplay();
1037
1038 bool has_edid_property = false;
1039 int num_properties = 0;
1040 Atom* properties = XRRListOutputProperties(display, output, &num_properties);
1041 for (int i = 0; i < num_properties; ++i) {
1042 if (properties[i] == edid_property) {
1043 has_edid_property = true;
1044 break;
1045 }
1046 }
1047 XFree(properties);
1048 if (!has_edid_property)
1049 return false;
1050
1051 Atom actual_type;
1052 int actual_format;
1053 unsigned long nitems;
1054 unsigned long bytes_after;
1055 unsigned char *prop;
1056 XRRGetOutputProperty(display,
1057 output,
1058 edid_property,
1059 0, // offset
1060 128, // length
1061 false, // _delete
1062 false, // pending
1063 AnyPropertyType, // req_type
1064 &actual_type,
1065 &actual_format,
1066 &nitems,
1067 &bytes_after,
1068 &prop);
1069 DCHECK_EQ(XA_INTEGER, actual_type);
1070 DCHECK_EQ(8, actual_format);
1071
1072 // See http://en.wikipedia.org/wiki/Extended_display_identification_data
1073 // for the details of EDID data format. We use the following data:
1074 // bytes 8-9: manufacturer EISA ID, in big-endian
1075 // bytes 12-15: represents serial number, in little-endian
1076 // bytes 54-125: four descriptors (18-bytes each) which may contain
1077 // the display name.
1078 const unsigned int kManufacturerOffset = 8;
1079 const unsigned int kManufacturerLength = 2;
1080 const unsigned int kSerialNumberOffset = 12;
1081 const unsigned int kSerialNumberLength = 4;
1082 const unsigned int kDescriptorOffset = 54;
1083 const unsigned int kNumDescriptors = 4;
1084 const unsigned int kDescriptorLength = 18;
1085 // The specifier types.
1086 const unsigned char kMonitorNameDescriptor = 0xfc;
1087 const unsigned char kUnspecifiedTextDescriptor = 0xfe;
1088
1089 if (manufacturer_id) {
1090 if (nitems < kManufacturerOffset + kManufacturerLength) {
1091 XFree(prop);
1092 return false;
1093 }
1094 *manufacturer_id = *reinterpret_cast<uint16*>(prop + kManufacturerOffset);
1095 #if defined(ARCH_CPU_LITTLE_ENDIAN)
1096 *manufacturer_id = base::ByteSwap(*manufacturer_id);
1097 #endif
1098 }
1099
1100 if (serial_number) {
1101 if (nitems < kSerialNumberOffset + kSerialNumberLength) {
1102 XFree(prop);
1103 return false;
1104 }
1105 *serial_number = base::ByteSwapToLE32(
1106 *reinterpret_cast<uint32*>(prop + kSerialNumberOffset));
1107 }
1108
1109 if (!human_readable_name) {
1110 XFree(prop);
1111 return true;
1112 }
1113
1114 std::string name_candidate;
1115 human_readable_name->clear();
1116 for (unsigned int i = 0; i < kNumDescriptors; ++i) {
1117 if (nitems < kDescriptorOffset + (i + 1) * kDescriptorLength) {
1118 break;
1119 }
1120
1121 unsigned char* desc_buf = prop + kDescriptorOffset + i * kDescriptorLength;
1122 // If the descriptor contains the display name, it has the following
1123 // structure:
1124 // bytes 0-2, 4: \0
1125 // byte 3: descriptor type, defined above.
1126 // bytes 5-17: text data, ending with \r, padding with spaces
1127 // we should check bytes 0-2 and 4, since it may have other values in
1128 // case that the descriptor contains other type of data.
1129 if (desc_buf[0] == 0 && desc_buf[1] == 0 && desc_buf[2] == 0 &&
1130 desc_buf[4] == 0) {
1131 if (desc_buf[3] == kMonitorNameDescriptor) {
1132 std::string found_name(
1133 reinterpret_cast<char*>(desc_buf + 5), kDescriptorLength - 5);
1134 TrimWhitespaceASCII(found_name, TRIM_TRAILING, human_readable_name);
1135 break;
1136 } else if (desc_buf[3] == kUnspecifiedTextDescriptor &&
1137 name_candidate.empty()) {
1138 // Sometimes the default display of a laptop device doesn't have "FC"
1139 // ("Monitor name") descriptor, but has some human readable text with
1140 // "FE" ("Unspecified text"). Thus here use this value as the fallback
1141 // if "FC" is missing. Note that multiple descriptors may have "FE",
1142 // and the first one is the monitor name.
1143 std::string found_name(
1144 reinterpret_cast<char*>(desc_buf + 5), kDescriptorLength - 5);
1145 TrimWhitespaceASCII(found_name, TRIM_TRAILING, &name_candidate);
1146 }
1147 }
1148 }
1149 if (human_readable_name->empty() && !name_candidate.empty())
1150 *human_readable_name = name_candidate;
1151
1152 XFree(prop);
1153
1154 if (human_readable_name->empty())
1155 return false;
1156
1157 // Verify if the |human_readable_name| consists of printable characters only.
1158 for (size_t i = 0; i < human_readable_name->size(); ++i) {
1159 char c = (*human_readable_name)[i];
1160 if (!isascii(c) || !isprint(c)) {
1161 human_readable_name->clear();
1162 return false;
1163 }
1164 }
1165
1166 return true;
1167 }
1168
1169
990 bool GetWindowManagerName(std::string* wm_name) { 1170 bool GetWindowManagerName(std::string* wm_name) {
991 DCHECK(wm_name); 1171 DCHECK(wm_name);
992 int wm_window = 0; 1172 int wm_window = 0;
993 if (!GetIntProperty(GetX11RootWindow(), 1173 if (!GetIntProperty(GetX11RootWindow(),
994 "_NET_SUPPORTING_WM_CHECK", 1174 "_NET_SUPPORTING_WM_CHECK",
995 &wm_window)) { 1175 &wm_window)) {
996 return false; 1176 return false;
997 } 1177 }
998 1178
999 // It's possible that a window manager started earlier in this X session left 1179 // It's possible that a window manager started earlier in this X session left
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
1278 << "request_code " << static_cast<int>(error_event.request_code) << ", " 1458 << "request_code " << static_cast<int>(error_event.request_code) << ", "
1279 << "minor_code " << static_cast<int>(error_event.minor_code) 1459 << "minor_code " << static_cast<int>(error_event.minor_code)
1280 << " (" << request_str << ")"; 1460 << " (" << request_str << ")";
1281 } 1461 }
1282 1462
1283 // ---------------------------------------------------------------------------- 1463 // ----------------------------------------------------------------------------
1284 // End of x11_util_internal.h 1464 // End of x11_util_internal.h
1285 1465
1286 1466
1287 } // namespace ui 1467 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/x/x11_util.h ('k') | ui/gfx/display.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698