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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 static CachedPictFormats* formats = NULL; | 58 static CachedPictFormats* formats = NULL; |
59 if (!formats) | 59 if (!formats) |
60 formats = new CachedPictFormats(); | 60 formats = new CachedPictFormats(); |
61 return formats; | 61 return formats; |
62 } | 62 } |
63 | 63 |
64 // Maximum number of CachedPictFormats we keep around. | 64 // Maximum number of CachedPictFormats we keep around. |
65 const size_t kMaxCacheSize = 5; | 65 const size_t kMaxCacheSize = 5; |
66 | 66 |
67 int DefaultX11ErrorHandler(Display* d, XErrorEvent* e) { | 67 int DefaultX11ErrorHandler(Display* d, XErrorEvent* e) { |
68 DCHECK(!MessageLoop::current() || | |
69 MessageLoop::current()->type() == MessageLoop::TYPE_UI); | |
70 MessageLoop::current()->PostTask( | 68 MessageLoop::current()->PostTask( |
71 FROM_HERE, NewRunnableFunction(LogErrorEventDescription, d, *e)); | 69 FROM_HERE, NewRunnableFunction(LogErrorEventDescription, d, *e)); |
72 return 0; | 70 return 0; |
73 } | 71 } |
74 | 72 |
75 int DefaultX11IOErrorHandler(Display* d) { | 73 int DefaultX11IOErrorHandler(Display* d) { |
76 // If there's an IO error it likely means the X server has gone away | 74 // If there's an IO error it likely means the X server has gone away |
77 LOG(ERROR) << "X IO Error detected"; | 75 LOG(ERROR) << "X IO Error detected"; |
78 _exit(1); | 76 _exit(1); |
79 } | 77 } |
80 | 78 |
81 XErrorHandler current_error_handler = DefaultX11ErrorHandler; | |
82 XErrorEvent last_error_event = {0, NULL, 0, 0, 0, 0, 0 }; | |
83 | |
84 int BaseX11ErrorHandler(Display* d, XErrorEvent* e) { | |
85 last_error_event = *e; | |
86 return current_error_handler(d, e); | |
87 } | |
88 | |
89 Atom GetAtom(const char* name) { | 79 Atom GetAtom(const char* name) { |
90 #if defined(TOOLKIT_USES_GTK) | 80 #if defined(TOOLKIT_USES_GTK) |
91 return gdk_x11_get_xatom_by_name_for_display( | 81 return gdk_x11_get_xatom_by_name_for_display( |
92 gdk_display_get_default(), name); | 82 gdk_display_get_default(), name); |
93 #else | 83 #else |
94 return XInternAtom(GetXDisplay(), name, false); | 84 return XInternAtom(GetXDisplay(), name, false); |
95 #endif | 85 #endif |
96 } | 86 } |
97 | 87 |
98 // Note: The caller should free the resulting value data. | 88 // Note: The caller should free the resulting value data. |
99 bool GetProperty(XID window, const std::string& property_name, long max_length, | 89 bool GetProperty(XID window, const std::string& property_name, long max_length, |
100 Atom* type, int* format, unsigned long* num_items, | 90 Atom* type, int* format, unsigned long* num_items, |
101 unsigned char** property) { | 91 unsigned char** property) { |
102 Atom property_atom = GetAtom(property_name.c_str()); | 92 Atom property_atom = GetAtom(property_name.c_str()); |
103 unsigned long remaining_bytes = 0; | 93 unsigned long remaining_bytes = 0; |
104 return XGetWindowProperty(GetXDisplay(), | 94 return XGetWindowProperty(GetXDisplay(), |
105 window, | 95 window, |
106 property_atom, | 96 property_atom, |
107 0, // offset into property data to read | 97 0, // offset into property data to read |
108 max_length, // max length to get | 98 max_length, // max length to get |
109 False, // deleted | 99 False, // deleted |
110 AnyPropertyType, | 100 AnyPropertyType, |
111 type, | 101 type, |
112 format, | 102 format, |
113 num_items, | 103 num_items, |
114 &remaining_bytes, | 104 &remaining_bytes, |
115 property); | 105 property); |
116 } | 106 } |
117 | 107 |
118 std::string BuildX11ErrorString(const XErrorEvent& error_event) { | |
119 char error_str[256]; | |
120 char request_str[256]; | |
121 | |
122 XGetErrorText(error_event.display, error_event.error_code, error_str, | |
123 sizeof(error_str)); | |
124 | |
125 strncpy(request_str, "Unknown", sizeof(request_str)); | |
126 if (error_event.request_code < 128) { | |
127 std::string num = base::UintToString(error_event.request_code); | |
128 XGetErrorDatabaseText(error_event.display, "XRequest", num.c_str(), | |
129 "Unknown", request_str, sizeof(request_str)); | |
130 } else { | |
131 int num_ext; | |
132 char** ext_list = XListExtensions(error_event.display, &num_ext); | |
133 | |
134 for (int i = 0; i < num_ext; i++) { | |
135 int ext_code, first_event, first_error; | |
136 XQueryExtension(error_event.display, ext_list[i], &ext_code, &first_event, | |
137 &first_error); | |
138 if (error_event.request_code == ext_code) { | |
139 std::string msg = StringPrintf( | |
140 "%s.%d", ext_list[i], error_event.minor_code); | |
141 XGetErrorDatabaseText(error_event.display, "XRequest", msg.c_str(), | |
142 "Unknown", request_str, sizeof(request_str)); | |
143 break; | |
144 } | |
145 } | |
146 XFreeExtensionList(ext_list); | |
147 } | |
148 | |
149 std::ostringstream error_ss; | |
150 error_ss << "X Error detected: " | |
151 << "serial " << error_event.serial << ", " | |
152 << "error_code " << static_cast<int>(error_event.error_code) | |
153 << " (" << error_str << "), " | |
154 << "request_code " << static_cast<int>(error_event.request_code) | |
155 << ", " | |
156 << "minor_code " << static_cast<int>(error_event.minor_code) | |
157 << " (" << request_str << ")"; | |
158 return error_ss.str(); | |
159 } | |
160 | |
161 } // namespace | 108 } // namespace |
162 | 109 |
163 bool XDisplayExists() { | 110 bool XDisplayExists() { |
164 return (GetXDisplay() != NULL); | 111 return (GetXDisplay() != NULL); |
165 } | 112 } |
166 | 113 |
167 Display* GetXDisplay() { | 114 Display* GetXDisplay() { |
168 return base::MessagePumpForUI::GetDefaultXDisplay(); | 115 return base::MessagePumpForUI::GetDefaultXDisplay(); |
169 } | 116 } |
170 | 117 |
(...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 event.xclient.format = 32; | 688 event.xclient.format = 32; |
742 event.xclient.data.l[0] = desktop; | 689 event.xclient.data.l[0] = desktop; |
743 event.xclient.data.l[1] = 1; // source indication | 690 event.xclient.data.l[1] = 1; // source indication |
744 | 691 |
745 int result = XSendEvent(GetXDisplay(), GetX11RootWindow(), False, | 692 int result = XSendEvent(GetXDisplay(), GetX11RootWindow(), False, |
746 SubstructureNotifyMask, &event); | 693 SubstructureNotifyMask, &event); |
747 return result == Success; | 694 return result == Success; |
748 } | 695 } |
749 | 696 |
750 void SetDefaultX11ErrorHandlers() { | 697 void SetDefaultX11ErrorHandlers() { |
751 XSetErrorHandler(BaseX11ErrorHandler); | |
752 SetX11ErrorHandlers(NULL, NULL); | 698 SetX11ErrorHandlers(NULL, NULL); |
753 } | 699 } |
754 | 700 |
755 bool IsX11WindowFullScreen(XID window) { | 701 bool IsX11WindowFullScreen(XID window) { |
756 // First check if _NET_WM_STATE property contains _NET_WM_STATE_FULLSCREEN. | 702 // First check if _NET_WM_STATE property contains _NET_WM_STATE_FULLSCREEN. |
757 static Atom atom = GetAtom("_NET_WM_STATE_FULLSCREEN"); | 703 static Atom atom = GetAtom("_NET_WM_STATE_FULLSCREEN"); |
758 | 704 |
759 std::vector<Atom> atom_properties; | 705 std::vector<Atom> atom_properties; |
760 if (GetAtomArrayProperty(window, | 706 if (GetAtomArrayProperty(window, |
761 "_NET_WM_STATE", | 707 "_NET_WM_STATE", |
(...skipping 15 matching lines...) Expand all Loading... |
777 return monitor_rect.x == window_rect.x() && | 723 return monitor_rect.x == window_rect.x() && |
778 monitor_rect.y == window_rect.y() && | 724 monitor_rect.y == window_rect.y() && |
779 monitor_rect.width == window_rect.width() && | 725 monitor_rect.width == window_rect.width() && |
780 monitor_rect.height == window_rect.height(); | 726 monitor_rect.height == window_rect.height(); |
781 #else | 727 #else |
782 NOTIMPLEMENTED(); | 728 NOTIMPLEMENTED(); |
783 return false; | 729 return false; |
784 #endif | 730 #endif |
785 } | 731 } |
786 | 732 |
787 void CheckForReportedX11Error() { | |
788 DCHECK(!MessageLoop::current() || | |
789 MessageLoop::current()->type() == MessageLoop::TYPE_UI); | |
790 if (!last_error_event.display) | |
791 return; | |
792 XSync(last_error_event.display, False); | |
793 LOG(FATAL) << BuildX11ErrorString(last_error_event); | |
794 } | |
795 | |
796 // ---------------------------------------------------------------------------- | 733 // ---------------------------------------------------------------------------- |
797 // These functions are declared in x11_util_internal.h because they require | 734 // These functions are declared in x11_util_internal.h because they require |
798 // XLib.h to be included, and it conflicts with many other headers. | 735 // XLib.h to be included, and it conflicts with many other headers. |
799 XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { | 736 XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { |
800 static XRenderPictFormat* pictformat = NULL; | 737 static XRenderPictFormat* pictformat = NULL; |
801 if (pictformat) | 738 if (pictformat) |
802 return pictformat; | 739 return pictformat; |
803 | 740 |
804 // First look for a 32-bit format which ignores the alpha value | 741 // First look for a 32-bit format which ignores the alpha value |
805 XRenderPictFormat templ; | 742 XRenderPictFormat templ; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
864 // always blowing away the cache. If we are, then we should figure out why | 801 // always blowing away the cache. If we are, then we should figure out why |
865 // and make it bigger. | 802 // and make it bigger. |
866 NOTREACHED(); | 803 NOTREACHED(); |
867 } | 804 } |
868 | 805 |
869 return pictformat; | 806 return pictformat; |
870 } | 807 } |
871 | 808 |
872 void SetX11ErrorHandlers(XErrorHandler error_handler, | 809 void SetX11ErrorHandlers(XErrorHandler error_handler, |
873 XIOErrorHandler io_error_handler) { | 810 XIOErrorHandler io_error_handler) { |
874 DCHECK(!MessageLoop::current() || | 811 XSetErrorHandler(error_handler ? error_handler : DefaultX11ErrorHandler); |
875 MessageLoop::current()->type() == MessageLoop::TYPE_UI); | 812 XSetIOErrorHandler( |
876 current_error_handler = error_handler ? | 813 io_error_handler ? io_error_handler : DefaultX11IOErrorHandler); |
877 error_handler : DefaultX11ErrorHandler; | |
878 XSetIOErrorHandler(io_error_handler ? | |
879 io_error_handler : DefaultX11IOErrorHandler); | |
880 } | 814 } |
881 | 815 |
882 void LogErrorEventDescription(Display* dpy, | 816 void LogErrorEventDescription(Display* dpy, |
883 const XErrorEvent& error_event) { | 817 const XErrorEvent& error_event) { |
884 DCHECK(!MessageLoop::current() || | 818 char error_str[256]; |
885 MessageLoop::current()->type() == MessageLoop::TYPE_UI); | 819 char request_str[256]; |
886 DCHECK_EQ(dpy, error_event.display) | 820 |
887 << "Attempt to log error for mismatching X11 display."; | 821 XGetErrorText(dpy, error_event.error_code, error_str, sizeof(error_str)); |
888 LOG(ERROR) << BuildX11ErrorString(error_event); | 822 |
| 823 strncpy(request_str, "Unknown", sizeof(request_str)); |
| 824 if (error_event.request_code < 128) { |
| 825 std::string num = base::UintToString(error_event.request_code); |
| 826 XGetErrorDatabaseText( |
| 827 dpy, "XRequest", num.c_str(), "Unknown", request_str, |
| 828 sizeof(request_str)); |
| 829 } else { |
| 830 int num_ext; |
| 831 char** ext_list = XListExtensions(dpy, &num_ext); |
| 832 |
| 833 for (int i = 0; i < num_ext; i++) { |
| 834 int ext_code, first_event, first_error; |
| 835 XQueryExtension(dpy, ext_list[i], &ext_code, &first_event, &first_error); |
| 836 if (error_event.request_code == ext_code) { |
| 837 std::string msg = StringPrintf( |
| 838 "%s.%d", ext_list[i], error_event.minor_code); |
| 839 XGetErrorDatabaseText( |
| 840 dpy, "XRequest", msg.c_str(), "Unknown", request_str, |
| 841 sizeof(request_str)); |
| 842 break; |
| 843 } |
| 844 } |
| 845 XFreeExtensionList(ext_list); |
| 846 } |
| 847 |
| 848 LOG(ERROR) |
| 849 << "X Error detected: " |
| 850 << "serial " << error_event.serial << ", " |
| 851 << "error_code " << static_cast<int>(error_event.error_code) |
| 852 << " (" << error_str << "), " |
| 853 << "request_code " << static_cast<int>(error_event.request_code) << ", " |
| 854 << "minor_code " << static_cast<int>(error_event.minor_code) |
| 855 << " (" << request_str << ")"; |
889 } | 856 } |
890 | 857 |
891 // ---------------------------------------------------------------------------- | 858 // ---------------------------------------------------------------------------- |
892 // End of x11_util_internal.h | 859 // End of x11_util_internal.h |
893 | 860 |
894 | 861 |
895 } // namespace ui | 862 } // namespace ui |
OLD | NEW |