dockapps/wmmixer/xhandler.cc
2014-10-05 19:18:49 +01:00

558 lines
17 KiB
C++

// wmmixer - A mixer designed for WindowMaker
//
// Release 1.5
// Copyright (C) 1998 Sam Hawker <shawkie@geocities.com>
// Copyright (C) 2002 Gordon Fraser <gordon@debian.org>
// This software comes with ABSOLUTELY NO WARRANTY
// This software is free software, and you are welcome to redistribute it
// under certain conditions
// See the COPYING file for details.
#include "xhandler.h"
//--------------------------------------------------------------------
XHandler::XHandler()
{
is_wmaker_ = WINDOWMAKER;
is_ushape_ = USESHAPE;
is_astep_ = AFTERSTEP;
strcpy(display_name_, "");
strcpy(position_name_, "");
strcpy(ledcolor_name_, LEDCOLOR);
strcpy(ledcolor_high_name_, LEDCOLOR_HIGH);
strcpy(backcolor_name_, BACKCOLOR);
strcpy(window_class_, CLASS);
button_state_ = 0;
icon_list_ = NULL;
}
//--------------------------------------------------------------------
XHandler::~XHandler()
{
XFreeGC(display_default_, graphics_context_);
XFreePixmap(display_default_, pixmap_main);
XFreePixmap(display_default_, pixmap_tile);
XFreePixmap(display_default_, pixmap_disp);
XFreePixmap(display_default_, pixmap_mask);
XFreePixmap(display_default_, pixmap_icon);
XFreePixmap(display_default_, pixmap_nrec);
XDestroyWindow(display_default_, window_main_);
if(is_wmaker_)
XDestroyWindow(display_default_, window_icon_);
XCloseDisplay(display_default_);
delete[] icon_list_;
}
//--------------------------------------------------------------------
void XHandler::init(int argc, char** argv, int num_channels)
{
int display_depth;
window_size_=is_astep_ ? ASTEPSIZE : NORMSIZE;
if((display_default_ = XOpenDisplay(display_name_))==NULL)
{
std::cerr << NAME << " : Unable to open X display '" << XDisplayName(display_name_) << "'." << std::endl;
exit(1);
}
initWindow(argc, argv);
initColors();
display_depth = DefaultDepth(display_default_, DefaultScreen(display_default_));
initPixmaps(display_depth);
initGraphicsContext();
initMask();
initIcons(num_channels);
}
//--------------------------------------------------------------------
bool XHandler::isLeftButton(int x, int y)
{
return(x>=BTN_LEFT_X && y>=BTN_LEFT_Y && x<=BTN_LEFT_X + BTN_WIDTH && y<=BTN_LEFT_Y + BTN_HEIGHT);
}
//--------------------------------------------------------------------
bool XHandler::isRightButton(int x, int y)
{
return(x>=BTN_RIGHT_X && y>=BTN_RIGHT_Y && x<=BTN_RIGHT_X + BTN_WIDTH && y<=BTN_RIGHT_Y + BTN_HEIGHT);
}
//--------------------------------------------------------------------
bool XHandler::isMuteButton(int x, int y)
{
return(x>=BTN_MUTE_X && y>=BTN_MUTE_Y && x<=BTN_MUTE_X + BTN_WIDTH && y<=BTN_MUTE_Y + BTN_HEIGHT);
}
//--------------------------------------------------------------------
bool XHandler::isRecButton(int x, int y)
{
return(x>=BTN_REC_X && y>=BTN_REC_Y && x<=BTN_REC_X + BTN_WIDTH && y<=BTN_REC_Y + BTN_HEIGHT);
}
//--------------------------------------------------------------------
bool XHandler::isVolumeBar(int x, int y)
{
return(x>=37 && x<=56 && y>=8 && y<=56);
}
//--------------------------------------------------------------------
unsigned long XHandler::getColor(char *colorname)
{
XColor color;
XWindowAttributes winattr;
XGetWindowAttributes(display_default_, window_root_, &winattr);
color.pixel=0;
XParseColor(display_default_, winattr.colormap, colorname, &color);
color.flags=DoRed | DoGreen | DoBlue;
XAllocColor(display_default_, winattr.colormap, &color);
return color.pixel;
}
//--------------------------------------------------------------------
unsigned long XHandler::mixColor(char *colorname1, int prop1, char *colorname2, int prop2)
{
XColor color, color1, color2;
XWindowAttributes winattr;
XGetWindowAttributes(display_default_, window_root_, &winattr);
XParseColor(display_default_, winattr.colormap, colorname1, &color1);
XParseColor(display_default_, winattr.colormap, colorname2, &color2);
color.pixel = 0;
color.red = (color1.red*prop1+color2.red*prop2)/(prop1+prop2);
color.green = (color1.green*prop1+color2.green*prop2)/(prop1+prop2);
color.blue = (color1.blue*prop1+color2.blue*prop2)/(prop1+prop2);
color.flags = DoRed | DoGreen | DoBlue;
XAllocColor(display_default_, winattr.colormap, &color);
return color.pixel;
}
//--------------------------------------------------------------------
void XHandler::repaint()
{
flush_expose(window_icon_);
XCopyArea(display_default_, pixmap_disp, window_icon_, graphics_context_, 0, 0, 64, 64, window_size_/2-32, window_size_/2-32);
flush_expose(window_main_);
XCopyArea(display_default_, pixmap_disp, window_main_, graphics_context_, 0, 0, 64, 64, window_size_/2-32, window_size_/2-32);
XEvent xev;
while(XCheckTypedEvent(display_default_, Expose, &xev));
}
//--------------------------------------------------------------------
void XHandler::update(unsigned channel)
{
if(is_wmaker_ || is_ushape_ || is_astep_)
{
XShapeCombineMask(display_default_, window_icon_, ShapeBounding, window_size_/2-32, window_size_/2-32, pixmap_mask, ShapeSet);
XShapeCombineMask(display_default_, window_main_, ShapeBounding, window_size_/2-32, window_size_/2-32, pixmap_mask, ShapeSet);
}
else
{
XCopyArea(display_default_, pixmap_tile, pixmap_disp, graphics_context_, 0, 0, 64, 64, 0, 0);
}
XSetClipMask(display_default_, graphics_context_, pixmap_mask);
XCopyArea(display_default_, pixmap_main, pixmap_disp, graphics_context_, 0, 0, 64, 64, 0, 0);
XSetClipMask(display_default_, graphics_context_, None);
XCopyArea(display_default_, pixmap_icon, pixmap_disp, graphics_context_, icon_list_[channel]*22, 0, 22, 22, 6, 5);
}
//--------------------------------------------------------------------
void XHandler::drawLeft(unsigned curleft)
{
XSetForeground(display_default_, graphics_context_, shade_colors_[(curleft*25)/100]);
for(unsigned i=0;i<25;i++)
{
if(i >= (curleft*25)/100)
{
XSetForeground(display_default_, graphics_context_, colors_[3]);
}
else
{
XSetForeground(display_default_, graphics_context_, shade_colors_[i]);
}
XFillRectangle(display_default_, pixmap_disp, graphics_context_, 37, 55-2*i, 9, 1);
}
}
//--------------------------------------------------------------------
void XHandler::drawRight(unsigned curright)
{
for(unsigned i=0;i<25;i++)
{
if(i >= (curright*25)/100)
{
XSetForeground(display_default_, graphics_context_, colors_[3]);
}
else
{
XSetForeground(display_default_, graphics_context_, shade_colors_[i]);
}
XFillRectangle(display_default_, pixmap_disp, graphics_context_, 48, 55-2*i, 9, 1);
}
}
//--------------------------------------------------------------------
// Based on wmsmixer by Damian Kramer <psiren@hibernaculum.demon.co.uk>
void XHandler::drawMono(unsigned curright)
{
XSetForeground(display_default_, graphics_context_, colors_[1]);
for(unsigned i=0;i<25;i++)
{
if(i >= (curright*25)/100)
{
XSetForeground(display_default_, graphics_context_, colors_[3]);
}
else
{
XSetForeground(display_default_, graphics_context_, shade_colors_[i]);
}
XFillRectangle(display_default_, pixmap_disp, graphics_context_, 37, 55-2*i, 20, 1);
}
}
//--------------------------------------------------------------------
void XHandler::drawBtns(int buttons, bool curshowrec)
{
if(buttons & BTNPREV)
drawButton(BTN_LEFT_X, BTN_LEFT_Y, BTN_WIDTH, BTN_HEIGHT, (button_state_ & BTNPREV));
if(buttons & BTNNEXT)
drawButton(BTN_RIGHT_X, BTN_RIGHT_Y, BTN_WIDTH, BTN_HEIGHT, (button_state_ & BTNNEXT));
if(buttons & BTNMUTE)
drawButton(BTN_MUTE_X, BTN_MUTE_Y, BTN_WIDTH, BTN_HEIGHT, (button_state_ & BTNMUTE));
if(buttons & BTNREC){
drawButton(BTN_REC_X, BTN_REC_Y, BTN_WIDTH, BTN_HEIGHT, (button_state_ & BTNREC));
if(!curshowrec)
XCopyArea(display_default_, pixmap_nrec, pixmap_disp, graphics_context_, 0, 0, 9, 8, 6, 47);
else
XCopyArea(display_default_, pixmap_main, pixmap_disp, graphics_context_, 6, 48, 9, 8, 6, 47);
}
}
//--------------------------------------------------------------------
void XHandler::drawButton(int x, int y, int w, int h, bool down)
{
if(!down)
XCopyArea(display_default_, pixmap_main, pixmap_disp, graphics_context_, x, y, w, h, x, y);
else {
XCopyArea(display_default_, pixmap_main, pixmap_disp, graphics_context_, x, y, 1, h-1, x+w-1, y+1);
XCopyArea(display_default_, pixmap_main, pixmap_disp, graphics_context_, x+w-1, y+1, 1, h-1, x, y);
XCopyArea(display_default_, pixmap_main, pixmap_disp, graphics_context_, x, y, w-1, 1, x+1, y+h-1);
XCopyArea(display_default_, pixmap_main, pixmap_disp, graphics_context_, x+1, y+h-1, w-1, 1, x, y);
}
}
//--------------------------------------------------------------------
int XHandler::flush_expose(Window w)
{
XEvent dummy;
int i=0;
while (XCheckTypedWindowEvent(display_default_, w, Expose, &dummy))
i++;
return i;
}
//--------------------------------------------------------------------
int XHandler::getWindowSize()
{
return window_size_;
}
//--------------------------------------------------------------------
// --> inline
//Display* XHandler::getDisplay()
//{
// return display_default_;
//}
//--------------------------------------------------------------------
int XHandler::getButtonState()
{
return button_state_;
}
//--------------------------------------------------------------------
void XHandler::setButtonState(int button_state)
{
button_state_ = button_state;
}
//--------------------------------------------------------------------
void XHandler::setDisplay(char* arg)
{
sprintf(display_name_, "%s", arg);
}
//--------------------------------------------------------------------
void XHandler::setPosition(char* arg)
{
sprintf(position_name_, "%s", arg);
}
//--------------------------------------------------------------------
void XHandler::setLedColor(char* arg)
{
sprintf(ledcolor_name_, "%s", arg);
}
//--------------------------------------------------------------------
void XHandler::setLedHighColor(char* arg)
{
sprintf(ledcolor_high_name_, "%s", arg);
}
//--------------------------------------------------------------------
void XHandler::setBackColor(char* arg)
{
sprintf(backcolor_name_, "%s", arg);
}
//--------------------------------------------------------------------
void XHandler::setWindowClass(char* arg)
{
snprintf(window_class_, 254, "%s", arg);
}
//--------------------------------------------------------------------
void XHandler::setUnshaped()
{
is_ushape_ = 1;
}
//--------------------------------------------------------------------
void XHandler::setWindowMaker()
{
is_wmaker_ = 1;
}
//--------------------------------------------------------------------
void XHandler::setAfterStep()
{
is_astep_ = 1;
}
//--------------------------------------------------------------------
Atom XHandler::getDeleteWin()
{
return deleteWin;
}
//--------------------------------------------------------------------
void XHandler::initIcons(int num)
{
if(icon_list_)
delete[] icon_list_;
icon_list_ = new unsigned[num];
icon_list_[0] = 0;
icon_list_[1] = 7;
icon_list_[2] = 8;
icon_list_[3] = 2;
icon_list_[4] = 1;
icon_list_[5] = 6;
icon_list_[6] = 4;
icon_list_[7] = 5;
icon_list_[8] = 3;
for(int counter=9; counter<num; counter++)
icon_list_[counter] = 9;
}
//--------------------------------------------------------------------
void XHandler::initGraphicsContext()
{
XGCValues gcv;
unsigned long gcm;
gcm = GCForeground | GCBackground | GCGraphicsExposures;
gcv.graphics_exposures = 0;
gcv.foreground = fore_pix;
gcv.background = back_pix;
graphics_context_ = XCreateGC(display_default_, window_root_, gcm, &gcv);
}
//--------------------------------------------------------------------
void XHandler::initPixmaps(int display_depth)
{
XpmColorSymbol const xpmcsym[4]={{(char *)"back_color", NULL, colors_[0]},
{(char *)"led_color_high", NULL, colors_[1]},
{(char *)"led_color_med", NULL, colors_[2]},
{(char *)"led_color_low", NULL, colors_[3]}};
XpmAttributes xpmattr;
xpmattr.numsymbols = 4;
xpmattr.colorsymbols = (XpmColorSymbol *)xpmcsym;
xpmattr.exactColors = false;
xpmattr.closeness = 40000;
xpmattr.valuemask = XpmColorSymbols | XpmExactColors | XpmCloseness;
XpmCreatePixmapFromData(display_default_, window_root_, (char **)wmmixer_xpm, &pixmap_main, &pixmap_mask, &xpmattr);
XpmCreatePixmapFromData(display_default_, window_root_, (char **)tile_xpm, &pixmap_tile, NULL, &xpmattr);
XpmCreatePixmapFromData(display_default_, window_root_, (char **)icons_xpm, &pixmap_icon, NULL, &xpmattr);
XpmCreatePixmapFromData(display_default_, window_root_, (char **)norec_xpm, &pixmap_nrec, NULL, &xpmattr);
pixmap_disp = XCreatePixmap(display_default_, window_root_, 64, 64, display_depth);
}
//--------------------------------------------------------------------
void XHandler::initWindow(int argc, char** argv)
{
char *wname = argv[0];
int screen, dummy = 0;
XWMHints wmhints;
XSizeHints shints;
XClassHint classHint;
XTextProperty name;
screen = DefaultScreen(display_default_);
_XA_GNUSTEP_WM_FUNC = XInternAtom(display_default_, "_GNUSTEP_WM_FUNCTION", false);
deleteWin = XInternAtom(display_default_, "WM_DELETE_WINDOW", false);
shints.x = 0;
shints.y = 0;
// shints.flags = USSize;
shints.flags = 0; // Gordon
bool pos = (XWMGeometry(display_default_, DefaultScreen(display_default_),
position_name_, NULL, 0, &shints, &shints.x, &shints.y,
&shints.width, &shints.height, &dummy)
& (XValue | YValue));
shints.min_width = window_size_;
shints.min_height = window_size_;
shints.max_width = window_size_;
shints.max_height = window_size_;
shints.base_width = window_size_;
shints.base_height = window_size_;
shints.width = window_size_;
shints.height = window_size_;
shints.flags=PMinSize | PMaxSize | PBaseSize; // Gordon
window_root_ = RootWindow(display_default_, screen);
back_pix = getColor((char *)"white");
fore_pix = getColor((char *)"black");
window_main_ = XCreateSimpleWindow(display_default_, window_root_, shints.x, shints.y,
shints.width, shints.height, 0, fore_pix, back_pix);
window_icon_ = XCreateSimpleWindow(display_default_, window_root_, shints.x, shints.y,
shints.width, shints.height, 0, fore_pix, back_pix);
XSetWMNormalHints(display_default_, window_main_, &shints);
wmhints.icon_x = shints.x;
wmhints.icon_y = shints.y;
if(is_wmaker_ || is_astep_ || pos)
shints.flags |= USPosition;
if(is_wmaker_)
{
wmhints.initial_state = WithdrawnState;
wmhints.flags = StateHint | IconWindowHint | IconPositionHint | WindowGroupHint;
wmhints.icon_window = window_icon_;
wmhints.icon_x = shints.x;
wmhints.icon_y = shints.y;
wmhints.window_group = window_main_;
}
else
{
wmhints.initial_state = NormalState;
wmhints.flags = WindowGroupHint | StateHint;
}
classHint.res_name=(char *)NAME;
classHint.res_class = window_class_;
XSetClassHint(display_default_, window_main_, &classHint);
XSetClassHint(display_default_, window_icon_, &classHint);
if (XStringListToTextProperty(&wname, 1, &name) == 0)
{
std::cerr << wname << ": can't allocate window name" << std::endl;
exit(1);
}
XSetWMName(display_default_, window_main_, &name);
XSetWMHints(display_default_, window_main_, &wmhints);
XSetCommand(display_default_, window_main_, argv, argc);
XSetWMProtocols(display_default_, window_main_, &deleteWin, 1); // Close
}
//--------------------------------------------------------------------
// Initialize main colors and shaded color-array for bars
void XHandler::initColors()
{
colors_[0] = mixColor(ledcolor_name_, 0, backcolor_name_, 100);
colors_[1] = mixColor(ledcolor_name_, 100, backcolor_name_, 0);
colors_[2] = mixColor(ledcolor_name_, 60, backcolor_name_, 40);
colors_[3] = mixColor(ledcolor_name_, 25, backcolor_name_, 75);
for(int count=0; count<25; count++)
{
shade_colors_[count] = mixColor(ledcolor_high_name_, count*2, ledcolor_name_, 100-count*4);
}
}
//--------------------------------------------------------------------
void XHandler::initMask()
{
XSetClipMask(display_default_, graphics_context_, pixmap_mask);
XCopyArea( display_default_, pixmap_main, pixmap_disp, graphics_context_, 0, 0, 64, 64, 0, 0);
XSetClipMask(display_default_, graphics_context_, None);
XStoreName( display_default_, window_main_, NAME);
XSetIconName(display_default_, window_main_, NAME);
if(is_wmaker_ || is_ushape_ || is_astep_)
{
XShapeCombineMask(display_default_, window_icon_, ShapeBounding, window_size_/2-32, window_size_/2-32, pixmap_mask, ShapeSet);
XShapeCombineMask(display_default_, window_main_, ShapeBounding, window_size_/2-32, window_size_/2-32, pixmap_mask, ShapeSet);
}
else
{
XCopyArea(display_default_, pixmap_tile, pixmap_disp, graphics_context_, 0, 0, 64, 64, 0, 0);
}
XSelectInput(display_default_, window_main_, ButtonPressMask | ExposureMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
XSelectInput(display_default_, window_icon_, ButtonPressMask | ExposureMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
XMapWindow(display_default_, window_main_);
}