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