Chromium Code Reviews| 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 // 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 <sys/ipc.h> | 11 #include <sys/ipc.h> |
| 12 #include <sys/shm.h> | 12 #include <sys/shm.h> |
| 13 | 13 |
| 14 #include <list> | 14 #include <list> |
| 15 #include <map> | 15 #include <map> |
| 16 #include <vector> | 16 #include <vector> |
| 17 | 17 |
| 18 #include <X11/extensions/Xrandr.h> | |
| 19 #include <X11/extensions/randr.h> | |
| 20 | |
| 18 #include "base/bind.h" | 21 #include "base/bind.h" |
| 19 #include "base/command_line.h" | 22 #include "base/command_line.h" |
| 20 #include "base/logging.h" | 23 #include "base/logging.h" |
| 21 #include "base/memory/scoped_ptr.h" | 24 #include "base/memory/scoped_ptr.h" |
| 22 #include "base/memory/singleton.h" | 25 #include "base/memory/singleton.h" |
| 23 #include "base/message_loop.h" | 26 #include "base/message_loop.h" |
| 24 #include "base/string_number_conversions.h" | 27 #include "base/string_number_conversions.h" |
| 25 #include "base/string_util.h" | 28 #include "base/string_util.h" |
| 26 #include "base/stringprintf.h" | 29 #include "base/stringprintf.h" |
| 30 #include "base/sys_byteorder.h" | |
| 27 #include "base/threading/thread.h" | 31 #include "base/threading/thread.h" |
| 28 #include "ui/base/keycodes/keyboard_code_conversion_x.h" | 32 #include "ui/base/keycodes/keyboard_code_conversion_x.h" |
| 29 #include "ui/base/x/x11_util_internal.h" | 33 #include "ui/base/x/x11_util_internal.h" |
| 30 #include "ui/gfx/rect.h" | 34 #include "ui/gfx/rect.h" |
| 31 #include "ui/gfx/size.h" | 35 #include "ui/gfx/size.h" |
| 32 | 36 |
| 33 #if defined(OS_FREEBSD) | 37 #if defined(OS_FREEBSD) |
| 34 #include <sys/sysctl.h> | 38 #include <sys/sysctl.h> |
| 35 #include <sys/types.h> | 39 #include <sys/types.h> |
| 36 #endif | 40 #endif |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 295 } | 299 } |
| 296 | 300 |
| 297 ~XButtonMap() {} | 301 ~XButtonMap() {} |
| 298 | 302 |
| 299 unsigned char map_[256]; | 303 unsigned char map_[256]; |
| 300 int count_; | 304 int count_; |
| 301 | 305 |
| 302 DISALLOW_COPY_AND_ASSIGN(XButtonMap); | 306 DISALLOW_COPY_AND_ASSIGN(XButtonMap); |
| 303 }; | 307 }; |
| 304 | 308 |
| 309 bool IsRandRAvailable(Display* display) { | |
| 310 int randr_version_major = 0; | |
| 311 int randr_version_minor = 0; | |
| 312 return XRRQueryVersion( | |
| 313 display, &randr_version_major, &randr_version_minor) == Success; | |
| 314 } | |
| 315 | |
| 305 } // namespace | 316 } // namespace |
| 306 | 317 |
| 307 bool XDisplayExists() { | 318 bool XDisplayExists() { |
| 308 return (GetXDisplay() != NULL); | 319 return (GetXDisplay() != NULL); |
| 309 } | 320 } |
| 310 | 321 |
| 311 Display* GetXDisplay() { | 322 Display* GetXDisplay() { |
| 312 return base::MessagePumpForUI::GetDefaultXDisplay(); | 323 return base::MessagePumpForUI::GetDefaultXDisplay(); |
| 313 } | 324 } |
| 314 | 325 |
| (...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 980 } | 991 } |
| 981 | 992 |
| 982 void FreePicture(Display* display, XID picture) { | 993 void FreePicture(Display* display, XID picture) { |
| 983 XRenderFreePicture(display, picture); | 994 XRenderFreePicture(display, picture); |
| 984 } | 995 } |
| 985 | 996 |
| 986 void FreePixmap(Display* display, XID pixmap) { | 997 void FreePixmap(Display* display, XID pixmap) { |
| 987 XFreePixmap(display, pixmap); | 998 XFreePixmap(display, pixmap); |
| 988 } | 999 } |
| 989 | 1000 |
| 1001 bool GetOutputDeviceHandles(std::vector<XID>* outputs) { | |
| 1002 DCHECK(outputs); | |
| 1003 outputs->clear(); | |
| 1004 | |
| 1005 Display* display = GetXDisplay(); | |
| 1006 if (!display) | |
| 1007 return false; | |
| 1008 | |
| 1009 if (!IsRandRAvailable(display)) | |
| 1010 return false; | |
| 1011 | |
| 1012 Window root_window = DefaultRootWindow(display); | |
| 1013 XRRScreenResources* screen_resources = | |
| 1014 XRRGetScreenResources(display, root_window); | |
| 1015 for (int i = 0; i < screen_resources->noutput; ++i) | |
| 1016 outputs->push_back(screen_resources->outputs[i]); | |
| 1017 XRRFreeScreenResources(screen_resources); | |
| 1018 return true; | |
| 1019 } | |
| 1020 | |
| 1021 bool GetOutputDeviceData(XID output, | |
| 1022 uint16* manufacturer_id, | |
| 1023 uint32* serial_number, | |
| 1024 std::string* human_readable_name) { | |
| 1025 DCHECK(manufacturer_id); | |
| 1026 DCHECK(serial_number); | |
| 1027 DCHECK(human_readable_name); | |
| 1028 | |
| 1029 Display* display = GetXDisplay(); | |
| 1030 if (!display) | |
| 1031 return false; | |
| 1032 | |
| 1033 if (!IsRandRAvailable(display)) | |
| 1034 return false; | |
| 1035 | |
| 1036 Atom edid_property = GetAtom(RR_PROPERTY_RANDR_EDID); | |
| 1037 bool has_edid_property = false; | |
| 1038 int num_properties = 0; | |
| 1039 Atom* properties = XRRListOutputProperties(display, output, &num_properties); | |
| 1040 for (int i = 0; i < num_properties; ++i) { | |
| 1041 if (properties[i] == edid_property) { | |
| 1042 has_edid_property = true; | |
| 1043 break; | |
| 1044 } | |
| 1045 } | |
| 1046 XFree(properties); | |
| 1047 if (!has_edid_property) | |
| 1048 return false; | |
| 1049 | |
| 1050 Atom actual_type; | |
| 1051 int actual_format; | |
| 1052 unsigned long nitems; | |
| 1053 unsigned long bytes_after; | |
| 1054 unsigned char *prop; | |
| 1055 XRRGetOutputProperty(display, output, edid_property, 0, 128, false, false, | |
| 1056 AnyPropertyType, &actual_type, &actual_format, &nitems, | |
| 1057 &bytes_after, &prop); | |
| 1058 DCHECK(actual_type == XA_INTEGER); | |
| 1059 DCHECK(actual_format == 8); | |
| 1060 | |
| 1061 // See http://en.wikipedia.org/wiki/Extended_display_identification_data | |
| 1062 // for the details of EDID data format. We use the following data: | |
| 1063 // bytes 8-9: manufacturer EISA ID, in big-endian | |
| 1064 // bytes 12-15: represents serial number, in little-endian | |
| 1065 // bytes 54-125: four descriptors (18-bytes each) which may contain | |
| 1066 // the display name. | |
| 1067 const int kManufacturerOffset = 8; | |
| 1068 const int kSerialNumberOffset = 12; | |
| 1069 const int kDescriptorOffset = 54; | |
| 1070 const int kNumDescriptors = 4; | |
| 1071 const int kDescriptorLength = 18; | |
| 1072 | |
| 1073 *manufacturer_id = *reinterpret_cast<uint16*>(prop + kManufacturerOffset); | |
| 1074 #if defined(ARCH_CPU_LITTLE_ENDIAN) | |
| 1075 *manufacturer_id = base::ByteSwap(*manufacturer_id); | |
| 1076 #endif | |
| 1077 *serial_number = base::ByteSwapToLE32( | |
| 1078 *reinterpret_cast<uint32*>(prop + kSerialNumberOffset)); | |
| 1079 | |
| 1080 std::string name_candidate; | |
| 1081 human_readable_name->clear(); | |
| 1082 for (int i = 0; i < kNumDescriptors; ++i) { | |
| 1083 unsigned char* desc_buf = prop + kDescriptorOffset + i * kDescriptorLength; | |
| 1084 // If the descriptor contains the display name, it has the following | |
| 1085 // structure: | |
| 1086 // bytes 0-2, 4: \0 | |
| 1087 // byte 3: \xfc for "Monitor name", \xfe for "Unspecified text" | |
| 1088 // bytes 5-17: text data, ending with \r, padding with spaces | |
| 1089 // we should check bytes 0-2 and 4, since it may have other values in | |
| 1090 // case that the descriptor contains other type of data. | |
| 1091 if (desc_buf[0] == 0 && desc_buf[1] == 0 && desc_buf[2] == 0 && | |
| 1092 desc_buf[4] == 0) { | |
| 1093 if (desc_buf[3] == 0xfc) { | |
|
marcheu
2012/08/14 21:29:53
maybe replace 0xfc with kMonitorNameDescriptor or
Jun Mukai
2012/08/15 05:14:09
Done.
| |
| 1094 std::string found_name( | |
| 1095 reinterpret_cast<char*>(desc_buf + 5), kDescriptorLength - 5); | |
| 1096 TrimWhitespaceASCII(found_name, TRIM_TRAILING, human_readable_name); | |
| 1097 break; | |
| 1098 } else if (desc_buf[3] == 0xfe && name_candidate.empty()) { | |
|
marcheu
2012/08/14 21:29:53
Here maybe replace 0xfe with kUnspecifiedTextDescr
Jun Mukai
2012/08/15 05:14:09
Done.
| |
| 1099 // Sometimes the default display of a laptop device doesn't have "FC" | |
| 1100 // ("Monitor name") descriptor, but has some human readable text with | |
| 1101 // "FE" ("Unspecified text"). Thus here uses this value as the fallback | |
| 1102 // of the lack of "FC". Note that multiple descriptors may have "FE", | |
| 1103 // and the first one is the monitor name. | |
| 1104 std::string found_name( | |
| 1105 reinterpret_cast<char*>(desc_buf + 5), kDescriptorLength - 5); | |
| 1106 TrimWhitespaceASCII(found_name, TRIM_TRAILING, &name_candidate); | |
| 1107 } | |
| 1108 } | |
| 1109 } | |
|
marcheu
2012/08/14 21:29:53
At this point I'd probably sanity check the string
Jun Mukai
2012/08/15 05:14:09
Done. Using isprint() too.
| |
| 1110 if (human_readable_name->empty() && !name_candidate.empty()) | |
| 1111 *human_readable_name = name_candidate; | |
| 1112 | |
| 1113 XFree(prop); | |
| 1114 return true; | |
| 1115 } | |
| 1116 | |
| 1117 | |
| 990 bool GetWindowManagerName(std::string* wm_name) { | 1118 bool GetWindowManagerName(std::string* wm_name) { |
| 991 DCHECK(wm_name); | 1119 DCHECK(wm_name); |
| 992 int wm_window = 0; | 1120 int wm_window = 0; |
| 993 if (!GetIntProperty(GetX11RootWindow(), | 1121 if (!GetIntProperty(GetX11RootWindow(), |
| 994 "_NET_SUPPORTING_WM_CHECK", | 1122 "_NET_SUPPORTING_WM_CHECK", |
| 995 &wm_window)) { | 1123 &wm_window)) { |
| 996 return false; | 1124 return false; |
| 997 } | 1125 } |
| 998 | 1126 |
| 999 // It's possible that a window manager started earlier in this X session left | 1127 // 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 Loading... | |
| 1278 << "request_code " << static_cast<int>(error_event.request_code) << ", " | 1406 << "request_code " << static_cast<int>(error_event.request_code) << ", " |
| 1279 << "minor_code " << static_cast<int>(error_event.minor_code) | 1407 << "minor_code " << static_cast<int>(error_event.minor_code) |
| 1280 << " (" << request_str << ")"; | 1408 << " (" << request_str << ")"; |
| 1281 } | 1409 } |
| 1282 | 1410 |
| 1283 // ---------------------------------------------------------------------------- | 1411 // ---------------------------------------------------------------------------- |
| 1284 // End of x11_util_internal.h | 1412 // End of x11_util_internal.h |
| 1285 | 1413 |
| 1286 | 1414 |
| 1287 } // namespace ui | 1415 } // namespace ui |
| OLD | NEW |