summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/wm_ipc.h
blob: 2d35c0b10ab061dc8dff80a5d1f598930b7d03fd (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
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
// 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.
    WINDOW_TYPE_CHROME_TOPLEVEL,

    // A window showing scaled-down views of all of the tabs within a
    // Chrome window.
    WINDOW_TYPE_CHROME_TAB_SUMMARY,

    // A tab that's been detached from a Chrome window and is currently
    // being dragged.
    //   param[0]: Cursor's initial X position at the start of the drag
    //   param[1]: Cursor's initial Y position
    //   param[2]: X component of cursor's offset from upper-left corner of
    //             tab at start of drag
    //   param[3]: Y component of cursor's offset
    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,

    // A small window that when clicked creates a new browser window.
    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 tab order (range is 0 to
    //             sum of all tabs in all browsers).
    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,

      // Notify Chrome when a floating tab has entered or left a tab
      // summary window.  Sent to the summary window.
      //   param[0]: X ID of the floating tab window
      //   param[1]: state (0 means left, 1 means entered or currently in)
      //   param[2]: X coordinate relative to summary window
      //   param[3]: Y coordinate
      CHROME_NOTIFY_FLOATING_TAB_OVER_TAB_SUMMARY,

      // Notify Chrome when a floating tab has entered or left a top-level
      // window.  Sent to the window being entered/left.
      //   param[0]: X ID of the floating tab window
      //   param[1]: state (0 means left, 1 means entered)
      CHROME_NOTIFY_FLOATING_TAB_OVER_TOPLEVEL,

      // Instruct a top-level Chrome window to change the visibility of its
      // tab summary window.
      //   param[0]: desired visibility (0 means hide, 1 means show)
      //   param[1]: X position (relative to the left edge of the root
      //             window) of the center of the top-level window.  Only
      //             relevant for "show" messages
      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)
      CHROME_NOTIFY_PANEL_STATE,

      // Instruct the WM to move a floating tab.  The passed-in position is
      // that of the cursor; the tab's composited window is displaced based
      // on the cursor's offset from the upper-left corner of the tab at
      // the start of the drag.
      //   param[0]: X ID of the floating tab window
      //   param[1]: X coordinate to which the tab should be moved
      //   param[2]: Y coordinate
      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
      // focused) has changed.
      //   param[0]: new mode (0 means focused, 1 means overview)
      CHROME_NOTIFY_LAYOUT_MODE,

      // Instruct the WM to enter overview mode.
      //   param[0]: X ID of the window to show the tab overview for.
      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 snapshot has been 'magnified' in the
      // overview.  Sent to the top level window.
      //   param[0]: X ID of the tab snapshot window
      //   param[1]: state (0 means end magnify, 1 means begin magnify)
      CHROME_NOTIFY_TAB_SNAPSHOT_MAGNIFY,

      // 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. The caller is responsible for trapping
  // errors from the X server.
  WmIpc::WindowType GetWindowType(GtkWidget* widget);

  // 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_