fully documented OBClient
[mikachu/openbox.git] / src / client.hh
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 #ifndef   __client_hh
3 #define   __client_hh
4
5 /*! @file client.hh
6   @brief The OBClient class maintains the state of a client window by handling
7   property changes on the window and some client messages
8 */
9
10 extern "C" {
11 #include <X11/Xlib.h>
12 }
13
14 #include <string>
15
16 #include "otk/strut.hh"
17 #include "otk/rect.hh"
18
19 namespace ob {
20
21 //! Maintains the state of a client window.
22 /*!
23   OBClient maintains the state of a client window. The state consists of the
24   hints that the application sets on the window, such as the title, or window
25   gravity.
26   <p>
27   OBClient also manages client messages for the client window. When the
28   application (or any application) requests something to be changed for the
29   client, it will call the ActionHandler (for client messages) or update the
30   class' member variables and call whatever is nessary to complete the
31   change (such as causing a redraw of the titlebar after the title is changed).
32 */
33 class OBClient {
34 public:
35   //! Possible window types
36   enum WindowType { Type_Desktop, //!< A desktop (bottom-most window)
37                     Type_Dock,    //!< A dock bar/panel window
38                     Type_Toolbar, //!< A toolbar window, pulled off an app
39                     Type_Menu,    //!< A sticky menu from an app
40                     Type_Utility, //!< A small utility window such as a palette
41                     Type_Splash,  //!< A splash screen window
42                     Type_Dialog,  //!< A dialog window
43                     Type_Normal   //!< A normal application window
44   };
45
46   //! Possible flags for MWM Hints (defined by Motif 2.0)
47   enum MwmFlags { MwmFlag_Functions   = 1 << 0, //!< The MMW Hints define funcs
48                   MwmFlag_Decorations = 1 << 1  //!< The MWM Hints define decor
49   };
50
51   //! Possible functions for MWM Hints (defined by Motif 2.0)
52   enum MwmFunctions { MwmFunc_All      = 1 << 0, //!< All functions
53                       MwmFunc_Resize   = 1 << 1, //!< Allow resizing
54                       MwmFunc_Move     = 1 << 2, //!< Allow moving
55                       MwmFunc_Iconify  = 1 << 3, //!< Allow to be iconfied
56                       MwmFunc_Maximize = 1 << 4  //!< Allow to be maximized
57                       //MwmFunc_Close    = 1 << 5 //!< Allow to be closed
58   };
59
60   //! Possible decorations for MWM Hints (defined by Motif 2.0)
61   enum MemDecorations { MwmDecor_All      = 1 << 0, //!< All decorations
62                         MwmDecor_Border   = 1 << 1, //!< Show a border
63                         MwmDecor_Handle   = 1 << 2, //!< Show a handle (bottom)
64                         MwmDecor_Title    = 1 << 3, //!< Show a titlebar
65                         //MwmDecor_Menu     = 1 << 4, //!< Show a menu
66                         MwmDecor_Iconify  = 1 << 5, //!< Show an iconify button
67                         MwmDecor_Maximize = 1 << 6  //!< Show a maximize button
68   };
69
70   //! The things the user can do to the client window
71   enum Function { Func_Resize   = 1 << 0, //!< Allow resizing
72                   Func_Move     = 1 << 1, //!< Allow moving
73                   Func_Iconify  = 1 << 2, //!< Allow to be iconified
74                   Func_Maximize = 1 << 3, //!< Allow to be maximized
75                   Func_Close    = 1 << 4  //!< Allow to be closed
76   };
77   //! Holds a bitmask of OBClient::Function values
78   typedef unsigned char FunctionFlags;
79
80   //! The decorations the client window wants to be displayed on it
81   enum Decoration { Decor_Titlebar = 1 << 0, //!< Display a titlebar
82                     Decor_Handle   = 1 << 1, //!< Display a handle (bottom)
83                     Decor_Border   = 1 << 2, //!< Display a border
84                     Decor_Iconify  = 1 << 3, //!< Display an iconify button
85                     Decor_Maximize = 1 << 4, //!< Display a maximize button
86                     Decor_Close    = 1 << 5  //!< Display a close button
87   };
88   //! Holds a bitmask of OBClient::Decoration values
89   typedef unsigned char DecorationFlags;
90
91   //! The MWM Hints as retrieved from the window property
92   /*!
93     This structure only contains 3 elements, even though the Motif 2.0
94     structure contains 5. We only use the first 3, so that is all gets defined.
95   */
96   typedef struct MwmHints {
97     //! The number of elements in the OBClient::MwmHints struct
98     static const unsigned int elements = 3;
99     unsigned long flags;      //!< A bitmask of OBClient::MwmFlags values
100     unsigned long functions;  //!< A bitmask of OBClient::MwmFunctions values
101     unsigned long decorations;//!< A bitmask of OBClient::MwmDecorations values
102   };
103
104   //! Possible actions that can be made with the _NET_WM_STATE client message
105   enum StateAction { State_Remove = 0, //!< _NET_WM_STATE_REMOVE
106                      State_Add,        //!< _NET_WM_STATE_ADD
107                      State_Toggle      //!< _NET_WM_STATE_TOGGLE
108   };
109
110 private:
111   //! The actual window that this class is wrapping up
112   Window   _window;
113
114   //! The id of the group the window belongs to
115   Window   _group;
116
117   // XXX: transient_for, transients
118
119   //! The desktop on which the window resides (0xffffffff for all desktops)
120   unsigned long _desktop;
121
122   //! Normal window title
123   std::string  _title; // XXX: Have to keep track if this string is Utf8 or not
124   //! Window title when iconifiged
125   std::string  _icon_title;
126
127   //! The application that created the window
128   std::string  _app_name;
129   //! The class of the window, can used for grouping
130   std::string  _app_class;
131
132   //! The type of window (what its function is)
133   WindowType   _type;
134
135   //! Position and size of the window (relative to the root window)
136   otk::Rect    _area;
137
138   //! Width of the border on the window.
139   /*!
140     The window manager will set this to 0 while the window is being managed,
141     but needs to restore it afterwards, so it is saved here.
142   */
143   int _border_width;
144
145   //! The minimum width of the client window
146   /*!
147     If the min is > the max, then the window is not resizable
148   */
149   int _min_x;
150   //! The minimum height of the client window
151   /*!
152     If the min is > the max, then the window is not resizable
153   */
154   int _min_y;
155   //! The maximum width of the client window
156   /*!
157     If the min is > the max, then the window is not resizable
158   */
159   int _max_x;
160   //! The maximum height of the client window
161   /*!
162     If the min is > the max, then the window is not resizable
163   */
164   int _max_y;
165   //! The size of increments to resize the client window by (for the width)
166   int _inc_x;
167   //! The size of increments to resize the client window by (for the height)
168   int _inc_y;
169   //! The base width of the client window
170   /*!
171     This value should be subtracted from the window's actual width when
172     displaying its size to the user, or working with its min/max width
173   */
174   int _base_x;
175   //! The base height of the client window
176   /*!
177     This value should be subtracted from the window's actual height when
178     displaying its size to the user, or working with its min/max height
179   */
180   int _base_y;
181
182   //! Where to place the decorated window in relation to the undecorated window
183   int _gravity;
184
185   //! The state of the window, one of WithdrawnState, IconicState, or
186   //! NormalState
187   long _wmstate;
188
189   //! Was the window's position requested by the application? if not, we should
190   //! place the window ourselves when it first appears
191   bool _positioned;
192   
193   //! Can the window receive input focus?
194   bool _can_focus;
195   //! Urgency flag
196   bool _urgent;
197   //! Notify the window when it receives focus?
198   bool _focus_notify;
199
200   //! The window uses shape extension to be non-rectangular?
201   bool _shaped;
202
203   //! The window is modal, so it must be processed before any windows it is
204   //! related to can be focused
205   bool _modal;
206   //! Only the window's titlebar is displayed
207   bool _shaded;
208   //! The window is iconified
209   bool _iconic;
210   //! The window is maximized to fill the screen vertically
211   bool _max_vert;
212   //! The window is maximized to fill the screen horizontally
213   bool _max_horz;
214   //! The window is a 'fullscreen' window, and should be on top of all others
215   bool _fullscreen;
216   //! The window should be on top of other windows of the same type
217   bool _floating;
218
219   //! A bitmask of values in the OBClient::Decoration enum
220   /*!
221     The values in the variable are the decorations that the client wants to be
222     displayed around it.
223   */
224   DecorationFlags _decorations;
225
226   //! A bitmask of values in the OBClient::Function enum
227   /*!
228     The values in the variable specify the ways in which the user is allowed to
229     modify this window.
230   */
231   FunctionFlags _functions;
232
233   //! Retrieves the desktop hint's value and sets OBClient::_desktop
234   void getDesktop();
235   //! Retrieves the window's type and sets OBClient::_type
236   void getType();
237   //! Gets the MWM Hints and adjusts OBClient::_functions and
238   //! OBClient::_decorations
239   void getMwmHints();
240   //! Gets the position and size of the window and sets OBClient::_area
241   void getArea();
242   //! Gets the net_state hint and sets the boolean flags for any states set in
243   //! the hint
244   void getState();
245   //! Determines if the window uses the Shape extension and sets
246   //! OBClient::_shaped
247   void getShaped();
248
249   //! Sets the wm_state to the specified value
250   void setWMState(long state);
251   //! Sends the window to the specified desktop
252   void setDesktop(long desktop);
253   //! Adjusts the window's net_state
254   void setState(StateAction action, long data1, long data2);
255
256   //! Update the protocols that the window supports and adjusts things if they
257   //! change
258   void updateProtocols();
259   //! Updates the WMNormalHints and adjusts things if they change
260   void updateNormalHints();
261   //! Updates the WMHints and adjusts things if they change
262   void updateWMHints();
263   //! Updates the window's title
264   void updateTitle();
265   //! Updates the window's icon title
266   void updateIconTitle();
267   //! Updates the window's application name and class
268   void updateClass();
269   // XXX: updateTransientFor();
270
271 public:
272   //! Constructs a new OBClient object around a specified window id
273   /*!
274     @param window The window id that the OBClient class should handle
275   */
276   OBClient(Window window);
277   //! Destroys the OBClient object
278   virtual ~OBClient();
279
280   //! Returns the window id that the OBClient object is handling
281   inline Window window() const { return _window; }
282
283   //! Returns the type of the window, one of the OBClient::WindowType values
284   inline WindowType type() const { return _type; }
285   //! Returns the desktop on which the window resides
286   /*!
287     This value is a 0-based index.<br>
288     A value of 0xffffffff indicates that the window exists on all desktops.
289   */
290   inline unsigned long desktop() const { return _desktop; }
291   //! Returns the window's title
292   inline const std::string &title() const { return _title; }
293   //! Returns the window's title when it is iconified
294   inline const std::string &iconTitle() const { return _title; }
295   //! Returns the application's name to whom the window belongs
296   inline const std::string &appName() const { return _app_name; }
297   //! Returns the class of the window
298   inline const std::string &appClass() const { return _app_class; }
299   //! Returns if the window can be focused
300   /*!
301     @return true if the window can receive focusl otherwise, false
302   */
303   inline bool canFocus() const { return _can_focus; }
304   //! Returns if the window has indicated that it needs urgent attention
305   inline bool urgent() const { return _urgent; }
306   //! Returns if the window wants to be notified when it receives focus
307   inline bool focusNotify() const { return _focus_notify; }
308   //! Returns if the window uses the Shape extension
309   inline bool shaped() const { return _shaped; }
310   //! Returns the window's gravity
311   /*!
312     This value determines where to place the decorated window in relation to
313     its position without decorations.<br>
314     One of: NorthWestGravity, SouthWestGravity, EastGravity, ...,
315     SouthGravity, StaticGravity, ForgetGravity
316   */
317   inline int gravity() const { return _gravity; }
318   //! Returns if the application requested the initial position for the window
319   /*!
320     If the application did not request a position (this function returns false)
321     then the window should be placed intelligently by the window manager
322     initially
323   */
324   inline bool positionRequested() const { return _positioned; }
325   //! Returns the decorations that the client window wishes to be displayed on
326   //! it
327   inline DecorationFlags decorations() const { return _decorations; }
328   //! Returns the functions that the user can perform on the window
329   inline FunctionFlags funtions() const { return _functions; }
330
331   //! Returns if the window is modal
332   /*!
333     If the window is modal, then no other windows that it is related to can get
334     focus while it exists/remains modal.
335   */
336   inline bool modal() const { return _modal; }
337   //! Returns if the window is shaded
338   /*!
339     When the window is shaded, only its titlebar is visible, the client itself
340     is not mapped
341   */
342   inline bool shaded() const { return _shaded; }
343   //! Returns if the window is iconified
344   /*!
345     When the window is iconified, it is not visible at all (except in iconbars/
346     panels/etc that want to show lists of iconified windows
347   */
348   inline bool iconic() const { return _iconic; }
349   //! Returns if the window is maximized vertically
350   inline bool maxVert() const { return _max_vert; }
351   //! Returns if the window is maximized horizontally
352   inline bool maxHorz() const { return _max_horz; }
353   //! Returns if the window is fullscreen
354   /*!
355     When the window is fullscreen, it is kept above all others
356   */
357   inline bool fullscreen() const { return _fullscreen; }
358   //! Returns if the window is floating
359   /*!
360     When the window is floating, it is kept above all others in the same
361     stacking layer as it
362   */
363   inline bool floating() const { return _floating; }
364
365   //! Returns the window's border width
366   /*!
367     The border width is set to 0 when the client becomes managed, but the
368     border width is stored here so that it can be restored to the client window
369     when it is unmanaged later.
370   */
371   inline int borderWidth() const { return _border_width; }
372   //! Returns the minimum width of the client window
373   /*!
374     If the min is > the max, then the window is not resizable
375   */
376   inline int minX() const { return _min_x; }
377   //! Returns the minimum height of the client window
378   /*!
379     If the min is > the max, then the window is not resizable
380   */
381   inline int minY() const { return _min_y; }
382   //! Returns the maximum width of the client window
383   /*!
384     If the min is > the max, then the window is not resizable
385   */
386   inline int maxX() const { return _max_x; }
387   //! Returns the maximum height of the client window
388   /*!
389     If the min is > the max, then the window is not resizable
390   */
391   inline int maxY() const { return _max_y; }
392   //! Returns the increment size for resizing the window (for the width)
393   inline int incrementX() const { return _inc_x; }
394   //! Returns the increment size for resizing the window (for the height)
395   inline int incrementY() const { return _inc_y; }
396   //! Returns the base width of the window
397   /*!
398     This value should be subtracted from the window's actual width when
399     displaying its size to the user, or working with its min/max width
400   */
401   inline int baseX() const { return _base_x; }
402   //! Returns the base height of the window
403   /*!
404     This value should be subtracted from the window's actual height when
405     displaying its size to the user, or working with its min/max height
406   */
407   inline int baseY() const { return _base_y; }
408
409   //! Returns the position and size of the client relative to the root window
410   inline const otk::Rect &area() const { return _area; }
411
412   //! Updates the OBClient class from a property change XEvent
413   void update(const XPropertyEvent &e);
414   //! Processes a client message XEvent for the window and causes an action
415   //! or whatever was specified to occur
416   void update(const XClientMessageEvent &e);
417
418   //! Changes the stored positions and size of the OBClient window
419   /*!
420     This does not actually change the physical geometry, that needs to be done
421     before/after setting this value to keep it in sync
422   */
423   void setArea(const otk::Rect &area);
424 };
425
426 }
427
428 #endif // __client_hh