finish conversion to the new otk::OBProperty class with its new interface
[mikachu/openbox.git] / src / bbwindow.hh
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 #ifndef   __Window_hh
3 #define   __Window_hh
4
5 extern "C" {
6 #include <X11/Xlib.h>
7 #include <X11/Xutil.h>
8 #ifdef    SHAPE
9 #  include <X11/extensions/shape.h>
10 #endif // SHAPE
11 }
12
13 #include <string>
14
15 #include "otk/timer.hh"
16 #include "otk/property.hh"
17 #include "blackbox.hh"
18 #include "util.hh"
19
20 #define MwmHintsFunctions     (1l << 0)
21 #define MwmHintsDecorations   (1l << 1)
22
23 #define MwmFuncAll            (1l << 0)
24 #define MwmFuncResize         (1l << 1)
25 #define MwmFuncMove           (1l << 2)
26 #define MwmFuncIconify        (1l << 3)
27 #define MwmFuncMaximize       (1l << 4)
28 #define MwmFuncClose          (1l << 5)
29
30 #define MwmDecorAll           (1l << 0)
31 #define MwmDecorBorder        (1l << 1)
32 #define MwmDecorHandle        (1l << 2)
33 #define MwmDecorTitle         (1l << 3)
34 #define MwmDecorMenu          (1l << 4) // not used
35 #define MwmDecorIconify       (1l << 5)
36 #define MwmDecorMaximize      (1l << 6)
37
38 namespace ob {
39
40 // this structure only contains 3 elements... the Motif 2.0 structure contains
41 // 5... we only need the first 3... so that is all we will define
42 typedef struct MwmHints {
43   unsigned long flags, functions, decorations;
44 } MwmHints;
45
46 #define PropMwmHintsElements  3
47
48 class BWindowGroup {
49 private:
50   Blackbox *blackbox;
51   Window group;
52   BlackboxWindowList windowList;
53
54 public:
55   BWindowGroup(Blackbox *b, Window _group);
56   ~BWindowGroup(void);
57
58   inline Window groupWindow(void) const { return group; }
59
60   inline bool empty(void) const { return windowList.empty(); }
61
62   void addWindow(BlackboxWindow *w) { windowList.push_back(w); }
63   void removeWindow(BlackboxWindow *w) { windowList.remove(w); }
64
65   /*
66     find a window on the specified screen. the focused window (if any) is
67     checked first, otherwise the first matching window found is returned.
68     transients are returned only if allow_transients is True.
69   */
70   BlackboxWindow *find(BScreen *screen, bool allow_transients = False) const;
71 };
72
73
74 class BlackboxWindow {
75 public:
76   enum Function { Func_Resize   = (1l << 0),
77                   Func_Move     = (1l << 1),
78                   Func_Iconify  = (1l << 2),
79                   Func_Maximize = (1l << 3),
80                   Func_Close    = (1l << 4) };
81   typedef unsigned char FunctionFlags;
82
83   enum Decoration { Decor_Titlebar = (1l << 0),
84                     Decor_Handle   = (1l << 1),
85                     Decor_Border   = (1l << 2),
86                     Decor_Iconify  = (1l << 3),
87                     Decor_Maximize = (1l << 4),
88                     Decor_Close    = (1l << 5) };
89   typedef unsigned char DecorationFlags;
90
91   enum WindowType { Type_Desktop,
92                     Type_Dock,
93                     Type_Toolbar,
94                     Type_Menu,
95                     Type_Utility,
96                     Type_Splash,
97                     Type_Dialog,
98                     Type_Normal };
99
100   enum Corner { TopLeft,
101                 TopRight,
102                 BottomLeft,
103                 BottomRight };
104
105 private:
106   Blackbox *blackbox;
107   BScreen *screen;
108   otk::OBProperty *xatom;
109   otk::OBTimer *timer;
110   BlackboxAttributes blackbox_attrib;
111
112   Time lastButtonPressTime;  // used for double clicks, when were we clicked
113
114   unsigned int window_number;
115   unsigned long current_state;
116   unsigned int mod_mask;    // the mod mask used to grab buttons
117
118   enum FocusMode { F_NoInput = 0, F_Passive,
119                    F_LocallyActive, F_GloballyActive };
120   FocusMode focus_mode;
121
122   struct _flags {
123     bool moving,             // is moving?
124       resizing,              // is resizing?
125       shaded,                // is shaded?
126       visible,               // is visible?
127       iconic,                // is iconified?
128       focused,               // has focus?
129       stuck,                 // is omnipresent?
130       modal,                 // is modal? (must be dismissed to continue)
131       skip_taskbar,          // skipped by taskbars?
132       skip_pager,            // skipped by pagers?
133       fullscreen,            // a fullscreen window?
134       send_focus_message,    // should we send focus messages to our client?
135       shaped;                // does the frame use the shape extension?
136     unsigned int maximized;  // maximize is special, the number corresponds
137                              // with a mouse button
138                              // if 0, not maximized
139                              // 1 = HorizVert, 2 = Vertical, 3 = Horizontal
140   } flags;
141
142   struct _client {
143     Window window,                  // the client's window
144       window_group;
145     BlackboxWindow *transient_for;  // which window are we a transient for?
146     BlackboxWindowList transientList; // which windows are our transients?
147
148     std::string title, icon_title;
149
150     otk::Rect rect;
151     Strut strut;
152
153     int old_bw;                       // client's borderwidth
154
155     unsigned int
156       min_width, min_height,        // can not be resized smaller
157       max_width, max_height,        // can not be resized larger
158       width_inc, height_inc,        // increment step
159 #if 0 // not supported at the moment
160       min_aspect_x, min_aspect_y,   // minimum aspect ratio
161       max_aspect_x, max_aspect_y,   // maximum aspect ratio
162 #endif
163       base_width, base_height,
164       win_gravity;
165
166     unsigned long initial_state, normal_hint_flags;
167   } client;
168
169   FunctionFlags functions;
170   /*
171    * what decorations do we have?
172    * this is based on the type of the client window as well as user input
173    */
174   DecorationFlags decorations;
175   DecorationFlags mwm_decorations;
176   Corner resize_dir;
177   WindowType window_type;
178
179   /*
180    * client window = the application's window
181    * frame window = the window drawn around the outside of the client window
182    *                by the window manager which contains items like the
183    *                titlebar and close button
184    * title = the titlebar drawn above the client window, it displays the
185    *         window's name and any buttons for interacting with the window,
186    *         such as iconify, maximize, and close
187    * label = the window in the titlebar where the title is drawn
188    * buttons = maximize, iconify, close
189    * handle = the bar drawn at the bottom of the window, which contains the
190    *          left and right grips used for resizing the window
191    * grips = the smaller reactangles in the handle, one of each side of it.
192    *         When clicked and dragged, these resize the window interactively
193    * border = the line drawn around the outside edge of the frame window,
194    *          between the title, the bordered client window, and the handle.
195    *          Also drawn between the grips and the handle
196    */
197
198   struct _frame {
199     // u -> unfocused, f -> has focus, p -> pressed
200     unsigned long ulabel_pixel, flabel_pixel, utitle_pixel,
201       ftitle_pixel, uhandle_pixel, fhandle_pixel, ubutton_pixel,
202       fbutton_pixel, pfbutton_pixel, pubutton_pixel,
203       uborder_pixel, fborder_pixel, ugrip_pixel, fgrip_pixel;
204     Pixmap ulabel, flabel, utitle, ftitle, uhandle, fhandle,
205       ubutton, fbutton, pfbutton, pubutton, ugrip, fgrip;
206
207     Window window,       // the frame
208       plate,             // holds the client
209       title,
210       label,
211       handle,
212       close_button, iconify_button, maximize_button, stick_button,
213       right_grip, left_grip;
214
215     /*
216      * size and location of the box drawn while the window dimensions or
217      * location is being changed, ie. resized or moved
218      */
219     otk::Rect changing;
220
221     otk::Rect rect;                  // frame geometry
222     Strut margin;               // margins between the frame and client
223
224     int grab_x, grab_y;         // where was the window when it was grabbed?
225
226     unsigned int inside_w, inside_h, // window w/h without border_w
227       title_h, label_w, label_h, handle_h,
228       button_w, grip_w, mwm_border_w, border_w,
229       bevel_w;
230   } frame;
231
232   BlackboxWindow(const BlackboxWindow&);
233   BlackboxWindow& operator=(const BlackboxWindow&);
234
235   bool getState(void);
236   Window createToplevelWindow();
237   Window createChildWindow(Window parent, unsigned long event_mask,
238                            Cursor = None);
239
240   bool getWindowType(void);
241   void updateStrut(void);
242   void getWMName(void);
243   void getWMIconName(void);
244   void getWMNormalHints(void);
245   void getWMProtocols(void);
246   void getWMHints(void);
247   void getNetWMHints(void);
248   void getMWMHints(void);
249   bool getBlackboxHints(void);
250   void getTransientInfo(void);
251   void setNetWMAttributes(void);
252   void associateClientWindow(void);
253   void decorate(void);
254   void decorateLabel(void);
255   void positionButtons(bool redecorate_label = False);
256   void positionWindows(void);
257   void createHandle(void);
258   void destroyHandle(void);
259   void createTitlebar(void);
260   void destroyTitlebar(void);
261   void createCloseButton(void);
262   void destroyCloseButton(void);
263   void createIconifyButton(void);
264   void destroyIconifyButton(void);
265   void createMaximizeButton(void);
266   void destroyMaximizeButton(void);
267   void createStickyButton(void);
268   void destroyStickyButton(void);
269   void redrawWindowFrame(void) const;
270   void redrawLabel(void) const;
271   void redrawAllButtons(void) const;
272   void redrawButton(bool pressed, Window win,
273                     Pixmap fppix, unsigned long fppixel,
274                     Pixmap uppix, unsigned long uppixel,
275                     Pixmap fpix, unsigned long fpixel,
276                     Pixmap upix, unsigned long upixel) const;
277   void redrawCloseButton(bool pressed) const;
278   void redrawIconifyButton(bool pressed) const;
279   void redrawMaximizeButton(bool pressed) const;
280   void redrawStickyButton(bool pressed) const;
281   void applyGravity(otk::Rect &r);
282   void restoreGravity(otk::Rect &r);
283   void setAllowedActions(void);
284   void setState(unsigned long new_state);
285   void upsize(void);
286   void doMove(int x_root, int y_root);
287   void doWorkspaceWarping(int x_root, int y_root, int &dx);
288   void doWindowSnapping(int &dx, int &dy);
289   void endMove(void);
290   void doResize(int x_root, int y_root);
291   void endResize(void);
292
293   void constrain(Corner anchor, unsigned int *pw = 0, unsigned int *ph = 0);
294
295 public:
296   BlackboxWindow(Blackbox *b, Window w, BScreen *s);
297   virtual ~BlackboxWindow(void);
298
299   inline bool isTransient(void) const { return client.transient_for != 0; }
300   inline bool isFocused(void) const { return flags.focused; }
301   inline bool isVisible(void) const { return flags.visible; }
302   inline bool isIconic(void) const { return flags.iconic; }
303   inline bool isShaded(void) const { return flags.shaded; }
304   inline bool isMaximized(void) const { return flags.maximized; }
305   inline bool isMaximizedHoriz(void) const { return flags.maximized == 3; }
306   inline bool isMaximizedVert(void) const { return flags.maximized == 2; }
307   inline bool isMaximizedFull(void) const { return flags.maximized == 1; }
308   inline bool isStuck(void) const { return flags.stuck; }
309   inline bool isModal(void) const { return flags.modal; }
310   inline bool isIconifiable(void) const { return functions & Func_Iconify; }
311   inline bool isMaximizable(void) const { return functions & Func_Maximize; }
312   inline bool isResizable(void) const { return functions & Func_Resize; }
313   inline bool isClosable(void) const { return functions & Func_Close; }
314
315   // is a 'normal' window? meaning, a standard client application
316   inline bool isNormal(void) const
317   { return window_type == Type_Dialog || window_type == Type_Normal ||
318            window_type == Type_Toolbar || window_type == Type_Utility; }
319   inline bool isTopmost(void) const
320   { return window_type == Type_Toolbar || window_type == Type_Utility; }
321   inline bool isDesktop(void) const { return window_type == Type_Desktop; }
322   
323   inline bool hasTitlebar(void) const { return decorations & Decor_Titlebar; }
324
325   inline const BlackboxWindowList &getTransients(void) const
326   { return client.transientList; }
327   BlackboxWindow *getTransientFor(void) const;
328
329   inline BScreen *getScreen(void) const { return screen; }
330
331   inline Window getFrameWindow(void) const { return frame.window; }
332   inline Window getClientWindow(void) const { return client.window; }
333   inline Window getGroupWindow(void) const { return client.window_group; }
334
335   inline const char *getTitle(void) const
336   { return client.title.c_str(); }
337   inline const char *getIconTitle(void) const
338   { return client.icon_title.c_str(); }
339
340   inline unsigned int getWorkspaceNumber(void) const
341   { return blackbox_attrib.workspace; }
342   inline unsigned int getWindowNumber(void) const { return window_number; }
343
344   inline const otk::Rect &frameRect(void) const { return frame.rect; }
345   inline const otk::Rect &clientRect(void) const { return client.rect; }
346
347   inline unsigned int getTitleHeight(void) const
348   { return frame.title_h; }
349
350   inline void setWindowNumber(int n) { window_number = n; }
351
352   bool validateClient(void) const;
353   bool setInputFocus(void);
354
355   // none of these are used by the window manager, they are here to persist
356   // them properly in the window's netwm state property.
357   inline bool skipTaskbar(void) const { return flags.skip_taskbar; }
358   inline void setSkipTaskbar(const bool s) { flags.skip_taskbar = s; }
359   inline bool skipPager(void) const { return flags.skip_pager; }
360   inline void setSkipPager(const bool s) { flags.skip_pager = s; }
361   inline bool isFullscreen(void) const { return flags.fullscreen; }
362   inline void setFullscreen(const bool f) { flags.fullscreen = f; }
363
364   inline void setModal(const bool m) { flags.modal = m; }
365
366   void beginMove(int x_root, int y_root);
367   void beginResize(int x_root, int y_root, Corner dir);
368   void enableDecor(bool enable);
369   void setupDecor();
370   void setFocusFlag(bool focus);
371   void iconify(void);
372   void deiconify(bool reassoc = True, bool raise = True);
373   void show(void);
374   void close(void);
375   void withdraw(void);
376   void maximize(unsigned int button);
377   void remaximize(void);
378   void shade(void);
379   void stick(void);
380   void reconfigure(void);
381   void grabButtons(void);
382   void ungrabButtons(void);
383   void installColormap(bool install);
384   void restore(bool remap);
385   void configure(int dx, int dy, unsigned int dw, unsigned int dh);
386   void setWorkspace(unsigned int n);
387   void changeBlackboxHints(const BlackboxHints *net);
388   void restoreAttributes(void);
389
390   void buttonPressEvent(const XButtonEvent *be);
391   void buttonReleaseEvent(const XButtonEvent *re);
392   void motionNotifyEvent(const XMotionEvent *me);
393   void destroyNotifyEvent(const XDestroyWindowEvent* /*unused*/);
394   void mapRequestEvent(const XMapRequestEvent *mre);
395   void unmapNotifyEvent(const XUnmapEvent* /*unused*/);
396   void reparentNotifyEvent(const XReparentEvent* /*unused*/);
397   void propertyNotifyEvent(const XPropertyEvent *pe);
398   void exposeEvent(const XExposeEvent *ee);
399   void configureRequestEvent(const XConfigureRequestEvent *cr);
400   void enterNotifyEvent(const XCrossingEvent *ce);
401   void leaveNotifyEvent(const XCrossingEvent* /*unused*/);
402
403 #ifdef    SHAPE
404   void configureShape(void);
405   void clearShape(void);
406   void shapeEvent(XShapeEvent * /*unused*/);
407 #endif // SHAPE
408
409   static void timeout(BlackboxWindow *t);
410 };
411
412 }
413
414 #endif // __Window_hh