summaryrefslogtreecommitdiffstats
path: root/base/message_loop/message_pump_x11.h
blob: f1f678a79c71b48ee784af57e9c22a77fc0a33eb (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
// Copyright (c) 2012 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 BASE_MESSAGE_LOOP_MESSAGE_PUMP_X11_H
#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_X11_H

#include <bitset>
#include <map>

#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_pump.h"
#include "base/message_loop/message_pump_dispatcher.h"
#include "base/message_loop/message_pump_glib.h"
#include "base/message_loop/message_pump_observer.h"
#include "base/observer_list.h"

// It would be nice to include the X11 headers here so that we use Window
// instead of its typedef of unsigned long, but we can't because everything in
// chrome includes us through base/message_loop/message_loop.h, and X11's crappy
// #define heavy headers muck up half of chrome.

typedef struct _GPollFD GPollFD;
typedef struct _GSource GSource;
typedef struct _XDisplay Display;

namespace base {

// This class implements a message-pump for dispatching X events.
//
// If there's a current dispatcher given through RunWithDispatcher(), that
// dispatcher receives events. Otherwise, we route to messages to dispatchers
// who have subscribed to messages from a specific X11 window.
class BASE_EXPORT MessagePumpX11 : public MessagePumpGlib,
                                   public MessagePumpDispatcher {
 public:
  MessagePumpX11();
  virtual ~MessagePumpX11();

  // Returns default X Display.
  static Display* GetDefaultXDisplay();

  // Returns true if the system supports XINPUT2.
  static bool HasXInput2();

  // Returns the UI or GPU message pump.
  static MessagePumpX11* Current();

  // Adds/Removes |dispatcher| for the |xid|. This will route all messages from
  // the window |xid| to |dispatcher.
  void AddDispatcherForWindow(MessagePumpDispatcher* dispatcher,
                              unsigned long xid);
  void RemoveDispatcherForWindow(unsigned long xid);

  // Adds/Removes |dispatcher| to receive all events sent to the X root
  // window. A root window can have multiple dispatchers, and events on root
  // windows will be dispatched to all.
  void AddDispatcherForRootWindow(MessagePumpDispatcher* dispatcher);
  void RemoveDispatcherForRootWindow(MessagePumpDispatcher* dispatcher);

  // Adds an Observer, which will start receiving notifications immediately.
  void AddObserver(MessagePumpObserver* observer);

  // Removes an Observer.  It is safe to call this method while an Observer is
  // receiving a notification callback.
  void RemoveObserver(MessagePumpObserver* observer);

  // Internal function. Called by the glib source dispatch function. Processes
  // all available X events.
  bool DispatchXEvents();

  // Blocks on the X11 event queue until we receive notification from the
  // xserver that |w| has been mapped; StructureNotifyMask events on |w| are
  // pulled out from the queue and dispatched out of order.
  //
  // For those that know X11, this is really a wrapper around XWindowEvent
  // which still makes sure the preempted event is dispatched instead of
  // dropped on the floor. This method exists because mapping a window is
  // asynchronous (and we receive an XEvent when mapped), while there are also
  // functions which require a mapped window.
  void BlockUntilWindowMapped(unsigned long xid);

 private:
  typedef std::map<unsigned long, MessagePumpDispatcher*> DispatchersMap;

  // Initializes the glib event source for X.
  void InitXSource();

  // Dispatches the XEvent and returns true if we should exit the current loop
  // of message processing.
  bool ProcessXEvent(MessagePumpDispatcher* dispatcher, XEvent* event);

  // Sends the event to the observers. If an observer returns true, then it does
  // not send the event to any other observers and returns true. Returns false
  // if no observer returns true.
  bool WillProcessXEvent(XEvent* xevent);
  void DidProcessXEvent(XEvent* xevent);

  // Returns the Dispatcher based on the event's target window.
  MessagePumpDispatcher* GetDispatcherForXEvent(const NativeEvent& xev) const;

  ObserverList<MessagePumpObserver>& observers() { return observers_; }

  // Overridden from MessagePumpDispatcher:
  virtual bool Dispatch(const NativeEvent& event) OVERRIDE;

  // The event source for X events.
  GSource* x_source_;

  // The poll attached to |x_source_|.
  scoped_ptr<GPollFD> x_poll_;

  DispatchersMap dispatchers_;

  // Dispatch calls can cause addition of new dispatchers as we iterate
  // through them. Use ObserverList to ensure the iterator remains valid across
  // additions.
  ObserverList<MessagePumpDispatcher> root_window_dispatchers_;

  // List of observers.
  ObserverList<MessagePumpObserver> observers_;

  unsigned long x_root_window_;

  DISALLOW_COPY_AND_ASSIGN(MessagePumpX11);
};

#if !defined(TOOLKIT_GTK)
typedef MessagePumpX11 MessagePumpForUI;
#endif

}  // namespace base

#endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_X11_H