mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
255 lines
7.2 KiB
C++
255 lines
7.2 KiB
C++
|
//
|
||
|
// WorkspaceIndicator.hh for pekwm
|
||
|
// Copyright © 2009 Claes Nästén <me@pekdon.net>
|
||
|
//
|
||
|
// This program is licensed under the GNU GPL.
|
||
|
// See the LICENSE file for more information.
|
||
|
//
|
||
|
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
#include "config.h"
|
||
|
#endif // HAVE_CONFIG_H
|
||
|
|
||
|
#include <iostream>
|
||
|
|
||
|
#include "Config.hh"
|
||
|
#include "PixmapHandler.hh"
|
||
|
#include "PScreen.hh"
|
||
|
#include "ScreenResources.hh"
|
||
|
#include "Workspaces.hh"
|
||
|
#include "WorkspaceIndicator.hh"
|
||
|
|
||
|
using std::cerr;
|
||
|
using std::endl;
|
||
|
using std::vector;
|
||
|
|
||
|
/**
|
||
|
* Display constructor
|
||
|
*/
|
||
|
WorkspaceIndicator::Display::Display(PWinObj *parent, Theme *theme)
|
||
|
: PWinObj(),
|
||
|
_theme(theme), _pixmap(None)
|
||
|
{
|
||
|
_parent = parent;
|
||
|
// Do not give the indicator focus, it doesn't handle input
|
||
|
_focusable = false;
|
||
|
|
||
|
XSetWindowAttributes attr;
|
||
|
attr.override_redirect = false;
|
||
|
attr.event_mask = ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|
|
||
|
FocusChangeMask|KeyPressMask|KeyReleaseMask;
|
||
|
_window = XCreateWindow(_dpy, _parent->getWindow(), 0, 0, 1, 1, 0,
|
||
|
CopyFromParent, InputOutput, CopyFromParent,
|
||
|
CWOverrideRedirect|CWEventMask, &attr);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Display destructor
|
||
|
*/
|
||
|
WorkspaceIndicator::Display::~Display(void)
|
||
|
{
|
||
|
XDestroyWindow(_dpy, _window);
|
||
|
ScreenResources::instance()->getPixmapHandler()->returnPixmap(_pixmap);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get required size to render workspaces.
|
||
|
*/
|
||
|
bool
|
||
|
WorkspaceIndicator::Display::getSizeRequest(Geometry &gm)
|
||
|
{
|
||
|
Geometry head;
|
||
|
uint head_nr = PScreen::instance()->getNearestHead(_parent->getX(), _parent->getY());
|
||
|
PScreen::instance()->getHeadInfo(head_nr, head);
|
||
|
|
||
|
uint head_size = std::min(head.width, head.height) / Config::instance()->getWorkspaceIndicatorScale();
|
||
|
gm.x = gm.y = 0;
|
||
|
gm.width = head_size * Workspaces::instance()->getPerRow() + getPaddingHorizontal();
|
||
|
gm.height = head_size * Workspaces::instance()->getRows() + getPaddingVertical();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render workspace view to pixmap
|
||
|
*/
|
||
|
void
|
||
|
WorkspaceIndicator::Display::render(void)
|
||
|
{
|
||
|
Theme::WorkspaceIndicatorData &data(_theme->getWorkspaceIndicatorData());
|
||
|
|
||
|
// Make sure pixmap has correct size
|
||
|
ScreenResources::instance()->getPixmapHandler()->returnPixmap(_pixmap);
|
||
|
_pixmap = ScreenResources::instance()->getPixmapHandler()->getPixmap(_gm.width, _gm.height,
|
||
|
PScreen::instance()->getDepth());
|
||
|
|
||
|
// Render background
|
||
|
data.texture_background->render(_pixmap, 0, 0, _gm.width, _gm.height);
|
||
|
|
||
|
// Render workspace grid, then active workspace fill and end with
|
||
|
// rendering active workspace number and name
|
||
|
renderWorkspaces(data.edge_padding, data.edge_padding,
|
||
|
_gm.width - getPaddingHorizontal(),
|
||
|
_gm.height - getPaddingVertical());
|
||
|
|
||
|
data.font->setColor(data.font_color);
|
||
|
data.font->draw(_pixmap, data.edge_padding, _gm.height - data.edge_padding - data.font->getHeight(),
|
||
|
Workspaces::instance()->getActiveWorkspace()->getName(),
|
||
|
0 /* max_chars */, _gm.width - data.edge_padding * 2 /* max_width */);
|
||
|
|
||
|
// Refresh
|
||
|
setBackgroundPixmap(_pixmap);
|
||
|
clear();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render workspace part of indication
|
||
|
*
|
||
|
* @param x X offset on drawable
|
||
|
* @param y Y offset on drawable
|
||
|
* @param width Allowed width to use
|
||
|
* @param height Allowed height to use
|
||
|
*/
|
||
|
void
|
||
|
WorkspaceIndicator::Display::renderWorkspaces(int x, int y, uint width, uint height)
|
||
|
{
|
||
|
Theme::WorkspaceIndicatorData &data(_theme->getWorkspaceIndicatorData());
|
||
|
|
||
|
uint per_row = Workspaces::instance()->getPerRow();
|
||
|
uint rows = Workspaces::instance()->getRows();
|
||
|
|
||
|
uint ws_width = width / per_row;
|
||
|
uint ws_height = height / rows;
|
||
|
|
||
|
// Starting positions of the workspace squares
|
||
|
uint x_pos = x;
|
||
|
uint y_pos = y;
|
||
|
|
||
|
vector<Workspaces::Workspace*>::iterator it(Workspaces::instance()->ws_begin());
|
||
|
|
||
|
for (uint row = 0; it != Workspaces::instance()->ws_end(); ++it) {
|
||
|
// Check for next row
|
||
|
if (Workspaces::instance()->getRow((*it)->getNumber()) > row) {
|
||
|
row = Workspaces::instance()->getRow((*it)->getNumber());
|
||
|
|
||
|
x_pos = x;
|
||
|
y_pos += ws_height + data.workspace_padding;
|
||
|
}
|
||
|
|
||
|
if ((*it)->getNumber() == Workspaces::instance()->getActive()) {
|
||
|
data.texture_workspace_act->render(_pixmap, x_pos, y_pos, ws_width, ws_height);
|
||
|
} else {
|
||
|
data.texture_workspace->render(_pixmap, x_pos, y_pos, ws_width, ws_height);
|
||
|
}
|
||
|
|
||
|
x_pos += ws_width + data.workspace_padding;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get horizontal padding for window around workspaces.
|
||
|
*/
|
||
|
uint
|
||
|
WorkspaceIndicator::Display::getPaddingHorizontal(void)
|
||
|
{
|
||
|
Theme::WorkspaceIndicatorData &data(_theme->getWorkspaceIndicatorData());
|
||
|
|
||
|
return (data.edge_padding * 2 + data.workspace_padding * (Workspaces::instance()->getPerRow() - 1));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get vertical padding for window around workspaces.
|
||
|
*/
|
||
|
uint
|
||
|
WorkspaceIndicator::Display::getPaddingVertical(void)
|
||
|
{
|
||
|
Theme::WorkspaceIndicatorData &data(_theme->getWorkspaceIndicatorData());
|
||
|
|
||
|
return (data.edge_padding * 3 + data.font->getHeight()
|
||
|
+ data.workspace_padding * (Workspaces::instance()->getRows() - 1));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* WorkspaceIndicator constructor
|
||
|
*/
|
||
|
WorkspaceIndicator::WorkspaceIndicator(Theme *theme, Timer<ActionPerformed> &timer)
|
||
|
: PDecor(theme, "WORKSPACEINDICATOR"),
|
||
|
_timer(timer), _display_wo(this, theme),
|
||
|
_timer_hide(0)
|
||
|
{
|
||
|
_type = PWinObj::WO_WORKSPACE_INDICATOR;
|
||
|
setLayer(LAYER_NONE); // Make sure this goes on top of everything
|
||
|
_hidden = true; // Do not include in workspace handling etc
|
||
|
|
||
|
// Add hide action to timer action
|
||
|
_action_hide.action_list.push_back(Action(ACTION_HIDE_WORKSPACE_INDICATOR));
|
||
|
|
||
|
// Add title
|
||
|
titleAdd(&_title);
|
||
|
titleSetActive(0);
|
||
|
_title.setReal(L"Workspace");
|
||
|
|
||
|
// Add display window
|
||
|
addChild(&_display_wo);
|
||
|
activateChild(&_display_wo);
|
||
|
_display_wo.mapWindow();
|
||
|
|
||
|
// Load theme data, horay for pretty colors
|
||
|
loadTheme();
|
||
|
|
||
|
// Register ourselves
|
||
|
Workspaces::instance()->insert(this);
|
||
|
woListAdd(this);
|
||
|
_wo_map[_window] = this;
|
||
|
|
||
|
#ifdef OPACITY
|
||
|
setOpacity(Config::instance()->getWorkspaceIndicatorOpacity());
|
||
|
#endif // OPACITY
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* WorkspaceIndicator destructor
|
||
|
*/
|
||
|
WorkspaceIndicator::~WorkspaceIndicator(void)
|
||
|
{
|
||
|
removeChild(&_display_wo, false);
|
||
|
|
||
|
// Un-register ourselves
|
||
|
Workspaces::instance()->remove(this);
|
||
|
_wo_map.erase(_window);
|
||
|
woListRemove(this);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Resize indicator and render
|
||
|
*/
|
||
|
void
|
||
|
WorkspaceIndicator::render(void)
|
||
|
{
|
||
|
// Center on head
|
||
|
Geometry head, request;
|
||
|
PScreen::instance()->getHeadInfo(PScreen::instance()->getCurrHead(), head);
|
||
|
|
||
|
_display_wo.getSizeRequest(request);
|
||
|
resizeChild(request.width, request.height);
|
||
|
|
||
|
move(head.x + (head.width - _gm.width) / 2,
|
||
|
head.y + (head.height - _gm.height) / 2);
|
||
|
|
||
|
// Render workspaces
|
||
|
_display_wo.render();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Remove previous timer and add new hide timer for timeout seconds in
|
||
|
* the future.
|
||
|
*/
|
||
|
void
|
||
|
WorkspaceIndicator::updateHideTimer(uint timeout)
|
||
|
{
|
||
|
if (_timer_hide) {
|
||
|
_timer.remove(_timer_hide);
|
||
|
}
|
||
|
_timer_hide = _timer.add(timeout, ActionPerformed(this, _action_hide));
|
||
|
}
|