+ assert(dir == 0 || dir == 1 || dir == 2);
+ if (!(_functions & Func_Maximize)) return; // can't
+
+ // check if already done
+ if (max) {
+ if (dir == 0 && _max_horz && _max_vert) return;
+ if (dir == 1 && _max_horz) return;
+ if (dir == 2 && _max_vert) return;
+ } else {
+ if (dir == 0 && !_max_horz && !_max_vert) return;
+ if (dir == 1 && !_max_horz) return;
+ if (dir == 2 && !_max_vert) return;
+ }
+
+ const otk::Rect &a = openbox->screen(_screen)->area();
+ int x = frame->rect().x(), y = frame->rect().y(),
+ w = _area.width(), h = _area.height();
+
+ if (max) {
+ if (savearea) {
+ long dimensions[4];
+ long *readdim;
+ unsigned long n = 4;
+
+ dimensions[0] = x;
+ dimensions[1] = y;
+ dimensions[2] = w;
+ dimensions[3] = h;
+
+ // get the property off the window and use it for the dimentions we are
+ // already maxed on
+ if (otk::Property::get(_window, otk::Property::atoms.openbox_premax,
+ otk::Property::atoms.cardinal, &n,
+ (long unsigned**) &readdim)) {
+ if (n >= 4) {
+ if (_max_horz) {
+ dimensions[0] = readdim[0];
+ dimensions[2] = readdim[2];
+ }
+ if (_max_vert) {
+ dimensions[1] = readdim[1];
+ dimensions[3] = readdim[3];
+ }
+ }
+ delete readdim;
+ }
+
+ otk::Property::set(_window, otk::Property::atoms.openbox_premax,
+ otk::Property::atoms.cardinal,
+ (long unsigned*)dimensions, 4);
+ }
+ if (dir == 0 || dir == 1) { // horz
+ x = a.x();
+ w = a.width();
+ }
+ if (dir == 0 || dir == 2) { // vert
+ y = a.y();
+ h = a.height() - frame->size().top - frame->size().bottom;
+ }
+ } else {
+ long *dimensions;
+ long unsigned n = 4;
+
+ if (otk::Property::get(_window, otk::Property::atoms.openbox_premax,
+ otk::Property::atoms.cardinal, &n,
+ (long unsigned**) &dimensions)) {
+ if (n >= 4) {
+ if (dir == 0 || dir == 1) { // horz
+ x = (signed int)dimensions[0];
+ w = (signed int)dimensions[2];
+ }
+ if (dir == 0 || dir == 2) { // vert
+ y = (signed int)dimensions[1];
+ h = (signed int)dimensions[3];
+ }
+ }
+ delete dimensions;
+ } else {
+ // pick some fallbacks...
+ if (dir == 0 || dir == 1) { // horz
+ x = a.x() + a.width() / 4;
+ w = a.width() / 2;
+ }
+ if (dir == 0 || dir == 2) { // vert
+ y = a.y() + a.height() / 4;
+ h = a.height() / 2;
+ }
+ }
+ }
+
+ if (dir == 0 || dir == 1) // horz
+ _max_horz = max;
+ if (dir == 0 || dir == 2) // vert
+ _max_vert = max;
+
+ if (!_max_horz && !_max_vert)
+ otk::Property::erase(_window, otk::Property::atoms.openbox_premax);
+
+ changeState(); // change the state hints on the client
+
+ frame->frameGravity(x, y); // figure out where the client should be going
+ internal_resize(TopLeft, w, h, true, x, y);
+}
+
+
+void Client::fullscreen(bool fs, bool savearea)
+{
+ static FunctionFlags saved_func;
+ static DecorationFlags saved_decor;
+
+ if (!(_functions & Func_Fullscreen) || // can't
+ _fullscreen == fs) return; // already done
+
+ _fullscreen = fs;
+ changeState(); // change the state hints on the client
+
+ int x = _area.x(), y = _area.y(), w = _area.width(), h = _area.height();
+
+ if (fs) {
+ // save the functions and remove them
+ saved_func = _functions;
+ _functions = _functions & (Func_Close | Func_Fullscreen | Func_Iconify);
+ // save the decorations and remove them
+ saved_decor = _decorations;
+ _decorations = 0;
+ if (savearea) {
+ long dimensions[4];
+ dimensions[0] = _area.x();
+ dimensions[1] = _area.y();
+ dimensions[2] = _area.width();
+ dimensions[3] = _area.height();
+ otk::Property::set(_window, otk::Property::atoms.openbox_premax,
+ otk::Property::atoms.cardinal,
+ (long unsigned*)dimensions, 4);
+ }
+ const otk::ScreenInfo *info = otk::display->screenInfo(_screen);
+ x = 0;
+ y = 0;
+ w = info->width();
+ h = info->height();
+ } else {
+ _functions = saved_func;
+ _decorations = saved_decor;
+
+ long *dimensions;
+ long unsigned n = 4;
+
+ if (otk::Property::get(_window, otk::Property::atoms.openbox_premax,
+ otk::Property::atoms.cardinal, &n,
+ (long unsigned**) &dimensions)) {
+ if (n >= 4) {
+ x = dimensions[0];
+ y = dimensions[1];
+ w = dimensions[2];
+ h = dimensions[3];
+ }
+ delete dimensions;
+ } else {
+ // pick some fallbacks...
+ const otk::Rect &a = openbox->screen(_screen)->area();
+ x = a.x() + a.width() / 4;
+ y = a.y() + a.height() / 4;
+ w = a.width() / 2;
+ h = a.height() / 2;
+ }
+ }
+
+ changeAllowedActions(); // based on the new _functions
+
+ // when fullscreening, don't obey things like increments, fill the screen
+ internal_resize(TopLeft, w, h, !fs, x, y);
+
+ // raise (back) into our stacking layer
+ openbox->screen(_screen)->raiseWindow(this);
+
+ // try focus us when we go into fullscreen mode
+ if (fs) focus();
+}
+
+
+void Client::disableDecorations(DecorationFlags flags)
+{
+ _disabled_decorations = flags;
+ setupDecorAndFunctions();
+}
+
+
+bool Client::focus()
+{
+ // won't try focus if the client doesn't want it, or if the window isn't
+ // visible on the screen
+ if (!(frame->isVisible() && (_can_focus || _focus_notify))) return false;
+