Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 50 static CachedPictFormats* formats = NULL; | 50 static CachedPictFormats* formats = NULL; |
| 51 if (!formats) | 51 if (!formats) |
| 52 formats = new CachedPictFormats(); | 52 formats = new CachedPictFormats(); |
| 53 return formats; | 53 return formats; |
| 54 } | 54 } |
| 55 | 55 |
| 56 // Maximum number of CachedPictFormats we keep around. | 56 // Maximum number of CachedPictFormats we keep around. |
| 57 const size_t kMaxCacheSize = 5; | 57 const size_t kMaxCacheSize = 5; |
| 58 | 58 |
| 59 int DefaultX11ErrorHandler(Display* d, XErrorEvent* e) { | 59 int DefaultX11ErrorHandler(Display* d, XErrorEvent* e) { |
| 60 DCHECK(!MessageLoop::current() || | |
| 61 MessageLoop::current()->type() == MessageLoop::TYPE_UI); | |
| 60 MessageLoop::current()->PostTask( | 62 MessageLoop::current()->PostTask( |
| 61 FROM_HERE, NewRunnableFunction(LogErrorEventDescription, d, *e)); | 63 FROM_HERE, NewRunnableFunction(LogErrorEventDescription, d, *e)); |
| 62 return 0; | 64 return 0; |
| 63 } | 65 } |
| 64 | 66 |
| 65 int DefaultX11IOErrorHandler(Display* d) { | 67 int DefaultX11IOErrorHandler(Display* d) { |
| 66 // If there's an IO error it likely means the X server has gone away | 68 // If there's an IO error it likely means the X server has gone away |
| 67 LOG(ERROR) << "X IO Error detected"; | 69 LOG(ERROR) << "X IO Error detected"; |
| 68 _exit(1); | 70 _exit(1); |
| 69 } | 71 } |
| 70 | 72 |
| 73 XErrorHandler current_error_handler = DefaultX11ErrorHandler; | |
| 74 XErrorEvent last_error_event = {0, NULL, 0, 0, 0, 0, 0 }; | |
| 75 | |
| 76 int BaseX11ErrorHandler(Display* d, XErrorEvent* e) { | |
| 77 last_error_event = *e; | |
| 78 return current_error_handler(d, e); | |
| 79 } | |
| 80 | |
| 71 // Note: The caller should free the resulting value data. | 81 // Note: The caller should free the resulting value data. |
| 72 bool GetProperty(XID window, const std::string& property_name, long max_length, | 82 bool GetProperty(XID window, const std::string& property_name, long max_length, |
| 73 Atom* type, int* format, unsigned long* num_items, | 83 Atom* type, int* format, unsigned long* num_items, |
| 74 unsigned char** property) { | 84 unsigned char** property) { |
| 75 Atom property_atom = gdk_x11_get_xatom_by_name_for_display( | 85 Atom property_atom = gdk_x11_get_xatom_by_name_for_display( |
| 76 gdk_display_get_default(), property_name.c_str()); | 86 gdk_display_get_default(), property_name.c_str()); |
| 77 | 87 |
| 78 unsigned long remaining_bytes = 0; | 88 unsigned long remaining_bytes = 0; |
| 79 return XGetWindowProperty(GetXDisplay(), | 89 return XGetWindowProperty(GetXDisplay(), |
| 80 window, | 90 window, |
| 81 property_atom, | 91 property_atom, |
| 82 0, // offset into property data to read | 92 0, // offset into property data to read |
| 83 max_length, // max length to get | 93 max_length, // max length to get |
| 84 False, // deleted | 94 False, // deleted |
| 85 AnyPropertyType, | 95 AnyPropertyType, |
| 86 type, | 96 type, |
| 87 format, | 97 format, |
| 88 num_items, | 98 num_items, |
| 89 &remaining_bytes, | 99 &remaining_bytes, |
| 90 property); | 100 property); |
| 91 } | 101 } |
| 92 | 102 |
| 103 std::string BuildX11ErrorString(const XErrorEvent& error_event) { | |
| 104 char error_str[256]; | |
| 105 char request_str[256]; | |
| 106 | |
| 107 XGetErrorText(error_event.display, error_event.error_code, error_str, | |
| 108 sizeof(error_str)); | |
| 109 | |
| 110 strncpy(request_str, "Unknown", sizeof(request_str)); | |
| 111 if (error_event.request_code < 128) { | |
| 112 std::string num = base::UintToString(error_event.request_code); | |
| 113 XGetErrorDatabaseText(error_event.display, "XRequest", num.c_str(), | |
| 114 "Unknown", request_str, sizeof(request_str)); | |
| 115 } else { | |
| 116 int num_ext; | |
| 117 char** ext_list = XListExtensions(error_event.display, &num_ext); | |
| 118 | |
| 119 for (int i = 0; i < num_ext; i++) { | |
| 120 int ext_code, first_event, first_error; | |
| 121 XQueryExtension(error_event.display, ext_list[i], &ext_code, &first_event, | |
| 122 &first_error); | |
| 123 if (error_event.request_code == ext_code) { | |
| 124 std::string msg = StringPrintf( | |
| 125 "%s.%d", ext_list[i], error_event.minor_code); | |
| 126 XGetErrorDatabaseText(error_event.display, "XRequest", msg.c_str(), | |
| 127 "Unknown", request_str, sizeof(request_str)); | |
| 128 break; | |
| 129 } | |
| 130 } | |
| 131 XFreeExtensionList(ext_list); | |
| 132 } | |
| 133 | |
| 134 std::ostringstream error_ss; | |
| 135 error_ss << "X Error detected: " | |
| 136 << "serial " << error_event.serial << ", " | |
| 137 << "error_code " << static_cast<int>(error_event.error_code) | |
| 138 << " (" << error_str << "), " | |
| 139 << "request_code " << static_cast<int>(error_event.request_code) | |
| 140 << ", " | |
| 141 << "minor_code " << static_cast<int>(error_event.minor_code) | |
| 142 << " (" << request_str << ")"; | |
| 143 return error_ss.str(); | |
| 144 } | |
| 145 | |
| 93 } // namespace | 146 } // namespace |
| 94 | 147 |
| 95 bool XDisplayExists() { | 148 bool XDisplayExists() { |
| 96 return (gdk_display_get_default() != NULL); | 149 return (gdk_display_get_default() != NULL); |
| 97 } | 150 } |
| 98 | 151 |
| 99 Display* GetXDisplay() { | 152 Display* GetXDisplay() { |
| 100 return base::MessagePumpForUI::GetDefaultXDisplay(); | 153 return base::MessagePumpForUI::GetDefaultXDisplay(); |
| 101 } | 154 } |
| 102 | 155 |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 672 event.xclient.format = 32; | 725 event.xclient.format = 32; |
| 673 event.xclient.data.l[0] = desktop; | 726 event.xclient.data.l[0] = desktop; |
| 674 event.xclient.data.l[1] = 1; // source indication | 727 event.xclient.data.l[1] = 1; // source indication |
| 675 | 728 |
| 676 int result = XSendEvent(GetXDisplay(), GetX11RootWindow(), False, | 729 int result = XSendEvent(GetXDisplay(), GetX11RootWindow(), False, |
| 677 SubstructureNotifyMask, &event); | 730 SubstructureNotifyMask, &event); |
| 678 return result == Success; | 731 return result == Success; |
| 679 } | 732 } |
| 680 | 733 |
| 681 void SetDefaultX11ErrorHandlers() { | 734 void SetDefaultX11ErrorHandlers() { |
| 735 XSetErrorHandler(BaseX11ErrorHandler); | |
| 682 SetX11ErrorHandlers(NULL, NULL); | 736 SetX11ErrorHandlers(NULL, NULL); |
| 683 } | 737 } |
| 684 | 738 |
| 685 bool IsX11WindowFullScreen(XID window) { | 739 bool IsX11WindowFullScreen(XID window) { |
| 686 // First check if _NET_WM_STATE property contains _NET_WM_STATE_FULLSCREEN. | 740 // First check if _NET_WM_STATE property contains _NET_WM_STATE_FULLSCREEN. |
| 687 static Atom atom = gdk_x11_get_xatom_by_name_for_display( | 741 static Atom atom = gdk_x11_get_xatom_by_name_for_display( |
| 688 gdk_display_get_default(), "_NET_WM_STATE_FULLSCREEN"); | 742 gdk_display_get_default(), "_NET_WM_STATE_FULLSCREEN"); |
| 689 | 743 |
| 690 std::vector<Atom> atom_properties; | 744 std::vector<Atom> atom_properties; |
| 691 if (GetAtomArrayProperty(window, | 745 if (GetAtomArrayProperty(window, |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 703 gfx::Rect window_rect; | 757 gfx::Rect window_rect; |
| 704 if (!ui::GetWindowRect(window, &window_rect)) | 758 if (!ui::GetWindowRect(window, &window_rect)) |
| 705 return false; | 759 return false; |
| 706 | 760 |
| 707 return monitor_rect.x == window_rect.x() && | 761 return monitor_rect.x == window_rect.x() && |
| 708 monitor_rect.y == window_rect.y() && | 762 monitor_rect.y == window_rect.y() && |
| 709 monitor_rect.width == window_rect.width() && | 763 monitor_rect.width == window_rect.width() && |
| 710 monitor_rect.height == window_rect.height(); | 764 monitor_rect.height == window_rect.height(); |
| 711 } | 765 } |
| 712 | 766 |
| 767 bool CheckFailOnReportedX11Error() { | |
| 768 DCHECK(!MessageLoop::current() || | |
| 769 MessageLoop::current()->type() == MessageLoop::TYPE_UI); | |
| 770 if (!last_error_event.display) | |
| 771 return false; | |
| 772 XSync(last_error_event.display, False); | |
| 773 LOG(FATAL) << BuildX11ErrorString(last_error_event); | |
|
Ami GONE FROM CHROMIUM
2011/09/22 17:17:50
once you FATAL the rest of this method doesn't mat
dominich
2011/09/22 18:24:12
There might one day be a build that disables FATAL
| |
| 774 last_error_event.display = NULL; | |
| 775 return true; | |
| 776 } | |
| 777 | |
| 713 // ---------------------------------------------------------------------------- | 778 // ---------------------------------------------------------------------------- |
| 714 // These functions are declared in x11_util_internal.h because they require | 779 // These functions are declared in x11_util_internal.h because they require |
| 715 // XLib.h to be included, and it conflicts with many other headers. | 780 // XLib.h to be included, and it conflicts with many other headers. |
| 716 XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { | 781 XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { |
| 717 static XRenderPictFormat* pictformat = NULL; | 782 static XRenderPictFormat* pictformat = NULL; |
| 718 if (pictformat) | 783 if (pictformat) |
| 719 return pictformat; | 784 return pictformat; |
| 720 | 785 |
| 721 // First look for a 32-bit format which ignores the alpha value | 786 // First look for a 32-bit format which ignores the alpha value |
| 722 XRenderPictFormat templ; | 787 XRenderPictFormat templ; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 781 // always blowing away the cache. If we are, then we should figure out why | 846 // always blowing away the cache. If we are, then we should figure out why |
| 782 // and make it bigger. | 847 // and make it bigger. |
| 783 NOTREACHED(); | 848 NOTREACHED(); |
| 784 } | 849 } |
| 785 | 850 |
| 786 return pictformat; | 851 return pictformat; |
| 787 } | 852 } |
| 788 | 853 |
| 789 void SetX11ErrorHandlers(XErrorHandler error_handler, | 854 void SetX11ErrorHandlers(XErrorHandler error_handler, |
| 790 XIOErrorHandler io_error_handler) { | 855 XIOErrorHandler io_error_handler) { |
| 791 XSetErrorHandler(error_handler ? error_handler : DefaultX11ErrorHandler); | 856 DCHECK(!MessageLoop::current() || |
| 792 XSetIOErrorHandler( | 857 MessageLoop::current()->type() == MessageLoop::TYPE_UI); |
| 793 io_error_handler ? io_error_handler : DefaultX11IOErrorHandler); | 858 current_error_handler = error_handler ? |
| 859 error_handler : DefaultX11ErrorHandler; | |
| 860 XSetIOErrorHandler(io_error_handler ? | |
| 861 io_error_handler : DefaultX11IOErrorHandler); | |
| 794 } | 862 } |
| 795 | 863 |
| 796 void LogErrorEventDescription(Display* dpy, | 864 void LogErrorEventDescription(Display* dpy, |
| 797 const XErrorEvent& error_event) { | 865 const XErrorEvent& error_event) { |
| 798 char error_str[256]; | 866 DCHECK(!MessageLoop::current() || |
| 799 char request_str[256]; | 867 MessageLoop::current()->type() == MessageLoop::TYPE_UI); |
| 800 | 868 DCHECK_EQ(dpy, error_event.display) |
| 801 XGetErrorText(dpy, error_event.error_code, error_str, sizeof(error_str)); | 869 << "Attempt to log error for mismatching X11 display."; |
| 802 | 870 LOG(ERROR) << BuildX11ErrorString(error_event); |
| 803 strncpy(request_str, "Unknown", sizeof(request_str)); | |
| 804 if (error_event.request_code < 128) { | |
| 805 std::string num = base::UintToString(error_event.request_code); | |
| 806 XGetErrorDatabaseText( | |
| 807 dpy, "XRequest", num.c_str(), "Unknown", request_str, | |
| 808 sizeof(request_str)); | |
| 809 } else { | |
| 810 int num_ext; | |
| 811 char** ext_list = XListExtensions(dpy, &num_ext); | |
| 812 | |
| 813 for (int i = 0; i < num_ext; i++) { | |
| 814 int ext_code, first_event, first_error; | |
| 815 XQueryExtension(dpy, ext_list[i], &ext_code, &first_event, &first_error); | |
| 816 if (error_event.request_code == ext_code) { | |
| 817 std::string msg = StringPrintf( | |
| 818 "%s.%d", ext_list[i], error_event.minor_code); | |
| 819 XGetErrorDatabaseText( | |
| 820 dpy, "XRequest", msg.c_str(), "Unknown", request_str, | |
| 821 sizeof(request_str)); | |
| 822 break; | |
| 823 } | |
| 824 } | |
| 825 XFreeExtensionList(ext_list); | |
| 826 } | |
| 827 | |
| 828 LOG(ERROR) | |
| 829 << "X Error detected: " | |
| 830 << "serial " << error_event.serial << ", " | |
| 831 << "error_code " << static_cast<int>(error_event.error_code) | |
| 832 << " (" << error_str << "), " | |
| 833 << "request_code " << static_cast<int>(error_event.request_code) << ", " | |
| 834 << "minor_code " << static_cast<int>(error_event.minor_code) | |
| 835 << " (" << request_str << ")"; | |
| 836 } | 871 } |
| 837 | 872 |
| 838 // ---------------------------------------------------------------------------- | 873 // ---------------------------------------------------------------------------- |
| 839 // End of x11_util_internal.h | 874 // End of x11_util_internal.h |
| 840 | 875 |
| 841 | 876 |
| 842 } // namespace ui | 877 } // namespace ui |
| OLD | NEW |