1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- 2 // Window.hh for Blackbox - an X11 Window manager 3 // Copyright (c) 2001 - 2005 Sean 'Shaleh' Perry <shaleh@debian.org> 4 // Copyright (c) 1997 - 2000, 2002 - 2005 5 // Bradley T Hughes <bhughes at trolltech.com> 6 // 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: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 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. 24 25 #ifndef __Window_hh 26 #define __Window_hh 27 28 #include "BlackboxResource.hh" 29 #include "Screen.hh" 30 31 #include <EWMH.hh> 32 33 34 enum WindowType { 35 WindowTypeNormal, 36 WindowTypeDialog, 37 WindowTypeDesktop, 38 WindowTypeDock, 39 WindowTypeMenu, 40 WindowTypeSplash, 41 WindowTypeToolbar, 42 WindowTypeUtility 43 }; 44 45 enum WindowFunction { 46 WindowFunctionResize = 1<<0, 47 WindowFunctionMove = 1<<1, 48 WindowFunctionShade = 1<<2, 49 WindowFunctionIconify = 1<<3, 50 WindowFunctionMaximize = 1<<4, 51 WindowFunctionClose = 1<<5, 52 WindowFunctionChangeWorkspace = 1<<6, 53 WindowFunctionChangeLayer = 1<<7, 54 WindowFunctionFullScreen = 1<<8, 55 NoWindowFunctions = 0, 56 AllWindowFunctions = (WindowFunctionResize | 57 WindowFunctionMove | 58 WindowFunctionShade | 59 WindowFunctionIconify | 60 WindowFunctionMaximize | 61 WindowFunctionClose | 62 WindowFunctionChangeWorkspace | 63 WindowFunctionChangeLayer | 64 WindowFunctionFullScreen) 65 }; 66 typedef unsigned short WindowFunctionFlags; 67 68 enum WindowDecoration { 69 WindowDecorationTitlebar = 1<<0, 70 WindowDecorationHandle = 1<<1, 71 WindowDecorationGrip = 1<<2, 72 WindowDecorationBorder = 1<<3, 73 WindowDecorationIconify = 1<<4, 74 WindowDecorationMaximize = 1<<5, 75 WindowDecorationClose = 1<<6, 76 NoWindowDecorations = 0, 77 AllWindowDecorations = (WindowDecorationTitlebar | 78 WindowDecorationHandle | 79 WindowDecorationGrip | 80 WindowDecorationBorder | 81 WindowDecorationIconify | 82 WindowDecorationMaximize | 83 WindowDecorationClose) 84 }; 85 typedef unsigned char WindowDecorationFlags; 86 87 struct EWMH { 88 WindowType window_type; 89 unsigned int workspace; 90 unsigned int modal : 1; 91 unsigned int maxv : 1; 92 unsigned int maxh : 1; 93 unsigned int shaded : 1; 94 unsigned int skip_taskbar : 1; 95 unsigned int skip_pager : 1; 96 unsigned int hidden : 1; 97 unsigned int fullscreen : 1; 98 unsigned int above : 1; 99 unsigned int below : 1; 100 }; 101 struct MotifHints { 102 WindowDecorationFlags decorations; 103 WindowFunctionFlags functions; 104 }; 105 struct WMHints { 106 bool accept_focus; 107 Window window_group; 108 unsigned long initial_state; 109 }; 110 struct WMNormalHints { 111 long flags; 112 unsigned int min_width, min_height; 113 unsigned int max_width, max_height; 114 unsigned int width_inc, height_inc; 115 unsigned int min_aspect_x, min_aspect_y; 116 unsigned int max_aspect_x, max_aspect_y; 117 unsigned int base_width, base_height; 118 unsigned int win_gravity; 119 }; 120 struct WMProtocols { 121 unsigned int wm_delete_window : 1; 122 unsigned int wm_take_focus : 1; 123 }; 124 125 126 class BlackboxWindow : public StackEntity, public bt::TimeoutHandler, 127 public bt::EventHandler, public bt::NoCopy { 128 Blackbox *blackbox; 129 BScreen *_screen; 130 bt::Timer *timer; 131 132 Time lastButtonPressTime; // used for double clicks, when were we clicked 133 134 unsigned int window_number; 135 136 struct ClientState { 137 unsigned int visible : 1; // is visible? 138 unsigned int iconic : 1; // is iconified? 139 unsigned int moving : 1; // is moving? 140 unsigned int resizing : 1; // is resizing? 141 unsigned int focused : 1; // has focus? 142 unsigned int shaped : 1; // does the frame use the shape extension? 143 }; 144 145 struct _client { 146 Window window; // the client's window 147 Colormap colormap; 148 Window transient_for; // which window are we a transient for? 149 BlackboxWindowList transientList; // which windows are our transients? 150 151 bt::ustring title, visible_title, icon_title; 152 153 bt::Rect rect, premax; 154 155 int old_bw; // client's borderwidth 156 157 unsigned long current_state; 158 159 bt::EWMH::Strut *strut; 160 161 WindowFunctionFlags functions; 162 WindowDecorationFlags decorations; 163 164 ClientState state; 165 166 EWMH ewmh; 167 MotifHints motif; 168 WMHints wmhints; 169 WMNormalHints wmnormal; 170 WMProtocols wmprotocols; 171 } client; 172 173 /* 174 * client window = the application's window 175 * frame window = the window drawn around the outside of the client window 176 * by the window manager which contains items like the 177 * titlebar and close button 178 * title = the titlebar drawn above the client window, it displays the 179 * window's name and any buttons for interacting with the window, 180 * such as iconify, maximize, and close 181 * label = the window in the titlebar where the title is drawn 182 * buttons = maximize, iconify, close 183 * handle = the bar drawn at the bottom of the window, which contains the 184 * left and right grips used for resizing the window 185 * grips = the smaller reactangles in the handle, one of each side of it. 186 * When clicked and dragged, these resize the window interactively 187 * border = the line drawn around the outside edge of the frame window, 188 * between the title, the bordered client window, and the handle. 189 * Also drawn between the grips and the handle 190 */ 191 192 struct _frame { 193 // u -> unfocused, f -> has focus 194 Pixmap ulabel, flabel, utitle, ftitle, uhandle, fhandle, 195 ubutton, fbutton, pbutton, ugrip, fgrip; 196 197 Window window, // the frame 198 plate, // holds the client 199 title, 200 label, 201 handle, 202 close_button, iconify_button, maximize_button, 203 right_grip, left_grip; 204 205 // frame geometry 206 bt::Rect rect; 207 208 // used during move/resize 209 bt::Rect changing; 210 int corner; 211 212 /* 213 * margins between the frame and client, this has nothing to do 214 * with EWMH, it is simply code reuse for similar functionality 215 */ 216 bt::EWMH::Strut margin; 217 int grab_x, grab_y; // where was the window when it was grabbed? 218 219 unsigned int label_w; // width of the label 220 } frame; 221 222 Window createToplevelWindow(); 223 Window createChildWindow(Window parent, unsigned long event_mask, 224 Cursor = None); 225 226 void associateClientWindow(void); 227 228 void decorate(void); 229 230 void positionButtons(bool redecorate_label = false); 231 void positionWindows(void); 232 233 void createTitlebar(void); 234 void destroyTitlebar(void); 235 void createHandle(void); 236 void destroyHandle(void); 237 void createGrips(void); 238 void destroyGrips(void); 239 void createIconifyButton(void); 240 void destroyIconifyButton(void); 241 void createMaximizeButton(void); 242 void destroyMaximizeButton(void); 243 void createCloseButton(void); 244 void destroyCloseButton(void); 245 246 void redrawWindowFrame(void) const; 247 void redrawTitle(void) const; 248 void redrawLabel(void) const; 249 void redrawAllButtons(void) const; 250 void redrawCloseButton(bool pressed = false) const; 251 void redrawIconifyButton(bool pressed = false) const; 252 void redrawMaximizeButton(bool pressed = false) const; 253 void redrawHandle(void) const; 254 void redrawGrips(void) const; 255 256 void setState(unsigned long new_state); 257 void updateEWMHState(); 258 void updateEWMHAllowedActions(); 259 260 void startMove(); 261 void snapAdjust(int *x, int *y); 262 void continueMove(int x_root, int y_root); 263 void finishMove(); 264 265 void startResize(Window window); 266 void continueResize(int x_root, int y_root); 267 void finishResize(); 268 269 void showGeometry(const bt::Rect &r) const; 270 271 public: 272 BlackboxWindow(Blackbox *b, Window w, BScreen *s); 273 virtual ~BlackboxWindow(void); 274 isTransient(void) const275 inline bool isTransient(void) const 276 { return client.transient_for != 0; } isGroupTransient(void) const277 inline bool isGroupTransient(void) const 278 { return (client.transient_for != 0 279 && client.transient_for == client.wmhints.window_group); } isModal(void) const280 inline bool isModal(void) const 281 { return client.ewmh.modal; } 282 windowType(void) const283 inline WindowType windowType(void) const 284 { return client.ewmh.window_type; } 285 hasWindowFunction(WindowFunction function) const286 inline bool hasWindowFunction(WindowFunction function) const 287 { return client.functions & function; } hasWindowDecoration(WindowDecoration decoration) const288 inline bool hasWindowDecoration(WindowDecoration decoration) const 289 { return client.decorations & decoration; } 290 291 // ordered newest to oldest transients(void) const292 inline const BlackboxWindowList &transients(void) const 293 { return client.transientList; } 294 295 void addTransient(BlackboxWindow *win); 296 void removeTransient(BlackboxWindow *win); 297 298 BlackboxWindow *findTransientFor(void) const; 299 BlackboxWindow *findNonTransientParent(void) const; 300 BlackboxWindowList buildFullTransientList(void) const; 301 302 BWindowGroup *findWindowGroup(void) const; 303 screen(void) const304 inline BScreen *screen(void) const 305 { return _screen; } 306 307 // StackEntity interface windowID(void) const308 inline Window windowID(void) const 309 { return frame.window; } 310 frameWindow(void) const311 inline Window frameWindow(void) const 312 { return frame.window; } clientWindow(void) const313 inline Window clientWindow(void) const 314 { return client.window; } 315 title(void) const316 inline const bt::ustring &title(void) const 317 { return client.title; } iconTitle(void) const318 inline const bt::ustring &iconTitle(void) const 319 { return client.icon_title.empty() ? client.title : client.icon_title; } 320 workspace(void) const321 inline unsigned int workspace(void) const 322 { return client.ewmh.workspace; } 323 void setWorkspace(unsigned int new_workspace); 324 325 enum ChangeWorkspaceOption { 326 StayOnCurrentWorkspace, 327 SwitchToNewWorkspace 328 }; 329 void changeWorkspace(unsigned int new_workspace, 330 ChangeWorkspaceOption how = StayOnCurrentWorkspace); 331 332 void changeLayer(StackingList::Layer new_layer); 333 windowNumber(void) const334 inline unsigned int windowNumber(void) const 335 { return window_number; } setWindowNumber(int n)336 inline void setWindowNumber(int n) 337 { window_number = n; } 338 frameRect(void) const339 inline const bt::Rect &frameRect(void) const 340 { return frame.rect; } clientRect(void) const341 inline const bt::Rect &clientRect(void) const 342 { return client.rect; } 343 wmHints(void) const344 const WMHints &wmHints(void) const 345 { return client.wmhints; } wmNormalHints(void) const346 const WMNormalHints &wmNormalHints(void) const 347 { return client.wmnormal; } wmProtocols(void) const348 const WMProtocols &wmProtocols(void) const 349 { return client.wmprotocols; } 350 currentState(void) const351 unsigned long currentState(void) const 352 { return client.current_state; } 353 isFocused(void) const354 inline bool isFocused(void) const 355 { return client.state.focused; } 356 void setFocused(bool focused); 357 bool setInputFocus(void); 358 isVisible(void) const359 inline bool isVisible(void) const 360 { return client.state.visible; } 361 void show(void); 362 void hide(void); 363 void close(void); 364 void activate(void); 365 isShaded(void) const366 inline bool isShaded(void) const 367 { return client.ewmh.shaded; } 368 void setShaded(bool shaded); 369 isIconic(void) const370 inline bool isIconic(void) const 371 { return client.state.iconic; } 372 void iconify(void); // call show() to deiconify 373 isMaximized(void) const374 inline bool isMaximized(void) const 375 { return client.ewmh.maxh || client.ewmh.maxv; } 376 // ### change to setMaximized()? 377 void maximize(unsigned int button); 378 void remaximize(void); 379 isFullScreen(void) const380 inline bool isFullScreen(void) const 381 { return client.ewmh.fullscreen; } 382 void setFullScreen(bool b); 383 384 void reconfigure(void); 385 void grabButtons(void); 386 void ungrabButtons(void); 387 void restore(void); 388 void configure(int dx, int dy, unsigned int dw, unsigned int dh); configure(const bt::Rect & r)389 inline void configure(const bt::Rect &r) 390 { configure(r.x(), r.y(), r.width(), r.height()); } 391 392 void clientMessageEvent(const XClientMessageEvent * const ce); 393 void buttonPressEvent(const XButtonEvent * const be); 394 void buttonReleaseEvent(const XButtonEvent * const re); 395 void motionNotifyEvent(const XMotionEvent * const me); 396 void destroyNotifyEvent(const XDestroyWindowEvent * const /*unused*/); 397 void unmapNotifyEvent(const XUnmapEvent * const /*unused*/); 398 void reparentNotifyEvent(const XReparentEvent * const /*unused*/); 399 void propertyNotifyEvent(const XPropertyEvent * const pe); 400 void exposeEvent(const XExposeEvent * const ee); 401 void configureRequestEvent(const XConfigureRequestEvent * const cr); 402 void enterNotifyEvent(const XCrossingEvent * const ce); 403 void leaveNotifyEvent(const XCrossingEvent * const /*unused*/); 404 405 #ifdef SHAPE 406 void configureShape(void); 407 void shapeEvent(const XEvent * const /*unused*/); 408 #endif // SHAPE 409 410 virtual void timeout(bt::Timer *); 411 }; 412 413 #endif // __Window_hh 414