/* * 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 #include #include #include #include #include #include #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::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(); }