From 6d46164b6377a00b61dee5766c6e23e054cefd46 Mon Sep 17 00:00:00 2001 From: simonb Date: Mon, 6 Aug 2007 04:20:31 +0000 Subject: port kde dockapp fix from trunk --- src/SystemTray.cc | 125 ++++++++++++++++++++++++++++++++++-------------------- src/SystemTray.hh | 5 ++- 2 files changed, 84 insertions(+), 46 deletions(-) diff --git a/src/SystemTray.cc b/src/SystemTray.cc index 00d9b11..eac0ea4 100644 --- a/src/SystemTray.cc +++ b/src/SystemTray.cc @@ -49,11 +49,12 @@ using std::dec; /// helper class for tray windows, so we dont call XDestroyWindow class TrayWindow: public FbTk::FbWindow { public: - TrayWindow(Window win):FbTk::FbWindow(win), m_visible(false) { + TrayWindow(Window win, bool using_xembed):FbTk::FbWindow(win), m_visible(false), m_xembedded(using_xembed) { setEventMask(PropertyChangeMask); } bool isVisible() { return m_visible; } + bool isXEmbedded() { return m_xembedded; } void show() { if (!m_visible) { m_visible = true; @@ -67,8 +68,33 @@ public: } } +/* Flags for _XEMBED_INFO */ +#define XEMBED_MAPPED (1 << 0) + + bool getMappedDefault() const { + Atom actual_type; + int actual_format; + unsigned long nitems, bytes_after; + unsigned long *prop; + bool mapped = false; + Atom embed_info = SystemTray::getXEmbedInfoAtom(); + if (property(embed_info, 0l, 2l, false, embed_info, + &actual_type, &actual_format, &nitems, &bytes_after, + (unsigned char **) &prop) && prop != 0) { + mapped = (bool)(static_cast(prop[1]) & XEMBED_MAPPED); + XFree(static_cast(prop)); + +#ifdef DEBUG + cerr<<__FILE__<<"(SystemTray::TrayWindow::getMappedDefault(): XEMBED_MAPPED = "<display(), "_NET_SYSTEM_TRAY_OPCODE", False); - if (event.message_type == - XInternAtom(FbTk::App::instance()->display(), "_NET_SYSTEM_TRAY_OPCODE", False)) { + if (event.message_type == systray_opcode_atom) { int type = event.data.l[1]; if (type == SYSTEM_TRAY_REQUEST_DOCK) { @@ -285,7 +311,7 @@ bool SystemTray::clientMessage(const XClientMessageEvent &event) { cerr<<"SystemTray::clientMessage(const XClientMessageEvent): SYSTEM_TRAY_REQUEST_DOCK"<display(); // make sure we have the same screen number XWindowAttributes attr; attr.screen = 0; - if (XGetWindowAttributes(FbTk::App::instance()->display(), - win, &attr) != 0 && + if (XGetWindowAttributes(disp, win, &attr) != 0 && attr.screen != 0 && XScreenNumberOfScreen(attr.screen) != window().screenNumber()) { return; } - TrayWindow *traywin = new TrayWindow(win); + TrayWindow *traywin = new TrayWindow(win, using_xembed); #ifdef DEBUG cerr<<"SystemTray::addClient(Window): 0x"<add(*this, win); - XChangeSaveSet(FbTk::App::instance()->display(), win, SetModeInsert); traywin->reparent(m_window, 0, 0); traywin->addToSaveSet(); - showClient(traywin); + + if (using_xembed) { + static Atom xembed_atom = XInternAtom(disp, "_XEMBED", False); + +#define XEMBED_EMBEDDED_NOTIFY 0 + // send embedded message + XEvent ce; + ce.xclient.type = ClientMessage; + ce.xclient.message_type = xembed_atom; + ce.xclient.display = disp; + ce.xclient.window = win; + ce.xclient.format = 32; + ce.xclient.data.l[0] = CurrentTime; // timestamp + ce.xclient.data.l[1] = XEMBED_EMBEDDED_NOTIFY; + ce.xclient.data.l[2] = 0l; // The protocol version we support + ce.xclient.data.l[3] = m_window.window(); // the window owning the selection + ce.xclient.data.l[4] = 0l; // unused + + XSendEvent(disp, win, false, NoEventMask, &ce); + } + + if (traywin->getMappedDefault()) + showClient(traywin); } void SystemTray::removeClient(Window win, bool destroyed) { @@ -404,36 +451,15 @@ void SystemTray::handleEvent(XEvent &event) { } else if (event.type == PropertyNotify) { ClientList::iterator it = findClient(event.xproperty.window); if (it != m_clients.end()) { - Atom embed_info = XInternAtom(FbTk::App::instance()->display(),"_XEMBED_INFO",false); - if (event.xproperty.atom == embed_info) { - -/* Flags for _XEMBED_INFO */ -#define XEMBED_MAPPED (1 << 0) - - TrayWindow *traywin = *it; - Atom actual_type; - int actual_format; - unsigned long nitems, bytes_after; - unsigned long *prop; - if (traywin->property(embed_info, 0l, 2l, false, embed_info, - &actual_type, &actual_format, &nitems, &bytes_after, - (unsigned char **) &prop)) { - - bool mapped = (bool)(static_cast(prop[1]) & XEMBED_MAPPED); - XFree(static_cast(prop)); - -#ifdef DEBUG - cerr<<__FILE__<<"(SystemTray::handleEvent(XEvent)): XEMBED_MAPPED = "<getMappedDefault()) + showClient(*it); + else + hideClient(*it); } } - } + } + } void SystemTray::rearrangeClients() { @@ -465,12 +491,16 @@ void SystemTray::rearrangeClients() { void SystemTray::removeAllClients() { BScreen *screen = Fluxbox::instance()->findScreen(window().screenNumber()); while (!m_clients.empty()) { - m_clients.back()->setEventMask(NoEventMask); - m_clients.back()->hide(); + TrayWindow * traywin = m_clients.back(); + traywin->setEventMask(NoEventMask); + + if (traywin->isXEmbedded()) + traywin->hide(); + if (screen) - m_clients.back()->reparent(screen->rootWindow(), 0, 0); - m_clients.back()->removeFromSaveSet(); - delete m_clients.back(); + traywin->reparent(screen->rootWindow(), 0, 0, false); + traywin->removeFromSaveSet(); + delete traywin; m_clients.pop_back(); } m_num_visible_clients = 0; @@ -524,3 +554,8 @@ void SystemTray::update(FbTk::Subject* subject) { } } + +Atom SystemTray::getXEmbedInfoAtom() { +static Atom theatom = XInternAtom(Fluxbox::instance()->display(), "_XEMBED_INFO", False); +return theatom; +} diff --git a/src/SystemTray.hh b/src/SystemTray.hh index 557d1e4..e5c1f8c 100644 --- a/src/SystemTray.hh +++ b/src/SystemTray.hh @@ -59,7 +59,7 @@ public: void exposeEvent(XExposeEvent &event); void handleEvent(XEvent &event); - void addClient(Window win); + void addClient(Window win, bool using_xembed); void removeClient(Window win, bool destroyed); unsigned int width() const; @@ -74,6 +74,8 @@ public: void parentMoved() { m_window.parentMoved(); } + static Atom getXEmbedInfoAtom(); + private: void update(FbTk::Subject *subj); @@ -99,6 +101,7 @@ private: // gaim/pidgin seems to barf if the selection is not an independent window. // I suspect it's an interacton with parent relationship and gdk window caching. FbTk::FbWindow m_selection_owner; + }; #endif // SYSTEMTRAY_HH -- cgit v0.11.2