all repos — openbox @ 1766453ca2ce30adf84798cb504e8b4d258bd08f

openbox fork - make it a bit more like ryudo

sync with blackbox-cvs
Dana Jansens danakj@orodu.net
commit

1766453ca2ce30adf84798cb504e8b4d258bd08f

parent

8941da8e41d15ae6729c04b2933d74869c25e857

M src/BaseDisplay.ccsrc/BaseDisplay.cc

@@ -411,43 +411,55 @@ basedisplay = d;

screen_number = num; root_window = RootWindow(basedisplay->getXDisplay(), screen_number); - depth = DefaultDepth(basedisplay->getXDisplay(), screen_number); rect.setSize(WidthOfScreen(ScreenOfDisplay(basedisplay->getXDisplay(), screen_number)), HeightOfScreen(ScreenOfDisplay(basedisplay->getXDisplay(), screen_number))); + /* + If the default depth is at least 15 we will use that, + otherwise we try to find the largest TrueColor visual. + Preference is given to 24 bit over larger depths if 24 bit is an option. + */ - // search for a TrueColor Visual... if we can't find one... we will use the - // default visual for the screen - XVisualInfo vinfo_template, *vinfo_return; - int vinfo_nitems; + depth = DefaultDepth(basedisplay->getXDisplay(), screen_number); + visual = DefaultVisual(basedisplay->getXDisplay(), screen_number); + colormap = DefaultColormap(basedisplay->getXDisplay(), screen_number); + + if (depth < 15) { + // search for a TrueColor Visual... if we can't find one... + // we will use the default visual for the screen + XVisualInfo vinfo_template, *vinfo_return; + int vinfo_nitems; + int best = -1; - vinfo_template.screen = screen_number; - vinfo_template.c_class = TrueColor; + vinfo_template.screen = screen_number; + vinfo_template.c_class = TrueColor; - visual = (Visual *) 0; - - vinfo_return = XGetVisualInfo(basedisplay->getXDisplay(), - VisualScreenMask | VisualClassMask, - &vinfo_template, &vinfo_nitems); - if (vinfo_return && vinfo_nitems > 0) { - for (int i = 0; i < vinfo_nitems; i++) { - if (depth < (vinfo_return + i)->depth) { - depth = (vinfo_return + i)->depth; - visual = (vinfo_return + i)->visual; + vinfo_return = XGetVisualInfo(basedisplay->getXDisplay(), + VisualScreenMask | VisualClassMask, + &vinfo_template, &vinfo_nitems); + if (vinfo_return) { + int max_depth = 1; + for (int i = 0; i < vinfo_nitems; ++i) { + if (vinfo_return[i].depth > max_depth) { + if (max_depth == 24 && vinfo_return[i].depth > 24) + break; // prefer 24 bit over 32 + max_depth = vinfo_return[i].depth; + best = i; + } } + if (max_depth < depth) best = -1; + } + + if (best != -1) { + depth = vinfo_return[best].depth; + visual = vinfo_return[best].visual; + colormap = XCreateColormap(basedisplay->getXDisplay(), root_window, + visual, AllocNone); } XFree(vinfo_return); - } - - if (visual) { - colormap = XCreateColormap(basedisplay->getXDisplay(), root_window, - visual, AllocNone); - } else { - visual = DefaultVisual(basedisplay->getXDisplay(), screen_number); - colormap = DefaultColormap(basedisplay->getXDisplay(), screen_number); } // get the default display string and strip the screen number
M src/Basemenu.ccsrc/Basemenu.cc

@@ -201,14 +201,11 @@ XDestroyWindow(display, menu.window);

} -BasemenuItem::~BasemenuItem(void) {} - - BasemenuItem *Basemenu::find(int index) { - if (index < 0 || index > static_cast<signed>(menuitems.size())) + if (index < 0 || index >= static_cast<signed>(menuitems.size())) return (BasemenuItem*) 0; - return *(menuitems.begin() + index); + return menuitems[index]; }

