| Index: ui/base/x/x11_window_cache.h
|
| diff --git a/ui/base/x/x11_window_cache.h b/ui/base/x/x11_window_cache.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..eca87c7a64e98385176f42d92f3c18d9a3e211c8
|
| --- /dev/null
|
| +++ b/ui/base/x/x11_window_cache.h
|
| @@ -0,0 +1,228 @@
|
| +// Copyright 2016 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 UI_BASE_X_X11_WINDOW_CACHE_H_
|
| +#define UI_BASE_X_X11_WINDOW_CACHE_H_
|
| +
|
| +#include <xcb/xcb.h>
|
| +
|
| +#include <algorithm>
|
| +#include <list>
|
| +#include <unordered_map>
|
| +
|
| +#include "base/macros.h"
|
| +#include "ui/base/x/ui_base_x_export.h"
|
| +#include "ui/events/platform/platform_event_observer.h"
|
| +#include "ui/gfx/x/x11_types.h"
|
| +
|
| +namespace ui {
|
| +
|
| +class X11EventSource;
|
| +class XScopedEventSelector;
|
| +
|
| +// Keep tabs on the window tree starting from a root window.
|
| +class UI_BASE_X_EXPORT XWindowCache : public PlatformEventObserver {
|
| + private:
|
| + struct GetWindowAttributesRequest;
|
| + struct GetGeometryRequest;
|
| + struct ListPropertiesRequest;
|
| + struct QueryTreeRequest;
|
| + struct GetPropertyRequest;
|
| +
|
| + public:
|
| + class Window;
|
| + class Property {
|
| + public:
|
| + ~Property();
|
| +
|
| + XID name() const { return name_; }
|
| +
|
| + XID type() const { return type_; }
|
| + uint8_t format() const { return format_; }
|
| + int length() const { return length_; }
|
| + const void* data() const { return data_; }
|
| +
|
| + private:
|
| + friend class XWindowCache;
|
| + Property(xcb_atom_t name, Window* window, XWindowCache* cache);
|
| +
|
| + // Ensures the Property is fully cached, and clients can get any
|
| + // data from it they want. |this| will be destructed and
|
| + // Validate() will return false if the window was destroyed before
|
| + // it could be cached. Otherwise, returns true.
|
| + bool Validate();
|
| +
|
| + xcb_atom_t name_;
|
| +
|
| + GetPropertyRequest* property_request_;
|
| + xcb_atom_t type_;
|
| + // Format can be 8, 16, or 32, indicating how |data| should be
|
| + // interpreted.
|
| + uint8_t format_;
|
| + int length_;
|
| + uint8_t* data_;
|
| +
|
| + XWindowCache* cache_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Property);
|
| + };
|
| +
|
| + class Window {
|
| + public:
|
| + // A container for children so clients can use range-based for loops, and we
|
| + // don't have begin() and end() methods in Window.
|
| + class Children {
|
| + public:
|
| + class iterator
|
| + : public std::iterator<std::forward_iterator_tag, const Window*> {
|
| + public:
|
| + ~iterator();
|
| + iterator(const iterator& other);
|
| +
|
| + iterator& operator++();
|
| + bool operator==(const iterator& other) const;
|
| + bool operator!=(const iterator& other) const;
|
| + const Window* operator*() const;
|
| +
|
| + private:
|
| + friend class Children;
|
| +
|
| + explicit iterator(
|
| + std::list<std::unique_ptr<Window>>::const_iterator it,
|
| + std::list<std::unique_ptr<Window>>::const_iterator end);
|
| +
|
| + void SkipInvalidChildren();
|
| +
|
| + std::list<std::unique_ptr<Window>>::const_iterator it_, end_;
|
| + };
|
| +
|
| + Children(const Window* window);
|
| +
|
| + std::size_t size() const;
|
| +
|
| + Children::iterator begin() const;
|
| + Children::iterator end() const;
|
| +
|
| + private:
|
| + const Window* window_;
|
| + };
|
| +
|
| + ~Window();
|
| +
|
| + XID id() const { return id_; }
|
| + const Window* parent() const { return parent_; }
|
| +
|
| + bool override_redirect() const { return override_redirect_; }
|
| + bool is_mapped() const { return is_mapped_; }
|
| +
|
| + int16_t x() const { return x_; }
|
| + int16_t y() const { return y_; }
|
| + uint16_t width() const { return width_; }
|
| + uint16_t height() const { return height_; }
|
| + uint16_t border_width() const { return border_width_; }
|
| +
|
| + // Callers should not hold onto the returned Property. Returns
|
| + // nullptr if the property doesn't exist.
|
| + const Property* GetProperty(XID name) const;
|
| +
|
| + Children GetChildren() const;
|
| +
|
| + private:
|
| + friend class XWindowCache;
|
| + Window(xcb_window_t id, Window* parent, XWindowCache* cache);
|
| +
|
| + // Ensures the Window is fully cached, and clients can get any
|
| + // data from it they want. |this| will be destructed and
|
| + // Validate() will return false if the window was destroyed before
|
| + // it could be cached. Otherwise, returns true.
|
| + bool Validate();
|
| + bool IsValid() const;
|
| +
|
| + xcb_window_t id_;
|
| + Window* parent_;
|
| +
|
| + GetWindowAttributesRequest* attributes_request_;
|
| + bool override_redirect_;
|
| + // |is_mapped| is different from the map_state that is returned
|
| + // by XGetWindowAttributes. map_state can be one of IsUnmapped,
|
| + // IsUnviewable, or IsViewable. map_state is set to
|
| + // IsUnviewable when the window is mapped but some ancestor
|
| + // window is unmapped. If you need to check for this case, you
|
| + // must do so manually.
|
| + bool is_mapped_;
|
| +
|
| + GetGeometryRequest* geometry_request_;
|
| + int16_t x_, y_;
|
| + uint16_t width_, height_;
|
| + uint16_t border_width_;
|
| +
|
| + ListPropertiesRequest* properties_request_;
|
| + std::unordered_map<xcb_atom_t, std::unique_ptr<Property>> properties_;
|
| +
|
| + QueryTreeRequest* children_request_;
|
| + std::list<std::unique_ptr<Window>> children_;
|
| +
|
| + std::unique_ptr<XScopedEventSelector> selected_events_;
|
| +
|
| + XWindowCache* cache_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Window);
|
| + };
|
| +
|
| + XWindowCache(XDisplay* display, X11EventSource* event_source, XID root);
|
| + ~XWindowCache() override;
|
| +
|
| + // Callers should not hold onto the returned Window. Returns
|
| + // nullptr when window |id| is not cached.
|
| + const Window* GetWindow(XID id) const;
|
| +
|
| + protected:
|
| + // Overridden from PlatformEventDispatcher:
|
| + void WillProcessEvent(const PlatformEvent& event) override;
|
| + void DidProcessEvent(const PlatformEvent& event) override;
|
| +
|
| + private:
|
| + friend class XWindowCacheTest;
|
| +
|
| + template <typename T>
|
| + static void CacheWindowGeometryFromResponse(Window* window,
|
| + const T& response);
|
| +
|
| + static auto FindChild(Window* parent, xcb_window_t child_id)
|
| + -> decltype(parent->children_.begin());
|
| +
|
| + // Clears all state and rebuilds the entire cache.
|
| + void ResetCache();
|
| + void ResetCacheImpl();
|
| +
|
| + // Creates and adds a new property to |window|.
|
| + void CacheProperty(Window* window, xcb_atom_t atom);
|
| +
|
| + // Allocates/Deallocates a Window. Responsible for setting up and breaking
|
| + // parent/child relationships.
|
| + void CreateWindow(xcb_window_t id, XWindowCache::Window* parent);
|
| + void DestroyWindow(Window* window);
|
| +
|
| + void ProcessEvent(const XEvent* event);
|
| +
|
| + Window* GetWindowInternal(XID id) const;
|
| +
|
| + XDisplay* display_;
|
| + xcb_connection_t* connection_;
|
| + xcb_window_t root_id_;
|
| +
|
| + X11EventSource* event_source_;
|
| +
|
| + std::unique_ptr<Window> root_;
|
| + std::unordered_map<xcb_window_t, Window*> windows_;
|
| +
|
| + // Don't cache icon properties because they take up too much space and we
|
| + // currently never use them.
|
| + xcb_intern_atom_cookie_t net_wm_icon_cookie_;
|
| + xcb_atom_t net_wm_icon_;
|
| +};
|
| +
|
| +} // namespace ui
|
| +
|
| +#endif // UI_BASE_X_X11_WINDOW_CACHE_H_
|
|
|