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 |
| 11 #include <gdk/gdk.h> | |
| 12 #include <gdk/gdkx.h> | |
| 13 #include <gtk/gtk.h> | |
| 14 | |
| 15 #include <sys/ipc.h> | 11 #include <sys/ipc.h> |
| 16 #include <sys/shm.h> | 12 #include <sys/shm.h> |
| 17 | 13 |
| 18 #include <list> | 14 #include <list> |
| 19 #include <vector> | 15 #include <vector> |
| 20 | 16 |
| 21 #include "base/command_line.h" | 17 #include "base/command_line.h" |
| 22 #include "base/logging.h" | 18 #include "base/logging.h" |
| 23 #include "base/message_loop.h" | 19 #include "base/message_loop.h" |
| 24 #include "base/stringprintf.h" | 20 #include "base/stringprintf.h" |
| 25 #include "base/string_number_conversions.h" | 21 #include "base/string_number_conversions.h" |
| 26 #include "base/threading/thread.h" | 22 #include "base/threading/thread.h" |
| 27 #include "ui/base/x/x11_util_internal.h" | 23 #include "ui/base/x/x11_util_internal.h" |
| 28 #include "ui/gfx/rect.h" | 24 #include "ui/gfx/rect.h" |
| 29 #include "ui/gfx/size.h" | 25 #include "ui/gfx/size.h" |
| 30 | 26 |
| 27 #if defined(TOOLKIT_USES_GTK) | |
| 28 #include <gdk/gdk.h> | |
| 29 #include <gdk/gdkx.h> | |
| 30 #include <gtk/gtk.h> | |
| 31 #else | |
| 32 #define gdk_error_trap_push() | |
|
Daniel Erat
2011/09/21 20:27:08
stubbing these means that we're not trapping X err
Daniel Erat
2011/09/21 20:31:47
http://codereview.chromium.org/7889040/ may be rel
sadrul
2011/09/21 21:56:18
Thanks for the link. I think that change can be us
| |
| 33 #define gdk_error_trap_pop() false | |
| 34 #define gdk_flush() | |
| 35 #endif | |
| 36 | |
| 31 namespace ui { | 37 namespace ui { |
| 32 | 38 |
| 33 namespace { | 39 namespace { |
| 34 | 40 |
| 35 // Used to cache the XRenderPictFormat for a visual/display pair. | 41 // Used to cache the XRenderPictFormat for a visual/display pair. |
| 36 struct CachedPictFormat { | 42 struct CachedPictFormat { |
| 37 bool equals(Display* display, Visual* visual) const { | 43 bool equals(Display* display, Visual* visual) const { |
| 38 return display == this->display && visual == this->visual; | 44 return display == this->display && visual == this->visual; |
| 39 } | 45 } |
| 40 | 46 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 61 FROM_HERE, NewRunnableFunction(LogErrorEventDescription, d, *e)); | 67 FROM_HERE, NewRunnableFunction(LogErrorEventDescription, d, *e)); |
| 62 return 0; | 68 return 0; |
| 63 } | 69 } |
| 64 | 70 |
| 65 int DefaultX11IOErrorHandler(Display* d) { | 71 int DefaultX11IOErrorHandler(Display* d) { |
| 66 // If there's an IO error it likely means the X server has gone away | 72 // If there's an IO error it likely means the X server has gone away |
| 67 LOG(ERROR) << "X IO Error detected"; | 73 LOG(ERROR) << "X IO Error detected"; |
| 68 _exit(1); | 74 _exit(1); |
| 69 } | 75 } |
| 70 | 76 |
| 77 Atom GetAtom(const char* name) { | |
| 78 #if defined(TOOLKIT_USES_GTK) | |
| 79 return gdk_x11_get_xatom_by_name_for_display( | |
| 80 gdk_display_get_default(), name); | |
| 81 #else | |
| 82 return XInternAtom(GetXDisplay(), name, false); | |
| 83 #endif | |
| 84 } | |
| 85 | |
| 71 // Note: The caller should free the resulting value data. | 86 // Note: The caller should free the resulting value data. |
| 72 bool GetProperty(XID window, const std::string& property_name, long max_length, | 87 bool GetProperty(XID window, const std::string& property_name, long max_length, |
| 73 Atom* type, int* format, unsigned long* num_items, | 88 Atom* type, int* format, unsigned long* num_items, |
| 74 unsigned char** property) { | 89 unsigned char** property) { |
| 75 Atom property_atom = gdk_x11_get_xatom_by_name_for_display( | 90 Atom property_atom = GetAtom(property_name.c_str()); |
| 76 gdk_display_get_default(), property_name.c_str()); | |
| 77 | |
| 78 unsigned long remaining_bytes = 0; | 91 unsigned long remaining_bytes = 0; |
| 79 return XGetWindowProperty(GetXDisplay(), | 92 return XGetWindowProperty(GetXDisplay(), |
| 80 window, | 93 window, |
| 81 property_atom, | 94 property_atom, |
| 82 0, // offset into property data to read | 95 0, // offset into property data to read |
| 83 max_length, // max length to get | 96 max_length, // max length to get |
| 84 False, // deleted | 97 False, // deleted |
| 85 AnyPropertyType, | 98 AnyPropertyType, |
| 86 type, | 99 type, |
| 87 format, | 100 format, |
| 88 num_items, | 101 num_items, |
| 89 &remaining_bytes, | 102 &remaining_bytes, |
| 90 property); | 103 property); |
| 91 } | 104 } |
| 92 | 105 |
| 93 } // namespace | 106 } // namespace |
| 94 | 107 |
| 95 bool XDisplayExists() { | 108 bool XDisplayExists() { |
| 96 return (gdk_display_get_default() != NULL); | 109 return (GetXDisplay() != NULL); |
| 97 } | 110 } |
| 98 | 111 |
| 99 Display* GetXDisplay() { | 112 Display* GetXDisplay() { |
| 100 return base::MessagePumpForUI::GetDefaultXDisplay(); | 113 return base::MessagePumpForUI::GetDefaultXDisplay(); |
| 101 } | 114 } |
| 102 | 115 |
| 103 static SharedMemorySupport DoQuerySharedMemorySupport(Display* dpy) { | 116 static SharedMemorySupport DoQuerySharedMemorySupport(Display* dpy) { |
| 104 int dummy; | 117 int dummy; |
| 105 Bool pixmaps_supported; | 118 Bool pixmaps_supported; |
| 106 // Query the server's support for XSHM. | 119 // Query the server's support for XSHM. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 159 render_supported_cached = true; | 172 render_supported_cached = true; |
| 160 | 173 |
| 161 return render_supported; | 174 return render_supported; |
| 162 } | 175 } |
| 163 | 176 |
| 164 int GetDefaultScreen(Display* display) { | 177 int GetDefaultScreen(Display* display) { |
| 165 return XDefaultScreen(display); | 178 return XDefaultScreen(display); |
| 166 } | 179 } |
| 167 | 180 |
| 168 XID GetX11RootWindow() { | 181 XID GetX11RootWindow() { |
| 169 return GDK_WINDOW_XID(gdk_get_default_root_window()); | 182 return DefaultRootWindow(GetXDisplay()); |
| 170 } | 183 } |
| 171 | 184 |
| 172 bool GetCurrentDesktop(int* desktop) { | 185 bool GetCurrentDesktop(int* desktop) { |
| 173 return GetIntProperty(GetX11RootWindow(), "_NET_CURRENT_DESKTOP", desktop); | 186 return GetIntProperty(GetX11RootWindow(), "_NET_CURRENT_DESKTOP", desktop); |
| 174 } | 187 } |
| 175 | 188 |
| 189 #if defined(TOOLKIT_USES_GTK) | |
| 176 XID GetX11WindowFromGtkWidget(GtkWidget* widget) { | 190 XID GetX11WindowFromGtkWidget(GtkWidget* widget) { |
| 177 return GDK_WINDOW_XID(widget->window); | 191 return GDK_WINDOW_XID(widget->window); |
| 178 } | 192 } |
| 179 | 193 |
| 180 XID GetX11WindowFromGdkWindow(GdkWindow* window) { | 194 XID GetX11WindowFromGdkWindow(GdkWindow* window) { |
| 181 return GDK_WINDOW_XID(window); | 195 return GDK_WINDOW_XID(window); |
| 182 } | 196 } |
| 183 | 197 |
| 184 GtkWindow* GetGtkWindowFromX11Window(XID xid) { | 198 GtkWindow* GetGtkWindowFromX11Window(XID xid) { |
| 185 GdkWindow* gdk_window = | 199 GdkWindow* gdk_window = |
| 186 gdk_window_lookup_for_display(gdk_display_get_default(), xid); | 200 gdk_window_lookup_for_display(gdk_display_get_default(), xid); |
| 187 if (!gdk_window) | 201 if (!gdk_window) |
| 188 return NULL; | 202 return NULL; |
| 189 GtkWindow* gtk_window = NULL; | 203 GtkWindow* gtk_window = NULL; |
| 190 gdk_window_get_user_data(gdk_window, | 204 gdk_window_get_user_data(gdk_window, |
| 191 reinterpret_cast<gpointer*>(>k_window)); | 205 reinterpret_cast<gpointer*>(>k_window)); |
| 192 if (!gtk_window) | 206 if (!gtk_window) |
| 193 return NULL; | 207 return NULL; |
| 194 return gtk_window; | 208 return gtk_window; |
| 195 } | 209 } |
| 196 | 210 |
| 197 void* GetVisualFromGtkWidget(GtkWidget* widget) { | 211 void* GetVisualFromGtkWidget(GtkWidget* widget) { |
| 198 return GDK_VISUAL_XVISUAL(gtk_widget_get_visual(widget)); | 212 return GDK_VISUAL_XVISUAL(gtk_widget_get_visual(widget)); |
| 199 } | 213 } |
| 214 #endif // defined(TOOLKIT_USES_GTK) | |
| 200 | 215 |
| 201 int BitsPerPixelForPixmapDepth(Display* dpy, int depth) { | 216 int BitsPerPixelForPixmapDepth(Display* dpy, int depth) { |
| 202 int count; | 217 int count; |
| 203 XPixmapFormatValues* formats = XListPixmapFormats(dpy, &count); | 218 XPixmapFormatValues* formats = XListPixmapFormats(dpy, &count); |
| 204 if (!formats) | 219 if (!formats) |
| 205 return -1; | 220 return -1; |
| 206 | 221 |
| 207 int bits_per_pixel = -1; | 222 int bits_per_pixel = -1; |
| 208 for (int i = 0; i < count; ++i) { | 223 for (int i = 0; i < count; ++i) { |
| 209 if (formats[i].depth == depth) { | 224 if (formats[i].depth == depth) { |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 660 return false; | 675 return false; |
| 661 | 676 |
| 662 // If |window| is sticky, use the current desktop. | 677 // If |window| is sticky, use the current desktop. |
| 663 if (desktop == kAllDesktops && | 678 if (desktop == kAllDesktops && |
| 664 !GetCurrentDesktop(&desktop)) | 679 !GetCurrentDesktop(&desktop)) |
| 665 return false; | 680 return false; |
| 666 | 681 |
| 667 XEvent event; | 682 XEvent event; |
| 668 event.xclient.type = ClientMessage; | 683 event.xclient.type = ClientMessage; |
| 669 event.xclient.window = window; | 684 event.xclient.window = window; |
| 670 event.xclient.message_type = gdk_x11_get_xatom_by_name_for_display( | 685 event.xclient.message_type = GetAtom("_NET_WM_DESKTOP"); |
| 671 gdk_display_get_default(), "_NET_WM_DESKTOP"); | |
| 672 event.xclient.format = 32; | 686 event.xclient.format = 32; |
| 673 event.xclient.data.l[0] = desktop; | 687 event.xclient.data.l[0] = desktop; |
| 674 event.xclient.data.l[1] = 1; // source indication | 688 event.xclient.data.l[1] = 1; // source indication |
| 675 | 689 |
| 676 int result = XSendEvent(GetXDisplay(), GetX11RootWindow(), False, | 690 int result = XSendEvent(GetXDisplay(), GetX11RootWindow(), False, |
| 677 SubstructureNotifyMask, &event); | 691 SubstructureNotifyMask, &event); |
| 678 return result == Success; | 692 return result == Success; |
| 679 } | 693 } |
| 680 | 694 |
| 681 void SetDefaultX11ErrorHandlers() { | 695 void SetDefaultX11ErrorHandlers() { |
| 682 SetX11ErrorHandlers(NULL, NULL); | 696 SetX11ErrorHandlers(NULL, NULL); |
| 683 } | 697 } |
| 684 | 698 |
| 685 bool IsX11WindowFullScreen(XID window) { | 699 bool IsX11WindowFullScreen(XID window) { |
| 686 // First check if _NET_WM_STATE property contains _NET_WM_STATE_FULLSCREEN. | 700 // First check if _NET_WM_STATE property contains _NET_WM_STATE_FULLSCREEN. |
| 687 static Atom atom = gdk_x11_get_xatom_by_name_for_display( | 701 static Atom atom = GetAtom("_NET_WM_STATE_FULLSCREEN"); |
| 688 gdk_display_get_default(), "_NET_WM_STATE_FULLSCREEN"); | |
| 689 | 702 |
| 690 std::vector<Atom> atom_properties; | 703 std::vector<Atom> atom_properties; |
| 691 if (GetAtomArrayProperty(window, | 704 if (GetAtomArrayProperty(window, |
| 692 "_NET_WM_STATE", | 705 "_NET_WM_STATE", |
| 693 &atom_properties) && | 706 &atom_properties) && |
| 694 std::find(atom_properties.begin(), atom_properties.end(), atom) | 707 std::find(atom_properties.begin(), atom_properties.end(), atom) |
| 695 != atom_properties.end()) | 708 != atom_properties.end()) |
| 696 return true; | 709 return true; |
| 697 | 710 |
| 711 #if defined(TOOLKIT_USES_GTK) | |
| 698 // As the last resort, check if the window size is as large as the main | 712 // As the last resort, check if the window size is as large as the main |
| 699 // screen. | 713 // screen. |
| 700 GdkRectangle monitor_rect; | 714 GdkRectangle monitor_rect; |
| 701 gdk_screen_get_monitor_geometry(gdk_screen_get_default(), 0, &monitor_rect); | 715 gdk_screen_get_monitor_geometry(gdk_screen_get_default(), 0, &monitor_rect); |
| 702 | 716 |
| 703 gfx::Rect window_rect; | 717 gfx::Rect window_rect; |
| 704 if (!ui::GetWindowRect(window, &window_rect)) | 718 if (!ui::GetWindowRect(window, &window_rect)) |
| 705 return false; | 719 return false; |
| 706 | 720 |
| 707 return monitor_rect.x == window_rect.x() && | 721 return monitor_rect.x == window_rect.x() && |
| 708 monitor_rect.y == window_rect.y() && | 722 monitor_rect.y == window_rect.y() && |
| 709 monitor_rect.width == window_rect.width() && | 723 monitor_rect.width == window_rect.width() && |
| 710 monitor_rect.height == window_rect.height(); | 724 monitor_rect.height == window_rect.height(); |
| 725 #else | |
| 726 NOTIMPLEMENTED(); | |
| 727 return false; | |
| 728 #endif | |
| 711 } | 729 } |
| 712 | 730 |
| 713 // ---------------------------------------------------------------------------- | 731 // ---------------------------------------------------------------------------- |
| 714 // These functions are declared in x11_util_internal.h because they require | 732 // 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. | 733 // XLib.h to be included, and it conflicts with many other headers. |
| 716 XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { | 734 XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { |
| 717 static XRenderPictFormat* pictformat = NULL; | 735 static XRenderPictFormat* pictformat = NULL; |
| 718 if (pictformat) | 736 if (pictformat) |
| 719 return pictformat; | 737 return pictformat; |
| 720 | 738 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 833 << "request_code " << static_cast<int>(error_event.request_code) << ", " | 851 << "request_code " << static_cast<int>(error_event.request_code) << ", " |
| 834 << "minor_code " << static_cast<int>(error_event.minor_code) | 852 << "minor_code " << static_cast<int>(error_event.minor_code) |
| 835 << " (" << request_str << ")"; | 853 << " (" << request_str << ")"; |
| 836 } | 854 } |
| 837 | 855 |
| 838 // ---------------------------------------------------------------------------- | 856 // ---------------------------------------------------------------------------- |
| 839 // End of x11_util_internal.h | 857 // End of x11_util_internal.h |
| 840 | 858 |
| 841 | 859 |
| 842 } // namespace ui | 860 } // namespace ui |
| OLD | NEW |