1 // FbWinFrame.hh for Fluxbox Window Manager
2 // Copyright (c) 2003 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org)
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 // DEALINGS IN THE SOFTWARE.
21 
22 #ifndef FBWINFRAME_HH
23 #define FBWINFRAME_HH
24 
25 #include "WindowState.hh"
26 
27 #include "FbTk/FbWindow.hh"
28 #include "FbTk/EventHandler.hh"
29 #include "FbTk/RefCount.hh"
30 #include "FbTk/Color.hh"
31 #include "FbTk/LayerItem.hh"
32 #include "FbTk/TextButton.hh"
33 #include "FbTk/Container.hh"
34 #include "FbTk/Shape.hh"
35 #include "FbTk/Signal.hh"
36 
37 #include <vector>
38 #include <memory>
39 
40 class FbWinFrameTheme;
41 class BScreen;
42 class IconButton;
43 class Focusable;
44 template <class T> class FocusableTheme;
45 
46 namespace FbTk {
47 class ImageControl;
48 template <class T> class Command;
49 class Texture;
50 }
51 
52 /// holds a window frame with a client window
53 /// (see: <a href="fluxbox_fbwinframe.png">image</a>)
54 class FbWinFrame:public FbTk::EventHandler {
55 public:
56     // STRICTINTERNAL means it doesn't go external automatically when no titlebar
57     enum TabMode { NOTSET = 0, INTERNAL = 1, EXTERNAL };
58 
59    /// Toolbar placement on the screen
60     enum TabPlacement{
61         // top and bottom placement
62         TOPLEFT = 1, TOP, TOPRIGHT,
63         BOTTOMLEFT, BOTTOM, BOTTOMRIGHT,
64         // left and right placement
65         LEFTBOTTOM, LEFT, LEFTTOP,
66         RIGHTBOTTOM, RIGHT, RIGHTTOP,
67 
68         DEFAULT = TOPLEFT
69     };
70 
71     /// create a top level window
72     FbWinFrame(BScreen &screen, unsigned int client_depth, WindowState &state,
73                FocusableTheme<FbWinFrameTheme> &theme);
74 
75     /// destroy frame
76     ~FbWinFrame();
77 
78     void hide();
79     void show();
isVisible() const80     bool isVisible() const { return m_visible; }
81 
82     void move(int x, int y);
83     void resize(unsigned int width, unsigned int height);
84     /// resize client to specified size and resize frame to it
85     void resizeForClient(unsigned int width, unsigned int height, int win_gravity=ForgetGravity, unsigned int client_bw = 0);
86 
87     // for when there needs to be an atomic move+resize operation
88     void moveResizeForClient(int x, int y,
89                              unsigned int width, unsigned int height,
90                              int win_gravity=ForgetGravity, unsigned int client_bw = 0, bool move = true, bool resize = true);
91 
92     // can elect to ignore move or resize (mainly for use of move/resize individual functions
93     void moveResize(int x, int y,
94                     unsigned int width, unsigned int height,
95                     bool move = true, bool resize = true);
96 
97     // move without transparency or special effects (generally when dragging)
98     void quietMoveResize(int x, int y,
99                          unsigned int width, unsigned int height);
100 
101     /// some outside move/resize happened, and we need to notify all of our windows
102     /// in case of transparency
103     void notifyMoved(bool clear);
104     void clearAll();
105 
106     /// set focus/unfocus style
107     void setFocus(bool newvalue);
108 
setFocusTitle(const FbTk::BiDiString & str)109     void setFocusTitle(const FbTk::BiDiString &str) { m_label.setText(str); }
110     bool setTabMode(TabMode tabmode);
updateTabProperties()111     void updateTabProperties() { alignTabs(); }
112 
113     /// Alpha settings
114     void setAlpha(bool focused, int value);
115     int getAlpha(bool focused) const;
116     void applyAlpha();
117 
118     void setDefaultAlpha();
119     bool getUseDefaultAlpha() const;
120 
121     /// add a button to the left of the label
122     void addLeftButton(FbTk::Button *btn);
123     /// add a button to the right of the label
124     void addRightButton(FbTk::Button *btn);
125     /// remove all buttons from titlebar
126     void removeAllButtons();
127     /// adds a button to tab container
128     void createTab(FbTk::Button &button);
129     /// removes a specific button from label window
130     void removeTab(IconButton *id);
131     /// move label button to the left
132     void moveLabelButtonLeft(FbTk::TextButton &btn);
133     /// move label button to the right
134     void moveLabelButtonRight(FbTk::TextButton &btn);
135     /// move label button to the given location( x and y are relative to the root window)
136     void moveLabelButtonTo(FbTk::TextButton &btn, int x, int y);
137     /// move the first label button to the left of the second
138     void moveLabelButtonLeftOf(FbTk::TextButton &btn, const FbTk::TextButton &dest);
139     //move the first label button to the right of the second
140     void moveLabelButtonRightOf(FbTk::TextButton &btn, const FbTk::TextButton &dest);
141     /// attach a client window for client area
142     void setClientWindow(FbTk::FbWindow &win);
143     /// remove attached client window
144     void removeClient();
145     /// redirect events to another eventhandler
146     void setEventHandler(FbTk::EventHandler &evh);
147     /// remove any handler for the windows
148     void removeEventHandler();
149 
sizeHints() const150     const SizeHints &sizeHints() const { return m_state.size_hints; }
setSizeHints(const SizeHints & hint)151     void setSizeHints(const SizeHints &hint) { m_state.size_hints = hint; }
152 
153     void applySizeHints(unsigned int &width, unsigned int &height,
154                         bool maximizing = false) const;
155     void displaySize(unsigned int width, unsigned int height) const;
156 
setDecorationMask(unsigned int mask)157     void setDecorationMask(unsigned int mask) { m_state.deco_mask = mask; }
158     void applyDecorations(bool do_move = true);
159     void applyState();
160 
161     // this function translates its arguments according to win_gravity
162     // if win_gravity is negative, it does an inverse translation
163     void gravityTranslate(int &x, int &y, int win_gravity, unsigned int client_bw, bool move_frame = false);
setActiveGravity(int gravity,unsigned int orig_client_bw)164     void setActiveGravity(int gravity, unsigned int orig_client_bw) { m_state.size_hints.win_gravity = gravity; m_active_orig_client_bw = orig_client_bw; }
165 
166     /**
167        @name Event handlers
168     */
169     //@{
170     void exposeEvent(XExposeEvent &event);
171     void configureNotifyEvent(XConfigureEvent &event);
172     void handleEvent(XEvent &event);
173     //@}
174 
175     void reconfigure();
176     void setShapingClient(FbTk::FbWindow *win, bool always_update);
updateShape()177     void updateShape() { m_shape.update(); }
178 
179     /**
180        @name accessors
181     */
182     //@{
x() const183     int x() const { return m_window.x(); }
y() const184     int y() const { return m_window.y(); }
width() const185     unsigned int width() const { return m_window.width(); }
height() const186     unsigned int height() const { return m_window.height(); }
187 
188     // extra bits for tabs
189     int xOffset() const;
190     int yOffset() const;
191     int widthOffset() const;
192     int heightOffset() const;
193 
window() const194     const FbTk::FbWindow &window() const { return m_window; }
window()195     FbTk::FbWindow &window() { return m_window; }
196     /// @return titlebar window
titlebar() const197     const FbTk::FbWindow &titlebar() const { return m_titlebar; }
titlebar()198     FbTk::FbWindow &titlebar() { return m_titlebar; }
label() const199     const FbTk::FbWindow &label() const { return m_label; }
label()200     FbTk::FbWindow &label() { return m_label; }
201 
tabcontainer() const202     const FbTk::Container &tabcontainer() const { return m_tab_container; }
tabcontainer()203     FbTk::Container &tabcontainer() { return m_tab_container; }
204 
205     /// @return clientarea window
clientArea() const206     const FbTk::FbWindow &clientArea() const { return m_clientarea; }
clientArea()207     FbTk::FbWindow &clientArea() { return m_clientarea; }
208     /// @return handle window
handle() const209     const FbTk::FbWindow &handle() const { return m_handle; }
handle()210     FbTk::FbWindow &handle() { return m_handle; }
gripLeft() const211     const FbTk::FbWindow &gripLeft() const { return m_grip_left; }
gripLeft()212     FbTk::FbWindow &gripLeft() { return m_grip_left; }
gripRight() const213     const FbTk::FbWindow &gripRight() const { return m_grip_right; }
gripRight()214     FbTk::FbWindow &gripRight() { return m_grip_right; }
focused() const215     bool focused() const { return m_state.focused; }
theme() const216     FocusableTheme<FbWinFrameTheme> &theme() const { return m_theme; }
217     /// @return titlebar height
titlebarHeight() const218     unsigned int titlebarHeight() const { return (m_use_titlebar?m_titlebar.height()+m_titlebar.borderWidth():0); }
handleHeight() const219     unsigned int handleHeight() const { return (m_use_handle?m_handle.height()+m_handle.borderWidth():0); }
220     /// @return size of button
221     unsigned int buttonHeight() const;
externalTabMode() const222     bool externalTabMode() const { return m_tabmode == EXTERNAL && m_use_tabs; }
223 
layerItem() const224     const FbTk::LayerItem &layerItem() const { return m_layeritem; }
layerItem()225     FbTk::LayerItem &layerItem() { return m_layeritem; }
226 
frameExtentSig()227     FbTk::Signal<> &frameExtentSig() { return m_frame_extent_sig; }
228     /// @returns true if the window is inside titlebar,
229     /// assuming window is an event window that was generated for this frame.
230     bool insideTitlebar(Window win) const;
231 
232     /// @returns context for window,
233     /// assuming window is an event window that was generated for this frame.
234     int getContext(Window win, int x=0, int y=0, int last_x=0, int last_y=0, bool doBorders=false);
235 
236     //@}
237 
238 private:
239     void redrawTitlebar();
240 
241     /// reposition titlebar items
242     void reconfigureTitlebar();
243     /**
244        @name render helper functions
245     */
246     //@{
247     void renderAll();
248     void renderTitlebar();
249     void renderHandles();
250     void renderTabContainer(); // and labelbuttons
251 
252     void renderButtons(); // subset of renderTitlebar - don't call directly
253 
254     //@}
255 
256     // these return true/false for if something changed
257     bool hideTitlebar();
258     bool showTitlebar();
259     bool hideTabs();
260     bool showTabs();
261     bool hideHandle();
262     bool showHandle();
263     bool setBorderWidth(bool do_move = true);
264 
265     // check which corners should be rounded
266     int getShape() const;
267 
268     /**
269        @name apply pixmaps depending on focus
270     */
271     //@{
272     void applyAll();
273     void applyTitlebar();
274     void applyHandles();
275     void applyTabContainer(); // and label buttons
276     void applyButtons(); // only called within applyTitlebar
277 
278 #if 0
279     void getCurrentFocusPixmap(Pixmap &label_pm, Pixmap &title_pm,
280                                FbTk::Color &label_color, FbTk::Color &title_color);
281 #endif
282 
283     /// initiate inserted button for current theme
284     void applyButton(FbTk::Button &btn);
285 
286     void alignTabs();
287     //@}
288 
289     /// initiate some commont variables
290     void init();
291 
292     BScreen &m_screen;
293 
294     FocusableTheme<FbWinFrameTheme> &m_theme; ///< theme to be used
295     FbTk::ImageControl &m_imagectrl; ///< Image control for rendering
296     WindowState &m_state;
297 
298     /**
299        @name windows
300     */
301     //@{
302     FbTk::FbWindow m_window; ///< base window that holds each decorations (ie titlebar, handles)
303     // want this deleted before the windows in it
304     FbTk::LayerItem m_layeritem;
305 
306     FbTk::FbWindow m_titlebar; ///<  titlebar window
307     FbTk::Container m_tab_container; ///< Holds tabs
308     FbTk::TextButton m_label; ///< holds title
309     FbTk::FbWindow m_handle; ///< handle between grips
310     FbTk::FbWindow m_grip_right,  ///< rightgrip
311         m_grip_left; ///< left grip
312     FbTk::FbWindow m_clientarea; ///< window that sits behind client window to fill gaps @see setClientWindow
313     //@}
314 
315     FbTk::Signal<> m_frame_extent_sig;
316 
317     typedef std::vector<FbTk::Button *> ButtonList;
318     ButtonList m_buttons_left, ///< buttons to the left
319         m_buttons_right; ///< buttons to the right
320     typedef std::list<FbTk::TextButton *> LabelList;
321     int m_bevel;  ///< bevel between titlebar items and titlebar
322     bool m_use_titlebar; ///< if we should use titlebar
323     bool m_use_tabs; ///< if we should use tabs (turns them off in external mode only)
324     bool m_use_handle; ///< if we should use handle
325     bool m_visible; ///< if we are currently showing
326     ///< do we use screen or window alpha settings ? (0 = window, 1 = default, 2 = default and window never set)
327 
328     /**
329        @name pixmaps and colors for rendering
330     */
331     //@{
332 
333     // 0-unfocus, 1-focus
334     struct Face { Pixmap pm[2]; FbTk::Color color[2]; };
335     // 0-unfocus, 1-focus, 2-pressed
336     struct BtnFace { Pixmap pm[3]; FbTk::Color color[3]; };
337 
338     Face m_title_face;
339     Face m_label_face;
340     Face m_tabcontainer_face;
341     Face m_handle_face;
342     Face m_grip_face;
343     BtnFace m_button_face;
344 
345     //@}
346 
347     TabMode m_tabmode;
348 
349     unsigned int m_active_orig_client_bw;
350 
351     bool m_need_render;
352     int m_button_size; ///< size for all titlebar buttons
353     int m_alpha[2]; // 0-unfocused, 1-focused
354 
355     FbTk::Shape m_shape;
356 };
357 
358 #endif // FBWINFRAME_HH
359