/*
* tooltip.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 <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>
#include "main.h"
#include "tooltip.h"
#include "misc.h"
#include "timer.h"
#include "qvwmrc.h"
#include "util.h"
XContext Tooltip::context;
#define XMARGIN 3
#define YMARGIN 1
Tooltip::Tooltip(char* str, XFontSet* fs)
: m_str(str), m_fs(fs)
{
m_win = None;
m_mapped = False;
}
void Tooltip::CreateWindow()
{
XSetWindowAttributes attributes;
unsigned long valueMask;
XRectangle ink, log;
if (m_fs == NULL)
m_fs = &fsTitle;
XmbTextExtents(*m_fs, m_str, strlen(m_str), &ink, &log);
m_rc.x = log.x;
m_rc.y = log.y;
m_rc.width = log.width + XMARGIN * 2;
m_rc.height = log.height + YMARGIN * 2;
attributes.event_mask = ExposureMask;
attributes.background_pixel = TooltipColor.pixel;
attributes.border_pixel = TooltipStringColor.pixel;
attributes.override_redirect = True;
valueMask = CWBackPixel | CWBorderPixel | CWOverrideRedirect | CWEventMask;
m_win = XCreateWindow(display, root,
0, 0, m_rc.width, m_rc.height,
1, CopyFromParent, InputOutput, CopyFromParent,
valueMask, &attributes);
XSaveContext(display, m_win, context, (caddr_t)this);
m_mapped = False;
}
Tooltip::~Tooltip()
{
Disable();
if (m_win != None) {
XDeleteContext(display, m_win, context);
XDestroyWindow(display, m_win);
}
}
void Tooltip::SetString(char* str, XFontSet* fs)
{
if (str == NULL)
return;
m_str = str;
m_fs = fs;
m_rc.width = 0;
}
void Tooltip::MapTooltip()
{
Window junkRoot, junkChild;
Point ptRoot, ptJunk, pt;
unsigned int mask;
if (m_str == NULL)
return;
// on-demand creation
if (m_win == None)
CreateWindow();
// on-demand resize
if (m_rc.width == 0)
ResizeTooltip();
XQueryPointer(display, root, &junkRoot, &junkChild, &ptRoot.x, &ptRoot.y,
&ptJunk.x, &ptJunk.y, &mask);
pt = AdjustPosition(ptRoot);
if (ptRoot.y < pt.y)
XMoveResizeWindow(display, m_win, pt.x, pt.y, m_rc.width, 1);
else
XMoveResizeWindow(display, m_win, pt.x, pt.y - m_rc.height, m_rc.width, 1);
XMapRaised(display, m_win);
for (int i = 1; i <= TooltipMotionSpeed; i++) {
int height = m_rc.height * i / TooltipMotionSpeed;
int y;
if (height == 0)
height = 1;
if (ptRoot.y < pt.y)
y = pt.y;
else
y = pt.y + m_rc.height - height;
XMoveResizeWindow(display, m_win, pt.x, y, m_rc.width, height);
XFlush(display);
usleep(10000);
}
m_mapped = True;
timer->SetTimeout(TooltipDisplayTime,
new Callback<Tooltip>(this, &Tooltip::UnmapTooltip));
}
void Tooltip::ResizeTooltip()
{
XRectangle ink, log;
if (m_fs == NULL)
m_fs = &fsTitle;
XmbTextExtents(*m_fs, m_str, strlen(m_str), &ink, &log);
m_rc.x = log.x;
m_rc.y = log.y;
m_rc.width = log.width + XMARGIN * 2;
m_rc.height = log.height + YMARGIN * 2;
}
Point Tooltip::AdjustPosition(const Point& pt)
{
Dim szRoot(DisplayWidth(display, screen), DisplayHeight(display, screen));
Point ptAdj;
if (pt.x + m_rc.width >= szRoot.width - 2) {
ptAdj.x = szRoot.width - 2 - m_rc.width;
if (ptAdj.x < 2)
ptAdj.x = 2;
}
else
ptAdj.x = pt.x;
if (pt.y + 19 + m_rc.height >= szRoot.height - 1)
ptAdj.y = szRoot.height - 1 - m_rc.height - 23;
else
ptAdj.y = pt.y + 19;
return ptAdj;
}
void Tooltip::UnmapTooltip()
{
XUnmapWindow(display, m_win);
m_mapped = False;
timer->ResetTimeout(new Callback<Tooltip>(this, &Tooltip::UnmapTooltip));
}
void Tooltip::DrawTooltip()
{
XSetForeground(display, gc, TooltipStringColor.pixel);
XmbDrawString(display, m_win, *m_fs, gc,
XMARGIN - m_rc.x, YMARGIN - m_rc.y, m_str, strlen(m_str));
}
void Tooltip::SetTimer()
{
timer->SetTimeout(TooltipDelayTime,
new Callback<Tooltip>(this, &Tooltip::MapTooltip));
}
void Tooltip::ResetTimer()
{
Bool hit;
hit = timer->ResetTimeout(new Callback<Tooltip>(this, &Tooltip::MapTooltip));
if (!hit)
return;
timer->SetTimeout(TooltipDelayTime,
new Callback<Tooltip>(this, &Tooltip::MapTooltip));
}
void Tooltip::Disable()
{
if (m_mapped)
UnmapTooltip();
else
timer->ResetTimeout(new Callback<Tooltip>(this, &Tooltip::MapTooltip));
}
void Tooltip::Initialize()
{
Tooltip::context = XUniqueContext();
}
syntax highlighted by Code2HTML, v. 0.9.1