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 943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
980 } | 984 } |
981 | 985 |
982 void FreePicture(Display* display, XID picture) { | 986 void FreePicture(Display* display, XID picture) { |
983 XRenderFreePicture(display, picture); | 987 XRenderFreePicture(display, picture); |
984 } | 988 } |
985 | 989 |
986 void FreePixmap(Display* display, XID pixmap) { | 990 void FreePixmap(Display* display, XID pixmap) { |
987 XFreePixmap(display, pixmap); | 991 XFreePixmap(display, pixmap); |
988 } | 992 } |
989 | 993 |
994 bool GetOutputDeviceHandles(std::vector<XID>* outputs) { | |
995 DCHECK(outputs); | |
996 outputs->clear(); | |
997 | |
998 if (!XDisplayExists()) | |
999 return false; | |
oshima
2012/08/10 03:09:51
Since you get XDisplay below,
if (!display)
re
Jun Mukai
2012/08/10 09:39:52
Done.
| |
1000 | |
1001 Display* display = GetXDisplay(); | |
1002 Window root_window = DefaultRootWindow(display); | |
1003 XRRScreenResources* screen_resources = | |
1004 XRRGetScreenResources(display, root_window); | |
oshima
2012/08/10 03:09:51
can this handle when the X doesn't support Xrandr?
Jun Mukai
2012/08/10 09:39:52
Done.
| |
1005 for (int i = 0; i < screen_resources->noutput; ++i) { | |
1006 outputs->push_back(screen_resources->outputs[i]); | |
1007 } | |
oshima
2012/08/10 03:09:51
nuke {}
Jun Mukai
2012/08/10 09:39:52
Done.
| |
1008 XRRFreeScreenResources(screen_resources); | |
1009 return true; | |
1010 } | |
1011 | |
1012 bool GetOutputDeviceData(XID output, | |
1013 uint16* manufacturer_id, | |
1014 uint32* serial_number, | |
1015 std::string* human_readable_name) { | |
1016 DCHECK(manufacturer_id); | |
1017 DCHECK(serial_number); | |
1018 DCHECK(human_readable_name); | |
1019 | |
1020 if (!XDisplayExists()) | |
1021 return false; | |
oshima
2012/08/10 03:09:51
ditto.
Jun Mukai
2012/08/10 09:39:52
Done.
| |
1022 | |
1023 Display* display = GetXDisplay(); | |
1024 Atom edid_property = GetAtom(RR_PROPERTY_RANDR_EDID); | |
1025 bool has_edid_property = false; | |
1026 int num_properties = 0; | |
1027 Atom* properties = XRRListOutputProperties(display, output, &num_properties); | |
1028 for (int i = 0; i < num_properties; ++i) { | |
1029 if (properties[i] == edid_property) { | |
1030 has_edid_property = true; | |
1031 break; | |
1032 } | |
1033 } | |
1034 XFree(properties); | |
1035 if (!has_edid_property) | |
1036 return false; | |
1037 | |
1038 Atom actual_type; | |
1039 int actual_format; | |
1040 unsigned long nitems; | |
1041 unsigned long bytes_after; | |
1042 unsigned char *prop; | |
1043 XRRGetOutputProperty(display, output, edid_property, 0, 128, false, false, | |
1044 AnyPropertyType, &actual_type, &actual_format, &nitems, | |
1045 &bytes_after, &prop); | |
1046 DCHECK(actual_type == XA_INTEGER); | |
1047 DCHECK(actual_format == 8); | |
1048 | |
1049 // See http://en.wikipedia.org/wiki/Extended_display_identification_data | |
1050 // for the details of EDID data format. We use the following data: | |
1051 // bytes 8-9: manufacturer EISA ID, in big-endian | |
1052 // bytes 12-15: represents serial number, in little-endian | |
1053 // bytes 54-125: four descriptors (18-bytes each) which may contain | |
1054 // the display name. | |
1055 const int kManufacturerOffset = 8; | |
1056 const int kSerialNumberOffset = 12; | |
1057 const int kDescriptorOffset = 54; | |
1058 const int kNumDescriptors = 4; | |
1059 const int kDescriptorLength = 18; | |
1060 | |
1061 *manufacturer_id = *reinterpret_cast<uint16*>(prop + kManufacturerOffset); | |
oshima
2012/08/10 03:09:51
I assume the format guarantees the correct alignme
Jun Mukai
2012/08/10 09:39:52
We do not have arm devices here... :(
As we discus
| |
1062 #if defined(ARCH_CPU_LITTLE_ENDIAN) | |
1063 *manufacturer_id = base::ByteSwap(*manufacturer_id); | |
1064 #endif | |
1065 *serial_number = base::ByteSwapToLE32( | |
1066 *reinterpret_cast<uint32*>(prop + kSerialNumberOffset)); | |
1067 | |
1068 std::string name_candidate; | |
1069 human_readable_name->clear(); | |
1070 for (int i = 0; i < kNumDescriptors; ++i) { | |
1071 unsigned char* desc_buf = prop + kDescriptorOffset + i * kDescriptorLength; | |
1072 // If the descriptor contains the display name, it has the following | |
1073 // structure: | |
1074 // bytes 0-2, 4: \0 | |
1075 // byte 3: \xfc for "Monitor name", \xfe for "Unspecified text" | |
1076 // bytes 5-17: text data, ending with \r, padding with spaces | |
1077 // we should check bytes 0-2 and 4, since it may have other values in | |
1078 // case that the descriptor contains other type of data. | |
1079 if (desc_buf[0] == 0 && desc_buf[1] == 0 && desc_buf[2] == 0 && | |
1080 desc_buf[4] == 0) { | |
1081 if (desc_buf[3] == 0xfc) { | |
1082 std::string found_name( | |
1083 reinterpret_cast<char*>(desc_buf + 5), kDescriptorLength - 5); | |
1084 TrimWhitespaceASCII(found_name, TRIM_TRAILING, human_readable_name); | |
1085 break; | |
1086 } else if (desc_buf[3] == 0xfe && name_candidate.empty()) { | |
1087 // Sometimes the default display of a laptop device doesn't have "FC" | |
1088 // ("Monitor name") descriptor, but has some human readable text with | |
1089 // "FE" ("Unspecified text"). Thus here uses this value as the fallback | |
1090 // of the lack of "FC". Note that multiple descriptors may have "FE", | |
1091 // and the first one is the monitor name. | |
1092 std::string found_name( | |
1093 reinterpret_cast<char*>(desc_buf + 5), kDescriptorLength - 5); | |
1094 TrimWhitespaceASCII(found_name, TRIM_TRAILING, &name_candidate); | |
1095 } | |
1096 } | |
1097 } | |
1098 if (human_readable_name->empty() && !name_candidate.empty()) | |
1099 *human_readable_name = name_candidate; | |
1100 | |
1101 XFree(prop); | |
1102 return true; | |
1103 } | |
1104 | |
1105 | |
990 bool GetWindowManagerName(std::string* wm_name) { | 1106 bool GetWindowManagerName(std::string* wm_name) { |
991 DCHECK(wm_name); | 1107 DCHECK(wm_name); |
992 int wm_window = 0; | 1108 int wm_window = 0; |
993 if (!GetIntProperty(GetX11RootWindow(), | 1109 if (!GetIntProperty(GetX11RootWindow(), |
994 "_NET_SUPPORTING_WM_CHECK", | 1110 "_NET_SUPPORTING_WM_CHECK", |
995 &wm_window)) { | 1111 &wm_window)) { |
996 return false; | 1112 return false; |
997 } | 1113 } |
998 | 1114 |
999 // It's possible that a window manager started earlier in this X session left | 1115 // 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) << ", " | 1394 << "request_code " << static_cast<int>(error_event.request_code) << ", " |
1279 << "minor_code " << static_cast<int>(error_event.minor_code) | 1395 << "minor_code " << static_cast<int>(error_event.minor_code) |
1280 << " (" << request_str << ")"; | 1396 << " (" << request_str << ")"; |
1281 } | 1397 } |
1282 | 1398 |
1283 // ---------------------------------------------------------------------------- | 1399 // ---------------------------------------------------------------------------- |
1284 // End of x11_util_internal.h | 1400 // End of x11_util_internal.h |
1285 | 1401 |
1286 | 1402 |
1287 } // namespace ui | 1403 } // namespace ui |
OLD | NEW |