/*
* paging.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 <stdio.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include "main.h"
#include "misc.h"
#include "blwm.h"
#include "blwmrc.h"
#include "paging.h"
#include "pager.h"
#include "mini.h"
#include "event.h"
#include "taskbar.h"
#include "desktop.h"
#include "gnome.h"
#include "util.h"
Paging::Paging(const Point& topLeft, const Dim& size)
: origin(Point(0, 0)), rcVirt(topLeft.x, topLeft.y, size.width, size.height)
{
if (size.width <= 0) {
BlwmError("The width of the pager must be positive (%d is an error)",
size.width);
rcVirt.width = 0;
}
if (size.height <= 0) {
BlwmError("The height of the pager must be positive (%d is an error)",
size.height);
rcVirt.width = 0;
}
if (topLeft.x > 0 || topLeft.x + size.width - 1 < 0) {
BlwmError("The pager must include a page (0, 0)");
rcVirt.x = 0;
}
if (topLeft.y > 0 || topLeft.y + size.height - 1 < 0) {
BlwmError("The pager must include a page (0, 0)");
rcVirt.y = 0;
}
XSetWindowAttributes attributes;
unsigned long valueMask;
Cursor cs;
Rect rcRoot = rootBlwm->GetRect();
unsigned int fontCursor[] = {
XC_bottom_side, XC_top_side,
XC_left_side, XC_right_side,
XC_bottom_left_corner, XC_bottom_right_corner,
XC_top_left_corner, XC_top_right_corner
};
/*
* Create transparent, long and slender windows in the 4 edges of screen
* for paging.
*/
attributes.override_redirect = True;
attributes.event_mask = EnterWindowMask | LeaveWindowMask |
Button1MotionMask;
valueMask = CWEventMask | CWOverrideRedirect;
for (int i = 0; i < 8; i++)
belt[i] = None;
}
Paging::~Paging()
{
return;
}
/*
* PagingProc --
* Do paging to the direction of win.
*/
Point Paging::PagingProc(Window win, Bool rootFocus)
{
Point ptDelta(0, 0);
Rect rcRoot = rootBlwm->GetRect();
Window junkRoot, junkChild;
Point ptRoot, ptJunk;
unsigned int mask;
if (win == belt[LEFT])
ptDelta.x = -(PagingMovement * rcRoot.width / 100);
else if (win == belt[RIGHT])
ptDelta.x = PagingMovement * rcRoot.width / 100;
else if (win == belt[TOP])
ptDelta.y = -(PagingMovement * rcRoot.height / 100);
else if (win == belt[BOTTOM])
ptDelta.y = PagingMovement * rcRoot.height / 100;
else if (win == belt[BOTTOM_LEFT]) {
ptDelta.x = -(PagingMovement * rcRoot.width / 100);
ptDelta.y = PagingMovement * rcRoot.height / 100;
}
else if (win == belt[BOTTOM_RIGHT]) {
ptDelta.x = PagingMovement * rcRoot.width / 100;
ptDelta.y = PagingMovement * rcRoot.height / 100;
}
else if (win == belt[TOP_LEFT]) {
ptDelta.x = -(PagingMovement * rcRoot.width / 100);
ptDelta.y = -(PagingMovement * rcRoot.height / 100);
}
else if (win == belt[TOP_RIGHT]) {
ptDelta.x = PagingMovement * rcRoot.width / 100;
ptDelta.y = -(PagingMovement * rcRoot.height / 100);
}
else
return Point(0, 0);
Point oldOrigin = origin;
origin.x += ptDelta.x;
origin.y += ptDelta.y;
PagingAllWindows(oldOrigin, rootFocus);
XQueryPointer(display, root, &junkRoot, &junkChild, &ptRoot.x, &ptRoot.y,
&ptJunk.x, &ptJunk.y, &mask);
Point pt(ptRoot.x - ptDelta.x, ptRoot.y - ptDelta.y);
pt.x = rcRoot.width - 1;
pt.y = rcRoot.height - 1;
XWarpPointer(display, None, root, 0, 0, 0, 0, pt.x, pt.y);
desktop.ChangeFocusToCursor();
return ptDelta;
}
/*
* PagingProc --
* Do paging to the position of pt.
*/
void Paging::PagingProc(const Point& pt, Bool rootFocus)
{
Point oldOrigin = origin;
origin = pt;
PagingAllWindows(oldOrigin, rootFocus);
}
/*
* PagingAllWindows --
* Move all windows according to paging movement.
*/
void Paging::PagingAllWindows(const Point& oldOrigin, Bool rootFocus)
{
MapBelts();
if (oldOrigin.x == origin.x && oldOrigin.y == origin.y)
return;
List<Blwm>::Iterator i(&desktop.GetBlwmList());
Point newOrigin = origin;
for (int j = 0; j < PagingSpeed; j++) {
origin.x = oldOrigin.x + (newOrigin.x - oldOrigin.x) * (j + 1)
/ PagingSpeed;
origin.y = oldOrigin.y + (newOrigin.y - oldOrigin.y) * (j + 1)
/ PagingSpeed;
for (Blwm* blWm = i.GetHead(); blWm; blWm = i.GetNext()) {
Rect rect = blWm->GetRect();
if (blWm->CheckFlags(STICKY)) {
Point pt(rect.x - oldOrigin.x + origin.x,
rect.y - oldOrigin.y + origin.y);
/*
* rc of STICKY window changes on paging.
* only last loop
*/
if (j == PagingSpeed - 1) {
rect.x = pt.x;
rect.y = pt.y;
blWm->SetRect(rect);
}
if (UsePager) {
ASSERT(blWm->mini);
blWm->mini->MoveMiniature(pager->ConvertToPagerPos(pt));
}
continue;
}
XMoveWindow(display, blWm->GetFrameWin(),
rect.x - origin.x, rect.y - origin.y);
// only last loop
if (j == PagingSpeed - 1) {
blWm->SendConfigureEvent();
if (Intersect(rect, rootBlwm->GetRect()))
Gnome::ResetState(blWm, WIN_STATE_HID_WORKSPACE);
else
Gnome::SetState(blWm, WIN_STATE_HID_WORKSPACE);
}
}
XFlush(display);
usleep(10000);
}
if (UsePager) {
ASSERT(pager);
pager->DrawVisualPage();
}
Gnome::SetActiveDesktop();
if (!ClickToFocus && NoDesktopFocus && rootFocus) {
Point ptJunk;
Window w;
// set focus root only if pointer is on root.
XTranslateCoordinates(display, root, root, ptJunk.x, ptJunk.y,
&ptJunk.x, &ptJunk.y, &w);
if (w == root)
rootBlwm->SetFocus();
}
if (rootFocus && UseTaskbar && TaskbarAutoHide)
taskBar->HideTaskbar();
if (TaskbarButtonInScr) {
if (taskBar)
taskBar->RedrawAllTaskbarButtons();
}
}
void Paging::MapBelts()
{
Rect rcRoot = rootBlwm->GetRect();
// check left-most edge
if (origin.x > rcVirt.x * rcRoot.width) {
}
else {
origin.x = rcVirt.x * rcRoot.width;
}
// check right-most edge
if (origin.x < (rcVirt.x + rcVirt.width - 1) * rcRoot.width) {
}
else {
origin.x = (rcVirt.x + rcVirt.width - 1) * rcRoot.width;
}
// check top-most edge
if (origin.y > rcVirt.y * rcRoot.height) {
}
else {
origin.y = rcVirt.y * rcRoot.height;
}
// check bottom-most side
if (origin.y < (rcVirt.y + rcVirt.height - 1) * rcRoot.height) {
}
else {
origin.y = (rcVirt.y + rcVirt.height - 1) * rcRoot.height;
}
}
Paging::BeltPos Paging::GetBeltPos(const Point& pt)
{
Rect rcRoot = rootBlwm->GetRect();
Rect rcBelt[] = {
Rect(0, rcRoot.height - 0, rcRoot.width - 0 * 2, 0),
Rect(0, 0, rcRoot.width - 0 * 2, 0),
Rect(0, 0, 0, rcRoot.height - 0 * 2),
Rect(rcRoot.width - 0, 0, 0, rcRoot.height - 0 * 2),
Rect(0, rcRoot.height - 0, 0, 0),
Rect(rcRoot.width - 0, rcRoot.height - 0, 0, 0),
Rect(0, 0, 0, 0),
Rect(rcRoot.width - 0, 0, 0, 0)
};
for (int i = 0; i < 8; i++) {
if (InRect(pt, rcBelt[i]))
return (BeltPos)i;
}
ASSERT(False);
return BOTTOM; // XXX
}
void Paging::SwitchPageLeft()
{
if (Menu::CheckAnyMenusMapped())
return;
Rect rcRoot = rootBlwm->GetRect();
Point oldOrigin = origin;
origin.x -= rcRoot.width;
PagingAllWindows(oldOrigin);
desktop.ChangeFocusToCursor();
}
void Paging::SwitchPageRight()
{
if (Menu::CheckAnyMenusMapped())
return;
Rect rcRoot = rootBlwm->GetRect();
Point oldOrigin = origin;
origin.x += rcRoot.width;
PagingAllWindows(oldOrigin);
desktop.ChangeFocusToCursor();
}
void Paging::SwitchPageUp()
{
if (Menu::CheckAnyMenusMapped())
return;
Rect rcRoot = rootBlwm->GetRect();
Point oldOrigin = origin;
origin.y -= rcRoot.height;
PagingAllWindows(oldOrigin);
desktop.ChangeFocusToCursor();
}
void Paging::SwitchPageDown()
{
if (Menu::CheckAnyMenusMapped())
return;
Rect rcRoot = rootBlwm->GetRect();
Point oldOrigin = origin;
origin.y += rcRoot.height;
PagingAllWindows(oldOrigin);
desktop.ChangeFocusToCursor();
}
syntax highlighted by Code2HTML, v. 0.9.1