diff options
Diffstat (limited to 'src/Window.cc')
| -rw-r--r-- | src/Window.cc | 116 |
1 files changed, 82 insertions, 34 deletions
diff --git a/src/Window.cc b/src/Window.cc index 417e15ac..9e3d9f5e 100644 --- a/src/Window.cc +++ b/src/Window.cc @@ -68,9 +68,11 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { fprintf(stderr, "BlackboxWindow::BlackboxWindow(): creating 0x%lx\n", w); #endif // DEBUG - // set timer to zero... it is initialized properly later, so we check - // if timer is zero in the destructor, and assume that the window is not - // fully constructed if timer is zero... + /* + set timer to zero... it is initialized properly later, so we check + if timer is zero in the destructor, and assume that the window is not + fully constructed if timer is zero... + */ timer = 0; blackbox = b; client.window = w; @@ -139,9 +141,11 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { client.wm_hint_flags = client.normal_hint_flags = 0; client.transient_for = 0; - // get the initial size and location of client window (relative to the - // _root window_). This position is the reference point used with the - // window's gravity to find the window's initial position. + /* + get the initial size and location of client window (relative to the + _root window_). This position is the reference point used with the + window's gravity to find the window's initial position. + */ client.rect.setRect(wattrib.x, wattrib.y, wattrib.width, wattrib.height); client.old_bw = wattrib.border_width; @@ -254,15 +258,48 @@ BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) { frame.rect.width(), frame.rect.height()); } + // preserve the window's initial state on first map, and its current state + // across a restart + if (! getState()) { + if (client.wm_hint_flags & StateHint) + current_state = client.initial_state; + else + current_state = NormalState; + } + if (flags.shaded) { flags.shaded = False; shade(); + + /* + Because the iconic'ness of shaded windows is lost, we need to set the + state to NormalState so that shaded windows on other workspaces will not + get shown on the first workspace. + At this point in the life of a window, current_state should only be set + to IconicState if the window was an *icon*, not if it was shaded. + */ + current_state = NormalState; + } + + if (flags.stuck) { + flags.stuck = False; + stick(); } if (flags.maximized && (functions & Func_Maximize)) { remaximize(); } + /* + When the window is mapped (and also when its attributes are restored), the + current_state that was set here will be used. + It is set to Normal if the window is to be mapped or it is set to Iconic + if the window is to be iconified. + *Note* that for sticky windows, the same rules apply here, they are in + fact never set to Iconic since there is no way for us to tell if a sticky + window was iconified previously. + */ + setFocusFlag(False); } @@ -1309,6 +1346,16 @@ void BlackboxWindow::configureShape(void) { bool BlackboxWindow::setInputFocus(void) { if (flags.focused) return True; + assert(! flags.iconic); + + // if the window is not visible, mark the window as wanting focus rather + // than give it focus. + if (! flags.visible) { + Workspace *wkspc = screen->getWorkspace(blackbox_attrib.workspace); + wkspc->setLastFocusedWindow(this); + return True; + } + if (! client.rect.intersects(screen->getRect())) { // client is outside the screen, move it to the center configure((screen->getWidth() - frame.rect.width()) / 2, @@ -1406,7 +1453,8 @@ void BlackboxWindow::iconify(void) { void BlackboxWindow::show(void) { - setState(NormalState); + current_state = (flags.shaded) ? IconicState : NormalState; + setState(current_state); XMapWindow(blackbox->getXDisplay(), client.window); XMapSubwindows(blackbox->getXDisplay(), frame.window); @@ -1463,11 +1511,13 @@ void BlackboxWindow::withdraw(void) { XUnmapWindow(blackbox->getXDisplay(), frame.window); XGrabServer(blackbox->getXDisplay()); + XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask); XUnmapWindow(blackbox->getXDisplay(), client.window); XSelectInput(blackbox->getXDisplay(), client.window, PropertyChangeMask | FocusChangeMask | StructureNotifyMask); - XUngrabServer(blackbox->getXDisplay()); + + XUngrabServer(blackbox->getXDisplay()); if (windowmenu) windowmenu->hide(); } @@ -1631,6 +1681,10 @@ void BlackboxWindow::stick(void) { void BlackboxWindow::setFocusFlag(bool focus) { + // only focus a window if it is visible + if (focus && !flags.visible) + return; + flags.focused = focus; if (decorations & Decor_Titlebar) { @@ -1785,8 +1839,6 @@ bool BlackboxWindow::getState(void) { void BlackboxWindow::restoreAttributes(void) { - if (! getState()) current_state = NormalState; - Atom atom_return; int foo; unsigned long ulfoo, nitems; @@ -1801,36 +1853,42 @@ void BlackboxWindow::restoreAttributes(void) { if (ret != Success || ! net || nitems != PropBlackboxAttributesElements) return; - if (net->flags & AttribShaded && - net->attrib & AttribShaded) { - int save_state = - ((current_state == IconicState) ? NormalState : current_state); - + if (net->flags & AttribShaded && net->attrib & AttribShaded) { flags.shaded = False; shade(); - current_state = save_state; - } + /* + Because the iconic'ness of shaded windows is lost, we need to set the + state to NormalState so that shaded windows on other workspaces will not + get shown on the first workspace. + At this point in the life of a window, current_state should only be set + to IconicState if the window was an *icon*, not if it was shaded. + */ + current_state = NormalState; + } if ((net->workspace != screen->getCurrentWorkspaceID()) && (net->workspace < screen->getWorkspaceCount())) { screen->reassociateWindow(this, net->workspace, True); + // set to WithdrawnState so it will be mapped on the new workspace if (current_state == NormalState) current_state = WithdrawnState; } else if (current_state == WithdrawnState) { + // the window is on this workspace and is Withdrawn, so it is waiting to + // be mapped current_state = NormalState; } - if (net->flags & AttribOmnipresent && - net->attrib & AttribOmnipresent) { + if (net->flags & AttribOmnipresent && net->attrib & AttribOmnipresent) { flags.stuck = False; stick(); - current_state = NormalState; + // if the window was on another workspace, it was going to be hidden. this + // specifies that the window should be mapped since it is sticky. + if (current_state == WithdrawnState) current_state = NormalState; } - if ((net->flags & AttribMaxHoriz) || - (net->flags & AttribMaxVert)) { + if (net->flags & AttribMaxHoriz || net->flags & AttribMaxVert) { int x = net->premax_x, y = net->premax_y; unsigned int w = net->premax_w, h = net->premax_h; flags.maximized = 0; @@ -1852,7 +1910,8 @@ void BlackboxWindow::restoreAttributes(void) { blackbox_attrib.premax_h = h; } - setState(current_state); + // with the state set it will then be the map events job to read the window's + // state and behave accordingly XFree((void *) net); } @@ -2091,17 +2150,6 @@ void BlackboxWindow::mapRequestEvent(XMapRequestEvent *re) { client.window); #endif // DEBUG - bool get_state_ret = getState(); - if (! (get_state_ret && blackbox->isStartup())) { - if ((client.wm_hint_flags & StateHint) && - (! (current_state == NormalState || current_state == IconicState))) - current_state = client.initial_state; - else - current_state = NormalState; - } else if (flags.iconic) { - current_state = NormalState; - } - switch (current_state) { case IconicState: iconify(); |
