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

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

Issue 15067012: Move chromeos specific utility functions for display to chromeos/display (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: added test Created 7 years, 7 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/base/x/x11_util_unittest.cc » ('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
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 } 310 }
311 311
312 ~XButtonMap() {} 312 ~XButtonMap() {}
313 313
314 unsigned char map_[256]; 314 unsigned char map_[256];
315 int count_; 315 int count_;
316 316
317 DISALLOW_COPY_AND_ASSIGN(XButtonMap); 317 DISALLOW_COPY_AND_ASSIGN(XButtonMap);
318 }; 318 };
319 319
320 bool IsRandRAvailable() {
321 int randr_version_major = 0;
322 int randr_version_minor = 0;
323 static bool is_randr_available = XRRQueryVersion(
324 GetXDisplay(), &randr_version_major, &randr_version_minor);
325 return is_randr_available;
326 }
327
328 bool IsShapeAvailable() { 320 bool IsShapeAvailable() {
329 int dummy; 321 int dummy;
330 static bool is_shape_available = 322 static bool is_shape_available =
331 XShapeQueryExtension(ui::GetXDisplay(), &dummy, &dummy); 323 XShapeQueryExtension(ui::GetXDisplay(), &dummy, &dummy);
332 return is_shape_available; 324 return is_shape_available;
333 325
334 } 326 }
335 327
336 // Get the EDID data from the |output| and stores to |prop|. |nitem| will store
337 // the number of characters |prop| will have. It doesn't take the ownership of
338 // |prop|, so caller must release it by XFree().
339 // Returns true if EDID property is successfully obtained. Otherwise returns
340 // false and does not touch |prop| and |nitems|.
341 bool GetEDIDProperty(XID output, unsigned long* nitems, unsigned char** prop) {
342 if (!IsRandRAvailable())
343 return false;
344
345 static Atom edid_property = GetAtom(RR_PROPERTY_RANDR_EDID);
346
347 Display* display = GetXDisplay();
348
349 bool has_edid_property = false;
350 int num_properties = 0;
351 Atom* properties = XRRListOutputProperties(display, output, &num_properties);
352 for (int i = 0; i < num_properties; ++i) {
353 if (properties[i] == edid_property) {
354 has_edid_property = true;
355 break;
356 }
357 }
358 XFree(properties);
359 if (!has_edid_property)
360 return false;
361
362 Atom actual_type;
363 int actual_format;
364 unsigned long bytes_after;
365 XRRGetOutputProperty(display,
366 output,
367 edid_property,
368 0, // offset
369 128, // length
370 false, // _delete
371 false, // pending
372 AnyPropertyType, // req_type
373 &actual_type,
374 &actual_format,
375 nitems,
376 &bytes_after,
377 prop);
378 DCHECK_EQ(XA_INTEGER, actual_type);
379 DCHECK_EQ(8, actual_format);
380 return true;
381 }
382
383 } // namespace 328 } // namespace
384 329
385 bool XDisplayExists() { 330 bool XDisplayExists() {
386 return (GetXDisplay() != NULL); 331 return (GetXDisplay() != NULL);
387 } 332 }
388 333
389 Display* GetXDisplay() { 334 Display* GetXDisplay() {
390 return base::MessagePumpForUI::GetDefaultXDisplay(); 335 return base::MessagePumpForUI::GetDefaultXDisplay();
391 } 336 }
392 337
(...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after
1290 } 1235 }
1291 1236
1292 void FreePicture(Display* display, XID picture) { 1237 void FreePicture(Display* display, XID picture) {
1293 XRenderFreePicture(display, picture); 1238 XRenderFreePicture(display, picture);
1294 } 1239 }
1295 1240
1296 void FreePixmap(Display* display, XID pixmap) { 1241 void FreePixmap(Display* display, XID pixmap) {
1297 XFreePixmap(display, pixmap); 1242 XFreePixmap(display, pixmap);
1298 } 1243 }
1299 1244
1300 bool GetOutputDeviceData(XID output,
1301 uint16* manufacturer_id,
1302 uint16* product_code,
1303 std::string* human_readable_name) {
1304 unsigned long nitems = 0;
1305 unsigned char *prop = NULL;
1306 if (!GetEDIDProperty(output, &nitems, &prop))
1307 return false;
1308
1309 bool result = ParseOutputDeviceData(
1310 prop, nitems, manufacturer_id, product_code, human_readable_name);
1311 XFree(prop);
1312 return result;
1313 }
1314
1315 bool ParseOutputDeviceData(const unsigned char* prop,
1316 unsigned long nitems,
1317 uint16* manufacturer_id,
1318 uint16* product_code,
1319 std::string* human_readable_name) {
1320 // See http://en.wikipedia.org/wiki/Extended_display_identification_data
1321 // for the details of EDID data format. We use the following data:
1322 // bytes 8-9: manufacturer EISA ID, in big-endian
1323 // bytes 10-11: represents product code, in little-endian
1324 // bytes 54-125: four descriptors (18-bytes each) which may contain
1325 // the display name.
1326 const unsigned int kManufacturerOffset = 8;
1327 const unsigned int kManufacturerLength = 2;
1328 const unsigned int kProductCodeOffset = 10;
1329 const unsigned int kProductCodeLength = 2;
1330 const unsigned int kDescriptorOffset = 54;
1331 const unsigned int kNumDescriptors = 4;
1332 const unsigned int kDescriptorLength = 18;
1333 // The specifier types.
1334 const unsigned char kMonitorNameDescriptor = 0xfc;
1335
1336 if (manufacturer_id) {
1337 if (nitems < kManufacturerOffset + kManufacturerLength)
1338 return false;
1339
1340 *manufacturer_id =
1341 *reinterpret_cast<const uint16*>(prop + kManufacturerOffset);
1342 #if defined(ARCH_CPU_LITTLE_ENDIAN)
1343 *manufacturer_id = base::ByteSwap(*manufacturer_id);
1344 #endif
1345 }
1346
1347 if (product_code) {
1348 if (nitems < kProductCodeOffset + kProductCodeLength)
1349 return false;
1350
1351 *product_code = base::ByteSwapToLE16(
1352 *reinterpret_cast<const uint16*>(prop + kProductCodeOffset));
1353 }
1354
1355 if (!human_readable_name)
1356 return true;
1357
1358 human_readable_name->clear();
1359 for (unsigned int i = 0; i < kNumDescriptors; ++i) {
1360 if (nitems < kDescriptorOffset + (i + 1) * kDescriptorLength)
1361 break;
1362
1363 const unsigned char* desc_buf =
1364 prop + kDescriptorOffset + i * kDescriptorLength;
1365 // If the descriptor contains the display name, it has the following
1366 // structure:
1367 // bytes 0-2, 4: \0
1368 // byte 3: descriptor type, defined above.
1369 // bytes 5-17: text data, ending with \r, padding with spaces
1370 // we should check bytes 0-2 and 4, since it may have other values in
1371 // case that the descriptor contains other type of data.
1372 if (desc_buf[0] == 0 && desc_buf[1] == 0 && desc_buf[2] == 0 &&
1373 desc_buf[4] == 0) {
1374 if (desc_buf[3] == kMonitorNameDescriptor) {
1375 std::string found_name(
1376 reinterpret_cast<const char*>(desc_buf + 5), kDescriptorLength - 5);
1377 TrimWhitespaceASCII(found_name, TRIM_TRAILING, human_readable_name);
1378 break;
1379 }
1380 }
1381 }
1382
1383 if (human_readable_name->empty())
1384 return false;
1385
1386 // Verify if the |human_readable_name| consists of printable characters only.
1387 for (size_t i = 0; i < human_readable_name->size(); ++i) {
1388 char c = (*human_readable_name)[i];
1389 if (!isascii(c) || !isprint(c)) {
1390 human_readable_name->clear();
1391 return false;
1392 }
1393 }
1394
1395 return true;
1396 }
1397
1398 bool GetOutputOverscanFlag(XID output, bool* flag) {
1399 unsigned long nitems = 0;
1400 unsigned char *prop = NULL;
1401 if (!GetEDIDProperty(output, &nitems, &prop))
1402 return false;
1403
1404 bool found = ParseOutputOverscanFlag(prop, nitems, flag);
1405 XFree(prop);
1406 return found;
1407 }
1408
1409 bool ParseOutputOverscanFlag(const unsigned char* prop,
1410 unsigned long nitems,
1411 bool *flag) {
1412 // See http://en.wikipedia.org/wiki/Extended_display_identification_data
1413 // for the extension format of EDID. Also see EIA/CEA-861 spec for
1414 // the format of the extensions and how video capability is encoded.
1415 // - byte 0: tag. should be 02h.
1416 // - byte 1: revision. only cares revision 3 (03h).
1417 // - byte 4-: data block.
1418 const unsigned int kExtensionBase = 128;
1419 const unsigned int kExtensionSize = 128;
1420 const unsigned int kNumExtensionsOffset = 126;
1421 const unsigned int kDataBlockOffset = 4;
1422 const unsigned char kCEAExtensionTag = '\x02';
1423 const unsigned char kExpectedExtensionRevision = '\x03';
1424 const unsigned char kExtendedTag = 7;
1425 const unsigned char kExtendedVideoCapabilityTag = 0;
1426 const unsigned int kPTOverscan = 4;
1427 const unsigned int kITOverscan = 2;
1428 const unsigned int kCEOverscan = 0;
1429
1430 if (nitems <= kNumExtensionsOffset)
1431 return false;
1432
1433 unsigned char num_extensions = prop[kNumExtensionsOffset];
1434
1435 for (size_t i = 0; i < num_extensions; ++i) {
1436 // Skip parsing the whole extension if size is not enough.
1437 if (nitems < kExtensionBase + (i + 1) * kExtensionSize)
1438 break;
1439
1440 const unsigned char* extension = prop + kExtensionBase + i * kExtensionSize;
1441 unsigned char tag = extension[0];
1442 unsigned char revision = extension[1];
1443 if (tag != kCEAExtensionTag || revision != kExpectedExtensionRevision)
1444 continue;
1445
1446 unsigned char timing_descriptors_start =
1447 std::min(extension[2], static_cast<unsigned char>(kExtensionSize));
1448 const unsigned char* data_block = extension + kDataBlockOffset;
1449 while (data_block < extension + timing_descriptors_start) {
1450 // A data block is encoded as:
1451 // - byte 1 high 3 bits: tag. '07' for extended tags.
1452 // - byte 1 remaining bits: the length of data block.
1453 // - byte 2: the extended tag. '0' for video capability.
1454 // - byte 3: the capability.
1455 unsigned char tag = data_block[0] >> 5;
1456 unsigned char payload_length = data_block[0] & 0x1f;
1457 if (static_cast<unsigned long>(data_block + payload_length - prop) >
1458 nitems)
1459 break;
1460
1461 if (tag != kExtendedTag || payload_length < 2) {
1462 data_block += payload_length + 1;
1463 continue;
1464 }
1465
1466 unsigned char extended_tag_code = data_block[1];
1467 if (extended_tag_code != kExtendedVideoCapabilityTag) {
1468 data_block += payload_length + 1;
1469 continue;
1470 }
1471
1472 // The difference between preferred, IT, and CE video formats
1473 // doesn't matter. Sets |flag| to true if any of these flags are true.
1474 if ((data_block[2] & (1 << kPTOverscan)) ||
1475 (data_block[2] & (1 << kITOverscan)) ||
1476 (data_block[2] & (1 << kCEOverscan))) {
1477 *flag = true;
1478 } else {
1479 *flag = false;
1480 }
1481 return true;
1482 }
1483 }
1484
1485 return false;
1486 }
1487
1488 bool GetWindowManagerName(std::string* wm_name) { 1245 bool GetWindowManagerName(std::string* wm_name) {
1489 DCHECK(wm_name); 1246 DCHECK(wm_name);
1490 int wm_window = 0; 1247 int wm_window = 0;
1491 if (!GetIntProperty(GetX11RootWindow(), 1248 if (!GetIntProperty(GetX11RootWindow(),
1492 "_NET_SUPPORTING_WM_CHECK", 1249 "_NET_SUPPORTING_WM_CHECK",
1493 &wm_window)) { 1250 &wm_window)) {
1494 return false; 1251 return false;
1495 } 1252 }
1496 1253
1497 // It's possible that a window manager started earlier in this X session left 1254 // It's possible that a window manager started earlier in this X session left
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
1811 << "request_code " << static_cast<int>(error_event.request_code) << ", " 1568 << "request_code " << static_cast<int>(error_event.request_code) << ", "
1812 << "minor_code " << static_cast<int>(error_event.minor_code) 1569 << "minor_code " << static_cast<int>(error_event.minor_code)
1813 << " (" << request_str << ")"; 1570 << " (" << request_str << ")";
1814 } 1571 }
1815 1572
1816 // ---------------------------------------------------------------------------- 1573 // ----------------------------------------------------------------------------
1817 // End of x11_util_internal.h 1574 // End of x11_util_internal.h
1818 1575
1819 1576
1820 } // namespace ui 1577 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/x/x11_util.h ('k') | ui/base/x/x11_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698