summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/wm_ipc.h
blob: 7df76a29289a1bae75df2748caa989ce21e19d22 (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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
// 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 CHROME_BROWSER_CHROMEOS_WM_IPC_H_
#define CHROME_BROWSER_CHROMEOS_WM_IPC_H_

#include <gtk/gtk.h>
#include <map>
#include <string>
#include <vector>

#include "base/logging.h"
#include "base/singleton.h"

typedef unsigned long Atom;
typedef unsigned long XID;

namespace chromeos {

class WmIpc {
 public:
  enum AtomType {
    ATOM_CHROME_WINDOW_TYPE = 0,
    ATOM_CHROME_WM_MESSAGE,
    ATOM_MANAGER,
    ATOM_NET_SUPPORTING_WM_CHECK,
    ATOM_NET_WM_NAME,
    ATOM_PRIMARY,
    ATOM_STRING,
    ATOM_UTF8_STRING,
    ATOM_WM_NORMAL_HINTS,
    ATOM_WM_S0,
    ATOM_WM_STATE,
    ATOM_WM_TRANSIENT_FOR,
    ATOM_WM_SYSTEM_METRICS,
    kNumAtoms,
  };

  enum WindowType {
    WINDOW_TYPE_UNKNOWN = 0,

    // A top-level Chrome window.
    //   param[0]: The number of tabs currently in this Chrome window.
    //   param[1]: The index of the currently selected tab in this
    //             Chrome window.
    WINDOW_TYPE_CHROME_TOPLEVEL,

    // Vestiges of the old windows-across-the-bottom overview mode.
    DEPRECATED_WINDOW_TYPE_CHROME_TAB_SUMMARY,
    DEPRECATED_WINDOW_TYPE_CHROME_FLOATING_TAB,

    // The contents of a popup window.
    //   param[0]: X ID of associated titlebar, which must be mapped before
    //             its content
    //   param[1]: Initial state for panel (0 is collapsed, 1 is expanded)
    WINDOW_TYPE_CHROME_PANEL_CONTENT,

    // A small window representing a collapsed panel in the panel bar and
    // drawn above the panel when it's expanded.
    WINDOW_TYPE_CHROME_PANEL_TITLEBAR,

    // Vestiges of an earlier UI design.
    DEPRECATED_WINDOW_TYPE_CREATE_BROWSER_WINDOW,

    // A Chrome info bubble (e.g. the bookmark bubble).  These are
    // transient RGBA windows; we skip the usual transient behavior of
    // centering them over their owner and omit drawing a drop shadow.
    WINDOW_TYPE_CHROME_INFO_BUBBLE,

    // A window showing a view of a tab within a Chrome window.
    //   param[0]: X ID of toplevel window that owns it.
    //   param[1]: index of this tab in the toplevel window that owns it.
    WINDOW_TYPE_CHROME_TAB_SNAPSHOT,

    // The following types are used for the windows that represent a user that
    // has already logged into the system.
    //
    // Visually the BORDER contains the IMAGE and CONTROLS windows, the LABEL
    // and UNSELECTED_LABEL are placed beneath the BORDER. The LABEL window is
    // onscreen when the user is selected, otherwise the UNSELECTED_LABEL is
    // on screen. The GUEST window is used when the user clicks on the entry
    // that represents the 'guest' user.
    //
    // The following parameters are set for these windows (except GUEST and
    // BACKGROUND):
    //   param[0]: the visual index of the user the window corresponds to.
    //             For example, all windows with an index of 0 occur first,
    //             followed by windows with an index of 1...
    //
    // The following additional params are set on the first BORDER window
    // (BORDER window whose param[0] == 0).
    //   param[1]: the total number of users.
    //   param[2]: size of the unselected image.
    //   param[3]: gap between image and controls.
    WINDOW_TYPE_LOGIN_BORDER,
    WINDOW_TYPE_LOGIN_IMAGE,
    WINDOW_TYPE_LOGIN_CONTROLS,
    WINDOW_TYPE_LOGIN_LABEL,
    WINDOW_TYPE_LOGIN_UNSELECTED_LABEL,
    WINDOW_TYPE_LOGIN_GUEST,
    WINDOW_TYPE_LOGIN_BACKGROUND,

    kNumWindowTypes,
  };

  struct Message {
   public:
    // NOTE: Don't remove values from this enum; it is shared between
    // Chrome and the window manager.
    enum Type {
      UNKNOWN = 0,

      // Vestiges of the old windows-across-the-bottom overview mode.
      DEPRECATED_CHROME_NOTIFY_FLOATING_TAB_OVER_TAB_SUMMARY,
      DEPRECATED_CHROME_NOTIFY_FLOATING_TAB_OVER_TOPLEVEL,
      DEPRECATED_CHROME_SET_TAB_SUMMARY_VISIBILITY,

      // Tell the WM to collapse or expand a panel.
      //   param[0]: X ID of the panel window
      //   param[1]: desired state (0 means collapsed, 1 means expanded)
      WM_SET_PANEL_STATE,

      // Notify Chrome that the panel state has changed.  Sent to the panel
      // window.
      //   param[0]: new state (0 means collapsed, 1 means expanded)
      // TODO: Deprecate this; Chrome can just watch for changes to the
      // _CHROME_STATE property to get the same information.
      CHROME_NOTIFY_PANEL_STATE,

      // From the old windows-across-the-bottom overview mode.
      DEPRECATED_WM_MOVE_FLOATING_TAB,

      // Notify the WM that a panel has been dragged.
      //   param[0]: X ID of the panel's content window
      //   param[1]: X coordinate to which the upper-right corner of the
      //             panel's titlebar window was dragged
      //   param[2]: Y coordinate to which the upper-right corner of the
      //             panel's titlebar window was dragged
      // Note: The point given is actually that of one pixel to the right
      // of the upper-right corner of the titlebar window.  For example, a
      // no-op move message for a 10-pixel wide titlebar whose upper-left
      // point is at (0, 0) would contain the X and Y paremeters (10, 0):
      // in other words, the position of the titlebar's upper-left point
      // plus its width.  This is intended to make both the Chrome and WM
      // side of things simpler and to avoid some easy-to-make off-by-one
      // errors.
      WM_NOTIFY_PANEL_DRAGGED,

      // Notify the WM that the panel drag is complete (that is, the mouse
      // button has been released).
      //   param[0]: X ID of the panel's content window
      WM_NOTIFY_PANEL_DRAG_COMPLETE,

      // Deprecated.  Send a _NET_ACTIVE_WINDOW client message to focus a
      // window instead (e.g. using gtk_window_present()).
      DEPRECATED_WM_FOCUS_WINDOW,

      // Notify Chrome that the layout mode (for example, overview or
      // active) has changed.  Since overview mode can be "cancelled"
      // (user hits escape to revert), we have an extra parameter to
      // indicate this.
      //   param[0]: new mode (0 means active mode, 1 means overview mode)
      //   param[1]: was mode cancelled? (0 = no, 1 = yes)
      CHROME_NOTIFY_LAYOUT_MODE,

      // Deprecated. Instruct the WM to enter overview mode.
      //   param[0]: X ID of the window to show the tab overview for.
      DEPRECATED_WM_SWITCH_TO_OVERVIEW_MODE,

      // Let the WM know which version of this file Chrome is using.  It's
      // difficult to make changes synchronously to Chrome and the WM (our
      // build scripts can use a locally-built Chromium, the latest one
      // from the buildbot, or an older hardcoded version), so it's useful
      // to be able to maintain compatibility in the WM with versions of
      // Chrome that exhibit older behavior.
      //
      // Chrome should send a message to the WM at startup containing the
      // latest version from the list below.  For backwards compatibility,
      // the WM assumes version 0 if it doesn't receive a message.  Here
      // are the changes that have been made in successive versions of the
      // protocol:
      //
      // 1: WM_NOTIFY_PANEL_DRAGGED contains the position of the
      //    upper-right, rather than upper-left, corner of of the titlebar
      //    window
      //
      // TODO: The latest version should be hardcoded in this file once the
      // file is being shared between Chrome and the WM so Chrome can just
      // pull it from there.  Better yet, the message could be sent
      // automatically in WmIpc's c'tor.
      //
      //   param[0]: version of this protocol currently supported
      WM_NOTIFY_IPC_VERSION,

      // Notify Chrome when a tab has been selected in the overview.
      // Sent to the toplevel window associated with the magnified
      // tab.
      //   param[0]: tab index of newly selected tab.
      CHROME_NOTIFY_TAB_SELECT,

      // Forces the window manager to hide the login windows.
      WM_HIDE_LOGIN,

      // Sets whether login is enabled. If true the user can click on any of the
      // login windows to select one, if false clicks on unselected windows are
      // ignored. This is used when the user attempts a login to make sure the
      // user doesn't select another user.
      //
      //   param[0]: true to enable, false to disable.
      WM_SET_LOGIN_STATE,

      // Notify chrome when the guest entry is selected and the guest window
      // hasn't been created yet.
      CHROME_CREATE_GUEST_WINDOW,

      kNumTypes,
    };

    Message() {
      Init(UNKNOWN);
    }
    explicit Message(Type type) {
      Init(type);
    }

    Type type() const { return type_; }
    void set_type(Type type) { type_ = type; }

    inline int max_params() const {
      return arraysize(params_);
    }
    long param(int index) const {
      DCHECK_GE(index, 0);
      DCHECK_LT(index, max_params());
      return params_[index];
    }
    void set_param(int index, long value) {
      DCHECK_GE(index, 0);
      DCHECK_LT(index, max_params());
      params_[index] = value;
    }

   private:
    // Common initialization code shared between constructors.
    void Init(Type type) {
      set_type(type);
      for (int i = 0; i < max_params(); ++i) {
        set_param(i, 0);
      }
    }

    // Type of message that was sent.
    Type type_;

    // Type-specific data.  This is bounded by the number of 32-bit values
    // that we can pack into a ClientMessageEvent -- it holds five, but we
    // use the first one to store the message type.
    long params_[4];
  };

  // Returns the single instance of WmIpc.
  static WmIpc* instance();

  // Get or set a property describing a window's type. Type-specific
  // parameters may also be supplied. The caller is responsible for trapping
  // errors from the X server.
  // TODO: Trap these ourselves.
  bool SetWindowType(GtkWidget* widget,
                     WindowType type,
                     const std::vector<int>* params);

  // Gets the type of the window, and any associated parameters. The
  // caller is responsible for trapping errors from the X server.  If
  // the parameters are not interesting to the caller, NULL may be
  // passed for |params|.
  WmIpc::WindowType GetWindowType(GtkWidget* widget, std::vector<int>* params);

  // Sends a message to the WM.
  void SendMessage(const Message& msg);

  // If |event| is a valid Message it is decoded into |msg| and true is
  // returned. If false is returned, |event| is not a valid Message.
  bool DecodeMessage(const GdkEventClient& event, Message* msg);

  // If |event| is a valid StringMessage it is decoded into |msg| and true is
  // returned. If false is returned, |event| is not a valid StringMessage.
  bool DecodeStringMessage(const GdkEventProperty& event, std::string* msg);

  // Handle ClientMessage events that weren't decodable using DecodeMessage().
  // Specifically, this catches messages about the WM_S0 selection that get sent
  // when a window manager process starts (so that we can re-run InitWmInfo()).
  // See ICCCM 2.8 for more info about MANAGER selections.
  void HandleNonChromeClientMessageEvent(const GdkEventClient& event);

 private:
  friend struct DefaultSingletonTraits<WmIpc>;

  WmIpc();

  // Initialize 'wm_' and send the window manager a message telling it the
  // version of the IPC protocol that we support.  This is called in our
  // constructor, but needs to be re-run if the window manager gets restarted.
  void InitWmInfo();

  // Maps from our Atom enum to the X server's atom IDs and from the
  // server's IDs to atoms' string names.  These maps aren't necessarily in
  // sync; 'atom_to_xatom_' is constant after the constructor finishes but
  // GetName() caches additional string mappings in 'xatom_to_string_'.
  std::map<AtomType, Atom> type_to_atom_;
  std::map<Atom, std::string> atom_to_string_;

  // Cached value of type_to_atom_[ATOM_CHROME_WM_MESSAGE].
  Atom wm_message_atom_;

  // Handle to the wm. Used for sending messages.
  XID wm_;

  DISALLOW_COPY_AND_ASSIGN(WmIpc);
};

}  // namespace chromeos

#endif  // CHROME_BROWSER_CHROMEOS_WM_IPC_H_