/* * taskbar.cc * * Copyright (C) 1995-2001 Kenichi Kourai * * 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, 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 qvwm; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "main.h" #include "misc.h" #include "qvwm.h" #include "taskbar.h" #include "tbutton.h" #include "sbutton.h" #include "startmenu.h" #include "event.h" #include "icon.h" #include "paging.h" #include "pager.h" #include "qvwmrc.h" #include "indicator.h" #include "desktop.h" #include "tooltip.h" #include "callback.h" #include "timer.h" int Taskbar::BASE_HEIGHT; int Taskbar::INC_HEIGHT; Taskbar::Taskbar(Qvwm* qvWm, int width, unsigned int rows) : hiding(False) { XSetWindowAttributes attributes; unsigned long valueMask; Dim dRoot(DisplayWidth(display, screen), DisplayHeight(display, screen)); Dim base; char str[128]; int len; XRectangle ink, log; if (UseClock) { /* * Calculate clock width. */ time_t t; struct tm* tm; time(&t); tm = localtime(&t); // set values with max font width tm->tm_sec = 59; tm->tm_min = 59; tm->tm_hour = 23; tm->tm_mday = 31; tm->tm_yday = 365; // if ClockLocaleName is not specified in the configuration files if (ClockLocaleName == NULL) ClockLocaleName = LocaleName; setlocale(LC_TIME, ClockLocaleName); strftime(str, sizeof(str), ClockFormat, tm); len = strlen(str); XmbTextExtents(fsTaskbar, str, len, &ink, &log); clockWidth = log.width; timer->SetTimeout(1000, new Callback(this, &Taskbar::AdvanceClock)); } else clockWidth = 0; indWidth = 0; dTbox.width = clockWidth + TBOX_MARGIN * 2; dTbox.height = TaskbarButton::BUTTON_HEIGHT; base.width = (width > clockWidth + 6) ? width : clockWidth + 6; base.height = (rows - 1) * INC_HEIGHT + BASE_HEIGHT; if (base.height > dRoot.height / 2) base.height = (dRoot.height / 2 - BASE_HEIGHT) / INC_HEIGHT * INC_HEIGHT + BASE_HEIGHT; rc[BOTTOM] = Rect(0, dRoot.height - base.height, dRoot.width, base.height); rc[TOP] = Rect(0, 0, dRoot.width, base.height); rc[LEFT] = Rect(0, 0, base.width, dRoot.height); rc[RIGHT] = Rect(dRoot.width - base.width, 0, base.width, dRoot.height); /* * Create taskbar. */ attributes.background_pixel = TaskbarColor.pixel; attributes.override_redirect = True; attributes.event_mask = ExposureMask | ButtonPressMask | ButtonReleaseMask | Button1MotionMask | EnterWindowMask | LeaveWindowMask; valueMask = CWBackPixel | CWOverrideRedirect | CWEventMask; frame = XCreateWindow(display, root, -10, -10, 10, 10, 0, CopyFromParent, InputOutput, CopyFromParent, valueMask, &attributes); attributes.event_mask = ExposureMask | ButtonPressMask | ButtonReleaseMask | Button1MotionMask; attributes.background_pixel = TaskbarColor.pixel; attributes.cursor = cursor[SYS]; valueMask = CWBackPixel | CWCursor | CWEventMask; w = XCreateWindow(display, frame, 0, 0, 10, 10, 0, CopyFromParent, InputOutput, CopyFromParent, valueMask, &attributes); /* * Create taskbar box. */ attributes.event_mask = ExposureMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask; valueMask = CWBackPixel | CWEventMask; tbox = XCreateWindow(display, w, 0, 0, dTbox.width, dTbox.height, 0, CopyFromParent, InputOutput, CopyFromParent, valueMask, &attributes); XMapWindow(display, w); XMapWindow(display, tbox); if (TaskbarImage) { imgTaskbar = CreateImageFromFile(TaskbarImage, timer); if (imgTaskbar) { imgTaskbar->SetBackground(frame); imgTWin = NULL; imgTBox = NULL; } else { delete [] TaskbarImage; TaskbarImage = NULL; } } ctrlMenu = new Menu(TaskbarMenuItem, fsCtrlMenu, NULL, qvWm); toolTip = new Tooltip(); } Taskbar::~Taskbar() { XDestroyWindow(display, frame); if (TaskbarImage) { QvImage::Destroy(imgTaskbar); QvImage::Destroy(imgTWin); QvImage::Destroy(imgTBox); } delete toolTip; delete ctrlMenu; } /* * MapTaskbar -- * Map the taskbar. */ void Taskbar::MapTaskbar() { XMapWindow(display, frame); RaiseTaskbar(); ASSERT(rootQvwm); ASSERT(rootQvwm->tButton); rootQvwm->tButton->MapButton(); // Start menu if (TaskbarAutoHide) { BasicCallback* cb; cb = new Callback(this, &Taskbar::HideTaskbar); timer->SetTimeout(TaskbarHideDelay, cb); } if (!hiding) paging->RaisePagingBelt(); } /* * UnmapTaskbar -- * Unmap the taskbar. */ void Taskbar::UnmapTaskbar() { XUnmapWindow(display, frame); } /* * MoveTaskbar -- * Move the taskbar to the tp position. */ void Taskbar::MoveTaskbar(TaskbarPos tp) { pos = tp; switch (pos) { case BOTTOM: XDefineCursor(display, frame, cursor[Y_RESIZE]); XMoveResizeWindow(display, w, 0, 4, rc[BOTTOM].width, rc[BOTTOM].height-4); TaskbarButton::rcTButton.x = 2; TaskbarButton::rcTButton.y = 0; if (TaskbarImage) { QvImage::Destroy(imgTWin); imgTWin = imgTaskbar->GetOffsetImage(Point(0, 4)); imgTWin->SetBackground(w); } break; case TOP: XDefineCursor(display, frame, cursor[Y_RESIZE]); XMoveResizeWindow(display, w, 0, 0, rc[TOP].width, rc[TOP].height-4); TaskbarButton::rcTButton.x = 2; TaskbarButton::rcTButton.y = 2; if (TaskbarImage) { QvImage::Destroy(imgTWin); imgTWin = imgTaskbar->GetOffsetImage(Point(0, 0)); imgTWin->SetBackground(w); } break; case LEFT: XDefineCursor(display, frame, cursor[X_RESIZE]); XMoveResizeWindow(display, w, 0, 0, rc[LEFT].width-4, rc[LEFT].height); TaskbarButton::rcTButton.x = 2; TaskbarButton::rcTButton.y = 2; if (TaskbarImage) { QvImage::Destroy(imgTWin); imgTWin = imgTaskbar->GetOffsetImage(Point(0, 0)); imgTWin->SetBackground(w); } break; case RIGHT: XDefineCursor(display, frame, cursor[X_RESIZE]); XMoveResizeWindow(display, w, 4, 0, rc[RIGHT].width-4, rc[RIGHT].height); TaskbarButton::rcTButton.x = 0; TaskbarButton::rcTButton.y = 2; if (TaskbarImage) { QvImage::Destroy(imgTWin); imgTWin = imgTaskbar->GetOffsetImage(Point(4, 0)); imgTWin->SetBackground(w); } break; } if (TaskbarAutoHide) rcScreen = GetScreenRectOnHiding(); else rcScreen = GetScreenRectOnShowing(); // relocate the contents of taskbar box MoveResizeTaskbarBox(); DrawTaskbarBox(); RedrawAllTaskbarButtons(); XMoveResizeWindow(display, frame, rc[pos].x, rc[pos].y, rc[pos].width, rc[pos].height); desktop.RecalcAllWindows(); desktop.RedrawAllIcons(); if (UsePager) { ASSERT(pager); pager->RecalcPager(); } ASSERT(paging); if (!hiding) paging->RaisePagingBelt(); } /* * MoveTaskbar -- * Drag the taskbar to move. */ void Taskbar::MoveTaskbar(const Point& ptRoot) { XEvent ev; Point ptNew; Rect rcRoot = rootQvwm->GetRect(); Bool pointer = False; if (DisableDesktopChange) return; /* * There is parts that cannot let taskbar to move. */ switch (pos) { case BOTTOM: if (ptRoot.y == rcRoot.height-1 || ptRoot.y == rcRoot.height-2) return; break; case TOP: if (ptRoot.y == 0 || ptRoot.y == 1) return; break; case LEFT: if (ptRoot.x == 0 || ptRoot.x == 1) return; break; case RIGHT: if (ptRoot.x == rcRoot.width-1 || ptRoot.x == rcRoot.width-2) return; break; } if (!OpaqueMove) { XGrabServer(display); XDrawRectangle(display, root, gcXor, rc[pos].x, rc[pos].y, rc[pos].width, rc[pos].height); } while (1) { XMaskEvent(display, Button1MotionMask | ButtonReleaseMask | ExposureMask | ButtonPressMask | PointerMotionMask, &ev); switch (ev.type) { case MotionNotify: if (!OpaqueMove) XDrawRectangle(display, root, gcXor, rc[pos].x, rc[pos].y, rc[pos].width, rc[pos].height); ptNew = Point(ev.xbutton.x_root, ev.xbutton.y_root); pos = desktop.GetDesktopArea(ptNew); if (OpaqueMove) MoveTaskbar(pos); else XDrawRectangle(display, root, gcXor, rc[pos].x, rc[pos].y, rc[pos].width, rc[pos].height); break; case ButtonRelease: if (LockDragState) { pointer = True; XGrabPointer(display, root, True, ButtonPressMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, root, None, CurrentTime); break; } else goto decide; case ButtonPress: if (pointer) { XUngrabPointer(display, CurrentTime); goto decide; } break; case Expose: event.ExposeProc((const XExposeEvent &)ev); break; } } decide: if (!OpaqueMove) { XDrawRectangle(display, root, gcXor, rc[pos].x, rc[pos].y, rc[pos].width, rc[pos].height); XUngrabServer(display); } ptNew = Point(ev.xbutton.x_root, ev.xbutton.y_root); pos = desktop.GetDesktopArea(ptNew); MoveTaskbar(pos); } /* * ResizeTaskbar -- * Resize the taskbar. */ void Taskbar::ResizeTaskbar(const Point& ptRoot) { RectPt resize; XEvent ev; Rect rcNew = rc[pos], rcOld = rc[pos]; Point ptNew; Rect rcRoot = rootQvwm->GetRect(); Bool pointer = False; int ctype; if (DisableDesktopChange) return; if (!OpaqueResize) { XGrabServer(display); XDrawRectangle(display, root, gcXor, rcNew.x, rcNew.y, rcNew.width, rcNew.height); } while (1) { XMaskEvent(display, Button1MotionMask | ButtonReleaseMask | ExposureMask | ButtonPressMask | PointerMotionMask, &ev); switch (ev.type) { case MotionNotify: if (!OpaqueResize) XDrawRectangle(display, root, gcXor, rcNew.x, rcNew.y, rcNew.width, rcNew.height); ptNew = Point(ev.xbutton.x_root, ev.xbutton.y_root); resize = RectPt(0, 0, 0, 0); switch (pos) { case BOTTOM: resize.top = ptNew.y - ptRoot.y; break; case TOP: resize.bottom = ptNew.y - ptRoot.y; break; case LEFT: resize.right = ptNew.x - ptRoot.x; break; case RIGHT: resize.left = ptNew.x - ptRoot.x; break; } rcNew.x = rcOld.x + resize.left; rcNew.y = rcOld.y + resize.top; rcNew.width = rcOld.width - resize.left + resize.right; rcNew.height = rcOld.height - resize.top + resize.bottom; /* * Adjust. */ switch (pos) { case BOTTOM: case TOP: if (rcNew.height > rcRoot.height/2) rcNew.height = rcRoot.height / 2; rcNew.height = rcNew.height / INC_HEIGHT * INC_HEIGHT + 3; if (rcNew.height < 6) rcNew.height = 6; break; case LEFT: case RIGHT: if (rcNew.width > rcRoot.width/2) rcNew.width = rcRoot.width / 2; if (rcNew.width < 6) rcNew.width = 6; break; } if (pos == BOTTOM) rcNew.y = rcRoot.height - rcNew.height; if (pos == RIGHT) rcNew.x = rcRoot.width - rcNew.width; if (OpaqueResize) { rc[pos] = rcNew; MoveTaskbar(pos); } else XDrawRectangle(display, root, gcXor, rcNew.x, rcNew.y, rcNew.width, rcNew.height); break; case ButtonRelease: if (LockDragState) { pointer = True; if (pos == BOTTOM || pos == TOP) ctype = Y_RESIZE; else ctype = X_RESIZE; XGrabPointer(display, root, True, ButtonPressMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, root, cursor[ctype], CurrentTime); break; } else goto decide; case ButtonPress: if (pointer) { XUngrabPointer(display, CurrentTime); goto decide; } break; case Expose: event.ExposeProc((const XExposeEvent &)ev); break; } } decide: if (!OpaqueResize) { XDrawRectangle(display, root, gcXor, rcNew.x, rcNew.y, rcNew.width, rcNew.height); XUngrabServer(display); } rc[pos] = rcNew; MoveTaskbar(pos); } /* * RaiseTaskbar -- * Raise the taskbar. */ void Taskbar::RaiseTaskbar() { Window win[2]; int nwindows = 0; Window menuFrame = Menu::GetMappedMenuFrame(); if (OnTopTaskbar) { if (menuFrame != None) win[nwindows++] = menuFrame; } else win[nwindows++] = desktop.GetTopWindow(); win[nwindows++] = frame; ASSERT(paging); if (hiding) { paging->RaisePagingBelt(); if (OnTopTaskbar) XRaiseWindow(display, frame); XRestackWindows(display, win, nwindows); } else { if (OnTopTaskbar) XRaiseWindow(display, frame); XRestackWindows(display, win, nwindows); paging->RaisePagingBelt(); } } /* * MoveResizeTaskbarBox -- * Move and resize taskbar box. */ void Taskbar::MoveResizeTaskbarBox() { Rect rcRoot = rootQvwm->GetRect(); StartButton *sButton = (StartButton *)rootQvwm->tButton; Point pt; indWidth = Indicator::RedrawAllIndicators(); dTbox.width = indWidth + IC_MARGIN + clockWidth + TBOX_MARGIN; switch (pos) { case BOTTOM: pt = Point(rc[BOTTOM].width - dTbox.width - 2, 0); XMoveResizeWindow(display, tbox, pt.x, pt.y, dTbox.width, TaskbarButton::BUTTON_HEIGHT); buttonArea = rcRoot.width - (sButton->buttonWidth + dTbox.width + 21); if (TaskbarImage) { QvImage::Destroy(imgTBox); imgTBox = imgTaskbar->GetOffsetImage(Point(pt.x, pt.y + 4)); imgTBox->SetBackground(tbox); } break; case TOP: pt = Point(rc[TOP].width - dTbox.width - 2, 2); XMoveResizeWindow(display, tbox, pt.x, pt.y, dTbox.width, TaskbarButton::BUTTON_HEIGHT); buttonArea = rcRoot.width - (sButton->buttonWidth + dTbox.width + 21); if (TaskbarImage) { QvImage::Destroy(imgTBox); imgTBox = imgTaskbar->GetOffsetImage(pt); imgTBox->SetBackground(tbox); } break; case LEFT: if (rc[LEFT].width < sButton->buttonWidth + dTbox.width + 19) { if (rc[LEFT].width - 9 > dTbox.width) { pt = Point((rc[LEFT].width - dTbox.width - 4) / 2 + 1, rc[LEFT].height - dTbox.height - 6); XMoveResizeWindow(display, tbox, pt.x, pt.y, dTbox.width, dTbox.height); } else { dTbox.width = rc[LEFT].width - 9; if (dTbox.width <= 0) dTbox.width = 1; pt = Point(3, rc[LEFT].height - dTbox.height - 6); XMoveResizeWindow(display, tbox, pt.x, pt.y, dTbox.width, dTbox.height); } } else { pt = Point(rc[LEFT].width - dTbox.width - 8, TaskbarButton::rcTButton.y); XMoveResizeWindow(display, tbox, pt.x, pt.y, dTbox.width, TaskbarButton::BUTTON_HEIGHT); } buttonArea = rcRoot.height - (TaskbarButton::rcTButton.y + TaskbarButton::BUTTON_HEIGHT + 12); if (rc[LEFT].width < sButton->buttonWidth + dTbox.width + 19) buttonArea -= dTbox.height + 9; if (TaskbarImage) { QvImage::Destroy(imgTBox); imgTBox = imgTaskbar->GetOffsetImage(pt); imgTBox->SetBackground(tbox); } break; case RIGHT: if (rc[RIGHT].width < sButton->buttonWidth + dTbox.width + 19) { if (rc[RIGHT].width - 9 > dTbox.width) { pt = Point((rc[RIGHT].width - dTbox.width - 4) / 2 - 1, rc[RIGHT].height - dTbox.height - 6); XMoveResizeWindow(display, tbox, pt.x, pt.y, dTbox.width, dTbox.height); } else { dTbox.width = rc[RIGHT].width - 9; if (dTbox.width <= 0) dTbox.width = 1; pt = Point(4, rc[RIGHT].height - dTbox.height - 6); XMoveResizeWindow(display, tbox, pt.x, pt.y, dTbox.width, dTbox.height); } } else { pt = Point(rc[RIGHT].width - dTbox.width - 8, TaskbarButton::rcTButton.y); XMoveResizeWindow(display, tbox, pt.x, pt.y, dTbox.width, TaskbarButton::BUTTON_HEIGHT); } buttonArea = rcRoot.height - (TaskbarButton::rcTButton.y + TaskbarButton::BUTTON_HEIGHT + 12); if (rc[RIGHT].width < sButton->buttonWidth + dTbox.width + 19) buttonArea -= dTbox.height + 9; if (TaskbarImage) { QvImage::Destroy(imgTBox); imgTBox = imgTaskbar->GetOffsetImage(Point(pt.x + 4, pt.y)); imgTBox->SetBackground(tbox); } break; } } /* * DrawTaskbarFrame -- * Draw the taskbar frame. */ void Taskbar::DrawTaskbarFrame() { if (hiding) return; switch (pos) { case BOTTOM: XSetForeground(display, gc, gray.pixel); XDrawLine(display, frame, gc, rc[BOTTOM].x, 0, rc[BOTTOM].width-1, 0); XSetForeground(display, gc, white.pixel); XDrawLine(display, frame, gc, rc[BOTTOM].x, 1, rc[BOTTOM].width-1, 1); break; case TOP: XSetForeground(display, gc, darkGray.pixel); XDrawLine(display, frame, gc, rc[TOP].x, rc[TOP].height-2, rc[TOP].width-1, rc[TOP].height-2); XSetForeground(display, gc, darkGrey.pixel); XDrawLine(display, frame, gc, rc[TOP].x, rc[TOP].height-1, rc[TOP].width-1, rc[TOP].height-1); break; case LEFT: XSetForeground(display, gc, darkGray.pixel); XDrawLine(display, frame, gc, rc[LEFT].width-2, rc[LEFT].y, rc[LEFT].width-2, rc[LEFT].height-1); XSetForeground(display, gc, darkGrey.pixel); XDrawLine(display, frame, gc, rc[LEFT].width-1, rc[LEFT].y, rc[LEFT].width-1, rc[LEFT].height-1); break; case RIGHT: XSetForeground(display, gc, gray.pixel); XDrawLine(display, frame, gc, 0, rc[RIGHT].y, 0, rc[RIGHT].height-1); XSetForeground(display, gc, white.pixel); XDrawLine(display, frame, gc, 1, rc[RIGHT].y, 1, rc[RIGHT].height-1); break; } } void Taskbar::DrawTaskbar() { if (hiding) return; StartButton *sButton = (StartButton *)rootQvwm->tButton; int x, y; XPoint xp[3]; XClearWindow(display, w); switch (pos) { case BOTTOM: case TOP: // between start button and taskbar buttons x = sButton->buttonWidth + 2; y = TaskbarButton::rcTButton.y; XSetForeground(display, gc, darkGray.pixel); XDrawLine(display, w, gc, x + 2, y, x + 2, y + rc[pos].height - 7); XSetForeground(display, gc, white.pixel); XDrawLine(display, w, gc, x + 3, y, x + 3, y + rc[pos].height - 7); xp[0].x = x + 7; xp[0].y = y + 2; xp[1].x = x + 6; xp[1].y = y + 2; xp[2].x = x + 6; xp[2].y = y + rc[pos].height - 9; XSetForeground(display, gc, white.pixel); XDrawLines(display, w, gc, xp, 3, CoordModeOrigin); xp[0].x = x + 8; xp[0].y = y + 2; xp[1].x = x + 8; xp[1].y = y + rc[pos].height - 9; xp[2].x = x + 6; xp[2].y = y + rc[pos].height - 9; XSetForeground(display, gc, darkGray.pixel); XDrawLines(display, w, gc, xp, 3, CoordModeOrigin); // line next to taskbar box x = rc[pos].width - dTbox.width - 6; XSetForeground(display, gc, darkGray.pixel); XDrawLine(display, w, gc, x, y, x, y + rc[pos].height - 7); XSetForeground(display, gc, white.pixel); XDrawLine(display, w, gc, x + 1, y, x + 1, y + rc[pos].height - 7); break; case LEFT: case RIGHT: // between start button and taskbar buttons x = TaskbarButton::rcTButton.x; y = TaskbarButton::BUTTON_HEIGHT + 2; XSetForeground(display, gc, darkGray.pixel); XDrawLine(display, w, gc, x, y + 1, x + rc[pos].width - 7, y + 1); XSetForeground(display, gc, white.pixel); XDrawLine(display, w, gc, x, y + 2, x + rc[pos].width - 7, y + 2); xp[0].x = rc[pos].width - 9; xp[0].y = y + 5; xp[1].x = x + 2; xp[1].y = y + 5; xp[2].x = x + 2; xp[2].y = y + 6; XSetForeground(display, gc, white.pixel); XDrawLines(display, w, gc, xp, 3, CoordModeOrigin); xp[0].x = x + 2; xp[0].y = y + 7; xp[1].x = x + rc[pos].width - 9; xp[1].y = y + 7; xp[2].x = x + rc[pos].width - 9; xp[2].y = y + 5; XSetForeground(display, gc, darkGray.pixel); XDrawLines(display, w, gc, xp, 3, CoordModeOrigin); if (rc[pos].width < sButton->buttonWidth + dTbox.width + 19) { // line next to taskbar box y = rc[pos].height - dTbox.height - 9; XSetForeground(display, gc, darkGray.pixel); XDrawLine(display, w, gc, x, y, x + rc[pos].width - 7, y); XSetForeground(display, gc, white.pixel); XDrawLine(display, w, gc, x, y + 1, x + rc[pos].width - 7, y + 1); } break; } } /* * DrawTaskbarBox -- * Draw the indicators and the clock in the taskbar box. */ void Taskbar::DrawTaskbarBox() { XPoint xp[3]; DrawClock(); xp[0].x = dTbox.width - 2; xp[0].y = 0; xp[1].x = 0; xp[1].y = 0; xp[2].x = 0; xp[2].y = dTbox.height - 2; XSetForeground(display, gc, darkGray.pixel); XDrawLines(display, tbox, gc, xp, 3, CoordModeOrigin); xp[0].x = dTbox.width - 1; xp[0].y = 0; xp[1].x = dTbox.width - 1; xp[1].y = dTbox.height - 1; xp[2].x = 0; xp[2].y = dTbox.height - 1; XSetForeground(display, gc, white.pixel); XDrawLines(display, tbox, gc, xp, 3, CoordModeOrigin); } /* * DrawClock -- * Draw the clock in the right or bottom side. */ void Taskbar::DrawClock() { time_t t; struct tm *tm; int len; Point pt; XRectangle ink, log; XClearArea(display, tbox, 1, 1, dTbox.width - 2, dTbox.height - 2, False); time(&t); tm = localtime(&t); strftime(strClk, sizeof(strClk), ClockFormat, tm); len = strlen(strClk); XmbTextExtents(fsTaskbar, strClk, len, &ink, &log); pt.x = indWidth + IC_MARGIN + (clockWidth - log.width) / 2 - log.x; pt.y = (TaskbarButton::BUTTON_HEIGHT - log.height) / 2 - log.y; XSetForeground(display, gc, ClockStringColor.pixel); XmbDrawString(display, tbox, fsTaskbar, gc, pt.x, pt.y, strClk, len); } void Taskbar::AdvanceClock() { time_t t; struct tm *tm; char str[128]; time(&t); tm = localtime(&t); strftime(str, sizeof(str), ClockFormat, tm); if (strcmp(str, strClk) != 0) DrawClock(); timer->SetTimeout(1000, new Callback(this, &Taskbar::AdvanceClock)); } /* * Exposure -- * Process expose event. */ void Taskbar::Exposure(Window win) { if (win == frame) DrawTaskbarFrame(); if (win == w) DrawTaskbar(); else if (win == tbox) DrawTaskbarBox(); } void Taskbar::Button1Press() { Menu::UnmapAllMenus(False); if (!OnTopTaskbar) { RaiseTaskbar(); if (UsePager && OnTopPager) pager->RaisePager(); } } /* * Button1Motion -- * Process drag. */ void Taskbar::Button1Motion(Window win, const Point& ptRoot) { if (win == w) MoveTaskbar(ptRoot); else if (win == frame) ResizeTaskbar(ptRoot); } void Taskbar::Button3Release(const Point& ptRoot) { int dir; Menu::UnmapAllMenus(False); rootQvwm->SetFocus(); Point pt = ctrlMenu->GetFixedMenuPos(ptRoot, dir); ctrlMenu->MapMenu(pt.x, pt.y, dir); } /* * IsTaskbarWindows -- * Return True if the window is taskbar window. */ Bool Taskbar::IsTaskbarWindows(Window win) { if (win == w || win == frame || win == tbox) return True; return False; } void Taskbar::Enter(Window win, const Point& ptRoot, int detail) { if (win == frame) { if (!TaskbarAutoHide) return; if (detail != NotifyInferior) if (!Menu::CheckAnyMenusMapped()) if (hiding) { BasicCallback* cb; cb= new Callback(this, &Taskbar::ShowTaskbar); timer->SetTimeout(TaskbarShowDelay, cb); } } else if (win == tbox) { time_t t; struct tm *tm; time(&t); tm = localtime(&t); strftime(strTip, sizeof(strTip), ClockMessageFormat, tm); toolTip->SetString(strTip, &fsTaskbar); toolTip->SetTimer(); } } void Taskbar::Leave(Window win, const Point& ptRoot, int detail) { if (win == frame) { if (!TaskbarAutoHide) return; if (detail != NotifyInferior) if (!Menu::CheckAnyMenusMapped()) if (!hiding) if (InRect(ptRoot, GetScreenRectOnShowing())) { BasicCallback* cb; cb = new Callback(this, &Taskbar::HideTaskbar); timer->SetTimeout(TaskbarHideDelay, cb); } } else if (win == tbox) toolTip->Disable(); } void Taskbar::PointerMotion() { if (!toolTip->IsMapped()) toolTip->ResetTimer(); } /* * Get the rectangle of screen except taskbar on taskbar showing. */ Rect Taskbar::GetScreenRectOnShowing() const { Rect rcRoot = rootQvwm->GetRect(); switch (pos) { case TOP: return Rect(0, rc[TOP].height, rcRoot.width, rcRoot.height - rc[TOP].height); case BOTTOM: return Rect(0, 0, rcRoot.width, rcRoot.height - rc[BOTTOM].height); case LEFT: return Rect(rc[LEFT].width, 0, rcRoot.width - rc[LEFT].width, rcRoot.height); case RIGHT: return Rect(0, 0, rcRoot.width - rc[RIGHT].width, rcRoot.height); } ASSERT(False); return Rect(0, 0, 0, 0); } /* * Get the rectangle of screen except taskbar on taskbar hiding. */ Rect Taskbar::GetScreenRectOnHiding() const { Rect rcRoot = rootQvwm->GetRect(); switch (pos) { case TOP: return Rect(0, 2, rcRoot.width, rcRoot.height - 2); case BOTTOM: return Rect(0, 0, rcRoot.width, rcRoot.height - 2); case LEFT: return Rect(2, 0, rcRoot.width - 2, rcRoot.height); case RIGHT: return Rect(0, 0, rcRoot.width - 2, rcRoot.height); } ASSERT(False); return Rect(0, 0, 0, 0); } void Taskbar::ShowTaskbar() { if (!hiding) return; hiding = False; Rect rcRoot = rootQvwm->GetRect(); Point pt; if (GradTaskbarMotion) { switch (pos) { case TOP: pt = Point(0, 2 - rc[TOP].height); break; case BOTTOM: pt = Point(0, rcRoot.height - 2); break; case LEFT: pt = Point(2 - rc[LEFT].width, 0); break; case RIGHT: pt = Point(rcRoot.width - 2, 0); break; } for (int i = GradTaskbarMotionSpeed - 1; i >= 0; i--) { XMoveWindow(display, frame, rc[pos].x + (pt.x - rc[pos].x) * i / GradTaskbarMotionSpeed, rc[pos].y + (pt.y - rc[pos].y) * i / GradTaskbarMotionSpeed); XFlush(display); usleep(10000); } } else XMoveWindow(display, frame, rc[pos].x, rc[pos].y); XClearWindow(display, frame); RaiseTaskbar(); if (UsePager && OnTopPager) pager->RaisePager(); } void Taskbar::HideTaskbar() { if (hiding) return; if (startMenu && startMenu->CheckMapped()) return; hiding = True; Rect rcRoot = rootQvwm->GetRect(); Point pt; switch (pos) { case TOP: pt = Point(0, 2 - rc[TOP].height); break; case BOTTOM: pt = Point(0, rcRoot.height - 2); break; case LEFT: pt = Point(2 - rc[LEFT].width, 0); break; case RIGHT: pt = Point(rcRoot.width - 2, 0); break; } if (GradTaskbarMotion) { for (int i = GradTaskbarMotionSpeed - 1; i >= 0; i--) { XMoveWindow(display, frame, pt.x + (rc[pos].x - pt.x) * i / GradTaskbarMotionSpeed, pt.y + (rc[pos].y - pt.y) * i / GradTaskbarMotionSpeed); XFlush(display); usleep(10000); } } else XMoveWindow(display, frame, pt.x, pt.y); XClearWindow(display, frame); if (OnTopTaskbar) RaiseTaskbar(); if (UsePager && OnTopPager) pager->RaisePager(); } /* * RedrawAllTaskbarButtons -- * Redraw all taskbar buttons. */ void Taskbar::RedrawAllTaskbarButtons() { List::Iterator i(&desktop.GetQvwmList()); Qvwm* tmpQvwm; int buttonWidth; int row, col; int buttonNum = 0, count = 0; StartButton *sButton = (StartButton *)rootQvwm->tButton; int x, y; Point offFrame; Rect rcCurPage(paging->origin.x, paging->origin.y, rcScreen.width, rcScreen.height); // get offset between frame and w switch (pos) { case BOTTOM: offFrame = Point(0, 4); break; case TOP: case LEFT: offFrame = Point(0, 0); break; case RIGHT: offFrame = Point(4, 0); break; } ASSERT(sButton); ASSERT(rootQvwm->tButton); XMoveWindow(display, sButton->GetFrameWin(), TaskbarButton::rcTButton.x, TaskbarButton::rcTButton.y); /* * Taskbar buttons are unvisible when the taskbar is shown minimumly. */ if (rc[pos].height == 6) TaskbarButton::rcTButton.y = -10000; if (rc[pos].width == 6) TaskbarButton::rcTButton.x = -10000; /* * Adjust the position and the size of the start button. */ Rect rect = sButton->GetRect(); rect.x = TaskbarButton::rcTButton.x; rect.y = TaskbarButton::rcTButton.y; if (rc[pos].width > sButton->buttonWidth + 6) rect.width = sButton->buttonWidth; else { rect.width = rc[pos].width - 6; if (rect.width == 0) rect.width = 1; } sButton->MoveResizeButton(rect); if (TaskbarImage) { sButton->SetBgImage(imgTaskbar, offFrame + Point(rect.x, rect.y)); sButton->SetBgActiveImage(imgTaskbar, offFrame + Point(rect.x, rect.y - 1)); sButton->DrawButton(); } // Count the number of taskbar buttons. for (tmpQvwm = i.GetHead(); tmpQvwm; tmpQvwm = i.GetNext()) { if (!tmpQvwm->CheckFlags(TRANSIENT) && !tmpQvwm->CheckFlags(NO_TBUTTON) && (tmpQvwm->CheckMapped() || tmpQvwm->CheckStatus(MINIMIZE_WINDOW))) { if (TaskbarButtonInScr) { // count only taskbar buttons in the current page if (!Intersect(tmpQvwm->GetRect(), rcCurPage)) continue; } buttonNum++; } } if (buttonNum == 0) return; /* * According to taskbar position, determine the way arranging buttons. */ switch (pos) { case BOTTOM: case TOP: row = rc[pos].height / (TaskbarButton::rcTButton.height + BETWEEN_SPACE); if (row == 0) row = 1; // quick hack buttonWidth = buttonArea * row / RoundUp(buttonNum, row) - BETWEEN_SPACE; if (buttonWidth > TaskbarButton::rcTButton.width) buttonWidth = TaskbarButton::rcTButton.width; if (buttonWidth == 0) buttonWidth = 1; col = buttonArea / buttonWidth; break; case LEFT: case RIGHT: row = buttonArea / (TaskbarButton::rcTButton.height + BETWEEN_SPACE); col = (buttonNum + row - 1) / row; buttonWidth = (rc[pos].width - 5) / col - BETWEEN_SPACE; if (buttonWidth == 0) buttonWidth = 1; break; default: col = row = buttonWidth = 0; // XXX for warning ASSERT(False); } /* * Reposition all taskbar buttons. */ for (tmpQvwm = i.GetHead(); tmpQvwm; tmpQvwm = i.GetNext()) { if (tmpQvwm->CheckFlags(TRANSIENT) || tmpQvwm->CheckFlags(NO_TBUTTON) || (!tmpQvwm->CheckMapped() && !tmpQvwm->CheckStatus(MINIMIZE_WINDOW))) continue; TaskbarButton* tb = tmpQvwm->tButton; if (TaskbarButtonInScr) { // show only taskbar buttons in the current page if (!Intersect(tmpQvwm->GetRect(), rcCurPage)) { tb->MoveResizeButton(Rect(-1, -1, 1, 1)); // hide continue; } } switch (pos) { case BOTTOM: case TOP: x = TaskbarButton::rcTButton.x + sButton->buttonWidth + 13 + (buttonWidth + BETWEEN_SPACE) * (count % col); y = TaskbarButton::rcTButton.y + (count / col) * (TaskbarButton::rcTButton.height + BETWEEN_SPACE); break; case LEFT: case RIGHT: x = TaskbarButton::rcTButton.x + (count % col) * (buttonWidth + BETWEEN_SPACE); y = TaskbarButton::rcTButton.y + TaskbarButton::BUTTON_HEIGHT + 12 + (TaskbarButton::rcTButton.height + BETWEEN_SPACE) * (count / col); break; default: x = y = 0; // XXX for warning ASSERT(False); } count++; tb->MoveResizeButton(Rect(x, y, buttonWidth, TaskbarButton::rcTButton.height)); if (TaskbarImage) { tb->SetBgImage(imgTaskbar, offFrame + Point(x, y)); tb->SetBgActiveImage(imgTaskbar, offFrame + Point(x, y - 1)); tb->DrawButton(); } } } void Taskbar::Initialize() { BASE_HEIGHT = TaskbarButton::BUTTON_HEIGHT + 6; INC_HEIGHT = TaskbarButton::BUTTON_HEIGHT + BETWEEN_SPACE; }