summaryrefslogtreecommitdiffstats
path: root/gfx/gtk_native_view_id_manager.h
blob: e97a852817eeb7c0eebe5dd7cd90c91036ba834f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// 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 GFX_GTK_NATIVE_VIEW_ID_MANAGER_H_
#define GFX_GTK_NATIVE_VIEW_ID_MANAGER_H_
#pragma once

#include <map>

#include "base/singleton.h"
#include "gfx/native_widget_types.h"

typedef unsigned long XID;
struct _GtkPreserveWindow;

// NativeViewIds are the opaque values which the renderer holds as a reference
// to a window. These ids are often used in sync calls from the renderer and
// one cannot terminate sync calls on the UI thread as that can lead to
// deadlocks.
//
// Because of this, we have the BACKGROUND_X11 thread for these calls and this
// thread has a separate X connection in order to answer them. But one cannot
// use GTK on multiple threads, so the BACKGROUND_X11 thread deals only in Xlib
// calls and, thus, XIDs.
//
// So we could make NativeViewIds be the X id of the window. However, at the
// time when we need to tell the renderer about its NativeViewId, an XID isn't
// availible and it goes very much against the grain of the code to make it so.
// Also, we worry that GTK might choose to change the underlying X window id
// when, say, the widget is hidden or repacked. Finally, if we used XIDs then a
// compromised renderer could start asking questions about any X windows on the
// system.
//
// Thus, we have this object. It produces random NativeViewIds from GtkWidget
// pointers and observes the various signals from the widget for when an X
// window is created, destroyed etc. Thus it provides a thread safe mapping
// from NativeViewIds to the current XID for that widget.
class GtkNativeViewManager {
 public:
  // Returns the singleton instance.
  static GtkNativeViewManager* GetInstance();

  // Must be called from the UI thread:
  //
  // Return a NativeViewId for the given widget and attach to the various
  // signals emitted by that widget. The NativeViewId is pseudo-randomly
  // allocated so that a compromised renderer trying to guess values will fail
  // with high probability. The NativeViewId will not be reused for the
  // lifetime of the GtkWidget.
  gfx::NativeViewId GetIdForWidget(gfx::NativeView widget);

  // May be called from any thread:
  //
  // xid: (output) the resulting X window ID, or 0
  // id: a value previously returned from GetIdForWidget
  // returns: true if |id| is a valid id, false otherwise.
  //
  // If the widget referenced by |id| does not current have an X window id,
  // |*xid| is set to 0.
  bool GetXIDForId(XID* xid, gfx::NativeViewId id);

  // Must be called from the UI thread because we may need the associated
  // widget to create a window.
  //
  // Keeping the XID permanent requires a bit of overhead, so it must
  // be explicitly requested.
  //
  // xid: (output) the resulting X window
  // id: a value previously returned from GetIdForWidget
  // returns: true if |id| is a valid id, false otherwise.
  bool GetPermanentXIDForId(XID* xid, gfx::NativeViewId id);

  // Must be called from the UI thread because we may need to access a
  // GtkWidget or destroy a GdkWindow.
  //
  // If the widget associated with the XID is still alive, allow the widget
  // to destroy the associated XID when it wants. Otherwise, destroy the
  // GdkWindow associated with the XID.
  void ReleasePermanentXID(XID xid);

  // These are actually private functions, but need to be called from statics.
  void OnRealize(gfx::NativeView widget);
  void OnUnrealize(gfx::NativeView widget);
  void OnDestroy(gfx::NativeView widget);

  Lock& unrealize_lock() { return unrealize_lock_; }

 private:
  // This object is a singleton:
  GtkNativeViewManager();
  ~GtkNativeViewManager();
  friend struct DefaultSingletonTraits<GtkNativeViewManager>;

  struct NativeViewInfo {
    NativeViewInfo() : widget(NULL), x_window_id(0) {
    }
    gfx::NativeView widget;
    XID x_window_id;
  };

  gfx::NativeViewId GetWidgetId(gfx::NativeView id);

  // This lock can be used to block GTK from unrealizing windows. This is needed
  // when the BACKGROUND_X11 thread is using a window obtained via GetXIDForId,
  // and can't allow the X11 resource to be deleted.
  Lock unrealize_lock_;

  // protects native_view_to_id_ and id_to_info_
  Lock lock_;

  // If asked for an id for the same widget twice, we want to return the same
  // id. So this records the current mapping.
  std::map<gfx::NativeView, gfx::NativeViewId> native_view_to_id_;
  std::map<gfx::NativeViewId, NativeViewInfo> id_to_info_;

  struct PermanentXIDInfo {
    PermanentXIDInfo() : widget(NULL), ref_count(0) {
    }
    _GtkPreserveWindow* widget;
    int ref_count;
  };

  // Used to maintain the reference count for permanent XIDs
  // (referenced by GetPermanentXIDForId and dereferenced by
  // ReleasePermanentXID). Only those XIDs with a positive reference count
  // will be in the table.
  //
  // In general, several GTK widgets may share the same X window. We assume
  // that is not true of the widgets stored in this registry.
  //
  // An XID will map to NULL, if there is an outstanding reference but the
  // widget was destroyed. In this case, the destruction of the X window
  // is deferred to the dropping of all references.
  std::map<XID, PermanentXIDInfo> perm_xid_to_info_;

  DISALLOW_COPY_AND_ASSIGN(GtkNativeViewManager);
};

#endif  // GFX_GTK_NATIVE_VIEW_ID_MANAGER_H_