@@ -593,8 +590,7 @@ }

void Basemenu::drawItem(int index, bool highlight, bool clear, - int x, int y, unsigned int w, unsigned int h) -{ + int x, int y, unsigned int w, unsigned int h) { BasemenuItem *item = find(index); if (! item) return;
M src/Basemenu.hhsrc/Basemenu.hh

@@ -163,8 +163,6 @@ BasemenuItem(const std::string& lp, Basemenu *mp): sub(mp), l(lp),

f(0), enabled(1), selected(0) {} - ~BasemenuItem(void); - inline const char *exec(void) const { return e.c_str(); } inline const char *label(void) const { return l.c_str(); } inline int function(void) const { return f; }
M src/Screen.ccsrc/Screen.cc

@@ -245,6 +245,8 @@ XAtom::cardinal, 0); //first workspace

workspacemenu->setItemSelected(2, True); + removeWorkspaceNames(); // do not need them any longer + toolbar = new Toolbar(this); slit = new Slit(this);

@@ -593,7 +595,6 @@ resource.col_direction = BottomTop;

else resource.col_direction = TopBottom; - removeWorkspaceNames(); if (config->getValue(screenstr + "workspaceNames", s)) { string::const_iterator it = s.begin(), end = s.end(); while(1) {

@@ -1060,10 +1061,6 @@ void BScreen::changeWorkspaceID(unsigned int id) {

if (! current_workspace) return; if (id != current_workspace->getID()) { - current_workspace->hideAll(); - - workspacemenu->setItemSelected(current_workspace->getID() + 2, False); - BlackboxWindow *focused = blackbox->getFocusedWindow(); if (focused && focused->getScreen() == this && ! focused->isStuck()) { if (focused->getWorkspaceNumber() != current_workspace->getID()) {

@@ -1072,8 +1069,15 @@ focused->getTitle());

abort(); } current_workspace->setLastFocusedWindow(focused); - blackbox->setFocusedWindow((BlackboxWindow *) 0); + } else { + // if no window had focus, no need to store a last focus + current_workspace->setLastFocusedWindow((BlackboxWindow *) 0); } + // when we switch workspaces, unfocus whatever was focused + blackbox->setFocusedWindow((BlackboxWindow *) 0); + + current_workspace->hideAll(); + workspacemenu->setItemSelected(current_workspace->getID() + 2, False); current_workspace = getWorkspace(id);

@@ -1229,7 +1233,7 @@ }

void BScreen::raiseWindows(Window *workspace_stack, unsigned int num) { - // XXX: why 13?? + // the 13 represents the number of blackbox windows such as menus Window *session_stack = new Window[(num + workspacesList.size() + rootmenuList.size() + 13)]; unsigned int i = 0, k = num;
M src/Slit.ccsrc/Slit.cc

@@ -433,25 +433,29 @@ void Slit::updateStrut(void) {

strut.top = strut.bottom = strut.left = strut.right = 0; if (! clientList.empty()) { + // when not hidden both borders are in use, when hidden only one is + unsigned int border_width = screen->getBorderWidth(); + if (! do_auto_hide) + border_width *= 2; + switch (direction) { case Vertical: switch (placement) { case TopCenter: - strut.top = getY() + getExposedHeight() + - (screen->getBorderWidth() * 2); + strut.top = getExposedHeight() + border_width; break; case BottomCenter: - strut.bottom = screen->getHeight() - getY(); + strut.bottom = getExposedHeight() + border_width; break; case TopLeft: case CenterLeft: case BottomLeft: - strut.left = getExposedWidth() + (screen->getBorderWidth() * 2); + strut.left = getExposedWidth() + border_width; break; case TopRight: case CenterRight: case BottomRight: - strut.right = getExposedWidth() + (screen->getBorderWidth() * 2); + strut.right = getExposedWidth() + border_width; break; } break;

@@ -460,19 +464,18 @@ switch (placement) {

case TopCenter: case TopLeft: case TopRight: - strut.top = getY() + getExposedHeight() + - (screen->getBorderWidth() * 2); + strut.top = getExposedHeight() + border_width; break; case BottomCenter: case BottomLeft: case BottomRight: - strut.bottom = screen->getHeight() - getY(); + strut.bottom = getExposedHeight() + border_width; break; case CenterLeft: - strut.left = getExposedWidth() + (screen->getBorderWidth() * 2); + strut.left = getExposedWidth() + border_width; break; case CenterRight: - strut.right = getExposedWidth() + (screen->getBorderWidth() * 2); + strut.right = getExposedWidth() + border_width; break; } break;
M src/Toolbar.ccsrc/Toolbar.cc

@@ -528,15 +528,20 @@ void Toolbar::updateStrut(void) {

// left and right are always 0 strut.top = strut.bottom = 0; + // when hidden only one border is visible + unsigned int border_width = screen->getBorderWidth(); + if (! do_auto_hide) + border_width *= 2; + if (! screen->doHideToolbar()) { switch(placement) { case TopLeft: case TopCenter: case TopRight: - strut.top = getExposedHeight() + (screen->getBorderWidth() * 2); + strut.top = getExposedHeight() + border_width; break; default: - strut.bottom = getExposedHeight() + (screen->getBorderWidth() * 2); + strut.bottom = getExposedHeight() + border_width; } }
M src/Window.ccsrc/Window.cc

@@ -68,9 +68,11 @@ #ifdef DEBUG

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 @@

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;

@@ -252,16 +256,49 @@ // don't need to call configure if we are letting the workspace

// place the window configure(frame.rect.x(), frame.rect.y(), 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 @@

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::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 @@

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::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 @@ }

void BlackboxWindow::restoreAttributes(void) { - if (! getState()) current_state = NormalState; - Atom atom_return; int foo; unsigned long ulfoo, nitems;

@@ -1801,36 +1853,42 @@ (unsigned char **) &net);

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 @@ blackbox_attrib.premax_w = w;

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); }

@@ -2090,17 +2149,6 @@ #ifdef DEBUG

fprintf(stderr, "BlackboxWindow::mapRequestEvent() for 0x%lx\n", 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:
M src/Workspace.ccsrc/Workspace.cc

@@ -97,18 +97,39 @@ assert(w != 0);

stackingList.remove(w); - if (w->isFocused() && ! screen->getBlackbox()->doShutdown()) { + // pass focus to the next appropriate window + if ((w->isFocused() || w == lastfocus) && + ! screen->getBlackbox()->doShutdown()) { BlackboxWindow *newfocus = 0; if (w->isTransient()) newfocus = w->getTransientFor(); if (! newfocus && ! stackingList.empty()) newfocus = stackingList.front(); - if (! newfocus || ! newfocus->setInputFocus()) - screen->getBlackbox()->setFocusedWindow(0); + + assert(newfocus != w); // this would be very wrong. + + if (id == screen->getCurrentWorkspaceID()) { + /* + if the window is on the visible workspace, then try focus it, and fall + back to the default focus target if the window won't focus. + */ + if (! newfocus || ! newfocus->setInputFocus()) + screen->getBlackbox()->setFocusedWindow(0); + } else if (lastfocus == w) { + /* + If this workspace is not the current one do not assume that + w == lastfocus. If a sticky window is removed on a workspace other + than where it originated, it will fire the removeWindow on a + non-visible workspace. + */ + + /* + If the window isn't on the visible workspace, don't focus the new one, + just mark it to be focused when the workspace comes into view. + */ + setLastFocusedWindow(newfocus); + } } - - if (lastfocus == w) - lastfocus = (BlackboxWindow *) 0; windowList.remove(w); clientmenu->remove(w->getWindowNumber());