ultimatepp/uppsrc/CtrlLib/TrayIconX11.cpp
cxl 2d04800ec8 CtrlLib: ChGtk2 removed, X11 now using standard skin
git-svn-id: svn://ultimatepp.org/upp/trunk@13857 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2020-01-11 16:48:15 +00:00

210 lines
3.9 KiB
C++

#include "CtrlLib.h"
#define LLOG(x) // LOG(x)
#ifdef GUI_X11
namespace Upp {
Atom TraySelection()
{
return XAtom(Format("_NET_SYSTEM_TRAY_S%d", Xscreenno));
}
void TrayIcon::Call(int code, unsigned long d1, unsigned long d2, unsigned long d3)
{
if(!traywin)
return;
bool x11trap = TrapX11Errors();
XEvent e;
Zero(e);
e.xclient.data.l[0] = CurrentTime;
e.xclient.data.l[1] = code;
e.xclient.data.l[2] = d1;
e.xclient.data.l[3] = d2;
e.xclient.data.l[4] = d3;
e.xclient.window = traywin;
e.xclient.type = ClientMessage;
e.xclient.message_type = XAtom("_NET_SYSTEM_TRAY_OPCODE");
e.xclient.format = 32;
XSendEvent(Xdisplay, traywin, XFalse, 0, &e);
XSync(Xdisplay, XFalse);
UntrapX11Errors(x11trap);
}
void TrayIcon::AddToTray()
{
Hide();
traywin = XGetSelectionOwner(Xdisplay, TraySelection());
if(!traywin) return;
XSelectInput(Xdisplay, traywin, StructureNotifyMask);
XWindowAttributes attr;
XGetWindowAttributes(Xdisplay, Xroot, &attr);
XSelectInput(Xdisplay, Xroot, attr.your_event_mask | StructureNotifyMask);
Window win = GetWindow();
XSizeHints *size_hints = XAllocSizeHints();
size_hints->min_width = 22;
size_hints->min_height = 22;
size_hints->max_width = 22;
size_hints->max_height = 22;
size_hints->width = 22;
size_hints->height = 22;
size_hints->x = 0;
size_hints->y = 0;
size_hints->win_gravity = StaticGravity;
size_hints->flags = PMinSize|PMaxSize|PPosition|PSize|PWinGravity;
XSetWMNormalHints(Xdisplay, win, size_hints);
Call(0, win, 0, 0);
XSetWMNormalHints(Xdisplay, win, size_hints);
Show();
XSetWMNormalHints(Xdisplay, win, size_hints);
XFree(size_hints);
}
void TrayIcon::Message(int type, const char *title, const char *text, int timeout)
{
if(!traywin)
return;
int len = strlen(text);
static int stamp;
Call(1, 1000 * timeout, len, ++stamp);
bool x11trap = TrapX11Errors();
while(len > 0) {
XClientMessageEvent ev;
Zero(ev);
ev.type = ClientMessage;
ev.window = GetWindow();
ev.format = 8;
ev.message_type = XAtom("_NET_SYSTEM_TRAY_MESSAGE_DATA");
int n = min(len, 20);
memcpy(&ev.data, text, n);
text += n;
len -= n;
XSendEvent(Xdisplay, traywin, XFalse, StructureNotifyMask, (XEvent *) &ev);
XSync(Xdisplay, XFalse);
}
UntrapX11Errors(x11trap);
}
bool TrayIcon::HookProc(XEvent *event)
{
XAnyEvent *e = (XAnyEvent *)event;
if(e->type == DestroyNotify && e->window == traywin) {
AddToTray();
return true;
}
if(e->type == ClientMessage && !traywin) {
XClientMessageEvent *cm = (XClientMessageEvent *)event;
if(cm->message_type == XAtom("MANAGER") && (Atom)cm->data.l[1] == TraySelection()) {
AddToTray();
return true;
}
}
return false;
}
void TrayIcon::Paint(Draw& w)
{
Size sz = GetSize();
Size isz = icon.GetSize();
Image m = icon;
if(isz.cx > sz.cx || isz.cy > sz.cy) {
m = Rescale(icon, sz);
isz = sz;
}
Point p = Rect(sz).CenterPos(isz);
w.DrawRect(sz, SColorFace());
w.DrawImage(p.x, p.y, m);
}
void TrayIcon::LeftDown()
{
WhenLeftDown();
}
void TrayIcon::LeftDown(Point p, dword keyflags)
{
LeftDown();
}
void TrayIcon::LeftUp()
{
WhenLeftUp();
}
void TrayIcon::LeftUp(Point p, dword keyflags)
{
LeftUp();
}
void TrayIcon::LeftDouble()
{
WhenLeftDouble();
}
void TrayIcon::LeftDouble(Point p, dword keyflags)
{
LeftDouble();
}
void TrayIcon::Menu(Bar& bar)
{
WhenBar(bar);
}
void TrayIcon::DoMenu(Bar& bar)
{
Menu(bar);
}
void TrayIcon::RightDown(Point p, dword keyflags)
{
MenuBar::Execute(this, THISBACK(DoMenu), GetMousePos());
}
void TrayIcon::Show(bool b)
{
/* if(!!b == !!IsOpen()) return; // Needs fixing....
if(b) {
}
else
Close();*/
}
TrayIcon::TrayIcon()
{
SetRect(0, 0, 24, 24);
ignoretakefocus = true;
Create(NULL, true, false);
if(top) {
popup = true;
Transparent();
AddToTray();
}
}
// Not implemented in X11 yet...
void TrayIcon::BalloonLeftDown()
{
}
void TrayIcon::BalloonShow()
{
}
void TrayIcon::BalloonHide()
{
}
void TrayIcon::BalloonTimeout()
{
}
}
#endif