# include <stdio.h>
# endif // HAVE_STDIO_H
#endif // DEBUG
-}
-#include <cstdlib>
+#ifdef HAVE_STDLIB_H
+ #include <stdlib.h>
+#endif // HAVE_STDLIB_H
+}
#include "i18n.hh"
#include "blackbox.hh"
#include "Window.hh"
#include "Windowmenu.hh"
#include "Workspace.hh"
-#include "Slit.hh"
using std::string;
+using std::abs;
// change this to change what modifier keys openbox uses for mouse bindings
// for example: Mod1Mask | ControlMask
return;
}
- // set the eventmask early in the game so that we make sure we get
- // all the events we are interested in
- XSetWindowAttributes attrib_set;
- attrib_set.event_mask = PropertyChangeMask | FocusChangeMask |
- StructureNotifyMask;
- attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask |
- ButtonMotionMask;
- XChangeWindowAttributes(blackbox->getXDisplay(), client.window,
- CWEventMask|CWDontPropagate, &attrib_set);
-
// fetch client size and placement
XWindowAttributes wattrib;
- if ((! XGetWindowAttributes(blackbox->getXDisplay(),
- client.window, &wattrib)) ||
- (! wattrib.screen) || wattrib.override_redirect) {
+ if (! XGetWindowAttributes(blackbox->getXDisplay(),
+ client.window, &wattrib) ||
+ ! wattrib.screen || wattrib.override_redirect) {
#ifdef DEBUG
fprintf(stderr,
"BlackboxWindow::BlackboxWindow(): XGetWindowAttributes failed\n");
return;
}
+ // set the eventmask early in the game so that we make sure we get
+ // all the events we are interested in
+ XSetWindowAttributes attrib_set;
+ attrib_set.event_mask = PropertyChangeMask | FocusChangeMask |
+ StructureNotifyMask;
+ attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask |
+ ButtonMotionMask;
+ XChangeWindowAttributes(blackbox->getXDisplay(), client.window,
+ CWEventMask|CWDontPropagate, &attrib_set);
+
flags.moving = flags.resizing = flags.shaded = flags.visible =
flags.iconic = flags.focused = flags.stuck = flags.modal =
flags.send_focus_message = flags.shaped = flags.skip_taskbar =
Decor_Iconify | Decor_Maximize;
functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize;
- client.wm_hint_flags = client.normal_hint_flags = 0;
+ client.normal_hint_flags = 0;
client.window_group = None;
client.transient_for = 0;
+ current_state = NormalState;
+
/*
get the initial size and location of client window (relative to the
_root window_). This position is the reference point used with the
client.rect.setRect(wattrib.x, wattrib.y, wattrib.width, wattrib.height);
client.old_bw = wattrib.border_width;
- windowmenu = 0;
lastButtonPressTime = 0;
timer = new BTimer(blackbox, this);
timer->setTimeout(blackbox->getAutoRaiseDelay());
+ windowmenu = new Windowmenu(this);
+
+ // get size, aspect, minimum/maximum size and other hints set by the
+ // client
+
if (! getBlackboxHints()) {
getMWMHints();
getNetWMHints();
}
- // get size, aspect, minimum/maximum size and other hints set by the
- // client
getWMProtocols();
getWMHints();
getWMNormalHints();
- if (client.initial_state == WithdrawnState) {
- screen->getSlit()->addClient(client.window);
- delete this;
- return;
- }
-
frame.window = createToplevelWindow();
- frame.plate = createChildWindow(frame.window);
- associateClientWindow();
blackbox->saveWindowSearch(frame.window, this);
+
+ frame.plate = createChildWindow(frame.window);
blackbox->saveWindowSearch(frame.plate, this);
- blackbox->saveWindowSearch(client.window, this);
// determine if this is a transient window
getTransientInfo();
getWindowType();
// adjust the window decorations/behavior based on the window type
+
switch (window_type) {
case Type_Desktop:
case Type_Dock:
// normal windows retain all of the possible decorations and functionality
break;
}
+
+ setAllowedActions();
// further adjeust the window's decorations/behavior based on window sizes
if ((client.normal_hint_flags & PMinSize) &&
decorations &= ~(Decor_Maximize | Decor_Handle);
functions &= ~(Func_Resize | Func_Maximize);
}
- upsize();
+
+ if (decorations & Decor_Titlebar)
+ createTitlebar();
- setAllowedActions();
+ if (decorations & Decor_Handle)
+ createHandle();
+
+ // apply the size and gravity hint to the frame
+
+ upsize();
bool place_window = True;
if (blackbox->isStartup() || isTransient() ||
screen->addStrut(&client.strut);
updateStrut();
- if (decorations & Decor_Titlebar)
- createTitlebar();
-
- if (decorations & Decor_Handle)
- createHandle();
-
#ifdef SHAPE
- if (blackbox->hasShapeExtensions() && flags.shaped) {
+ if (blackbox->hasShapeExtensions() && flags.shaped)
configureShape();
- }
#endif // SHAPE
- windowmenu = new Windowmenu(this);
-
if (blackbox_attrib.workspace >= screen->getWorkspaceCount())
screen->getCurrentWorkspace()->addWindow(this, place_window);
else
screen->getWorkspace(blackbox_attrib.workspace)->
addWindow(this, place_window);
+ /*
+ the server needs to be grabbed here to prevent client's from sending
+ events while we are in the process of configuring their window.
+ We hold the grab until after we are done moving the window around.
+ */
+
+ XGrabServer(blackbox->getXDisplay());
+
+ associateClientWindow();
+
+ blackbox->saveWindowSearch(client.window, this);
+
if (! place_window) {
// 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());
+
}
+ positionWindows();
+
+ XUngrabServer(blackbox->getXDisplay());
+
+ // now that we know where to put the window and what it should look like
+ // we apply the decorations
+ decorate();
+
+ grabButtons();
+
+ XMapSubwindows(blackbox->getXDisplay(), frame.window);
+
+ // this ensures the title, buttons, and other decor are properly displayed
+ redrawWindowFrame();
+
// 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;
- }
+ unsigned long initial_state = current_state;
+ if (! getState())
+ current_state = initial_state;
// get sticky state from our parent window if we've got one
if (isTransient() && client.transient_for != (BlackboxWindow *) ~0ul &&
client.transient_for->isStuck() != flags.stuck)
stick();
+ // the following flags are set by blackbox native apps only
if (flags.shaded) {
flags.shaded = False;
- unsigned long orig_state = current_state;
+ initial_state = current_state;
shade();
/*
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.
*/
- if (orig_state != IconicState)
+ if (initial_state != IconicState)
current_state = NormalState;
}
stick();
}
- if (flags.maximized && (functions & Func_Maximize)) {
+ 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.
- */
-
- positionWindows();
- decorate();
- grabButtons();
-
- XMapSubwindows(blackbox->getXDisplay(), frame.window);
-
- redrawWindowFrame();
}
if (flags.moving)
endMove();
+ delete timer;
+
+ delete windowmenu;
+
if (client.window_group) {
BWindowGroup *group = blackbox->searchGroup(client.window_group);
if (group) group->removeWindow(this);
if (client.transient_for != (BlackboxWindow *) ~0ul) {
client.transient_for->client.transientList.remove(this);
}
- // we save our transient_for though because the workspace will use it
- // when determining the next window to get focus
+ client.transient_for = (BlackboxWindow*) 0;
}
- if (blackbox_attrib.workspace != BSENTINEL &&
- window_number != BSENTINEL)
- screen->getWorkspace(blackbox_attrib.workspace)->removeWindow(this);
- else if (flags.iconic)
- screen->removeIcon(this);
-
- client.transient_for = (BlackboxWindow*) 0;
-
if (client.transientList.size() > 0) {
// reset transient_for for all transients
BlackboxWindowList::iterator it, end = client.transientList.end();
}
}
- delete timer;
-
- delete windowmenu;
-
if (frame.title)
destroyTitlebar();
XSelectInput(blackbox->getXDisplay(), frame.plate, SubstructureRedirectMask);
- XGrabServer(blackbox->getXDisplay());
-
+ /*
+ note we used to grab around this call to XReparentWindow however the
+ server is now grabbed before this method is called
+ */
unsigned long event_mask = PropertyChangeMask | FocusChangeMask |
StructureNotifyMask;
XSelectInput(blackbox->getXDisplay(), client.window,
XReparentWindow(blackbox->getXDisplay(), client.window, frame.plate, 0, 0);
XSelectInput(blackbox->getXDisplay(), client.window, event_mask);
- XUngrabServer(blackbox->getXDisplay());
-
XRaiseWindow(blackbox->getXDisplay(), frame.plate);
XMapSubwindows(blackbox->getXDisplay(), frame.plate);
-
#ifdef SHAPE
if (blackbox->hasShapeExtensions()) {
XShapeSelectInput(blackbox->getXDisplay(), client.window,
void BlackboxWindow::ungrabButtons(void) {
- if ((! screen->isSloppyFocus()) || screen->doClickRaise())
- blackbox->ungrabButton(Button1, 0, frame.plate);
-
+ blackbox->ungrabButton(Button1, 0, frame.plate);
blackbox->ungrabButton(Button1, ModMask, frame.window);
blackbox->ungrabButton(Button2, ModMask, frame.window);
blackbox->ungrabButton(Button3, ModMask, frame.window);
*/
void BlackboxWindow::getWMHints(void) {
focus_mode = F_Passive;
- client.initial_state = NormalState;
// remove from current window group
if (client.window_group) {
}
if (wmhint->flags & StateHint)
- client.initial_state = wmhint->initial_state;
+ current_state = wmhint->initial_state;
if (wmhint->flags & WindowGroupHint) {
client.window_group = wmhint->window_group;
group->addWindow(this);
}
- client.wm_hint_flags = wmhint->flags;
XFree(wmhint);
}
if (blackbox_hint->flags & AttribDecoration) {
switch (blackbox_hint->decoration) {
case DecorNone:
- // clear all decorations except close
- decorations &= Decor_Close;
- // clear all functions except close
- functions &= Func_Close;
-
+ decorations = 0;
break;
case DecorTiny:
decorations |= Decor_Titlebar | Decor_Iconify;
decorations &= ~(Decor_Border | Decor_Handle | Decor_Maximize);
- functions |= Func_Move | Func_Iconify;
functions &= ~(Func_Resize | Func_Maximize);
break;
case DecorTool:
decorations |= Decor_Titlebar;
decorations &= ~(Decor_Iconify | Decor_Border | Decor_Handle);
- functions |= Func_Move;
functions &= ~(Func_Resize | Func_Maximize | Func_Iconify);
break;
default:
decorations |= Decor_Titlebar | Decor_Border | Decor_Handle |
Decor_Iconify | Decor_Maximize;
- functions |= Func_Resize | Func_Move | Func_Iconify | Func_Maximize;
-
break;
}
void BlackboxWindow::getTransientInfo(void) {
if (client.transient_for &&
client.transient_for != (BlackboxWindow *) ~0ul) {
- // the transient for hint was removed, so we need to tell our
- // previous transient_for that we are going away
+ // reset transient_for in preparation of looking for a new owner
client.transient_for->client.transientList.remove(this);
}
assert(! flags.iconic &&
(flags.stuck || // window must be on the current workspace or sticky
blackbox_attrib.workspace == screen->getCurrentWorkspaceID()));
-#if 0
- // 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;
- }
-#endif
+
/*
We only do this check for normal windows and dialogs because other windows
do this on purpose, such as kde's kicker, and we don't want to go moving
if (focus_mode == F_LocallyActive || focus_mode == F_Passive) {
XSetInputFocus(blackbox->getXDisplay(), client.window,
RevertToPointerRoot, CurrentTime);
-
- blackbox->setFocusedWindow(this);
} else {
/* we could set the focus to none, since the window doesn't accept focus,
* but we shouldn't set focus to nothing since this would surely make
XMapSubwindows(blackbox->getXDisplay(), frame.window);
XMapWindow(blackbox->getXDisplay(), frame.window);
-#ifdef DEBUG
+#if 0
int real_x, real_y;
Window child;
XTranslateCoordinates(blackbox->getXDisplay(), client.window,
// re-maximizes the window to take into account availableArea changes
void BlackboxWindow::remaximize(void) {
+ if (flags.shaded) {
+ // we only update the window's attributes otherwise we lose the shade bit
+ switch(flags.maximized) {
+ case 1:
+ blackbox_attrib.flags |= AttribMaxHoriz | AttribMaxVert;
+ blackbox_attrib.attrib |= AttribMaxHoriz | AttribMaxVert;
+ break;
+
+ case 2:
+ blackbox_attrib.flags |= AttribMaxVert;
+ blackbox_attrib.attrib |= AttribMaxVert;
+ break;
+
+ case 3:
+ blackbox_attrib.flags |= AttribMaxHoriz;
+ blackbox_attrib.attrib |= AttribMaxHoriz;
+ break;
+ }
+ return;
+ }
+
// save the original dimensions because maximize will wipe them out
int premax_x = blackbox_attrib.premax_x,
premax_y = blackbox_attrib.premax_y,
blackbox_attrib.flags ^= AttribOmnipresent;
blackbox_attrib.attrib ^= AttribOmnipresent;
+ for (unsigned int i = 0; i < screen->getNumberOfWorkspaces(); ++i)
+ if (i != blackbox_attrib.workspace)
+ screen->getWorkspace(i)->removeWindow(this, True);
+
flags.stuck = False;
if (! flags.iconic)
// value than that contained in the class' data.
xatom->setValue(client.window, XAtom::net_wm_desktop, XAtom::cardinal,
0xffffffff);
+
+ for (unsigned int i = 0; i < screen->getNumberOfWorkspaces(); ++i)
+ if (i != blackbox_attrib.workspace)
+ screen->getWorkspace(i)->addWindow(this, False, True);
setState(current_state);
}
else timer->stop();
}
- if (isFocused())
+ if (flags.focused)
blackbox->setFocusedWindow(this);
-
- Clientmenu *menu = screen->getWorkspace(blackbox_attrib.workspace)->getMenu();
- menu->setItemSelected(window_number, isFocused());
+
+ if (! flags.iconic) {
+ // iconic windows arent in a workspace menu!
+ if (flags.stuck)
+ screen->getCurrentWorkspace()->setFocused(this, isFocused());
+ else
+ screen->getWorkspace(blackbox_attrib.workspace)->
+ setFocused(this, flags.focused);
+ }
}
blackbox_attrib.premax_h = h;
}
+ if (net->flags & AttribDecoration) {
+ switch (net->decoration) {
+ case DecorNone:
+ decorations = 0;
+
+ break;
+
+ default:
+ case DecorNormal:
+ decorations |= Decor_Titlebar | Decor_Handle | Decor_Border |
+ Decor_Iconify | Decor_Maximize;
+
+ break;
+
+ case DecorTiny:
+ decorations |= Decor_Titlebar | Decor_Iconify;
+ decorations &= ~(Decor_Border | Decor_Handle | Decor_Maximize);
+
+ break;
+
+ case DecorTool:
+ decorations |= Decor_Titlebar;
+ decorations &= ~(Decor_Iconify | Decor_Border | Decor_Handle);
+
+ break;
+ }
+
+ // sanity check the new decor
+ if (! (functions & Func_Resize) || isTransient())
+ decorations &= ~(Decor_Maximize | Decor_Handle);
+ if (! (functions & Func_Maximize))
+ decorations &= ~Decor_Maximize;
+
+ if (decorations & Decor_Titlebar) {
+ if (functions & Func_Close) // close button is controlled by function
+ decorations |= Decor_Close; // not decor type
+ } else {
+ if (flags.shaded) // we can not be shaded if we lack a titlebar
+ shade();
+ }
+
+ if (flags.visible && frame.window) {
+ XMapSubwindows(blackbox->getXDisplay(), frame.window);
+ XMapWindow(blackbox->getXDisplay(), frame.window);
+ }
+
+ reconfigure();
+ setState(current_state);
+ }
+
// with the state set it will then be the map event's job to read the
// window's state and behave accordingly
/*
If the XWarpPointer is done after the configure, we can end up
grabbing another window, so made sure you do it first.
- */
+ */
int dest_x;
if (x_root <= 0) {
dest_x = screen->getRect().right() - 1;
bool snapped = False;
const Rect &winrect = snapwin->frameRect();
- int dleft = std::abs(wright - winrect.left()),
- dright = std::abs(wleft - winrect.right()),
- dtop = std::abs(wbottom - winrect.top()),
- dbottom = std::abs(wtop - winrect.bottom());
+ int dleft = abs(wright - winrect.left()),
+ dright = abs(wleft - winrect.right()),
+ dtop = abs(wbottom - winrect.top()),
+ dbottom = abs(wtop - winrect.bottom());
if (wtop >= (signed)(winrect.y() - frame.rect.height() + 1) &&
wtop < (signed)(winrect.y() + winrect.height() - 1)) {
if (snapped) {
if (screen->getWindowCornerSnap()) {
// try corner-snap to its other sides
- dtop = std::abs(wtop - winrect.top());
- dbottom = std::abs(wbottom - winrect.bottom());
+ dtop = abs(wtop - winrect.top());
+ dbottom = abs(wbottom - winrect.bottom());
if (dtop < snap_distance && dtop <= dbottom)
dy = winrect.top();
else if (dbottom < snap_distance)
if (snapped) {
if (screen->getWindowCornerSnap()) {
// try corner-snap to its other sides
- dleft = std::abs(wleft - winrect.left());
- dright = std::abs(wright - winrect.right());
+ dleft = abs(wleft - winrect.left());
+ dright = abs(wright - winrect.right());
if (dleft < snap_distance && dleft <= dright)
dx = winrect.left();
else if (dright < snap_distance)
frame.rect.height())))
continue;
- int dleft = std::abs(wleft - srect.left()),
- dright = std::abs(wright - srect.right()),
- dtop = std::abs(wtop - srect.top()),
- dbottom = std::abs(wbottom - srect.bottom());
+ int dleft = abs(wleft - srect.left()),
+ dright = abs(wright - srect.right()),
+ dtop = abs(wtop - srect.top()),
+ dbottom = abs(wbottom - srect.bottom());
// snap left?
if (dleft < snap_distance && dleft <= dright)
XSelectInput(blackbox->getXDisplay(), frame.plate, NoEventMask);
// do not leave a shaded window as an icon unless it was an icon
- if (flags.shaded && ! flags.iconic) setState(NormalState);
+ if (flags.shaded && ! flags.iconic)
+ setState(NormalState);
restoreGravity(client.rect);
}
-void BlackboxWindow::changeBlackboxHints(BlackboxHints *net) {
+void BlackboxWindow::changeBlackboxHints(const BlackboxHints *net) {
if ((net->flags & AttribShaded) &&
((blackbox_attrib.attrib & AttribShaded) !=
(net->attrib & AttribShaded)))
if (net->flags & AttribDecoration) {
switch (net->decoration) {
case DecorNone:
- // clear all decorations except close
- decorations &= Decor_Close;
+ decorations = 0;
break;