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