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