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