1
// Screen.hh for Fluxbox Window Manager
2
// Copyright (c) 2001 - 2005 Henrik Kinnunen (fluxgen at fluxbox dot org)
4
// Screen.hh for Blackbox - an X11 Window manager
5
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
7
// Permission is hereby granted, free of charge, to any person obtaining a
8
// copy of this software and associated documentation files (the "Software"),
9
// to deal in the Software without restriction, including without limitation
10
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
// and/or sell copies of the Software, and to permit persons to whom the
12
// Software is furnished to do so, subject to the following conditions:
14
// The above copyright notice and this permission notice shall be included in
15
// all copies or substantial portions of the Software.
17
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
// DEALINGS IN THE SOFTWARE.
25
// $Id: Screen.hh 4099 2005-09-07 16:46:17Z simonb $
31
#include "FbRootWindow.hh"
32
#include "MenuTheme.hh"
34
#include "FbTk/Resource.hh"
35
#include "FbTk/Subject.hh"
36
#include "FbTk/MultLayers.hh"
37
#include "FbTk/NotCopyable.hh"
38
#include "FbTk/Observer.hh"
41
#include <X11/Xresource.h>
57
class FbWinFrameTheme;
74
/// Handles screen connection, screen clients and workspaces
76
Create workspaces, handles switching between workspaces and windows
78
class BScreen : public FbTk::Observer, private FbTk::NotCopyable {
80
enum ResizeModel { BOTTOMRESIZE = 0, QUADRANTRESIZE, DEFAULTRESIZE = BOTTOMRESIZE };
81
enum FocusModel { MOUSEFOCUS = 0, CLICKFOCUS };
82
enum TabFocusModel { MOUSETABFOCUS = 0, CLICKTABFOCUS };
83
enum FollowModel { ///< a window becomes active / focussed on a different workspace
84
IGNORE_OTHER_WORKSPACES = 0, ///< who cares?
85
FOLLOW_ACTIVE_WINDOW, ///< go to that workspace
86
FETCH_ACTIVE_WINDOW ///< put that window to the current workspace
88
enum FocusDir { FOCUSUP, FOCUSDOWN, FOCUSLEFT, FOCUSRIGHT };
89
enum PlacementPolicy { ROWSMARTPLACEMENT, COLSMARTPLACEMENT,
90
CASCADEPLACEMENT, UNDERMOUSEPLACEMENT};
91
enum RowDirection { LEFTRIGHT, RIGHTLEFT};
92
enum ColumnDirection { TOPBOTTOM, BOTTOMTOP};
93
// prevFocus/nextFocus option bits
94
enum { CYCLEGROUPS = 0x01, CYCLESKIPSTUCK = 0x02, CYCLESKIPSHADED = 0x04,
95
CYCLELINEAR = 0x08, CYCLEDEFAULT = 0x00 };
97
typedef std::vector<FluxboxWindow *> Icons;
98
typedef std::list<WinClient *> FocusedWindows;
99
typedef std::vector<Workspace *> Workspaces;
100
typedef std::vector<std::string> WorkspaceNames;
101
typedef std::list<std::pair<const char *, FbTk::Menu *> > ExtraMenus;
103
BScreen(FbTk::ResourceManager &rm,
104
const std::string &screenname, const std::string &altscreenname,
105
int scrn, int number_of_layers);
110
bool isMouseFocus() const { return (*resource.focus_model == MOUSEFOCUS); }
111
bool isMouseTabFocus() const { return (*resource.tabfocus_model == MOUSETABFOCUS); }
112
bool isRootColormapInstalled() const { return root_colormap_installed; }
113
bool isScreenManaged() const { return managed; }
114
bool isSloppyWindowGrouping() const { return *resource.sloppy_window_grouping; }
115
bool isWorkspaceWarping() const { return *resource.workspace_warping; }
116
bool isDesktopWheeling() const { return *resource.desktop_wheeling; }
117
bool doAutoRaise() const { return *resource.auto_raise; }
118
bool clickRaises() const { return *resource.click_raises; }
119
bool doOpaqueMove() const { return *resource.opaque_move; }
120
bool doFullMax() const { return *resource.full_max; }
121
bool doFocusNew() const { return *resource.focus_new; }
122
bool doFocusLast() const { return *resource.focus_last; }
123
bool doShowWindowPos() const { return *resource.show_window_pos; }
124
bool antialias() const { return *resource.antialias; }
125
bool decorateTransient() const { return *resource.decorate_transient; }
126
const std::string &windowMenuFilename() const { return *resource.windowmenufile; }
127
FbTk::ImageControl &imageControl() { return *m_image_control.get(); }
129
const FbTk::Menu &rootMenu() const { return *m_rootmenu.get(); }
130
FbTk::Menu &rootMenu() { return *m_rootmenu.get(); }
131
const FbTk::Menu &configMenu() const { return *m_configmenu.get(); }
132
FbTk::Menu &configMenu() { return *m_configmenu.get(); }
133
const FbTk::Menu &windowMenu() const { return *m_windowmenu.get(); }
134
FbTk::Menu &windowMenu() { return *m_windowmenu.get(); }
135
ExtraMenus &extraWindowMenus() { return m_extramenus; }
136
const ExtraMenus &extraWindowMenus() const { return m_extramenus; }
138
ResizeModel getResizeModel() const { return *resource.resize_model; }
139
FocusModel getFocusModel() const { return *resource.focus_model; }
140
TabFocusModel getTabFocusModel() const { return *resource.tabfocus_model; }
142
inline FollowModel getFollowModel() const { return *resource.follow_model; }
144
inline const std::string &getScrollAction() const { return *resource.scroll_action; }
145
inline const bool getScrollReverse() const { return *resource.scroll_reverse; }
147
inline Slit *slit() { return m_slit.get(); }
148
inline const Slit *slit() const { return m_slit.get(); }
150
inline Workspace *getWorkspace(unsigned int w) { return ( w < m_workspaces_list.size() ? m_workspaces_list[w] : 0); }
151
inline Workspace *currentWorkspace() { return m_current_workspace; }
152
inline const Workspace *currentWorkspace() const { return m_current_workspace; }
154
const FbTk::Menu &workspaceMenu() const { return *m_workspacemenu.get(); }
155
FbTk::Menu &workspaceMenu() { return *m_workspacemenu.get(); }
158
unsigned int currentWorkspaceID() const;
160
maximum screen bounds for given window
162
unsigned int maxLeft(int head) const;
163
unsigned int maxRight(int head) const;
164
unsigned int maxTop(int head) const;
165
unsigned int maxBottom(int head) const;
166
/// @return true if window is kde dock app
167
bool isKdeDockapp(Window win) const;
168
/// @return true if dock app was added, else false
169
bool addKdeDockapp(Window win);
171
inline unsigned int width() const { return rootWindow().width(); }
172
inline unsigned int height() const { return rootWindow().height(); }
173
inline int screenNumber() const { return rootWindow().screenNumber(); }
175
/// @return number of workspaces
176
unsigned int numberOfWorkspaces() const { return m_workspaces_list.size(); }
178
inline const Icons &iconList() const { return m_icon_list; }
179
inline Icons &iconList() { return m_icon_list; }
180
inline const FocusedWindows &getFocusedList() const { return focused_list; }
181
inline FocusedWindows &getFocusedList() { return focused_list; }
182
WinClient *getLastFocusedWindow(int workspace = -1);
183
WinClient *getLastFocusedWindow(FluxboxWindow &group, WinClient *ignore_client = 0);
184
const Workspaces &getWorkspacesList() const { return m_workspaces_list; }
185
Workspaces &getWorkspacesList() { return m_workspaces_list; }
186
const WorkspaceNames &getWorkspaceNames() const { return m_workspace_names; }
191
/// client list signal
192
FbTk::Subject &clientListSig() { return m_clientlist_sig; }
194
FbTk::Subject &iconListSig() { return m_iconlist_sig; }
195
/// workspace count signal
196
FbTk::Subject &workspaceCountSig() { return m_workspacecount_sig; }
197
/// workspace names signal
198
FbTk::Subject &workspaceNamesSig() { return m_workspacenames_sig; }
199
/// workspace area signal
200
FbTk::Subject &workspaceAreaSig() { return m_workspace_area_sig; }
201
/// current workspace signal
202
FbTk::Subject ¤tWorkspaceSig() { return m_currentworkspace_sig; }
203
/// reconfigure signal
204
FbTk::Subject &reconfigureSig() { return m_reconfigure_sig; }
205
FbTk::Subject &resizeSig() { return m_resize_sig; }
208
void update(FbTk::Subject *subj);
210
FbTk::Menu *createMenu(const std::string &label);
212
// for extras to add menus.
213
// These menus will be marked internal,
214
// and deleted when the window dies (as opposed to Screen
215
void addExtraWindowMenu(const char *label, FbTk::Menu *menu);
216
void removeExtraWindowMenu(FbTk::Menu *menu);
218
/// hide all windowmenus except the given one (if given)
219
void hideWindowMenus(const FluxboxWindow* except= 0);
221
inline PlacementPolicy getPlacementPolicy() const { return *resource.placement_policy; }
222
inline int getEdgeSnapThreshold() const { return *resource.edge_snap_threshold; }
223
inline RowDirection getRowPlacementDirection() const { return *resource.row_direction; }
224
inline ColumnDirection getColPlacementDirection() const { return *resource.col_direction; }
226
void setRootColormapInstalled(bool r) { root_colormap_installed = r; }
227
void saveRootCommand(std::string rootcmd) { *resource.rootcommand = rootcmd; }
228
void saveFocusModel(FocusModel model) { resource.focus_model = model; }
229
void saveTabFocusModel(TabFocusModel model) { resource.tabfocus_model = model; }
231
void saveWorkspaces(int w) { *resource.workspaces = w; }
233
void saveMenu(FbTk::Menu &menu) { m_rootmenu_list.push_back(&menu); }
235
FbWinFrameTheme &winFrameTheme() { return *m_windowtheme.get(); }
236
const FbWinFrameTheme &winFrameTheme() const { return *m_windowtheme.get(); }
237
MenuTheme &menuTheme() { return *m_menutheme.get(); }
238
const MenuTheme &menuTheme() const { return *m_menutheme.get(); }
239
const RootTheme &rootTheme() const { return *m_root_theme.get(); }
240
WinButtonTheme &winButtonTheme() { return *m_winbutton_theme.get(); }
241
const WinButtonTheme &winButtonTheme() const { return *m_winbutton_theme.get(); }
243
FbRootWindow &rootWindow() { return m_root_window; }
244
const FbRootWindow &rootWindow() const { return m_root_window; }
246
FbTk::MultLayers &layerManager() { return m_layermanager; }
247
const FbTk::MultLayers &layerManager() const { return m_layermanager; }
248
FbTk::ResourceManager &resourceManager() { return m_resource_manager; }
249
const FbTk::ResourceManager &resourceManager() const { return m_resource_manager; }
250
const std::string &name() const { return m_name; }
251
const std::string &altName() const { return m_altname; }
252
bool isShuttingdown() const { return m_shutdown; }
256
int removeLastWorkspace();
258
void nextWorkspace() { nextWorkspace(1); }
259
void prevWorkspace() { prevWorkspace(1); }
260
void nextWorkspace(int delta);
261
void prevWorkspace(int delta);
262
void rightWorkspace(int delta);
263
void leftWorkspace(int delta);
265
void removeWorkspaceNames();
266
void updateWorkspaceNamesAtom();
268
void addWorkspaceName(const char *name);
269
void addNetizen(Window win);
270
void removeNetizen(Window win);
271
void addIcon(FluxboxWindow *win);
272
void removeIcon(FluxboxWindow *win);
274
void removeWindow(FluxboxWindow *win);
275
void removeClient(WinClient &client);
277
std::string getNameOfWorkspace(unsigned int workspace) const;
278
void changeWorkspaceID(unsigned int);
279
void sendToWorkspace(unsigned int workspace, FluxboxWindow *win=0,
280
bool changeworkspace=true);
281
void reassociateWindow(FluxboxWindow *window, unsigned int workspace_id,
283
void prevFocus() { prevFocus(0); }
284
void nextFocus() { nextFocus(0); }
285
void prevFocus(int options);
286
void nextFocus(int options);
288
void setFocusedWindow(WinClient &winclient);
291
void dirFocus(FluxboxWindow &win, const FocusDir dir);
296
/// show position window centered on the screen with "X x Y" text
297
void showPosition(int x, int y);
299
/// show geomentry with "width x height"-text, not size of window
300
void showGeometry(unsigned int width, unsigned int height);
303
void notifyReleasedKeys(XKeyEvent &ke);
305
void setLayer(FbTk::XLayerItem &item, int layernum);
306
// remove? no, items are never removed from their layer until they die
308
/// updates root window size and resizes/reconfigures screen clients
309
/// that depends on screen size (slit)
310
/// (and maximized windows?)
313
// Xinerama-related functions
314
bool hasXinerama() const { return m_xinerama_avail; }
315
int numHeads() const { return m_xinerama_num_heads; }
319
int getHead(int x, int y) const;
320
int getHead(FbTk::FbWindow &win) const;
321
int getCurrHead() const;
322
int getHeadX(int head) const;
323
int getHeadY(int head) const;
324
int getHeadWidth(int head) const;
325
int getHeadHeight(int head) const;
327
// returns the new (x,y) for a rectangle fitted on a head
328
std::pair<int,int> clampToHead(int head, int x, int y, int w, int h) const;
330
// magic to allow us to have "on head" placement (menu) without
331
// the object really knowing about it.
332
template <typename OnHeadObject>
333
int getOnHead(OnHeadObject &obj);
335
template <typename OnHeadObject>
336
void setOnHead(OnHeadObject &obj, int head);
338
// grouping - we want ordering, so we can either search for a
339
// group to the left, or to the right (they'll be different if
341
FluxboxWindow *findGroupLeft(WinClient &winclient);
342
FluxboxWindow *findGroupRight(WinClient &winclient);
345
void updateNetizenCurrentWorkspace();
346
void updateNetizenWorkspaceCount();
347
void updateNetizenWindowFocus();
348
void updateNetizenWindowAdd(Window, unsigned long);
349
void updateNetizenWindowDel(Window);
350
void updateNetizenConfigNotify(XEvent &ev);
351
void updateNetizenWindowRaise(Window);
352
void updateNetizenWindowLower(Window);
354
/// create window frame for client window and attach it
355
FluxboxWindow *createWindow(Window clientwin);
356
FluxboxWindow *createWindow(WinClient &client);
357
void setupWindowActions(FluxboxWindow &win);
358
/// request workspace space, i.e "don't maximize over this area"
359
Strut *requestStrut(int head, int left, int right, int top, int bottom);
360
/// remove requested space and destroy strut
361
void clearStrut(Strut *strut);
362
/// updates max avaible area for the workspace
363
void updateAvailableWorkspaceArea();
365
// for extras to add menus. These menus must be marked
366
// internal for their safety, and __the extension__ must
367
// delete and remove the menu itself (opposite to Window)
368
void addConfigMenu(const char *label, FbTk::Menu &menu);
369
void removeConfigMenu(FbTk::Menu &menu);
373
class ScreenSubject:public FbTk::Subject {
375
ScreenSubject(BScreen &scr):m_scr(scr) { }
376
const BScreen &screen() const { return m_scr; }
377
BScreen &screen() { return m_scr; }
383
void setupConfigmenu(FbTk::Menu &menu);
385
bool doSkipWindow(const WinClient &winclient, int options);
386
void renderGeomWindow();
387
void renderPosWindow();
389
const Strut* availableWorkspaceArea(int head) const;
392
m_clientlist_sig, ///< client signal
393
m_iconlist_sig, ///< notify if a window gets iconified/deiconified
394
m_workspacecount_sig, ///< workspace count signal
395
m_workspacenames_sig, ///< workspace names signal
396
m_workspace_area_sig, ///< workspace area changed signal
397
m_currentworkspace_sig, ///< current workspace signal
398
m_reconfigure_sig, ///< reconfigure signal
399
m_resize_sig; ///< resize signal
401
FbTk::MultLayers m_layermanager;
403
bool root_colormap_installed, managed, geom_visible, pos_visible, cycling_focus;
405
Pixmap geom_pixmap, pos_pixmap;
409
std::auto_ptr<FbTk::ImageControl> m_image_control;
410
std::auto_ptr<FbTk::Menu> m_configmenu, m_rootmenu, m_workspacemenu, m_windowmenu;
412
ExtraMenus m_extramenus;
414
typedef std::list<FbTk::Menu *> Rootmenus;
415
typedef std::list<Netizen *> Netizens;
416
typedef std::list<std::pair<const char *, FbTk::Menu *> > Configmenus;
419
Rootmenus m_rootmenu_list;
420
Netizens m_netizen_list;
421
Configmenus m_configmenu_list;
424
// This list keeps the order of window focusing for this screen
425
// Screen global so it works for sticky windows too.
426
FocusedWindows focused_list;
427
FocusedWindows::iterator cycling_window;
428
WinClient *cycling_last;
430
std::auto_ptr<Slit> m_slit;
432
Workspace *m_current_workspace;
434
WorkspaceNames m_workspace_names;
435
Workspaces m_workspaces_list;
437
std::auto_ptr<FbWinFrameTheme> m_windowtheme;
438
std::auto_ptr<WinButtonTheme> m_winbutton_theme;
439
std::auto_ptr<MenuTheme> m_menutheme;
440
std::auto_ptr<RootTheme> m_root_theme;
442
FbRootWindow m_root_window;
443
FbTk::FbWindow m_geom_window, m_pos_window;
445
struct ScreenResource {
446
ScreenResource(FbTk::ResourceManager &rm, const std::string &scrname,
447
const std::string &altscrname);
449
FbTk::Resource<bool> image_dither, opaque_move, full_max,
450
sloppy_window_grouping, workspace_warping,
451
desktop_wheeling, show_window_pos,
452
focus_last, focus_new,
453
antialias, auto_raise, click_raises, decorate_transient;
454
FbTk::Resource<std::string> rootcommand;
455
FbTk::Resource<ResizeModel> resize_model;
456
FbTk::Resource<std::string> windowmenufile;
457
FbTk::Resource<FocusModel> focus_model;
458
FbTk::Resource<TabFocusModel> tabfocus_model;
459
FbTk::Resource<FollowModel> follow_model;
461
FbTk::Resource<int> workspaces, edge_snap_threshold, focused_alpha,
462
unfocused_alpha, menu_alpha, menu_delay, menu_delay_close;
463
FbTk::Resource<FbTk::MenuTheme::MenuMode> menu_mode;
464
FbTk::Resource<PlacementPolicy> placement_policy;
465
FbTk::Resource<RowDirection> row_direction;
466
FbTk::Resource<ColumnDirection> col_direction;
467
FbTk::Resource<int> gc_line_width;
468
FbTk::Resource<FbTk::GContext::LineStyle> gc_line_style;
469
FbTk::Resource<FbTk::GContext::JoinStyle> gc_join_style;
470
FbTk::Resource<FbTk::GContext::CapStyle> gc_cap_style;
471
FbTk::Resource<std::string> scroll_action;
472
FbTk::Resource<bool> scroll_reverse;
476
// This is a map of windows to clients for clients that had a left
477
// window set, but that window wasn't present at the time
478
typedef std::map<Window, WinClient *> Groupables;
479
Groupables m_expecting_groups;
481
const std::string m_name, m_altname;
482
FbTk::ResourceManager &m_resource_manager;
484
// Xinerama related private data
485
bool m_xinerama_avail;
486
int m_xinerama_num_heads;
487
int m_xinerama_center_x, m_xinerama_center_y;
489
HeadArea *m_head_areas;
491
struct XineramaHeadInfo {
492
int x, y, width, height;
493
} *m_xinerama_headinfo;