diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/active_window_watcher_x.cc | 102 | ||||
-rw-r--r-- | app/active_window_watcher_x.h | 56 | ||||
-rw-r--r-- | app/event_synthesis_gtk.cc | 90 | ||||
-rw-r--r-- | app/event_synthesis_gtk.h | 37 | ||||
-rw-r--r-- | app/gfx/font_util.cc | 40 | ||||
-rw-r--r-- | app/gfx/font_util.h | 30 | ||||
-rw-r--r-- | app/gfx/gl/gl_context_linux.cc | 18 | ||||
-rw-r--r-- | app/gtk_integers.h | 28 | ||||
-rw-r--r-- | app/gtk_signal.h | 117 | ||||
-rw-r--r-- | app/gtk_signal_registrar.cc | 74 | ||||
-rw-r--r-- | app/gtk_signal_registrar.h | 68 | ||||
-rw-r--r-- | app/message_box_flags.h | 58 | ||||
-rw-r--r-- | app/scoped_handle_gtk.h | 51 | ||||
-rw-r--r-- | app/surface/transport_dib.h | 2 | ||||
-rw-r--r-- | app/surface/transport_dib_linux.cc | 6 | ||||
-rw-r--r-- | app/text_elider.cc | 665 | ||||
-rw-r--r-- | app/text_elider.h | 119 | ||||
-rw-r--r-- | app/text_elider_unittest.cc | 439 | ||||
-rw-r--r-- | app/theme_provider.cc | 12 | ||||
-rw-r--r-- | app/theme_provider.h | 115 | ||||
-rw-r--r-- | app/view_prop.cc | 103 | ||||
-rw-r--r-- | app/view_prop.h | 47 | ||||
-rw-r--r-- | app/view_prop_unittest.cc | 70 | ||||
-rw-r--r-- | app/x11_util.cc | 880 | ||||
-rw-r--r-- | app/x11_util.h | 183 | ||||
-rw-r--r-- | app/x11_util_internal.h | 46 |
26 files changed, 13 insertions, 3443 deletions
diff --git a/app/active_window_watcher_x.cc b/app/active_window_watcher_x.cc deleted file mode 100644 index 65749648..0000000 --- a/app/active_window_watcher_x.cc +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <X11/Xlib.h> -#include <gdk/gdk.h> -#include <gdk/gdkx.h> - -#include "app/active_window_watcher_x.h" - -static Atom kNetActiveWindowAtom = None; - -// static -ActiveWindowWatcherX* ActiveWindowWatcherX::GetInstance() { - return Singleton<ActiveWindowWatcherX>::get(); -} - -// static -void ActiveWindowWatcherX::AddObserver(Observer* observer) { - GetInstance()->observers_.AddObserver(observer); -} - -// static -void ActiveWindowWatcherX::RemoveObserver(Observer* observer) { - GetInstance()->observers_.RemoveObserver(observer); -} - -ActiveWindowWatcherX::ActiveWindowWatcherX() { - Init(); -} - -ActiveWindowWatcherX::~ActiveWindowWatcherX() { -} - -void ActiveWindowWatcherX::Init() { - GdkAtom kNetActiveWindow = gdk_atom_intern("_NET_ACTIVE_WINDOW", FALSE); - kNetActiveWindowAtom = gdk_x11_atom_to_xatom_for_display( - gdk_screen_get_display(gdk_screen_get_default()), kNetActiveWindow); - - GdkWindow* root = gdk_get_default_root_window(); - - // Set up X Event filter to listen for PropertyChange X events. These events - // tell us when the active window changes. - // Don't use XSelectInput directly here, as gdk internally seems to cache the - // mask and reapply XSelectInput after this, resetting any mask we set here. - gdk_window_set_events(root, - static_cast<GdkEventMask>(gdk_window_get_events(root) | - GDK_PROPERTY_CHANGE_MASK)); - gdk_window_add_filter(NULL, &ActiveWindowWatcherX::OnWindowXEvent, this); -} - -void ActiveWindowWatcherX::NotifyActiveWindowChanged() { - // We don't use gdk_screen_get_active_window() because it caches - // whether or not the window manager supports _NET_ACTIVE_WINDOW. - // This causes problems at startup for chromiumos. - Atom type = None; - int format = 0; // size in bits of each item in 'property' - long unsigned int num_items = 0, remaining_bytes = 0; - unsigned char* property = NULL; - - XGetWindowProperty(gdk_x11_get_default_xdisplay(), - GDK_WINDOW_XID(gdk_get_default_root_window()), - kNetActiveWindowAtom, - 0, // offset into property data to read - 1, // length to get in 32-bit quantities - False, // deleted - AnyPropertyType, - &type, - &format, - &num_items, - &remaining_bytes, - &property); - - // Check that the property was set and contained a single 32-bit item (we - // don't check that remaining_bytes is 0, though, as XFCE's window manager - // seems to actually store two values in the property for some unknown - // reason.) - if (format == 32 && num_items == 1) { - int xid = *reinterpret_cast<int*>(property); - GdkWindow* active_window = gdk_window_lookup(xid); - FOR_EACH_OBSERVER( - Observer, - observers_, - ActiveWindowChanged(active_window)); - } - if (property) - XFree(property); -} - -GdkFilterReturn ActiveWindowWatcherX::OnWindowXEvent(GdkXEvent* xevent, - GdkEvent* event, gpointer window_watcher) { - ActiveWindowWatcherX* watcher = reinterpret_cast<ActiveWindowWatcherX*>( - window_watcher); - XEvent* xev = static_cast<XEvent*>(xevent); - - if (xev->xany.type == PropertyNotify && - xev->xproperty.atom == kNetActiveWindowAtom) { - watcher->NotifyActiveWindowChanged(); - } - - return GDK_FILTER_CONTINUE; -} diff --git a/app/active_window_watcher_x.h b/app/active_window_watcher_x.h deleted file mode 100644 index 4a89686..0000000 --- a/app/active_window_watcher_x.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef APP_ACTIVE_WINDOW_WATCHER_X_H_ -#define APP_ACTIVE_WINDOW_WATCHER_X_H_ -#pragma once - -#include <gdk/gdk.h> - -#include "base/basictypes.h" -#include "base/observer_list.h" -#include "base/singleton.h" - -// This is a helper class that is used to keep track of which window the X -// window manager thinks is active. Add an Observer to listener for changes to -// the active window. -class ActiveWindowWatcherX { - public: - class Observer { - public: - // |active_window| will be NULL if the active window isn't one of Chrome's. - virtual void ActiveWindowChanged(GdkWindow* active_window) = 0; - - protected: - virtual ~Observer() {} - }; - - static ActiveWindowWatcherX* GetInstance(); - - static void AddObserver(Observer* observer); - static void RemoveObserver(Observer* observer); - - private: - friend struct DefaultSingletonTraits<ActiveWindowWatcherX>; - - ActiveWindowWatcherX(); - ~ActiveWindowWatcherX(); - - void Init(); - - // Sends a notification out through the NotificationService that the active - // window has changed. - void NotifyActiveWindowChanged(); - - // Callback for PropertyChange XEvents. - static GdkFilterReturn OnWindowXEvent(GdkXEvent* xevent, - GdkEvent* event, - gpointer window_watcher); - - ObserverList<Observer> observers_; - - DISALLOW_COPY_AND_ASSIGN(ActiveWindowWatcherX); -}; - -#endif // APP_ACTIVE_WINDOW_WATCHER_X_H_ diff --git a/app/event_synthesis_gtk.cc b/app/event_synthesis_gtk.cc deleted file mode 100644 index 72dd7b9..0000000 --- a/app/event_synthesis_gtk.cc +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "app/event_synthesis_gtk.h" - -#include "ui/base/keycodes/keyboard_code_conversion_gtk.h" - -namespace app { - -GdkEvent* SynthesizeKeyEvent(GdkWindow* window, - bool press, guint gdk_key, guint state) { - GdkEvent* event = gdk_event_new(press ? GDK_KEY_PRESS : GDK_KEY_RELEASE); - - event->key.type = press ? GDK_KEY_PRESS : GDK_KEY_RELEASE; - event->key.window = window; - if (window) - g_object_ref(window); - event->key.send_event = false; - - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - event->key.time = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; - - event->key.state = state; - event->key.keyval = gdk_key; - - GdkKeymapKey* keys; - gint n_keys; - if (event->key.keyval != 0 && - gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), - event->key.keyval, &keys, &n_keys)) { - event->key.hardware_keycode = keys[0].keycode; - event->key.group = keys[0].group; - g_free(keys); - } - - return event; -} - -void SynthesizeKeyPressEvents(GdkWindow* window, - ui::KeyboardCode key, - bool control, bool shift, bool alt, - std::vector<GdkEvent*>* events) { - if (control) - events->push_back( - SynthesizeKeyEvent(window, true, GDK_Control_L, 0)); - - if (shift) { - events->push_back(SynthesizeKeyEvent(window, true, GDK_Shift_L, - control ? GDK_CONTROL_MASK : 0)); - } - - if (alt) { - guint state = (control ? GDK_CONTROL_MASK : 0) | - (shift ? GDK_SHIFT_MASK : 0); - events->push_back( - SynthesizeKeyEvent(window, true, GDK_Alt_L, state)); - } - - // TODO(estade): handle other state flags besides control, shift, alt? - // For example caps lock. - guint state = (control ? GDK_CONTROL_MASK : 0) | - (shift ? GDK_SHIFT_MASK : 0) | - (alt ? GDK_MOD1_MASK : 0); - - guint gdk_key = GdkKeyCodeForWindowsKeyCode(key, shift); - events->push_back(SynthesizeKeyEvent(window, true, gdk_key, state)); - events->push_back(SynthesizeKeyEvent(window, false, gdk_key, state)); - - if (alt) { - guint state = (control ? GDK_CONTROL_MASK : 0) | - (shift ? GDK_SHIFT_MASK : 0) | GDK_MOD1_MASK; - events->push_back( - SynthesizeKeyEvent(window, false, GDK_Alt_L, state)); - } - - if (shift) { - events->push_back( - SynthesizeKeyEvent(window, false, GDK_Shift_L, - (control ? GDK_CONTROL_MASK : 0) | GDK_SHIFT_MASK)); - } - - if (control) { - events->push_back( - SynthesizeKeyEvent(window, false, GDK_Control_L, GDK_CONTROL_MASK)); - } -} - -} // namespace app diff --git a/app/event_synthesis_gtk.h b/app/event_synthesis_gtk.h deleted file mode 100644 index 3ee1cb3..0000000 --- a/app/event_synthesis_gtk.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This file declares routines for creating fake GDK events (at the moment, -// only keyboard events). This is useful for a variety of testing purposes. -// NOTE: This should not be used outside of testing. - -#ifndef APP_EVENT_SYNTHESIS_GTK_ -#define APP_EVENT_SYNTHESIS_GTK_ -#pragma once - -#include <gdk/gdk.h> -#include <gdk/gdkkeysyms.h> -#include <vector> - -#include "ui/base/keycodes/keyboard_codes.h" - -namespace app { - -// Creates and returns a key event. Passes ownership to the caller. -GdkEvent* SynthesizeKeyEvent(GdkWindow* event_window, - bool press, - guint gdk_key, - guint state); - -// Creates the proper sequence of key events for a key press + release. -// Ownership of the events in the vector is passed to the caller. -void SynthesizeKeyPressEvents( - GdkWindow* window, - ui::KeyboardCode key, - bool control, bool shift, bool alt, - std::vector<GdkEvent*>* events); - -} // namespace app - -#endif // APP_EVENT_SYNTHESIS_GTK_ diff --git a/app/gfx/font_util.cc b/app/gfx/font_util.cc deleted file mode 100644 index a977f57..0000000 --- a/app/gfx/font_util.cc +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "app/gfx/font_util.h" - -#include "app/l10n_util.h" -#include "base/logging.h" -#include "base/string_number_conversions.h" -#include "base/utf_string_conversions.h" -#include "gfx/font.h" - -namespace gfx { - -int GetLocalizedContentsWidthForFont(int col_resource_id, - const gfx::Font& font) { - double chars = 0; - base::StringToDouble(l10n_util::GetStringUTF8(col_resource_id), &chars); - int width = font.GetExpectedTextWidth(static_cast<int>(chars)); - DCHECK_GT(width, 0); - return width; -} - -int GetLocalizedContentsHeightForFont(int row_resource_id, - const gfx::Font& font) { - double lines = 0; - base::StringToDouble(l10n_util::GetStringUTF8(row_resource_id), &lines); - int height = static_cast<int>(font.GetHeight() * lines); - DCHECK_GT(height, 0); - return height; -} - -gfx::Size GetLocalizedContentsSizeForFont(int col_resource_id, - int row_resource_id, - const gfx::Font& font) { - return gfx::Size(GetLocalizedContentsWidthForFont(col_resource_id, font), - GetLocalizedContentsHeightForFont(row_resource_id, font)); -} - -} // namespace gfx diff --git a/app/gfx/font_util.h b/app/gfx/font_util.h deleted file mode 100644 index c7c3e97..0000000 --- a/app/gfx/font_util.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef APP_GFX_FONT_UTIL_H_ -#define APP_GFX_FONT_UTIL_H_ -#pragma once - -#include "gfx/size.h" - -namespace gfx { - -class Font; - -// Returns the preferred size of the contents view of a window based on -// its localized size data and the given font. The width in cols is held in a -// localized string resource identified by |col_resource_id|, the height in the -// same fashion. -int GetLocalizedContentsWidthForFont(int col_resource_id, - const gfx::Font& font); -int GetLocalizedContentsHeightForFont(int row_resource_id, - const gfx::Font& font); -gfx::Size GetLocalizedContentsSizeForFont(int col_resource_id, - int row_resource_id, - const gfx::Font& font); - -} // namespace gfx - -#endif // APP_GFX_FONT_UTIL_H_ - diff --git a/app/gfx/gl/gl_context_linux.cc b/app/gfx/gl/gl_context_linux.cc index 9e4bfee..ec31ceb 100644 --- a/app/gfx/gl/gl_context_linux.cc +++ b/app/gfx/gl/gl_context_linux.cc @@ -17,10 +17,10 @@ extern "C" { #include "app/gfx/gl/gl_context_osmesa.h" #include "app/gfx/gl/gl_context_stub.h" #include "app/gfx/gl/gl_implementation.h" -#include "app/x11_util.h" #include "base/basictypes.h" #include "base/logging.h" #include "base/scoped_ptr.h" +#include "ui/base/x/x11_util.h" namespace { @@ -420,14 +420,14 @@ bool OSMesaViewGLContext::SwapBuffers() { // Copy the frame into the pixmap. XWindowAttributes attributes; XGetWindowAttributes(display, window_, &attributes); - x11_util::PutARGBImage(display, - attributes.visual, - attributes.depth, - pixmap_, - pixmap_graphics_context_, - static_cast<const uint8*>(osmesa_context_.buffer()), - size.width(), - size.height()); + ui::PutARGBImage(display, + attributes.visual, + attributes.depth, + pixmap_, + pixmap_graphics_context_, + static_cast<const uint8*>(osmesa_context_.buffer()), + size.width(), + size.height()); // Copy the pixmap to the window. XCopyArea(display, diff --git a/app/gtk_integers.h b/app/gtk_integers.h deleted file mode 100644 index 6bc6013..0000000 --- a/app/gtk_integers.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef APP_GTK_INTEGERS_H_ -#define APP_GTK_INTEGERS_H_ -#pragma once - -// GLib/Gobject/Gtk all use their own integer typedefs. They are copied here -// for forward declaration reasons so we don't pull in all of gtk.h when we -// just need a gpointer. -typedef char gchar; -typedef short gshort; -typedef long glong; -typedef int gint; -typedef gint gboolean; -typedef unsigned char guchar; -typedef unsigned short gushort; -typedef unsigned long gulong; -typedef unsigned int guint; - -typedef unsigned short guint16; -typedef unsigned int guint32; - -typedef void* gpointer; -typedef const void *gconstpointer; - -#endif // APP_GTK_INTEGERS_H_ diff --git a/app/gtk_signal.h b/app/gtk_signal.h deleted file mode 100644 index 5d3defe..0000000 --- a/app/gtk_signal.h +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef APP_GTK_SIGNAL_H_ -#define APP_GTK_SIGNAL_H_ -#pragma once - -typedef void* gpointer; -typedef struct _GtkWidget GtkWidget; - -// At the time of writing this, there were two common ways of binding our C++ -// code to the gobject C system. We either defined a whole bunch of "static -// MethodThunk()" which just called nonstatic Method()s on a class (which hurt -// readability of the headers and signal connection code) OR we declared -// "static Method()" and passed in the current object as the gpointer (and hurt -// readability in the implementation by having "context->" before every -// variable). - -// The hopeful result of using these macros is that the code will be more -// readable and regular. There shouldn't be a bunch of static Thunks visible in -// the headers and the implementations shouldn't be filled with "context->" -// de-references. - -#define CHROMEG_CALLBACK_0(CLASS, RETURN, METHOD, SENDER) \ - static RETURN METHOD ## Thunk(SENDER sender, gpointer userdata) { \ - return reinterpret_cast<CLASS*>(userdata)->METHOD(sender); \ - } \ - \ - virtual RETURN METHOD(SENDER); - -#define CHROMEG_CALLBACK_1(CLASS, RETURN, METHOD, SENDER, ARG1) \ - static RETURN METHOD ## Thunk(SENDER sender, ARG1 one, \ - gpointer userdata) { \ - return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one); \ - } \ - \ - virtual RETURN METHOD(SENDER, ARG1); - -#define CHROMEG_CALLBACK_2(CLASS, RETURN, METHOD, SENDER, ARG1, ARG2) \ - static RETURN METHOD ## Thunk(SENDER sender, ARG1 one, ARG2 two, \ - gpointer userdata) { \ - return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one, two); \ - } \ - \ - virtual RETURN METHOD(SENDER, ARG1, ARG2); - -#define CHROMEG_CALLBACK_3(CLASS, RETURN, METHOD, SENDER, ARG1, ARG2, ARG3) \ - static RETURN METHOD ## Thunk(SENDER sender, ARG1 one, ARG2 two, \ - ARG3 three, gpointer userdata) { \ - return reinterpret_cast<CLASS*>(userdata)-> \ - METHOD(sender, one, two, three); \ - } \ - \ - virtual RETURN METHOD(SENDER, ARG1, ARG2, ARG3); - -#define CHROMEG_CALLBACK_4(CLASS, RETURN, METHOD, SENDER, ARG1, ARG2, ARG3, \ - ARG4) \ - static RETURN METHOD ## Thunk(SENDER sender, ARG1 one, ARG2 two, \ - ARG3 three, ARG4 four, \ - gpointer userdata) { \ - return reinterpret_cast<CLASS*>(userdata)-> \ - METHOD(sender, one, two, three, four); \ - } \ - \ - virtual RETURN METHOD(SENDER, ARG1, ARG2, ARG3, ARG4); - -#define CHROMEG_CALLBACK_5(CLASS, RETURN, METHOD, SENDER, ARG1, ARG2, ARG3, \ - ARG4, ARG5) \ - static RETURN METHOD ## Thunk(SENDER sender, ARG1 one, ARG2 two, \ - ARG3 three, ARG4 four, ARG5 five, \ - gpointer userdata) { \ - return reinterpret_cast<CLASS*>(userdata)-> \ - METHOD(sender, one, two, three, four, five); \ - } \ - \ - virtual RETURN METHOD(SENDER, ARG1, ARG2, ARG3, ARG4, ARG5); - -#define CHROMEG_CALLBACK_6(CLASS, RETURN, METHOD, SENDER, ARG1, ARG2, ARG3, \ - ARG4, ARG5, ARG6) \ - static RETURN METHOD ## Thunk(SENDER sender, ARG1 one, ARG2 two, \ - ARG3 three, ARG4 four, ARG5 five, \ - ARG6 six, gpointer userdata) { \ - return reinterpret_cast<CLASS*>(userdata)-> \ - METHOD(sender, one, two, three, four, five, six); \ - } \ - \ - virtual RETURN METHOD(SENDER, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6); - -// These macros handle the common case where the sender object will be a -// GtkWidget*. -#define CHROMEGTK_CALLBACK_0(CLASS, RETURN, METHOD) \ - CHROMEG_CALLBACK_0(CLASS, RETURN, METHOD, GtkWidget*); - -#define CHROMEGTK_CALLBACK_1(CLASS, RETURN, METHOD, ARG1) \ - CHROMEG_CALLBACK_1(CLASS, RETURN, METHOD, GtkWidget*, ARG1); - -#define CHROMEGTK_CALLBACK_2(CLASS, RETURN, METHOD, ARG1, ARG2) \ - CHROMEG_CALLBACK_2(CLASS, RETURN, METHOD, GtkWidget*, ARG1, ARG2); - -#define CHROMEGTK_CALLBACK_3(CLASS, RETURN, METHOD, ARG1, ARG2, ARG3) \ - CHROMEG_CALLBACK_3(CLASS, RETURN, METHOD, GtkWidget*, ARG1, ARG2, ARG3); - -#define CHROMEGTK_CALLBACK_4(CLASS, RETURN, METHOD, ARG1, ARG2, ARG3, ARG4) \ - CHROMEG_CALLBACK_4(CLASS, RETURN, METHOD, GtkWidget*, ARG1, ARG2, ARG3, ARG4); - -#define CHROMEGTK_CALLBACK_5(CLASS, RETURN, METHOD, ARG1, ARG2, ARG3, ARG4, \ - ARG5) \ - CHROMEG_CALLBACK_5(CLASS, RETURN, METHOD, GtkWidget*, ARG1, ARG2, ARG3, \ - ARG4, ARG5); - -#define CHROMEGTK_CALLBACK_6(CLASS, RETURN, METHOD, ARG1, ARG2, ARG3, ARG4, \ - ARG5, ARG6) \ - CHROMEG_CALLBACK_6(CLASS, RETURN, METHOD, GtkWidget*, ARG1, ARG2, ARG3, \ - ARG4, ARG5, ARG6); - -#endif // APP_GTK_SIGNAL_H_ diff --git a/app/gtk_signal_registrar.cc b/app/gtk_signal_registrar.cc deleted file mode 100644 index 5530405..0000000 --- a/app/gtk_signal_registrar.cc +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "app/gtk_signal_registrar.h" - -#include <glib-object.h> - -#include "base/logging.h" - -GtkSignalRegistrar::GtkSignalRegistrar() { -} - -GtkSignalRegistrar::~GtkSignalRegistrar() { - for (HandlerMap::iterator list_iter = handler_lists_.begin(); - list_iter != handler_lists_.end(); ++list_iter) { - GObject* object = list_iter->first; - g_object_weak_unref(object, WeakNotifyThunk, this); - - HandlerList& handlers = list_iter->second; - for (HandlerList::iterator ids_iter = handlers.begin(); - ids_iter != handlers.end(); ids_iter++) { - g_signal_handler_disconnect(list_iter->first, *ids_iter); - } - } -} - -glong GtkSignalRegistrar::Connect(gpointer instance, - const gchar* detailed_signal, - GCallback signal_handler, - gpointer data) { - return ConnectInternal(instance, detailed_signal, signal_handler, data, - false); -} - -glong GtkSignalRegistrar::ConnectAfter(gpointer instance, - const gchar* detailed_signal, - GCallback signal_handler, - gpointer data) { - return ConnectInternal(instance, detailed_signal, signal_handler, data, true); -} - -glong GtkSignalRegistrar::ConnectInternal(gpointer instance, - const gchar* detailed_signal, - GCallback signal_handler, - gpointer data, - bool after) { - GObject* object = G_OBJECT(instance); - - HandlerMap::iterator iter = handler_lists_.find(object); - if (iter == handler_lists_.end()) { - g_object_weak_ref(object, WeakNotifyThunk, this); - handler_lists_[object] = HandlerList(); - iter = handler_lists_.find(object); - } - - glong handler_id = after ? - g_signal_connect_after(instance, detailed_signal, signal_handler, data) : - g_signal_connect(instance, detailed_signal, signal_handler, data); - iter->second.push_back(handler_id); - - return handler_id; -} - -void GtkSignalRegistrar::WeakNotify(GObject* where_the_object_was) { - HandlerMap::iterator iter = handler_lists_.find(where_the_object_was); - if (iter == handler_lists_.end()) { - NOTREACHED(); - return; - } - // The signal handlers will be disconnected automatically. Just erase the - // handler id list. - handler_lists_.erase(iter); -} diff --git a/app/gtk_signal_registrar.h b/app/gtk_signal_registrar.h deleted file mode 100644 index 65e0917..0000000 --- a/app/gtk_signal_registrar.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef APP_GTK_SIGNAL_REGISTRAR_H_ -#define APP_GTK_SIGNAL_REGISTRAR_H_ -#pragma once - -#include <glib.h> -#include <map> -#include <vector> - -#include "base/basictypes.h" - -typedef void (*GCallback) (void); -typedef struct _GObject GObject; -typedef struct _GtkWidget GtkWidget; - -// A class that ensures that callbacks don't run on stale owner objects. Similar -// in spirit to NotificationRegistrar. Use as follows: -// -// class ChromeObject { -// public: -// ChromeObject() { -// ... -// -// signals_.Connect(widget, "event", CallbackThunk, this); -// } -// -// ... -// -// private: -// GtkSignalRegistrar signals_; -// }; -// -// When |signals_| goes down, it will disconnect the handlers connected via -// Connect. -class GtkSignalRegistrar { - public: - GtkSignalRegistrar(); - ~GtkSignalRegistrar(); - - // Connect before the default handler. Returns the handler id. - glong Connect(gpointer instance, const gchar* detailed_signal, - GCallback signal_handler, gpointer data); - // Connect after the default handler. Returns the handler id. - glong ConnectAfter(gpointer instance, const gchar* detailed_signal, - GCallback signal_handler, gpointer data); - - private: - typedef std::vector<glong> HandlerList; - typedef std::map<GObject*, HandlerList> HandlerMap; - - static void WeakNotifyThunk(gpointer data, GObject* where_the_object_was) { - reinterpret_cast<GtkSignalRegistrar*>(data)->WeakNotify( - where_the_object_was); - } - void WeakNotify(GObject* where_the_object_was); - - glong ConnectInternal(gpointer instance, const gchar* detailed_signal, - GCallback signal_handler, gpointer data, bool after); - - HandlerMap handler_lists_; - - DISALLOW_COPY_AND_ASSIGN(GtkSignalRegistrar); -}; - -#endif // APP_GTK_SIGNAL_REGISTRAR_H_ diff --git a/app/message_box_flags.h b/app/message_box_flags.h deleted file mode 100644 index 25816e9..0000000 --- a/app/message_box_flags.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef APP_MESSAGE_BOX_FLAGS_H_ -#define APP_MESSAGE_BOX_FLAGS_H_ -#pragma once - -#include "base/basictypes.h" - -// This class contains flags used to communicate the type of message box -// to show. E.g., the renderer can request the browser to show a -// javascript alert or a javascript confirm message. -class MessageBoxFlags { - public: - static const int kFlagHasOKButton = 0x1; - static const int kFlagHasCancelButton = 0x2; - static const int kFlagHasPromptField = 0x4; - static const int kFlagHasMessage = 0x8; - - // The following flag is used to indicate whether the message's alignment - // should be autodetected or inherited from Chrome UI. Callers should pass - // the correct flag based on the origin of the message. If the message is - // from a web page (such as the JavaScript alert message), its alignment and - // directionality are based on the first character with strong directionality - // in the message. Chrome UI strings are localized string and therefore they - // should have the same alignment and directionality as those of the Chrome - // UI. For example, in RTL locales, even though some strings might begin with - // an English character, they should still be right aligned and be displayed - // Right-To-Left. - // - // TODO(xji): If the message is from a web page, then the message - // directionality should be determined based on the directionality of the web - // page. Please refer to http://crbug.com/7166 for more information. - static const int kAutoDetectAlignment = 0x10; - - static const int kIsConfirmMessageBox = kFlagHasMessage | - kFlagHasOKButton | - kFlagHasCancelButton; - static const int kIsJavascriptAlert = kFlagHasOKButton | kFlagHasMessage; - static const int kIsJavascriptConfirm = kIsJavascriptAlert | - kFlagHasCancelButton; - static const int kIsJavascriptPrompt = kIsJavascriptConfirm | - kFlagHasPromptField; - - // Dialog button identifiers used to specify which buttons to show the user. - enum DialogButton { - DIALOGBUTTON_NONE = 0, // No dialog buttons, for WindowType == WINDOW. - DIALOGBUTTON_OK = 1, // Has an OK button. - DIALOGBUTTON_CANCEL = 2, // Has a Cancel button (becomes a Close button if - }; // no OK button). - - private: - MessageBoxFlags() {} - DISALLOW_COPY_AND_ASSIGN(MessageBoxFlags); -}; - -#endif // APP_MESSAGE_BOX_FLAGS_H_ diff --git a/app/scoped_handle_gtk.h b/app/scoped_handle_gtk.h deleted file mode 100644 index 95b1cd5..0000000 --- a/app/scoped_handle_gtk.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef APP_SCOPED_HANDLE_GTK_H_ -#define APP_SCOPED_HANDLE_GTK_H_ -#pragma once - -#include <gdk/gdk.h> - -// Wraps a GdkRegion. This class provides the same methods as ScopedGDIObject in -// scoped_handle_win. -class ScopedRegion { - public: - ScopedRegion() : region_(NULL) {} - explicit ScopedRegion(GdkRegion* region) : region_(region) {} - - ~ScopedRegion() { - Close(); - } - - void Set(GdkRegion* region) { - Close(); - - region_ = region; - } - - GdkRegion* Get() { - return region_; - } - - GdkRegion* release() { - GdkRegion* region = region_; - region_ = NULL; - return region; - } - - private: - void Close() { - if (region_) { - gdk_region_destroy(region_); - region_ = NULL; - } - } - - GdkRegion* region_; - - DISALLOW_COPY_AND_ASSIGN(ScopedRegion); -}; - -#endif // APP_SCOPED_HANDLE_GTK_H_ diff --git a/app/surface/transport_dib.h b/app/surface/transport_dib.h index d82c346..a55f624 100644 --- a/app/surface/transport_dib.h +++ b/app/surface/transport_dib.h @@ -15,7 +15,7 @@ #if defined(OS_WIN) #include <windows.h> #elif defined(USE_X11) -#include "app/x11_util.h" +#include "ui/base/x/x11_util.h" #endif namespace skia { diff --git a/app/surface/transport_dib_linux.cc b/app/surface/transport_dib_linux.cc index 9976e50..549ee52 100644 --- a/app/surface/transport_dib_linux.cc +++ b/app/surface/transport_dib_linux.cc @@ -8,11 +8,11 @@ #include <sys/shm.h> #include "app/surface/transport_dib.h" -#include "app/x11_util.h" #include "base/logging.h" #include "base/scoped_ptr.h" #include "gfx/size.h" #include "skia/ext/platform_canvas.h" +#include "ui/base/x/x11_util.h" // The shmat system call uses this as it's invalid return address static void *const kInvalidAddress = (void*) -1; @@ -33,7 +33,7 @@ TransportDIB::~TransportDIB() { if (x_shm_) { DCHECK(display_); - x11_util::DetachSharedMemory(display_, x_shm_); + ui::DetachSharedMemory(display_, x_shm_); } } @@ -128,7 +128,7 @@ TransportDIB::Handle TransportDIB::handle() const { XID TransportDIB::MapToX(Display* display) { if (!x_shm_) { - x_shm_ = x11_util::AttachSharedMemory(display, key_); + x_shm_ = ui::AttachSharedMemory(display, key_); display_ = display; } diff --git a/app/text_elider.cc b/app/text_elider.cc deleted file mode 100644 index 77ad958..0000000 --- a/app/text_elider.cc +++ /dev/null @@ -1,665 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <vector> - -#include "app/text_elider.h" -#include "base/file_path.h" -#include "base/i18n/break_iterator.h" -#include "base/i18n/char_iterator.h" -#include "base/i18n/rtl.h" -#include "base/string_split.h" -#include "base/string_util.h" -#include "base/sys_string_conversions.h" -#include "base/utf_string_conversions.h" -#include "gfx/font.h" -#include "googleurl/src/gurl.h" -#include "net/base/escape.h" -#include "net/base/net_util.h" -#include "net/base/registry_controlled_domain.h" - -namespace { - -const char* kEllipsis = "\xE2\x80\xA6"; - -// Cuts |text| to be |length| characters long. If |cut_in_middle| is true, the -// middle of the string is removed to leave equal-length pieces from the -// beginning and end of the string; otherwise, the end of the string is removed -// and only the beginning remains. If |insert_ellipsis| is true, then an -// ellipsis character will by inserted at the cut point. -string16 CutString(const string16& text, - size_t length, - bool cut_in_middle, - bool insert_ellipsis) { - // TODO(tony): This is wrong, it might split the string in the middle of a - // surrogate pair. - const string16 kInsert = insert_ellipsis ? UTF8ToUTF16(kEllipsis) : - ASCIIToUTF16(""); - if (!cut_in_middle) - return text.substr(0, length) + kInsert; - // We put the extra character, if any, before the cut. - const size_t half_length = length / 2; - return text.substr(0, length - half_length) + kInsert + - text.substr(text.length() - half_length, half_length); -} - -} // namespace - -namespace gfx { - -// This function takes a GURL object and elides it. It returns a string -// which composed of parts from subdomain, domain, path, filename and query. -// A "..." is added automatically at the end if the elided string is bigger -// than the available pixel width. For available pixel width = 0, a formatted, -// but un-elided, string is returned. -// -// TODO(pkasting): http://b/119635 This whole function gets -// kerning/ligatures/etc. issues potentially wrong by assuming that the width of -// a rendered string is always the sum of the widths of its substrings. Also I -// suspect it could be made simpler. -string16 ElideUrl(const GURL& url, - const gfx::Font& font, - int available_pixel_width, - const std::wstring& languages) { - // Get a formatted string and corresponding parsing of the url. - url_parse::Parsed parsed; - string16 url_string = net::FormatUrl(url, WideToUTF8(languages), - net::kFormatUrlOmitAll, UnescapeRule::SPACES, &parsed, NULL, NULL); - if (available_pixel_width <= 0) - return url_string; - - // If non-standard or not file type, return plain eliding. - if (!(url.SchemeIsFile() || url.IsStandard())) - return ElideText(url_string, font, available_pixel_width, false); - - // Now start eliding url_string to fit within available pixel width. - // Fist pass - check to see whether entire url_string fits. - int pixel_width_url_string = font.GetStringWidth(url_string); - if (available_pixel_width >= pixel_width_url_string) - return url_string; - - // Get the path substring, including query and reference. - size_t path_start_index = parsed.path.begin; - size_t path_len = parsed.path.len; - string16 url_path_query_etc = url_string.substr(path_start_index); - string16 url_path = url_string.substr(path_start_index, path_len); - - // Return general elided text if url minus the query fits. - string16 url_minus_query = url_string.substr(0, path_start_index + path_len); - if (available_pixel_width >= font.GetStringWidth(url_minus_query)) - return ElideText(url_string, font, available_pixel_width, false); - - // Get Host. - string16 url_host = UTF8ToUTF16(url.host()); - - // Get domain and registry information from the URL. - string16 url_domain = UTF8ToUTF16( - net::RegistryControlledDomainService::GetDomainAndRegistry(url)); - if (url_domain.empty()) - url_domain = url_host; - - // Add port if required. - if (!url.port().empty()) { - url_host += UTF8ToUTF16(":" + url.port()); - url_domain += UTF8ToUTF16(":" + url.port()); - } - - // Get sub domain. - string16 url_subdomain; - size_t domain_start_index = url_host.find(url_domain); - if (domain_start_index > 0) - url_subdomain = url_host.substr(0, domain_start_index); - static const string16 kWwwPrefix = UTF8ToUTF16("www."); - if ((url_subdomain == kWwwPrefix || url_subdomain.empty() || - url.SchemeIsFile())) { - url_subdomain.clear(); - } - - // If this is a file type, the path is now defined as everything after ":". - // For example, "C:/aa/aa/bb", the path is "/aa/bb/cc". Interesting, the - // domain is now C: - this is a nice hack for eliding to work pleasantly. - if (url.SchemeIsFile()) { - // Split the path string using ":" - std::vector<string16> file_path_split; - base::SplitString(url_path, ':', &file_path_split); - if (file_path_split.size() > 1) { // File is of type "file:///C:/.." - url_host.clear(); - url_domain.clear(); - url_subdomain.clear(); - - static const string16 kColon = UTF8ToUTF16(":"); - url_host = url_domain = file_path_split.at(0).substr(1) + kColon; - url_path_query_etc = url_path = file_path_split.at(1); - } - } - - // Second Pass - remove scheme - the rest fits. - int pixel_width_url_host = font.GetStringWidth(url_host); - int pixel_width_url_path = font.GetStringWidth(url_path_query_etc); - if (available_pixel_width >= - pixel_width_url_host + pixel_width_url_path) - return url_host + url_path_query_etc; - - // Third Pass: Subdomain, domain and entire path fits. - int pixel_width_url_domain = font.GetStringWidth(url_domain); - int pixel_width_url_subdomain = font.GetStringWidth(url_subdomain); - if (available_pixel_width >= - pixel_width_url_subdomain + pixel_width_url_domain + - pixel_width_url_path) - return url_subdomain + url_domain + url_path_query_etc; - - // Query element. - string16 url_query; - const int kPixelWidthDotsTrailer = - font.GetStringWidth(UTF8ToUTF16(kEllipsis)); - if (parsed.query.is_nonempty()) { - url_query = UTF8ToUTF16("?") + url_string.substr(parsed.query.begin); - if (available_pixel_width >= (pixel_width_url_subdomain + - pixel_width_url_domain + pixel_width_url_path - - font.GetStringWidth(url_query))) { - return ElideText(url_subdomain + url_domain + url_path_query_etc, - font, available_pixel_width, false); - } - } - - // Parse url_path using '/'. - static const string16 kForwardSlash = UTF8ToUTF16("/"); - std::vector<string16> url_path_elements; - base::SplitString(url_path, kForwardSlash[0], &url_path_elements); - - // Get filename - note that for a path ending with / - // such as www.google.com/intl/ads/, the file name is ads/. - size_t url_path_number_of_elements = url_path_elements.size(); - DCHECK(url_path_number_of_elements != 0); - string16 url_filename; - if ((url_path_elements.at(url_path_number_of_elements - 1)).length() > 0) { - url_filename = *(url_path_elements.end() - 1); - } else if (url_path_number_of_elements > 1) { // Path ends with a '/'. - url_filename = url_path_elements.at(url_path_number_of_elements - 2) + - kForwardSlash; - url_path_number_of_elements--; - } - DCHECK(url_path_number_of_elements != 0); - - const size_t kMaxNumberOfUrlPathElementsAllowed = 1024; - if (url_path_number_of_elements <= 1 || - url_path_number_of_elements > kMaxNumberOfUrlPathElementsAllowed) { - // No path to elide, or too long of a path (could overflow in loop below) - // Just elide this as a text string. - return ElideText(url_subdomain + url_domain + url_path_query_etc, font, - available_pixel_width, false); - } - - // Start eliding the path and replacing elements by "../". - const string16 kEllipsisAndSlash = UTF8ToUTF16(kEllipsis) + kForwardSlash; - int pixel_width_url_filename = font.GetStringWidth(url_filename); - int pixel_width_dot_dot_slash = font.GetStringWidth(kEllipsisAndSlash); - int pixel_width_slash = font.GetStringWidth(ASCIIToUTF16("/")); - int pixel_width_url_path_elements[kMaxNumberOfUrlPathElementsAllowed]; - for (size_t i = 0; i < url_path_number_of_elements; ++i) { - pixel_width_url_path_elements[i] = - font.GetStringWidth(url_path_elements.at(i)); - } - - // Check with both subdomain and domain. - string16 elided_path; - int pixel_width_elided_path; - for (size_t i = url_path_number_of_elements - 1; i >= 1; --i) { - // Add the initial elements of the path. - elided_path.clear(); - pixel_width_elided_path = 0; - for (size_t j = 0; j < i; ++j) { - elided_path += url_path_elements.at(j) + kForwardSlash; - pixel_width_elided_path += pixel_width_url_path_elements[j] + - pixel_width_slash; - } - - // Add url_file_name. - if (i == (url_path_number_of_elements - 1)) { - elided_path += url_filename; - pixel_width_elided_path += pixel_width_url_filename; - } else { - elided_path += kEllipsisAndSlash + url_filename; - pixel_width_elided_path += pixel_width_dot_dot_slash + - pixel_width_url_filename; - } - - if (available_pixel_width >= - pixel_width_url_subdomain + pixel_width_url_domain + - pixel_width_elided_path) { - return ElideText(url_subdomain + url_domain + elided_path + url_query, - font, available_pixel_width, false); - } - } - - // Check with only domain. - // If a subdomain is present, add an ellipsis before domain. - // This is added only if the subdomain pixel width is larger than - // the pixel width of kEllipsis. Otherwise, subdomain remains, - // which means that this case has been resolved earlier. - string16 url_elided_domain = url_subdomain + url_domain; - int pixel_width_url_elided_domain = pixel_width_url_domain; - if (pixel_width_url_subdomain > kPixelWidthDotsTrailer) { - if (!url_subdomain.empty()) { - url_elided_domain = kEllipsisAndSlash[0] + url_domain; - pixel_width_url_elided_domain += kPixelWidthDotsTrailer; - } else { - url_elided_domain = url_domain; - } - - for (size_t i = url_path_number_of_elements - 1; i >= 1; --i) { - // Add the initial elements of the path. - elided_path.clear(); - pixel_width_elided_path = 0; - for (size_t j = 0; j < i; ++j) { - elided_path += url_path_elements.at(j) + kForwardSlash; - pixel_width_elided_path += pixel_width_url_path_elements[j] + - pixel_width_slash; - } - - // Add url_file_name. - if (i == (url_path_number_of_elements - 1)) { - elided_path += url_filename; - pixel_width_elided_path += pixel_width_url_filename; - } else { - elided_path += kEllipsisAndSlash + url_filename; - pixel_width_elided_path += pixel_width_dot_dot_slash + - pixel_width_url_filename; - } - - if (available_pixel_width >= - pixel_width_url_elided_domain + pixel_width_elided_path) { - return ElideText(url_elided_domain + elided_path + url_query, font, - available_pixel_width, false); - } - } - } - - // Return elided domain/../filename anyway. - string16 final_elided_url_string(url_elided_domain); - int url_elided_domain_width = font.GetStringWidth(url_elided_domain); - - // A hack to prevent trailing "../...". - if ((available_pixel_width - url_elided_domain_width) > - pixel_width_dot_dot_slash + kPixelWidthDotsTrailer + - font.GetStringWidth(ASCIIToUTF16("UV"))) { - final_elided_url_string += elided_path; - } else { - final_elided_url_string += url_path; - } - - return ElideText(final_elided_url_string, font, available_pixel_width, false); -} - -string16 ElideFilename(const FilePath& filename, - const gfx::Font& font, - int available_pixel_width) { -#if defined(OS_WIN) - string16 filename_utf16 = filename.value(); - string16 extension = filename.Extension(); - string16 rootname = filename.BaseName().RemoveExtension().value(); -#elif defined(OS_POSIX) - string16 filename_utf16 = WideToUTF16(base::SysNativeMBToWide( - filename.value())); - string16 extension = WideToUTF16(base::SysNativeMBToWide( - filename.Extension())); - string16 rootname = WideToUTF16(base::SysNativeMBToWide( - filename.BaseName().RemoveExtension().value())); -#endif - - int full_width = font.GetStringWidth(filename_utf16); - if (full_width <= available_pixel_width) - return base::i18n::GetDisplayStringInLTRDirectionality(filename_utf16); - - if (rootname.empty() || extension.empty()) { - string16 elided_name = ElideText(filename_utf16, font, - available_pixel_width, false); - return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); - } - - int ext_width = font.GetStringWidth(extension); - int root_width = font.GetStringWidth(rootname); - - // We may have trimmed the path. - if (root_width + ext_width <= available_pixel_width) { - string16 elided_name = rootname + extension; - return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); - } - - int available_root_width = available_pixel_width - ext_width; - string16 elided_name = - ElideText(rootname, font, available_root_width, false); - elided_name += extension; - return base::i18n::GetDisplayStringInLTRDirectionality(elided_name); -} - -// This function adds an ellipsis at the end of the text if the text -// does not fit the given pixel width. -string16 ElideText(const string16& text, - const gfx::Font& font, - int available_pixel_width, - bool elide_in_middle) { - if (text.empty()) - return text; - - int current_text_pixel_width = font.GetStringWidth(text); - - // Pango will return 0 width for absurdly long strings. Cut the string in - // half and try again. - // This is caused by an int overflow in Pango (specifically, in - // pango_glyph_string_extents_range). It's actually more subtle than just - // returning 0, since on super absurdly long strings, the int can wrap and - // return positive numbers again. Detecting that is probably not worth it - // (eliding way too much from a ridiculous string is probably still - // ridiculous), but we should check other widths for bogus values as well. - if (current_text_pixel_width <= 0 && !text.empty()) { - return ElideText(CutString(text, text.length() / 2, elide_in_middle, false), - font, available_pixel_width, false); - } - - if (current_text_pixel_width <= available_pixel_width) - return text; - - if (font.GetStringWidth(UTF8ToUTF16(kEllipsis)) > available_pixel_width) - return string16(); - - // Use binary search to compute the elided text. - size_t lo = 0; - size_t hi = text.length() - 1; - for (size_t guess = (lo + hi) / 2; guess != lo; guess = (lo + hi) / 2) { - // We check the length of the whole desired string at once to ensure we - // handle kerning/ligatures/etc. correctly. - int guess_length = font.GetStringWidth( - CutString(text, guess, elide_in_middle, true)); - // Check again that we didn't hit a Pango width overflow. If so, cut the - // current string in half and start over. - if (guess_length <= 0) { - return ElideText(CutString(text, guess / 2, elide_in_middle, false), - font, available_pixel_width, elide_in_middle); - } - if (guess_length > available_pixel_width) - hi = guess; - else - lo = guess; - } - - return CutString(text, lo, elide_in_middle, true); -} - -// TODO(viettrungluu): convert |languages| to an |std::string|. -SortedDisplayURL::SortedDisplayURL(const GURL& url, - const std::wstring& languages) { - std::wstring host; - net::AppendFormattedHost(url, languages, &host, NULL, NULL); - sort_host_ = WideToUTF16Hack(host); - string16 host_minus_www = net::StripWWW(WideToUTF16Hack(host)); - url_parse::Parsed parsed; - display_url_ = net::FormatUrl(url, WideToUTF8(languages), - net::kFormatUrlOmitAll, UnescapeRule::SPACES, &parsed, &prefix_end_, - NULL); - if (sort_host_.length() > host_minus_www.length()) { - prefix_end_ += sort_host_.length() - host_minus_www.length(); - sort_host_.swap(host_minus_www); - } -} - -SortedDisplayURL::SortedDisplayURL() { -} - -SortedDisplayURL::~SortedDisplayURL() { -} - -int SortedDisplayURL::Compare(const SortedDisplayURL& other, - icu::Collator* collator) const { - // Compare on hosts first. The host won't contain 'www.'. - UErrorCode compare_status = U_ZERO_ERROR; - UCollationResult host_compare_result = collator->compare( - static_cast<const UChar*>(sort_host_.c_str()), - static_cast<int>(sort_host_.length()), - static_cast<const UChar*>(other.sort_host_.c_str()), - static_cast<int>(other.sort_host_.length()), - compare_status); - DCHECK(U_SUCCESS(compare_status)); - if (host_compare_result != 0) - return host_compare_result; - - // Hosts match, compare on the portion of the url after the host. - string16 path = this->AfterHost(); - string16 o_path = other.AfterHost(); - compare_status = U_ZERO_ERROR; - UCollationResult path_compare_result = collator->compare( - static_cast<const UChar*>(path.c_str()), - static_cast<int>(path.length()), - static_cast<const UChar*>(o_path.c_str()), - static_cast<int>(o_path.length()), - compare_status); - DCHECK(U_SUCCESS(compare_status)); - if (path_compare_result != 0) - return path_compare_result; - - // Hosts and paths match, compare on the complete url. This'll push the www. - // ones to the end. - compare_status = U_ZERO_ERROR; - UCollationResult display_url_compare_result = collator->compare( - static_cast<const UChar*>(display_url_.c_str()), - static_cast<int>(display_url_.length()), - static_cast<const UChar*>(other.display_url_.c_str()), - static_cast<int>(other.display_url_.length()), - compare_status); - DCHECK(U_SUCCESS(compare_status)); - return display_url_compare_result; -} - -string16 SortedDisplayURL::AfterHost() const { - size_t slash_index = display_url_.find(sort_host_, prefix_end_); - if (slash_index == string16::npos) { - NOTREACHED(); - return string16(); - } - return display_url_.substr(slash_index + sort_host_.length()); -} - -bool ElideString(const std::wstring& input, int max_len, std::wstring* output) { - DCHECK_GE(max_len, 0); - if (static_cast<int>(input.length()) <= max_len) { - output->assign(input); - return false; - } - - switch (max_len) { - case 0: - output->clear(); - break; - case 1: - output->assign(input.substr(0, 1)); - break; - case 2: - output->assign(input.substr(0, 2)); - break; - case 3: - output->assign(input.substr(0, 1) + L"." + - input.substr(input.length() - 1)); - break; - case 4: - output->assign(input.substr(0, 1) + L".." + - input.substr(input.length() - 1)); - break; - default: { - int rstr_len = (max_len - 3) / 2; - int lstr_len = rstr_len + ((max_len - 3) % 2); - output->assign(input.substr(0, lstr_len) + L"..." + - input.substr(input.length() - rstr_len)); - break; - } - } - - return true; -} - -} // namespace gfx - -namespace { - -// Internal class used to track progress of a rectangular string elide -// operation. Exists so the top-level ElideRectangleString() function -// can be broken into smaller methods sharing this state. -class RectangleString { - public: - RectangleString(size_t max_rows, size_t max_cols, string16 *output) - : max_rows_(max_rows), - max_cols_(max_cols), - current_row_(0), - current_col_(0), - suppressed_(false), - output_(output) {} - - // Perform deferred initializions following creation. Must be called - // before any input can be added via AddString(). - void Init() { output_->clear(); } - - // Add an input string, reformatting to fit the desired dimensions. - // AddString() may be called multiple times to concatenate together - // multiple strings into the region (the current caller doesn't do - // this, however). - void AddString(const string16& input); - - // Perform any deferred output processing. Must be called after the - // last AddString() call has occured. - bool Finalize(); - - private: - // Add a line to the rectangular region at the current position, - // either by itself or by breaking it into words. - void AddLine(const string16& line); - - // Add a word to the rectangluar region at the current position, - // either by itelf or by breaking it into characters. - void AddWord(const string16& word); - - // Add text to the output string if the rectangular boundaries - // have not been exceeded, advancing the current position. - void Append(const string16& string); - - // Add a newline to the output string if the rectangular boundaries - // have not been exceeded, resetting the current position to the - // beginning of the next line. - void NewLine(); - - // Maximum number of rows allowed in the output string. - size_t max_rows_; - - // Maximum number of characters allowed in the output string. - size_t max_cols_; - - // Current row position, always incremented and may exceed max_rows_ - // when the input can not fit in the region. We stop appending to - // the output string, however, when this condition occurs. In the - // future, we may want to expose this value to allow the caller to - // determine how many rows would actually be required to hold the - // formatted string. - size_t current_row_; - - // Current character position, should never exceed max_cols_. - size_t current_col_; - - // True when some of the input has been truncated. - bool suppressed_; - - // String onto which the output is accumulated. - string16 *output_; -}; - -void RectangleString::AddString(const string16& input) { - base::BreakIterator lines(&input, base::BreakIterator::BREAK_NEWLINE); - if (lines.Init()) { - while (lines.Advance()) - AddLine(lines.GetString()); - } else { - NOTREACHED() << "BreakIterator (lines) init failed"; - } -} - -bool RectangleString::Finalize() { - if (suppressed_) { - output_->append(ASCIIToUTF16("...")); - return true; - } - return false; -} - -void RectangleString::AddLine(const string16& line) { - if (line.length() < max_cols_) { - Append(line); - } else { - base::BreakIterator words(&line, base::BreakIterator::BREAK_SPACE); - if (words.Init()) { - while (words.Advance()) - AddWord(words.GetString()); - } else { - NOTREACHED() << "BreakIterator (words) init failed"; - } - } - // Account for naturally-occuring newlines. - ++current_row_; - current_col_ = 0; -} - -void RectangleString::AddWord(const string16& word) { - if (word.length() < max_cols_) { - // Word can be made to fit, no need to fragment it. - if (current_col_ + word.length() >= max_cols_) - NewLine(); - Append(word); - } else { - // Word is so big that it must be fragmented. - int array_start = 0; - int char_start = 0; - base::i18n::UTF16CharIterator chars(&word); - while (!chars.end()) { - // When boundary is hit, add as much as will fit on this line. - if (current_col_ + (chars.char_pos() - char_start) >= max_cols_) { - Append(word.substr(array_start, chars.array_pos() - array_start)); - NewLine(); - array_start = chars.array_pos(); - char_start = chars.char_pos(); - } - chars.Advance(); - } - // add last remaining fragment, if any. - if (array_start != chars.array_pos()) - Append(word.substr(array_start, chars.array_pos() - array_start)); - } -} - -void RectangleString::Append(const string16& string) { - if (current_row_ < max_rows_) - output_->append(string); - else - suppressed_ = true; - current_col_ += string.length(); -} - -void RectangleString::NewLine() { - if (current_row_ < max_rows_) - output_->append(ASCIIToUTF16("\n")); - else - suppressed_ = true; - ++current_row_; - current_col_ = 0; -} - -} // namespace - -namespace gfx { - -bool ElideRectangleString(const string16& input, size_t max_rows, - size_t max_cols, string16* output) { - RectangleString rect(max_rows, max_cols, output); - rect.Init(); - rect.AddString(input); - return rect.Finalize(); -} - -} // namespace gfx - diff --git a/app/text_elider.h b/app/text_elider.h deleted file mode 100644 index d6da860..0000000 --- a/app/text_elider.h +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef APP_TEXT_ELIDER_H_ -#define APP_TEXT_ELIDER_H_ -#pragma once - -#include <unicode/coll.h> -#include <unicode/uchar.h> - -#include "base/basictypes.h" -#include "base/string16.h" -#include "gfx/font.h" - -class FilePath; -class GURL; - -// TODO(port): this file should deal in string16s rather than wstrings. -namespace gfx { - -// This function takes a GURL object and elides it. It returns a string -// which composed of parts from subdomain, domain, path, filename and query. -// A "..." is added automatically at the end if the elided string is bigger -// than the available pixel width. For available pixel width = 0, empty -// string is returned. |languages| is a comma separted list of ISO 639 -// language codes and is used to determine what characters are understood -// by a user. It should come from |prefs::kAcceptLanguages|. -// -// Note: in RTL locales, if the URL returned by this function is going to be -// displayed in the UI, then it is likely that the string needs to be marked -// as an LTR string (using base::i18n::WrapStringWithLTRFormatting()) so that it -// is displayed properly in an RTL context. Please refer to -// http://crbug.com/6487 for more information. -string16 ElideUrl(const GURL& url, - const gfx::Font& font, - int available_pixel_width, - const std::wstring& languages); - -// Elides |text| to fit in |available_pixel_width|. If |elide_in_middle| is -// set the ellipsis is placed in the middle of the string; otherwise it is -// placed at the end. -string16 ElideText(const string16& text, - const gfx::Font& font, - int available_pixel_width, - bool elide_in_middle); - -// Elide a filename to fit a given pixel width, with an emphasis on not hiding -// the extension unless we have to. If filename contains a path, the path will -// be removed if filename doesn't fit into available_pixel_width. The elided -// filename is forced to have LTR directionality, which means that in RTL UI -// the elided filename is wrapped with LRE (Left-To-Right Embedding) mark and -// PDF (Pop Directional Formatting) mark. -string16 ElideFilename(const FilePath& filename, - const gfx::Font& font, - int available_pixel_width); - -// SortedDisplayURL maintains a string from a URL suitable for display to the -// use. SortedDisplayURL also provides a function used for comparing two -// SortedDisplayURLs for use in visually ordering the SortedDisplayURLs. -// -// SortedDisplayURL is relatively cheap and supports value semantics. -class SortedDisplayURL { - public: - SortedDisplayURL(const GURL& url, const std::wstring& languages); - SortedDisplayURL(); - ~SortedDisplayURL(); - - // Compares this SortedDisplayURL to |url| using |collator|. Returns a value - // < 0, = 1 or > 0 as to whether this url is less then, equal to or greater - // than the supplied url. - int Compare(const SortedDisplayURL& other, icu::Collator* collator) const; - - // Returns the display string for the URL. - const string16& display_url() const { return display_url_; } - - private: - // Returns everything after the host. This is used by Compare if the hosts - // match. - string16 AfterHost() const; - - // Host name minus 'www.'. Used by Compare. - string16 sort_host_; - - // End of the prefix (spec and separator) in display_url_. - size_t prefix_end_; - - string16 display_url_; -}; - -// Functions to elide strings when the font information is unknown. As -// opposed to the above functions, the ElideString() and -// ElideRectangleString() functions operate in terms of character units, -// not pixels. - -// If the size of |input| is more than |max_len|, this function returns -// true and |input| is shortened into |output| by removing chars in the -// middle (they are replaced with up to 3 dots, as size permits). -// Ex: ElideString(L"Hello", 10, &str) puts Hello in str and returns false. -// ElideString(L"Hello my name is Tom", 10, &str) puts "Hell...Tom" in str -// and returns true. -// TODO(tsepez): Doesn't handle UTF-16 surrogate pairs properly. -// TODO(tsepez): Doesn't handle bidi properly -bool ElideString(const std::wstring& input, int max_len, std::wstring* output); - -// Reformat |input| into |output| so that it fits into a |max_rows| by -// |max_cols| rectangle of characters. Input newlines are respected, but -// lines that are too long are broken into pieces, first at naturally -// occuring whitespace boundaries, and then intra-word (respecting UTF-16 -// surrogate pairs) as necssary. Truncation (indicated by an added 3 dots) -// occurs if the result is still too long. Returns true if the input had -// to be truncated (and not just reformatted). -bool ElideRectangleString(const string16& input, size_t max_rows, - size_t max_cols, string16* output); - - -} // namespace gfx. - -#endif // APP_TEXT_ELIDER_H_ diff --git a/app/text_elider_unittest.cc b/app/text_elider_unittest.cc deleted file mode 100644 index 7d0cbda..0000000 --- a/app/text_elider_unittest.cc +++ /dev/null @@ -1,439 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "app/text_elider.h" -#include "base/file_path.h" -#include "base/i18n/rtl.h" -#include "base/scoped_ptr.h" -#include "base/string_util.h" -#include "base/utf_string_conversions.h" -#include "gfx/font.h" -#include "googleurl/src/gurl.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -const wchar_t kEllipsis[] = L"\x2026"; - -struct Testcase { - const std::string input; - const std::wstring output; -}; - -struct FileTestcase { - const FilePath::StringType input; - const std::wstring output; -}; - -struct UTF16Testcase { - const string16 input; - const string16 output; -}; - -struct TestData { - const std::string a; - const std::string b; - const int compare_result; -}; - -void RunTest(Testcase* testcases, size_t num_testcases) { - static const gfx::Font font; - for (size_t i = 0; i < num_testcases; ++i) { - const GURL url(testcases[i].input); - // Should we test with non-empty language list? - // That's kinda redundant with net_util_unittests. - EXPECT_EQ(WideToUTF16(testcases[i].output), - ElideUrl(url, font, - font.GetStringWidth(WideToUTF16(testcases[i].output)), - std::wstring())); - } -} - -} // namespace - -// Test eliding of commonplace URLs. -TEST(TextEliderTest, TestGeneralEliding) { - const std::wstring kEllipsisStr(kEllipsis); - Testcase testcases[] = { - {"http://www.google.com/intl/en/ads/", - L"www.google.com/intl/en/ads/"}, - {"http://www.google.com/intl/en/ads/", L"www.google.com/intl/en/ads/"}, -// TODO(port): make this test case work on mac. -#if !defined(OS_MACOSX) - {"http://www.google.com/intl/en/ads/", - L"google.com/intl/" + kEllipsisStr + L"/ads/"}, -#endif - {"http://www.google.com/intl/en/ads/", - L"google.com/" + kEllipsisStr + L"/ads/"}, - {"http://www.google.com/intl/en/ads/", L"google.com/" + kEllipsisStr}, - {"http://www.google.com/intl/en/ads/", L"goog" + kEllipsisStr}, - {"https://subdomain.foo.com/bar/filename.html", - L"subdomain.foo.com/bar/filename.html"}, - {"https://subdomain.foo.com/bar/filename.html", - L"subdomain.foo.com/" + kEllipsisStr + L"/filename.html"}, - {"http://subdomain.foo.com/bar/filename.html", - kEllipsisStr + L"foo.com/" + kEllipsisStr + L"/filename.html"}, - {"http://www.google.com/intl/en/ads/?aLongQueryWhichIsNotRequired", - L"www.google.com/intl/en/ads/?aLongQ" + kEllipsisStr}, - }; - - RunTest(testcases, arraysize(testcases)); -} - -// Test eliding of empty strings, URLs with ports, passwords, queries, etc. -TEST(TextEliderTest, TestMoreEliding) { - const std::wstring kEllipsisStr(kEllipsis); - Testcase testcases[] = { - {"http://www.google.com/foo?bar", L"www.google.com/foo?bar"}, - {"http://xyz.google.com/foo?bar", L"xyz.google.com/foo?" + kEllipsisStr}, - {"http://xyz.google.com/foo?bar", L"xyz.google.com/foo" + kEllipsisStr}, - {"http://xyz.google.com/foo?bar", L"xyz.google.com/fo" + kEllipsisStr}, - {"http://a.b.com/pathname/c?d", L"a.b.com/" + kEllipsisStr + L"/c?d"}, - {"", L""}, - {"http://foo.bar..example.com...hello/test/filename.html", - L"foo.bar..example.com...hello/" + kEllipsisStr + L"/filename.html"}, - {"http://foo.bar../", L"foo.bar.."}, - {"http://xn--1lq90i.cn/foo", L"\x5317\x4eac.cn/foo"}, - {"http://me:mypass@secrethost.com:99/foo?bar#baz", - L"secrethost.com:99/foo?bar#baz"}, - {"http://me:mypass@ss%xxfdsf.com/foo", L"ss%25xxfdsf.com/foo"}, - {"mailto:elgoato@elgoato.com", L"mailto:elgoato@elgoato.com"}, - {"javascript:click(0)", L"javascript:click(0)"}, - {"https://chess.eecs.berkeley.edu:4430/login/arbitfilename", - L"chess.eecs.berkeley.edu:4430/login/arbitfilename"}, - {"https://chess.eecs.berkeley.edu:4430/login/arbitfilename", - kEllipsisStr + L"berkeley.edu:4430/" + kEllipsisStr + L"/arbitfilename"}, - - // Unescaping. - {"http://www/%E4%BD%A0%E5%A5%BD?q=%E4%BD%A0%E5%A5%BD#\xe4\xbd\xa0", - L"www/\x4f60\x597d?q=\x4f60\x597d#\x4f60"}, - - // Invalid unescaping for path. The ref will always be valid UTF-8. We don't - // bother to do too many edge cases, since these are handled by the escaper - // unittest. - {"http://www/%E4%A0%E5%A5%BD?q=%E4%BD%A0%E5%A5%BD#\xe4\xbd\xa0", - L"www/%E4%A0%E5%A5%BD?q=\x4f60\x597d#\x4f60"}, - }; - - RunTest(testcases, arraysize(testcases)); -} - -// Test eliding of file: URLs. -TEST(TextEliderTest, TestFileURLEliding) { - const std::wstring kEllipsisStr(kEllipsis); - Testcase testcases[] = { - {"file:///C:/path1/path2/path3/filename", - L"file:///C:/path1/path2/path3/filename"}, - {"file:///C:/path1/path2/path3/filename", - L"C:/path1/path2/path3/filename"}, -// GURL parses "file:///C:path" differently on windows than it does on posix. -#if defined(OS_WIN) - {"file:///C:path1/path2/path3/filename", - L"C:/path1/path2/" + kEllipsisStr + L"/filename"}, - {"file:///C:path1/path2/path3/filename", - L"C:/path1/" + kEllipsisStr + L"/filename"}, - {"file:///C:path1/path2/path3/filename", - L"C:/" + kEllipsisStr + L"/filename"}, -#endif - {"file://filer/foo/bar/file", L"filer/foo/bar/file"}, - {"file://filer/foo/bar/file", L"filer/foo/" + kEllipsisStr + L"/file"}, - {"file://filer/foo/bar/file", L"filer/" + kEllipsisStr + L"/file"}, - }; - - RunTest(testcases, arraysize(testcases)); -} - -TEST(TextEliderTest, TestFilenameEliding) { - const std::wstring kEllipsisStr(kEllipsis); - const FilePath::StringType kPathSeparator = - FilePath::StringType().append(1, FilePath::kSeparators[0]); - - FileTestcase testcases[] = { - {FILE_PATH_LITERAL(""), L""}, - {FILE_PATH_LITERAL("."), L"."}, - {FILE_PATH_LITERAL("filename.exe"), L"filename.exe"}, - {FILE_PATH_LITERAL(".longext"), L".longext"}, - {FILE_PATH_LITERAL("pie"), L"pie"}, - {FILE_PATH_LITERAL("c:") + kPathSeparator + FILE_PATH_LITERAL("path") + - kPathSeparator + FILE_PATH_LITERAL("filename.pie"), - L"filename.pie"}, - {FILE_PATH_LITERAL("c:") + kPathSeparator + FILE_PATH_LITERAL("path") + - kPathSeparator + FILE_PATH_LITERAL("longfilename.pie"), - L"long" + kEllipsisStr + L".pie"}, - {FILE_PATH_LITERAL("http://path.com/filename.pie"), L"filename.pie"}, - {FILE_PATH_LITERAL("http://path.com/longfilename.pie"), - L"long" + kEllipsisStr + L".pie"}, - {FILE_PATH_LITERAL("piesmashingtacularpants"), L"pie" + kEllipsisStr}, - {FILE_PATH_LITERAL(".piesmashingtacularpants"), L".pie" + kEllipsisStr}, - {FILE_PATH_LITERAL("cheese."), L"cheese."}, - {FILE_PATH_LITERAL("file name.longext"), - L"file" + kEllipsisStr + L".longext"}, - {FILE_PATH_LITERAL("fil ename.longext"), - L"fil " + kEllipsisStr + L".longext"}, - {FILE_PATH_LITERAL("filename.longext"), - L"file" + kEllipsisStr + L".longext"}, - {FILE_PATH_LITERAL("filename.middleext.longext"), - L"filename.mid" + kEllipsisStr + L".longext"} - }; - - static const gfx::Font font; - for (size_t i = 0; i < arraysize(testcases); ++i) { - FilePath filepath(testcases[i].input); - string16 expected = WideToUTF16(testcases[i].output); - expected = base::i18n::GetDisplayStringInLTRDirectionality(expected); - EXPECT_EQ(expected, ElideFilename(filepath, - font, - font.GetStringWidth(WideToUTF16(testcases[i].output)))); - } -} - -TEST(TextEliderTest, ElideTextLongStrings) { - const string16 kEllipsisStr(WideToUTF16(kEllipsis)); - string16 data_scheme(UTF8ToUTF16("data:text/plain,")); - size_t data_scheme_length = data_scheme.length(); - - string16 ten_a(10, 'a'); - string16 hundred_a(100, 'a'); - string16 thousand_a(1000, 'a'); - string16 ten_thousand_a(10000, 'a'); - string16 hundred_thousand_a(100000, 'a'); - string16 million_a(1000000, 'a'); - - size_t number_of_as = 156; - string16 long_string_end( - data_scheme + string16(number_of_as, 'a') + kEllipsisStr); - UTF16Testcase testcases_end[] = { - {data_scheme + ten_a, data_scheme + ten_a}, - {data_scheme + hundred_a, data_scheme + hundred_a}, - {data_scheme + thousand_a, long_string_end}, - {data_scheme + ten_thousand_a, long_string_end}, - {data_scheme + hundred_thousand_a, long_string_end}, - {data_scheme + million_a, long_string_end}, - }; - - const gfx::Font font; - int ellipsis_width = font.GetStringWidth(kEllipsisStr); - for (size_t i = 0; i < arraysize(testcases_end); ++i) { - // Compare sizes rather than actual contents because if the test fails, - // output is rather long. - EXPECT_EQ(testcases_end[i].output.size(), - ElideText(testcases_end[i].input, font, - font.GetStringWidth(testcases_end[i].output), - false).size()); - EXPECT_EQ(kEllipsisStr, - ElideText(testcases_end[i].input, font, ellipsis_width, false)); - } - - size_t number_of_trailing_as = (data_scheme_length + number_of_as) / 2; - string16 long_string_middle(data_scheme + - string16(number_of_as - number_of_trailing_as, 'a') + kEllipsisStr + - string16(number_of_trailing_as, 'a')); - UTF16Testcase testcases_middle[] = { - {data_scheme + ten_a, data_scheme + ten_a}, - {data_scheme + hundred_a, data_scheme + hundred_a}, - {data_scheme + thousand_a, long_string_middle}, - {data_scheme + ten_thousand_a, long_string_middle}, - {data_scheme + hundred_thousand_a, long_string_middle}, - {data_scheme + million_a, long_string_middle}, - }; - - for (size_t i = 0; i < arraysize(testcases_middle); ++i) { - // Compare sizes rather than actual contents because if the test fails, - // output is rather long. - EXPECT_EQ(testcases_middle[i].output.size(), - ElideText(testcases_middle[i].input, font, - font.GetStringWidth(testcases_middle[i].output), - false).size()); - EXPECT_EQ(kEllipsisStr, - ElideText(testcases_middle[i].input, font, ellipsis_width, - false)); - } -} - -// Verifies display_url is set correctly. -TEST(TextEliderTest, SortedDisplayURL) { - gfx::SortedDisplayURL d_url(GURL("http://www.google.com"), std::wstring()); - EXPECT_EQ("www.google.com", UTF16ToASCII(d_url.display_url())); -} - -// Verifies DisplayURL::Compare works correctly. -TEST(TextEliderTest, SortedDisplayURLCompare) { - UErrorCode create_status = U_ZERO_ERROR; - scoped_ptr<icu::Collator> collator( - icu::Collator::createInstance(create_status)); - if (!U_SUCCESS(create_status)) - return; - - TestData tests[] = { - // IDN comparison. Hosts equal, so compares on path. - { "http://xn--1lq90i.cn/a", "http://xn--1lq90i.cn/b", -1}, - - // Because the host and after host match, this compares the full url. - { "http://www.x/b", "http://x/b", -1 }, - - // Because the host and after host match, this compares the full url. - { "http://www.a:1/b", "http://a:1/b", 1 }, - - // The hosts match, so these end up comparing on the after host portion. - { "http://www.x:0/b", "http://x:1/b", -1 }, - { "http://www.x/a", "http://x/b", -1 }, - { "http://x/b", "http://www.x/a", 1 }, - - // Trivial Equality. - { "http://a/", "http://a/", 0 }, - - // Compares just hosts. - { "http://www.a/", "http://b/", -1 }, - }; - - for (size_t i = 0; i < arraysize(tests); ++i) { - gfx::SortedDisplayURL url1(GURL(tests[i].a), std::wstring()); - gfx::SortedDisplayURL url2(GURL(tests[i].b), std::wstring()); - EXPECT_EQ(tests[i].compare_result, url1.Compare(url2, collator.get())); - EXPECT_EQ(-tests[i].compare_result, url2.Compare(url1, collator.get())); - } -} - -TEST(TextEliderTest, ElideString) { - struct TestData { - const wchar_t* input; - int max_len; - bool result; - const wchar_t* output; - } cases[] = { - { L"Hello", 0, true, L"" }, - { L"", 0, false, L"" }, - { L"Hello, my name is Tom", 1, true, L"H" }, - { L"Hello, my name is Tom", 2, true, L"He" }, - { L"Hello, my name is Tom", 3, true, L"H.m" }, - { L"Hello, my name is Tom", 4, true, L"H..m" }, - { L"Hello, my name is Tom", 5, true, L"H...m" }, - { L"Hello, my name is Tom", 6, true, L"He...m" }, - { L"Hello, my name is Tom", 7, true, L"He...om" }, - { L"Hello, my name is Tom", 10, true, L"Hell...Tom" }, - { L"Hello, my name is Tom", 100, false, L"Hello, my name is Tom" } - }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { - std::wstring output; - EXPECT_EQ(cases[i].result, - gfx::ElideString(cases[i].input, cases[i].max_len, &output)); - EXPECT_EQ(cases[i].output, output); - } -} - -TEST(TextEliderTest, ElideRectangleString) { - struct TestData { - const wchar_t* input; - int max_rows; - int max_cols; - bool result; - const wchar_t* output; - } cases[] = { - { L"", 0, 0, false, L"" }, - { L"", 1, 1, false, L"" }, - { L"Hi, my name is\nTom", 0, 0, true, L"..." }, - { L"Hi, my name is\nTom", 1, 0, true, L"\n..." }, - { L"Hi, my name is\nTom", 0, 1, true, L"..." }, - { L"Hi, my name is\nTom", 1, 1, true, L"H\n..." }, - { L"Hi, my name is\nTom", 2, 1, true, L"H\ni\n..." }, - { L"Hi, my name is\nTom", 3, 1, true, L"H\ni\n,\n..." }, - { L"Hi, my name is\nTom", 4, 1, true, L"H\ni\n,\n \n..." }, - { L"Hi, my name is\nTom", 5, 1, true, L"H\ni\n,\n \nm\n..." }, - { L"Hi, my name is\nTom", 0, 2, true, L"..." }, - { L"Hi, my name is\nTom", 1, 2, true, L"Hi\n..." }, - { L"Hi, my name is\nTom", 2, 2, true, L"Hi\n, \n..." }, - { L"Hi, my name is\nTom", 3, 2, true, L"Hi\n, \nmy\n..." }, - { L"Hi, my name is\nTom", 4, 2, true, L"Hi\n, \nmy\n n\n..." }, - { L"Hi, my name is\nTom", 5, 2, true, L"Hi\n, \nmy\n n\nam\n..." }, - { L"Hi, my name is\nTom", 0, 3, true, L"..." }, - { L"Hi, my name is\nTom", 1, 3, true, L"Hi,\n..." }, - { L"Hi, my name is\nTom", 2, 3, true, L"Hi,\n my\n..." }, - { L"Hi, my name is\nTom", 3, 3, true, L"Hi,\n my\n na\n..." }, - { L"Hi, my name is\nTom", 4, 3, true, L"Hi,\n my\n na\nme \n..." }, - { L"Hi, my name is\nTom", 5, 3, true, L"Hi,\n my\n na\nme \nis\n..." }, - { L"Hi, my name is\nTom", 1, 4, true, L"Hi, \n..." }, - { L"Hi, my name is\nTom", 2, 4, true, L"Hi, \nmy n\n..." }, - { L"Hi, my name is\nTom", 3, 4, true, L"Hi, \nmy n\name \n..." }, - { L"Hi, my name is\nTom", 4, 4, true, L"Hi, \nmy n\name \nis\n..." }, - { L"Hi, my name is\nTom", 5, 4, false, L"Hi, \nmy n\name \nis\nTom" }, - { L"Hi, my name is\nTom", 1, 5, true, L"Hi, \n..." }, - { L"Hi, my name is\nTom", 2, 5, true, L"Hi, \nmy na\n..." }, - { L"Hi, my name is\nTom", 3, 5, true, L"Hi, \nmy na\nme \n..." }, - { L"Hi, my name is\nTom", 4, 5, true, L"Hi, \nmy na\nme \nis\n..." }, - { L"Hi, my name is\nTom", 5, 5, false, L"Hi, \nmy na\nme \nis\nTom" }, - { L"Hi, my name is\nTom", 1, 6, true, L"Hi, \n..." }, - { L"Hi, my name is\nTom", 2, 6, true, L"Hi, \nmy \n..." }, - { L"Hi, my name is\nTom", 3, 6, true, L"Hi, \nmy \nname \n..." }, - { L"Hi, my name is\nTom", 4, 6, true, L"Hi, \nmy \nname \nis\n..." }, - { L"Hi, my name is\nTom", 5, 6, false, L"Hi, \nmy \nname \nis\nTom" }, - { L"Hi, my name is\nTom", 1, 7, true, L"Hi, \n..." }, - { L"Hi, my name is\nTom", 2, 7, true, L"Hi, \nmy \n..." }, - { L"Hi, my name is\nTom", 3, 7, true, L"Hi, \nmy \nname \n..." }, - { L"Hi, my name is\nTom", 4, 7, true, L"Hi, \nmy \nname \nis\n..." }, - { L"Hi, my name is\nTom", 5, 7, false, L"Hi, \nmy \nname \nis\nTom" }, - { L"Hi, my name is\nTom", 1, 8, true, L"Hi, my \n..." }, - { L"Hi, my name is\nTom", 2, 8, true, L"Hi, my \nname \n..." }, - { L"Hi, my name is\nTom", 3, 8, true, L"Hi, my \nname \nis\n..." }, - { L"Hi, my name is\nTom", 4, 8, false, L"Hi, my \nname \nis\nTom" }, - { L"Hi, my name is\nTom", 1, 9, true, L"Hi, my \n..." }, - { L"Hi, my name is\nTom", 2, 9, true, L"Hi, my \nname is\n..." }, - { L"Hi, my name is\nTom", 3, 9, false, L"Hi, my \nname is\nTom" }, - { L"Hi, my name is\nTom", 1, 10, true, L"Hi, my \n..." }, - { L"Hi, my name is\nTom", 2, 10, true, L"Hi, my \nname is\n..." }, - { L"Hi, my name is\nTom", 3, 10, false, L"Hi, my \nname is\nTom" }, - { L"Hi, my name is\nTom", 1, 11, true, L"Hi, my \n..." }, - { L"Hi, my name is\nTom", 2, 11, true, L"Hi, my \nname is\n..." }, - { L"Hi, my name is\nTom", 3, 11, false, L"Hi, my \nname is\nTom" }, - { L"Hi, my name is\nTom", 1, 12, true, L"Hi, my \n..." }, - { L"Hi, my name is\nTom", 2, 12, true, L"Hi, my \nname is\n..." }, - { L"Hi, my name is\nTom", 3, 12, false, L"Hi, my \nname is\nTom" }, - { L"Hi, my name is\nTom", 1, 13, true, L"Hi, my name \n..." }, - { L"Hi, my name is\nTom", 2, 13, true, L"Hi, my name \nis\n..." }, - { L"Hi, my name is\nTom", 3, 13, false, L"Hi, my name \nis\nTom" }, - { L"Hi, my name is\nTom", 1, 20, true, L"Hi, my name is\n..." }, - { L"Hi, my name is\nTom", 2, 20, false, L"Hi, my name is\nTom" }, - { L"Hi, my name is Tom", 1, 40, false, L"Hi, my name is Tom" }, - }; - string16 output; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { - EXPECT_EQ(cases[i].result, - gfx::ElideRectangleString(WideToUTF16(cases[i].input), - cases[i].max_rows, cases[i].max_cols, - &output)); - EXPECT_EQ(cases[i].output, UTF16ToWide(output)); - } -} - -TEST(TextEliderTest, ElideRectangleWide16) { - // Two greek words separated by space. - const string16 str(WideToUTF16( - L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9" - L"\x03bf\x03c2\x0020\x0399\x03c3\x03c4\x03cc\x03c2")); - const string16 out1(WideToUTF16( - L"\x03a0\x03b1\x03b3\x03ba\n" - L"\x03cc\x03c3\x03bc\x03b9\n" - L"...")); - const string16 out2(WideToUTF16( - L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9\x03bf\x03c2\x0020\n" - L"\x0399\x03c3\x03c4\x03cc\x03c2")); - string16 output; - EXPECT_TRUE(gfx::ElideRectangleString(str, 2, 4, &output)); - EXPECT_EQ(out1, output); - EXPECT_FALSE(gfx::ElideRectangleString(str, 2, 12, &output)); - EXPECT_EQ(out2, output); -} - -TEST(TextEliderTest, ElideRectangleWide32) { - // Four U+1D49C MATHEMATICAL SCRIPT CAPITAL A followed by space "aaaaa". - const string16 str(UTF8ToUTF16( - "\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C" - " aaaaa")); - const string16 out(UTF8ToUTF16( - "\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\xF0\x9D\x92\x9C\n" - "\xF0\x9D\x92\x9C \naaa\n...")); - string16 output; - EXPECT_TRUE(gfx::ElideRectangleString(str, 3, 3, &output)); - EXPECT_EQ(out, output); -} - diff --git a/app/theme_provider.cc b/app/theme_provider.cc deleted file mode 100644 index 7593e15..0000000 --- a/app/theme_provider.cc +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "app/theme_provider.h" - -// We have the destructor here because GCC puts the vtable in the first file -// that includes a virtual function of the class. Leaving it just in the .h file -// means that GCC will fail to link. - -ThemeProvider::~ThemeProvider() { -} diff --git a/app/theme_provider.h b/app/theme_provider.h deleted file mode 100644 index 3d92e4d..0000000 --- a/app/theme_provider.h +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef APP_THEME_PROVIDER_H_ -#define APP_THEME_PROVIDER_H_ -#pragma once - -#include "base/basictypes.h" -#include "third_party/skia/include/core/SkColor.h" - -#if defined(OS_MACOSX) -#ifdef __OBJC__ -@class NSColor; -@class NSGradient; -@class NSImage; -#else -class NSColor; -class NSGradient; -class NSImage; -#endif // __OBJC__ -#elif !defined(OS_WIN) -typedef struct _GdkColor GdkColor; -typedef struct _GdkPixbuf GdkPixbuf; -#endif // OS_* - -class Profile; -class RefCountedMemory; -class SkBitmap; - -//////////////////////////////////////////////////////////////////////////////// -// -// ThemeProvider -// -// ThemeProvider is an abstract class that defines the API that should be -// implemented to provide bitmaps and color information for a given theme. -// -//////////////////////////////////////////////////////////////////////////////// - -class ThemeProvider { - public: - virtual ~ThemeProvider(); - - // Initialize the provider with the passed in profile. - virtual void Init(Profile* profile) = 0; - - // Get the bitmap specified by |id|. An implementation of ThemeProvider should - // have its own source of ids (e.g. an enum, or external resource bundle). - virtual SkBitmap* GetBitmapNamed(int id) const = 0; - - // Get the color specified by |id|. - virtual SkColor GetColor(int id) const = 0; - - // Get the property (e.g. an alignment expressed in an enum, or a width or - // height) specified by |id|. - virtual bool GetDisplayProperty(int id, int* result) const = 0; - - // Whether we should use the native system frame (typically Aero glass) or - // a custom frame. - virtual bool ShouldUseNativeFrame() const = 0; - - // Whether or not we have a certain image. Used for when the default theme - // doesn't provide a certain image, but custom themes might (badges, etc). - virtual bool HasCustomImage(int id) const = 0; - - // Reads the image data from the theme file into the specified vector. Only - // valid for un-themed resources and the themed IDR_THEME_NTP_* in most - // implementations of ThemeProvider. Returns NULL on error. - virtual RefCountedMemory* GetRawData(int id) const = 0; - -#if defined(OS_MACOSX) - // Gets the NSImage with the specified |id|. - // - // The bitmap is not assumed to exist. If a theme does not provide an image, - // if |allow_default| is true, then the default image will be returned, else - // this function will return nil. - virtual NSImage* GetNSImageNamed(int id, bool allow_default) const = 0; - - // Gets the NSImage that GetNSImageNamed (above) would return, but returns it - // as a pattern color. - virtual NSColor* GetNSImageColorNamed(int id, bool allow_default) const = 0; - - // Gets the NSColor with the specified |id|. - // - // The color is not assumed to exist. If a theme does not provide an color, if - // |allow_default| is true, then the default color will be returned, else this - // function will return nil. - virtual NSColor* GetNSColor(int id, bool allow_default) const = 0; - - // Gets the NSColor for tinting with the specified |id|. - // - // The tint is not assumed to exist. If a theme does not provide a tint with - // that id, if |allow_default| is true, then the default tint will be - // returned, else this function will return nil. - virtual NSColor* GetNSColorTint(int id, bool allow_default) const = 0; - - // Gets the NSGradient with the specified |id|. - virtual NSGradient* GetNSGradient(int id) const = 0; -#elif defined(OS_POSIX) && !defined(TOOLKIT_VIEWS) - // Gets the GdkPixbuf with the specified |id|. Returns a pointer to a shared - // instance of the GdkPixbuf. This shared GdkPixbuf is owned by the theme - // provider and should not be freed. - // - // The bitmap is assumed to exist. This function will log in release, and - // assert in debug mode if it does not. On failure, this will return a - // pointer to a shared empty placeholder bitmap so it will be visible what - // is missing. - virtual GdkPixbuf* GetPixbufNamed(int id) const = 0; - - // As above, but flips it in RTL locales. - virtual GdkPixbuf* GetRTLEnabledPixbufNamed(int id) const = 0; -#endif -}; - -#endif // APP_THEME_PROVIDER_H_ diff --git a/app/view_prop.cc b/app/view_prop.cc deleted file mode 100644 index d71b95c..0000000 --- a/app/view_prop.cc +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "app/view_prop.h" - -#include <set> - -namespace app { - -// Maints the actual view, key and data. -class ViewProp::Data : public base::RefCounted<ViewProp::Data> { - public: - // Returns the Data* for the view/key pair. If |create| is false and |Get| - // has not been invoked for the view/key pair, NULL is returned. - static void Get(gfx::NativeView view, - const char* key, - bool create, - scoped_refptr<Data>* data) { - if (!data_set_) - data_set_ = new DataSet; - scoped_refptr<Data> new_data(new Data(view, key)); - DataSet::const_iterator i = data_set_->find(new_data.get()); - if (i != data_set_->end()) { - *data = *i; - return; - } - if (!create) - return; - data_set_->insert(new_data.get()); - *data = new_data.get(); - } - - // The data. - void set_data(void* data) { data_ = data; } - void* data() const { return data_; } - - const char* key() const { return key_; } - - private: - friend class base::RefCounted<Data>; - - // Used to order the Data in the map. - class DataComparator { - public: - bool operator()(const Data* d1, const Data* d2) const { - return (d1->view_ == d2->view_) ? (d1->key_ < d2->key_) : - (d1->view_ < d2->view_); - } - }; - - typedef std::set<Data*, DataComparator> DataSet; - - Data(gfx::NativeView view, const char* key) - : view_(view), - key_(key), - data_(NULL) {} - - ~Data() { - DataSet::iterator i = data_set_->find(this); - // Also check for equality using == as |Get| creates dummy values in order - // to look up a value. - if (i != data_set_->end() && *i == this) - data_set_->erase(i); - } - - // The existing set of Data is stored here. ~Data removes from the set. - static DataSet* data_set_; - - const gfx::NativeView view_; - const char* key_; - void* data_; - - DISALLOW_COPY_AND_ASSIGN(Data); -}; - -// static -ViewProp::Data::DataSet* ViewProp::Data::data_set_ = NULL; - -ViewProp::ViewProp(gfx::NativeView view, const char* key, void* data) { - Data::Get(view, key, true, &data_); - data_->set_data(data); -} - -ViewProp::~ViewProp() { - // This is done to provide similar semantics to SetProp. In particular it's - // assumed that ~ViewProp should behave as though RemoveProp was invoked. - data_->set_data(NULL); -} - -// static -void* ViewProp::GetValue(gfx::NativeView view, const char* key) { - scoped_refptr<Data> data; - Data::Get(view, key, false, &data); - return data.get() ? data->data() : NULL; -} - -// static -const char* ViewProp::Key() const { - return data_->key(); -} - -} // namespace app diff --git a/app/view_prop.h b/app/view_prop.h deleted file mode 100644 index c319460..0000000 --- a/app/view_prop.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef APP_VIEW_PROP_H_ -#define APP_VIEW_PROP_H_ -#pragma once - -#include "base/basictypes.h" -#include "base/ref_counted.h" -#include "gfx/native_widget_types.h" - -namespace app { - -// ViewProp maintains a key/value pair for a particular view. ViewProp is -// designed as a replacement for the Win32's SetProp, but does not make use of -// window manager memory. ViewProp shares similar semantics as SetProp, the -// value for a particular view/key pair comes from the last ViewProp created. -class ViewProp { - public: - // Associates data with a view/key pair. If a ViewProp has already been - // created for the specified pair |data| replaces the current value. - // - // ViewProp does *not* make a copy of the char*, the pointer is used for - // sorting. - ViewProp(gfx::NativeView view, const char* key, void* data); - ~ViewProp(); - - // Returns the value associated with the view/key pair, or NULL if there is - // none. - static void* GetValue(gfx::NativeView view, const char* key); - - // Returns the key. - const char* Key() const; - - private: - class Data; - - // Stores the actual data. - scoped_refptr<Data> data_; - - DISALLOW_COPY_AND_ASSIGN(ViewProp); -}; - -} // namespace app - -#endif // APP_VIEW_PROP_H_ diff --git a/app/view_prop_unittest.cc b/app/view_prop_unittest.cc deleted file mode 100644 index 9b81cd5..0000000 --- a/app/view_prop_unittest.cc +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "testing/gtest/include/gtest/gtest.h" - -#include "app/view_prop.h" -#include "base/scoped_ptr.h" - -typedef testing::Test ViewPropTest; - -static const char* kKey1 = "key_1"; -static const char* kKey2 = "key_2"; - -using app::ViewProp; - -// Test a handful of viewprop assertions. -TEST_F(ViewPropTest, Basic) { - gfx::NativeView nv1 = reinterpret_cast<gfx::NativeView>(1); - gfx::NativeView nv2 = reinterpret_cast<gfx::NativeView>(2); - - void* data1 = reinterpret_cast<void*>(11); - void* data2 = reinterpret_cast<void*>(12); - - // Initial value for a new view/key pair should be NULL. - EXPECT_EQ(NULL, ViewProp::GetValue(nv1, kKey1)); - - { - // Register a value for a view/key pair. - ViewProp prop(nv1, kKey1, data1); - EXPECT_EQ(data1, ViewProp::GetValue(nv1, kKey1)); - } - - // The property fell out of scope, so the value should now be NULL. - EXPECT_EQ(NULL, ViewProp::GetValue(nv1, kKey1)); - - { - // Register a value for a view/key pair. - scoped_ptr<ViewProp> v1(new ViewProp(nv1, kKey1, data1)); - EXPECT_EQ(data1, ViewProp::GetValue(nv1, kKey1)); - - // Register a value for the same view/key pair. - scoped_ptr<ViewProp> v2(new ViewProp(nv1, kKey1, data2)); - // The new value should take over. - EXPECT_EQ(data2, ViewProp::GetValue(nv1, kKey1)); - - // Null out the first ViewProp, which should NULL out the value. - v1.reset(NULL); - EXPECT_EQ(NULL, ViewProp::GetValue(nv1, kKey1)); - } - - // The property fell out of scope, so the value should now be NULL. - EXPECT_EQ(NULL, ViewProp::GetValue(nv1, kKey1)); - - { - // Register a value for a view/key pair. - scoped_ptr<ViewProp> v1(new ViewProp(nv1, kKey1, data1)); - scoped_ptr<ViewProp> v2(new ViewProp(nv2, kKey2, data2)); - EXPECT_EQ(data1, ViewProp::GetValue(nv1, kKey1)); - EXPECT_EQ(data2, ViewProp::GetValue(nv2, kKey2)); - - v1.reset(NULL); - EXPECT_EQ(NULL, ViewProp::GetValue(nv1, kKey1)); - EXPECT_EQ(data2, ViewProp::GetValue(nv2, kKey2)); - - v2.reset(NULL); - EXPECT_EQ(NULL, ViewProp::GetValue(nv1, kKey1)); - EXPECT_EQ(NULL, ViewProp::GetValue(nv2, kKey2)); - } -} diff --git a/app/x11_util.cc b/app/x11_util.cc deleted file mode 100644 index 549cca8..0000000 --- a/app/x11_util.cc +++ /dev/null @@ -1,880 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file defines utility functions for X11 (Linux only). This code has been -// ported from XCB since we can't use XCB on Ubuntu while its 32-bit support -// remains woefully incomplete. - -#include "app/x11_util.h" - -#include <gdk/gdk.h> -#include <gdk/gdkx.h> -#include <gtk/gtk.h> - -#include <sys/ipc.h> -#include <sys/shm.h> - -#include <list> -#include <set> - -#include "base/command_line.h" -#include "base/logging.h" -#include "base/stringprintf.h" -#include "base/string_number_conversions.h" -#include "base/threading/thread.h" -#include "app/x11_util_internal.h" -#include "gfx/rect.h" -#include "gfx/size.h" - -namespace x11_util { - -namespace { - -// Used to cache the XRenderPictFormat for a visual/display pair. -struct CachedPictFormat { - bool equals(Display* display, Visual* visual) const { - return display == this->display && visual == this->visual; - } - - Display* display; - Visual* visual; - XRenderPictFormat* format; -}; - -typedef std::list<CachedPictFormat> CachedPictFormats; - -// Returns the cache of pict formats. -CachedPictFormats* get_cached_pict_formats() { - static CachedPictFormats* formats = NULL; - if (!formats) - formats = new CachedPictFormats(); - return formats; -} - -// Maximum number of CachedPictFormats we keep around. -const size_t kMaxCacheSize = 5; - -int DefaultX11ErrorHandler(Display* d, XErrorEvent* e) { - LOG(ERROR) << GetErrorEventDescription(d, e); - return 0; -} - -int DefaultX11IOErrorHandler(Display* d) { - // If there's an IO error it likely means the X server has gone away - LOG(ERROR) << "X IO Error detected"; - _exit(1); -} - -} // namespace - -bool XDisplayExists() { - return (gdk_display_get_default() != NULL); -} - -Display* GetXDisplay() { - static Display* display = NULL; - - if (!display) - display = gdk_x11_get_default_xdisplay(); - - return display; -} - -static SharedMemorySupport DoQuerySharedMemorySupport(Display* dpy) { - // A temporary flag for tracking down shared memory problems. - // TODO(evanm): remove this. - if (CommandLine::ForCurrentProcess()->HasSwitch("disable-xshm")) - return SHARED_MEMORY_NONE; - - int dummy; - Bool pixmaps_supported; - // Query the server's support for XSHM. - if (!XShmQueryVersion(dpy, &dummy, &dummy, &pixmaps_supported)) - return SHARED_MEMORY_NONE; - - // Next we probe to see if shared memory will really work - int shmkey = shmget(IPC_PRIVATE, 1, 0666); - if (shmkey == -1) - return SHARED_MEMORY_NONE; - void* address = shmat(shmkey, NULL, 0); - // Mark the shared memory region for deletion - shmctl(shmkey, IPC_RMID, NULL); - - XShmSegmentInfo shminfo; - memset(&shminfo, 0, sizeof(shminfo)); - shminfo.shmid = shmkey; - - gdk_error_trap_push(); - bool result = XShmAttach(dpy, &shminfo); - XSync(dpy, False); - if (gdk_error_trap_pop()) - result = false; - shmdt(address); - if (!result) - return SHARED_MEMORY_NONE; - - XShmDetach(dpy, &shminfo); - return pixmaps_supported ? SHARED_MEMORY_PIXMAP : SHARED_MEMORY_PUTIMAGE; -} - -SharedMemorySupport QuerySharedMemorySupport(Display* dpy) { - static SharedMemorySupport shared_memory_support = SHARED_MEMORY_NONE; - static bool shared_memory_support_cached = false; - - if (shared_memory_support_cached) - return shared_memory_support; - - shared_memory_support = DoQuerySharedMemorySupport(dpy); - shared_memory_support_cached = true; - - return shared_memory_support; -} - -bool QueryRenderSupport(Display* dpy) { - static bool render_supported = false; - static bool render_supported_cached = false; - - if (render_supported_cached) - return render_supported; - - // We don't care about the version of Xrender since all the features which - // we use are included in every version. - int dummy; - render_supported = XRenderQueryExtension(dpy, &dummy, &dummy); - render_supported_cached = true; - - return render_supported; -} - -int GetDefaultScreen(Display* display) { - return XDefaultScreen(display); -} - -XID GetX11RootWindow() { - return GDK_WINDOW_XID(gdk_get_default_root_window()); -} - -bool GetCurrentDesktop(int* desktop) { - return GetIntProperty(GetX11RootWindow(), "_NET_CURRENT_DESKTOP", desktop); -} - -XID GetX11WindowFromGtkWidget(GtkWidget* widget) { - return GDK_WINDOW_XID(widget->window); -} - -XID GetX11WindowFromGdkWindow(GdkWindow* window) { - return GDK_WINDOW_XID(window); -} - -void* GetVisualFromGtkWidget(GtkWidget* widget) { - return GDK_VISUAL_XVISUAL(gtk_widget_get_visual(widget)); -} - -int BitsPerPixelForPixmapDepth(Display* dpy, int depth) { - int count; - XPixmapFormatValues* formats = XListPixmapFormats(dpy, &count); - if (!formats) - return -1; - - int bits_per_pixel = -1; - for (int i = 0; i < count; ++i) { - if (formats[i].depth == depth) { - bits_per_pixel = formats[i].bits_per_pixel; - break; - } - } - - XFree(formats); - return bits_per_pixel; -} - -bool IsWindowVisible(XID window) { - XWindowAttributes win_attributes; - XGetWindowAttributes(GetXDisplay(), window, &win_attributes); - if (win_attributes.map_state != IsViewable) - return false; - // Some compositing window managers (notably kwin) do not actually unmap - // windows on desktop switch, so we also must check the current desktop. - int window_desktop, current_desktop; - return (!GetWindowDesktop(window, &window_desktop) || - !GetCurrentDesktop(¤t_desktop) || - window_desktop == kAllDesktops || - window_desktop == current_desktop); -} - -bool GetWindowRect(XID window, gfx::Rect* rect) { - Window root, child; - int x, y; - unsigned int width, height; - unsigned int border_width, depth; - - if (!XGetGeometry(GetXDisplay(), window, &root, &x, &y, - &width, &height, &border_width, &depth)) - return false; - - if (!XTranslateCoordinates(GetSecondaryDisplay(), window, root, - 0, 0, &x, &y, &child)) - return false; - - *rect = gfx::Rect(x, y, width, height); - return true; -} - -bool GetIntProperty(XID window, const std::string& property_name, int* value) { - Atom property_atom = gdk_x11_get_xatom_by_name_for_display( - gdk_display_get_default(), property_name.c_str()); - - Atom type = None; - int format = 0; // size in bits of each item in 'property' - long unsigned int num_items = 0, remaining_bytes = 0; - unsigned char* property = NULL; - - int result = XGetWindowProperty(GetXDisplay(), - window, - property_atom, - 0, // offset into property data to read - 1, // max length to get - False, // deleted - AnyPropertyType, - &type, - &format, - &num_items, - &remaining_bytes, - &property); - if (result != Success) - return false; - - if (format != 32 || num_items != 1) { - XFree(property); - return false; - } - - *value = *(reinterpret_cast<int*>(property)); - XFree(property); - return true; -} - -bool GetIntArrayProperty(XID window, - const std::string& property_name, - std::vector<int>* value) { - Atom property_atom = gdk_x11_get_xatom_by_name_for_display( - gdk_display_get_default(), property_name.c_str()); - - Atom type = None; - int format = 0; // size in bits of each item in 'property' - long unsigned int num_items = 0, remaining_bytes = 0; - unsigned char* properties = NULL; - - int result = XGetWindowProperty(GetXDisplay(), - window, - property_atom, - 0, // offset into property data to read - (~0L), // max length to get (all of them) - False, // deleted - AnyPropertyType, - &type, - &format, - &num_items, - &remaining_bytes, - &properties); - if (result != Success) - return false; - - if (format != 32) { - XFree(properties); - return false; - } - - int* int_properties = reinterpret_cast<int*>(properties); - value->clear(); - value->insert(value->begin(), int_properties, int_properties + num_items); - XFree(properties); - return true; -} - -bool GetStringProperty( - XID window, const std::string& property_name, std::string* value) { - Atom property_atom = gdk_x11_get_xatom_by_name_for_display( - gdk_display_get_default(), property_name.c_str()); - - Atom type = None; - int format = 0; // size in bits of each item in 'property' - long unsigned int num_items = 0, remaining_bytes = 0; - unsigned char* property = NULL; - - int result = XGetWindowProperty(GetXDisplay(), - window, - property_atom, - 0, // offset into property data to read - 1024, // max length to get - False, // deleted - AnyPropertyType, - &type, - &format, - &num_items, - &remaining_bytes, - &property); - if (result != Success) - return false; - - if (format != 8) { - XFree(property); - return false; - } - - value->assign(reinterpret_cast<char*>(property), num_items); - XFree(property); - return true; -} - -XID GetParentWindow(XID window) { - XID root = None; - XID parent = None; - XID* children = NULL; - unsigned int num_children = 0; - XQueryTree(GetXDisplay(), window, &root, &parent, &children, &num_children); - if (children) - XFree(children); - return parent; -} - -XID GetHighestAncestorWindow(XID window, XID root) { - while (true) { - XID parent = x11_util::GetParentWindow(window); - if (parent == None) - return None; - if (parent == root) - return window; - window = parent; - } -} - -bool GetWindowDesktop(XID window, int* desktop) { - return GetIntProperty(window, "_NET_WM_DESKTOP", desktop); -} - -// Returns true if |window| is a named window. -bool IsWindowNamed(XID window) { - XTextProperty prop; - if (!XGetWMName(GetXDisplay(), window, &prop) || !prop.value) - return false; - - XFree(prop.value); - return true; -} - -bool EnumerateChildren(EnumerateWindowsDelegate* delegate, XID window, - const int max_depth, int depth) { - if (depth > max_depth) - return false; - - XID root, parent, *children; - unsigned int num_children; - int status = XQueryTree(GetXDisplay(), window, &root, &parent, &children, - &num_children); - if (status == 0) - return false; - - std::set<XID> windows; - for (unsigned int i = 0; i < num_children; i++) - windows.insert(children[i]); - - XFree(children); - - // XQueryTree returns the children of |window| in bottom-to-top order, so - // reverse-iterate the list to check the windows from top-to-bottom. - std::set<XID>::reverse_iterator iter; - for (iter = windows.rbegin(); iter != windows.rend(); iter++) { - if (IsWindowNamed(*iter) && delegate->ShouldStopIterating(*iter)) - return true; - } - - // If we're at this point, we didn't find the window we're looking for at the - // current level, so we need to recurse to the next level. We use a second - // loop because the recursion and call to XQueryTree are expensive and is only - // needed for a small number of cases. - if (++depth <= max_depth) { - for (iter = windows.rbegin(); iter != windows.rend(); iter++) { - if (EnumerateChildren(delegate, *iter, max_depth, depth)) - return true; - } - } - - return false; -} - -bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate, int max_depth) { - XID root = GetX11RootWindow(); - return EnumerateChildren(delegate, root, max_depth, 0); -} - -bool GetXWindowStack(std::vector<XID>* windows) { - windows->clear(); - - static Atom atom = XInternAtom(GetXDisplay(), - "_NET_CLIENT_LIST_STACKING", False); - - Atom type; - int format; - unsigned long count; - unsigned long bytes_after; - unsigned char *data = NULL; - if (XGetWindowProperty(GetXDisplay(), - GetX11RootWindow(), - atom, - 0, // offset - ~0L, // length - False, // delete - AnyPropertyType, // requested type - &type, - &format, - &count, - &bytes_after, - &data) != Success) { - return false; - } - - bool result = false; - if (type == XA_WINDOW && format == 32 && data && count > 0) { - result = true; - XID* stack = reinterpret_cast<XID*>(data); - for (unsigned long i = 0; i < count; i++) - windows->insert(windows->begin(), stack[i]); - } - - if (data) - XFree(data); - - return result; -} - -void RestackWindow(XID window, XID sibling, bool above) { - XWindowChanges changes; - changes.sibling = sibling; - changes.stack_mode = above ? Above : Below; - XConfigureWindow(GetXDisplay(), window, CWSibling | CWStackMode, &changes); -} - -XSharedMemoryId AttachSharedMemory(Display* display, int shared_memory_key) { - DCHECK(QuerySharedMemorySupport(display)); - - XShmSegmentInfo shminfo; - memset(&shminfo, 0, sizeof(shminfo)); - shminfo.shmid = shared_memory_key; - - // This function is only called if QuerySharedMemorySupport returned true. In - // which case we've already succeeded in having the X server attach to one of - // our shared memory segments. - if (!XShmAttach(display, &shminfo)) - NOTREACHED(); - - return shminfo.shmseg; -} - -void DetachSharedMemory(Display* display, XSharedMemoryId shmseg) { - DCHECK(QuerySharedMemorySupport(display)); - - XShmSegmentInfo shminfo; - memset(&shminfo, 0, sizeof(shminfo)); - shminfo.shmseg = shmseg; - - if (!XShmDetach(display, &shminfo)) - NOTREACHED(); -} - -XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap) { - XID picture = XRenderCreatePicture( - display, pixmap, GetRenderARGB32Format(display), 0, NULL); - - return picture; -} - -void PutARGBImage(Display* display, void* visual, int depth, XID pixmap, - void* pixmap_gc, const uint8* data, int width, int height) { - // TODO(scherkus): potential performance impact... consider passing in as a - // parameter. - int pixmap_bpp = BitsPerPixelForPixmapDepth(display, depth); - - XImage image; - memset(&image, 0, sizeof(image)); - - image.width = width; - image.height = height; - image.format = ZPixmap; - image.byte_order = LSBFirst; - image.bitmap_unit = 8; - image.bitmap_bit_order = LSBFirst; - image.depth = depth; - image.bits_per_pixel = pixmap_bpp; - image.bytes_per_line = width * pixmap_bpp / 8; - - if (pixmap_bpp == 32) { - image.red_mask = 0xff0000; - image.green_mask = 0xff00; - image.blue_mask = 0xff; - - // If the X server depth is already 32-bits and the color masks match, - // then our job is easy. - Visual* vis = static_cast<Visual*>(visual); - if (image.red_mask == vis->red_mask && - image.green_mask == vis->green_mask && - image.blue_mask == vis->blue_mask) { - image.data = const_cast<char*>(reinterpret_cast<const char*>(data)); - XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image, - 0, 0 /* source x, y */, 0, 0 /* dest x, y */, - width, height); - } else { - // Otherwise, we need to shuffle the colors around. Assume red and blue - // need to be swapped. - // - // It's possible to use some fancy SSE tricks here, but since this is the - // slow path anyway, we do it slowly. - - uint8_t* bitmap32 = static_cast<uint8_t*>(malloc(4 * width * height)); - if (!bitmap32) - return; - uint8_t* const orig_bitmap32 = bitmap32; - const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data); - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { - const uint32_t pixel = *(bitmap_in++); - bitmap32[0] = (pixel >> 16) & 0xff; // Red - bitmap32[1] = (pixel >> 8) & 0xff; // Green - bitmap32[2] = pixel & 0xff; // Blue - bitmap32[3] = (pixel >> 24) & 0xff; // Alpha - bitmap32 += 4; - } - } - image.data = reinterpret_cast<char*>(orig_bitmap32); - XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image, - 0, 0 /* source x, y */, 0, 0 /* dest x, y */, - width, height); - free(orig_bitmap32); - } - } else if (pixmap_bpp == 16) { - // Some folks have VNC setups which still use 16-bit visuals and VNC - // doesn't include Xrender. - - uint16_t* bitmap16 = static_cast<uint16_t*>(malloc(2 * width * height)); - if (!bitmap16) - return; - uint16_t* const orig_bitmap16 = bitmap16; - const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data); - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { - const uint32_t pixel = *(bitmap_in++); - uint16_t out_pixel = ((pixel >> 8) & 0xf800) | - ((pixel >> 5) & 0x07e0) | - ((pixel >> 3) & 0x001f); - *(bitmap16++) = out_pixel; - } - } - - image.data = reinterpret_cast<char*>(orig_bitmap16); - image.red_mask = 0xf800; - image.green_mask = 0x07e0; - image.blue_mask = 0x001f; - - XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image, - 0, 0 /* source x, y */, 0, 0 /* dest x, y */, - width, height); - free(orig_bitmap16); - } else { - LOG(FATAL) << "Sorry, we don't support your visual depth without " - "Xrender support (depth:" << depth - << " bpp:" << pixmap_bpp << ")"; - } -} - -void FreePicture(Display* display, XID picture) { - XRenderFreePicture(display, picture); -} - -void FreePixmap(Display* display, XID pixmap) { - XFreePixmap(display, pixmap); -} - -// Called on BACKGROUND_X11 thread. -Display* GetSecondaryDisplay() { - static Display* display = NULL; - if (!display) { - display = XOpenDisplay(NULL); - CHECK(display); - } - - return display; -} - -// Called on BACKGROUND_X11 thread. -bool GetWindowGeometry(int* x, int* y, unsigned* width, unsigned* height, - XID window) { - Window root_window, child_window; - unsigned border_width, depth; - int temp; - - if (!XGetGeometry(GetSecondaryDisplay(), window, &root_window, &temp, &temp, - width, height, &border_width, &depth)) - return false; - if (!XTranslateCoordinates(GetSecondaryDisplay(), window, root_window, - 0, 0 /* input x, y */, x, y /* output x, y */, - &child_window)) - return false; - - return true; -} - -// Called on BACKGROUND_X11 thread. -bool GetWindowParent(XID* parent_window, bool* parent_is_root, XID window) { - XID root_window, *children; - unsigned num_children; - - Status s = XQueryTree(GetSecondaryDisplay(), window, &root_window, - parent_window, &children, &num_children); - if (!s) - return false; - - if (children) - XFree(children); - - *parent_is_root = root_window == *parent_window; - return true; -} - -bool GetWindowManagerName(std::string* wm_name) { - DCHECK(wm_name); - int wm_window = 0; - if (!x11_util::GetIntProperty(x11_util::GetX11RootWindow(), - "_NET_SUPPORTING_WM_CHECK", - &wm_window)) { - return false; - } - - // It's possible that a window manager started earlier in this X session left - // a stale _NET_SUPPORTING_WM_CHECK property when it was replaced by a - // non-EWMH window manager, so we trap errors in the following requests to - // avoid crashes (issue 23860). - - // EWMH requires the supporting-WM window to also have a - // _NET_SUPPORTING_WM_CHECK property pointing to itself (to avoid a stale - // property referencing an ID that's been recycled for another window), so we - // check that too. - gdk_error_trap_push(); - int wm_window_property = 0; - bool result = x11_util::GetIntProperty( - wm_window, "_NET_SUPPORTING_WM_CHECK", &wm_window_property); - gdk_flush(); - bool got_error = gdk_error_trap_pop(); - if (got_error || !result || wm_window_property != wm_window) - return false; - - gdk_error_trap_push(); - result = x11_util::GetStringProperty( - static_cast<XID>(wm_window), "_NET_WM_NAME", wm_name); - gdk_flush(); - got_error = gdk_error_trap_pop(); - return !got_error && result; -} - -static cairo_status_t SnapshotCallback( - void *closure, const unsigned char *data, unsigned int length) { - std::vector<unsigned char>* png_representation = - static_cast<std::vector<unsigned char>*>(closure); - - size_t old_size = png_representation->size(); - png_representation->resize(old_size + length); - memcpy(&(*png_representation)[old_size], data, length); - return CAIRO_STATUS_SUCCESS; -} - -void GrabWindowSnapshot(GtkWindow* gtk_window, - std::vector<unsigned char>* png_representation) { - GdkWindow* gdk_window = GTK_WIDGET(gtk_window)->window; - Display* display = GDK_WINDOW_XDISPLAY(gdk_window); - XID win = GDK_WINDOW_XID(gdk_window); - XWindowAttributes attr; - if (XGetWindowAttributes(display, win, &attr) == 0) { - LOG(ERROR) << "Couldn't get window attributes"; - return; - } - XImage* image = XGetImage( - display, win, 0, 0, attr.width, attr.height, AllPlanes, ZPixmap); - if (!image) { - LOG(ERROR) << "Couldn't get image"; - return; - } - if (image->depth != 24) { - LOG(ERROR)<< "Unsupported image depth " << image->depth; - return; - } - cairo_surface_t* surface = - cairo_image_surface_create_for_data( - reinterpret_cast<unsigned char*>(image->data), - CAIRO_FORMAT_RGB24, - image->width, - image->height, - image->bytes_per_line); - - if (!surface) { - LOG(ERROR) << "Unable to create Cairo surface from XImage data"; - return; - } - cairo_surface_write_to_png_stream( - surface, SnapshotCallback, png_representation); - cairo_surface_destroy(surface); -} - -bool ChangeWindowDesktop(XID window, XID destination) { - int desktop; - if (!GetWindowDesktop(destination, &desktop)) - return false; - - // If |window| is sticky, use the current desktop. - if (desktop == kAllDesktops && - !GetCurrentDesktop(&desktop)) - return false; - - XEvent event; - event.xclient.type = ClientMessage; - event.xclient.window = window; - event.xclient.message_type = gdk_x11_get_xatom_by_name_for_display( - gdk_display_get_default(), "_NET_WM_DESKTOP"); - event.xclient.format = 32; - event.xclient.data.l[0] = desktop; - event.xclient.data.l[1] = 1; // source indication - - int result = XSendEvent(GetXDisplay(), GetX11RootWindow(), False, - SubstructureNotifyMask, &event); - return result == Success; -} - -void SetDefaultX11ErrorHandlers() { - SetX11ErrorHandlers(NULL, NULL); -} - -// ---------------------------------------------------------------------------- -// These functions are declared in x11_util_internal.h because they require -// XLib.h to be included, and it conflicts with many other headers. -XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { - static XRenderPictFormat* pictformat = NULL; - if (pictformat) - return pictformat; - - // First look for a 32-bit format which ignores the alpha value - XRenderPictFormat templ; - templ.depth = 32; - templ.type = PictTypeDirect; - templ.direct.red = 16; - templ.direct.green = 8; - templ.direct.blue = 0; - templ.direct.redMask = 0xff; - templ.direct.greenMask = 0xff; - templ.direct.blueMask = 0xff; - templ.direct.alphaMask = 0; - - static const unsigned long kMask = - PictFormatType | PictFormatDepth | - PictFormatRed | PictFormatRedMask | - PictFormatGreen | PictFormatGreenMask | - PictFormatBlue | PictFormatBlueMask | - PictFormatAlphaMask; - - pictformat = XRenderFindFormat(dpy, kMask, &templ, 0 /* first result */); - - if (!pictformat) { - // Not all X servers support xRGB32 formats. However, the XRENDER spec says - // that they must support an ARGB32 format, so we can always return that. - pictformat = XRenderFindStandardFormat(dpy, PictStandardARGB32); - CHECK(pictformat) << "XRENDER ARGB32 not supported."; - } - - return pictformat; -} - -XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual) { - DCHECK(QueryRenderSupport(dpy)); - - CachedPictFormats* formats = get_cached_pict_formats(); - - for (CachedPictFormats::const_iterator i = formats->begin(); - i != formats->end(); ++i) { - if (i->equals(dpy, visual)) - return i->format; - } - - // Not cached, look up the value. - XRenderPictFormat* pictformat = XRenderFindVisualFormat(dpy, visual); - CHECK(pictformat) << "XRENDER does not support default visual"; - - // And store it in the cache. - CachedPictFormat cached_value; - cached_value.visual = visual; - cached_value.display = dpy; - cached_value.format = pictformat; - formats->push_front(cached_value); - - if (formats->size() == kMaxCacheSize) { - formats->pop_back(); - // We should really only have at most 2 display/visual combinations: - // one for normal browser windows, and possibly another for an argb window - // created to display a menu. - // - // If we get here it's not fatal, we just need to make sure we aren't - // always blowing away the cache. If we are, then we should figure out why - // and make it bigger. - NOTREACHED(); - } - - return pictformat; -} - -void SetX11ErrorHandlers(XErrorHandler error_handler, - XIOErrorHandler io_error_handler) { - XSetErrorHandler(error_handler ? error_handler : DefaultX11ErrorHandler); - XSetIOErrorHandler( - io_error_handler ? io_error_handler : DefaultX11IOErrorHandler); -} - -std::string GetErrorEventDescription(Display *dpy, - XErrorEvent *error_event) { - char error_str[256]; - char request_str[256]; - - XGetErrorText(dpy, error_event->error_code, error_str, sizeof(error_str)); - - strncpy(request_str, "Unknown", sizeof(request_str)); - if (error_event->request_code < 128) { - std::string num = base::UintToString(error_event->request_code); - XGetErrorDatabaseText( - dpy, "XRequest", num.c_str(), "Unknown", request_str, - sizeof(request_str)); - } else { - int num_ext; - char **ext_list = XListExtensions(dpy, &num_ext); - - for (int i = 0; i < num_ext; i++) { - int ext_code, first_event, first_error; - XQueryExtension(dpy, ext_list[i], &ext_code, &first_event, &first_error); - if (error_event->request_code == ext_code) { - std::string msg = StringPrintf( - "%s.%d", ext_list[i], error_event->minor_code); - XGetErrorDatabaseText( - dpy, "XRequest", msg.c_str(), "Unknown", request_str, - sizeof(request_str)); - break; - } - } - XFreeExtensionList(ext_list); - } - - return base::StringPrintf( - "X Error detected: serial %lu, error_code %u (%s), " - "request_code %u minor_code %u (%s)", - error_event->serial, error_event->error_code, error_str, - error_event->request_code, error_event->minor_code, request_str); -} -// ---------------------------------------------------------------------------- -// End of x11_util_internal.h - - -} // namespace x11_util diff --git a/app/x11_util.h b/app/x11_util.h deleted file mode 100644 index c07f42c..0000000 --- a/app/x11_util.h +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef APP_X11_UTIL_H_ -#define APP_X11_UTIL_H_ -#pragma once - -// This file declares utility functions for X11 (Linux only). -// -// These functions do not require the Xlib headers to be included (which is why -// we use a void* for Visual*). The Xlib headers are highly polluting so we try -// hard to limit their spread into the rest of the code. - -#include <string> -#include <vector> - -#include "base/basictypes.h" - -typedef struct _GdkDrawable GdkWindow; -typedef struct _GtkWidget GtkWidget; -typedef struct _GtkWindow GtkWindow; -typedef unsigned long XID; -typedef unsigned long XSharedMemoryId; // ShmSeg in the X headers. -typedef struct _XDisplay Display; - -namespace gfx { -class Rect; -} - -namespace x11_util { - -// These functions use the GDK default display and this /must/ be called from -// the UI thread. Thus, they don't support multiple displays. - -// These functions cache their results --------------------------------- - -// Check if there's an open connection to an X server. -bool XDisplayExists(); -// Return an X11 connection for the current, primary display. -Display* GetXDisplay(); - -// X shared memory comes in three flavors: -// 1) No SHM support, -// 2) SHM putimage, -// 3) SHM pixmaps + putimage. -enum SharedMemorySupport { - SHARED_MEMORY_NONE, - SHARED_MEMORY_PUTIMAGE, - SHARED_MEMORY_PIXMAP -}; -// Return the shared memory type of our X connection. -SharedMemorySupport QuerySharedMemorySupport(Display* dpy); - -// Return true iff the display supports Xrender -bool QueryRenderSupport(Display* dpy); - -// Return the default screen number for the display -int GetDefaultScreen(Display* display); - -// These functions do not cache their results -------------------------- - -// Get the X window id for the default root window -XID GetX11RootWindow(); -// Returns the user's current desktop. -bool GetCurrentDesktop(int* desktop); -// Get the X window id for the given GTK widget. -XID GetX11WindowFromGtkWidget(GtkWidget* widget); -XID GetX11WindowFromGdkWindow(GdkWindow* window); -// Get a Visual from the given widget. Since we don't include the Xlib -// headers, this is returned as a void*. -void* GetVisualFromGtkWidget(GtkWidget* widget); -// Return the number of bits-per-pixel for a pixmap of the given depth -int BitsPerPixelForPixmapDepth(Display* display, int depth); -// Returns true if |window| is visible. -bool IsWindowVisible(XID window); -// Returns the bounds of |window|. -bool GetWindowRect(XID window, gfx::Rect* rect); -// Get the value of an int, int array, or string property. On -// success, true is returned and the value is stored in |value|. -bool GetIntProperty(XID window, const std::string& property_name, int* value); -bool GetIntArrayProperty(XID window, const std::string& property_name, - std::vector<int>* value); -bool GetStringProperty( - XID window, const std::string& property_name, std::string* value); - -// Get |window|'s parent window, or None if |window| is the root window. -XID GetParentWindow(XID window); - -// Walk up |window|'s hierarchy until we find a direct child of |root|. -XID GetHighestAncestorWindow(XID window, XID root); - -static const int kAllDesktops = -1; -// Queries the desktop |window| is on, kAllDesktops if sticky. Returns false if -// property not found. -bool GetWindowDesktop(XID window, int* desktop); - -// Implementers of this interface receive a notification for every X window of -// the main display. -class EnumerateWindowsDelegate { - public: - // |xid| is the X Window ID of the enumerated window. Return true to stop - // further iteration. - virtual bool ShouldStopIterating(XID xid) = 0; - - protected: - virtual ~EnumerateWindowsDelegate() {} -}; - -// Enumerates all windows in the current display. Will recurse into child -// windows up to a depth of |max_depth|. -bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate, int max_depth); - -// Returns a list of top-level windows in top-to-bottom stacking order. -bool GetXWindowStack(std::vector<XID>* windows); - -// Restack a window in relation to one of its siblings. If |above| is true, -// |window| will be stacked directly above |sibling|; otherwise it will stacked -// directly below it. Both windows must be immediate children of the same -// window. -void RestackWindow(XID window, XID sibling, bool above); - -// Return a handle to a X ShmSeg. |shared_memory_key| is a SysV -// IPC key. The shared memory region must contain 32-bit pixels. -XSharedMemoryId AttachSharedMemory(Display* display, int shared_memory_support); -void DetachSharedMemory(Display* display, XSharedMemoryId shmseg); - -// Return a handle to an XRender picture where |pixmap| is a handle to a -// pixmap containing Skia ARGB data. -XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap); - -// Draws ARGB data on the given pixmap using the given GC, converting to the -// server side visual depth as needed. Destination is assumed to be the same -// dimensions as |data| or larger. |data| is also assumed to be in row order -// with each line being exactly |width| * 4 bytes long. -void PutARGBImage(Display* display, void* visual, int depth, XID pixmap, - void* pixmap_gc, const uint8* data, int width, int height); - -void FreePicture(Display* display, XID picture); -void FreePixmap(Display* display, XID pixmap); - -// These functions are for performing X opertions outside of the UI thread. - -// Return the Display for the secondary X connection. We keep a second -// connection around for making X requests outside of the UI thread. -// This function may only be called from the BACKGROUND_X11 thread. -Display* GetSecondaryDisplay(); - -// Since one cannot include both WebKit header and Xlib headers in the same -// file (due to collisions), we wrap all the Xlib functions that we need here. -// These functions must be called on the BACKGROUND_X11 thread since they -// reference GetSecondaryDisplay(). - -// Get the position of the given window in screen coordinates as well as its -// current size. -bool GetWindowGeometry(int* x, int* y, unsigned* width, unsigned* height, - XID window); - -// Find the immediate parent of an X window. -// -// parent_window: (output) the parent window of |window|, or 0. -// parent_is_root: (output) true iff the parent of |window| is the root window. -bool GetWindowParent(XID* parent_window, bool* parent_is_root, XID window); - -// Get the window manager name. -bool GetWindowManagerName(std::string* name); - -// Grabs a snapshot of the designated window and stores a PNG representation -// into a byte vector. -void GrabWindowSnapshot(GtkWindow* gdk_window, - std::vector<unsigned char>* png_representation); - -// Change desktop for |window| to the desktop of |destination| window. -bool ChangeWindowDesktop(XID window, XID destination); - -// Enable the default X error handlers. These will log the error and abort -// the process if called. Use SetX11ErrorHandlers() from x11_util_internal.h -// to set your own error handlers. -void SetDefaultX11ErrorHandlers(); - -} // namespace x11_util - -#endif // APP_X11_UTIL_H_ diff --git a/app/x11_util_internal.h b/app/x11_util_internal.h deleted file mode 100644 index a4953b5..0000000 --- a/app/x11_util_internal.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef APP_X11_UTIL_INTERNAL_H_ -#define APP_X11_UTIL_INTERNAL_H_ -#pragma once - -// This file declares utility functions for X11 (Linux only). -// -// These functions require the inclusion of the Xlib headers. Since the Xlib -// headers pollute so much of the namespace, this should only be included -// when needed. - -extern "C" { -#include <X11/Xatom.h> -#include <X11/Xlib.h> -#include <X11/extensions/XShm.h> -#include <X11/extensions/Xrender.h> -} - -namespace x11_util { - // -------------------------------------------------------------------------- - // NOTE: these functions cache the results and must be called from the UI - // thread. - // Get the XRENDER format id for ARGB32 (Skia's format). - // - // NOTE:Currently this don't support multiple screens/displays. - XRenderPictFormat* GetRenderARGB32Format(Display* dpy); - - // Get the XRENDER format id for the default visual on the first screen. This - // is the format which our GTK window will have. - XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual); - - // -------------------------------------------------------------------------- - // X11 error handling. - // Sets the X Error Handlers. Passing NULL for either will enable the default - // error handler, which if called will log the error and abort the process. - void SetX11ErrorHandlers(XErrorHandler error_handler, - XIOErrorHandler io_error_handler); - - // Returns a string suitable for logging the error event. - std::string GetErrorEventDescription(Display* dpy, XErrorEvent* error_event); -}; - -#endif // APP_X11_UTIL_INTERNAL_H_ |