/*
 * rearrange.cc
 *
 * Copyright (C) 1995, 1996, 1997, 1997, 1998, 1999, 2000, 2001, 2002 Kenichi Kourai
 * Copyright (C) 1999, 2000, 2001, 2002 Luiz Blanes
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with blwm; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "main.h"
#include "misc.h"
#include "blwm.h"
#include "util.h"
#include "paging.h"
#include "pager.h"
#include "mini.h"
#include "taskbar.h"
#include "blwmrc.h"
#include "desktop.h"

/*
 * Overlap --
 *   Rearrange windows in this screen in the overlapping form.
 */
void Desktop::Overlap(Bool all, const Rect& vt)
{
  List<Blwm>::Iterator i(&blwmList);
  Point topLeft(rcScreen.x, rcScreen.y);
  int unit = Blwm::TITLE_HEIGHT + Blwm::TOP_BORDER;
  int num = 0;

  for (Blwm* blWm = i.GetHead(); blWm; blWm = i.GetNext()) {

     if (blWm->CheckMapped() &&
 	(all ||
 	 (!blWm->CheckFlags(STICKY) && Intersect(blWm->GetRect(), vt)))) {

      XMoveWindow(display, blWm->GetFrameWin(), topLeft.x, topLeft.y);
      blWm->RaiseWindow(True);

      Rect rect(topLeft.x + vt.x, topLeft.y + vt.y,
		blWm->GetRect().width, blWm->GetRect().height);
      blWm->ConfigureNewRect(rect);

      if (UsePager) {
	Point pt(rect.x, rect.y);
	ASSERT(blWm->mini);
	ASSERT(pager);
	blWm->mini->MoveMiniature(pager->ConvertToPagerPos(pt));
      }
       topLeft += Point(unit, unit);
 
       if (topLeft.x > rcScreen.width / 2 || topLeft.y > rcScreen.height / 2) {
 	num++;
 	topLeft = Point(rcScreen.x + unit * num, rcScreen.y);
 	if (topLeft.x > rcScreen.width / 2) {
 	  topLeft.x = rcScreen.x;
 	  num = 0;
 	}
       }

    }
  }

  if (UseTaskbar && OnTopTaskbar)
    taskBar->RaiseTaskbar();
  if (UsePager && OnTopPager)
    pager->RaisePager();
}

/*
 * TileHorz --
 *   Rearrange windows in this screen in the horizontally-tiling form.
 */
void Desktop::TileHorz(Bool all, const Rect& vt)
{
  List<Blwm>::Iterator i(&blwmList);
  Blwm* blWm;
  Point topLeft(vt.x + rcScreen.x, vt.y + rcScreen.y);
  int num = 0;

  // count non-sticky window in this screen
  for (blWm = i.GetHead(); blWm; blWm = i.GetNext())
     if (blWm->CheckMapped() &&
 	(all || (!blWm->CheckFlags(STICKY) && Intersect(blWm->GetRect(), vt))))
      num++;
   if (num == 0)
     return;
 

  for (blWm = i.GetHead(); blWm; blWm = i.GetNext()) {
     if (blWm->CheckMapped() &&
 	(all ||
 	 (!blWm->CheckFlags(STICKY) && Intersect(blWm->GetRect(), vt)))) {
      Rect rect(topLeft.x, topLeft.y, vt.width / num, vt.height);
      XSizeHints hints = blWm->GetSizeHints();
      Rect rcFix = blWm->GetFixSize(rect, hints.max_width, hints.max_height,
				    hints.width_inc, hints.height_inc,
				    hints.base_width, hints.base_height);
      blWm->ConfigureNewRect(rcFix);
      blWm->RedrawWindow();
      blWm->RaiseWindow(True);

      topLeft.x += rcFix.width;
    }
  }

  if (UseTaskbar && OnTopTaskbar)
    taskBar->RaiseTaskbar();
}

/*
 * TileVert --
 *   Rearrange windows in this screen in the vertically-tiling form.
 */
void Desktop::TileVert(Bool all, const Rect& vt)
{
  List<Blwm>::Iterator i(&blwmList);
  Blwm* blWm;
  Point topLeft(vt.x + rcScreen.x, vt.y + rcScreen.y);
  int num = 0;

  // count non-sticky window in this screen
  for (blWm = i.GetHead(); blWm; blWm = i.GetNext())
     if (blWm->CheckMapped() &&
 	(all || (!blWm->CheckFlags(STICKY) && Intersect(blWm->GetRect(), vt))))
      num++;
   if (num == 0)
     return;

  for (blWm = i.GetHead(); blWm; blWm = i.GetNext()) {
     if (blWm->CheckMapped() &&
 	(all ||
 	 (!blWm->CheckFlags(STICKY) && Intersect(blWm->GetRect(), vt)))) {
      Rect rect(topLeft.x, topLeft.y, vt.width, vt.height / num);
      XSizeHints hints = blWm->GetSizeHints();
      Rect rcFix = blWm->GetFixSize(rect, hints.max_width, hints.max_height,
				    hints.width_inc, hints.height_inc,
				    hints.base_width, hints.base_height);
      blWm->ConfigureNewRect(rcFix);
      blWm->RedrawWindow();
      blWm->RaiseWindow(True);

      topLeft.y += rcFix.height;
    }
  }

  if (UseTaskbar && OnTopTaskbar)
    taskBar->RaiseTaskbar();
}

 void Desktop::MinimizeAll(Bool all, const Rect& vt)
 {
   List<Blwm>::Iterator i(&blwmList);
 
   rootBlwm->SetFocus();
 
   for (Blwm* blWm = i.GetHead(); blWm; blWm = i.GetNext()) {
     if (blWm->CheckMapped() && !blWm->CheckFlags(NO_TBUTTON) &&
 	(all || (!blWm->CheckFlags(STICKY) && Intersect(blWm->GetRect(), vt))))
       blWm->MinimizeWindow(True, False);
   }
 }
 
 void Desktop::RestoreAll(Bool all, const Rect& vt)
 {
   List<Blwm>::Iterator i(&blwmList);
 
   for (Blwm* blWm = i.GetHead(); blWm; blWm = i.GetNext()) {
     if (!blWm->CheckMapped() &&
 	(all || (!blWm->CheckFlags(STICKY) && Intersect(blWm->GetRect(), vt))))
       blWm->RestoreWindow(True, False);
   }
 }
 
 void Desktop::CloseAll(Bool all, const Rect& vt)
{
  List<Blwm>::Iterator i(&blwmList);

  rootBlwm->SetFocus();

  for (Blwm* blWm = i.GetHead(); blWm; blWm = i.GetNext()) {
     if (all || (!blWm->CheckFlags(STICKY) && Intersect(blWm->GetRect(), vt)))
       blWm->CloseWindow();
  }
}


syntax highlighted by Code2HTML, v. 0.9.1