summaryrefslogtreecommitdiffstats
path: root/src/qtraylabel.cpp
diff options
context:
space:
mode:
authorMichele Calgaro <[email protected]>2020-03-31 22:41:41 +0900
committerMichele Calgaro <[email protected]>2020-03-31 22:41:41 +0900
commit6fcc661ff72af5a957a1a8d2737d2327dba8841e (patch)
tree284b56632512e37875a8a19a5792551e147402d1 /src/qtraylabel.cpp
parent05add324c22f8fb2d1824a8a6145b2b8821e95bb (diff)
downloadtdedocker-6fcc661ff72af5a957a1a8d2737d2327dba8841e.tar.gz
tdedocker-6fcc661ff72af5a957a1a8d2737d2327dba8841e.zip
1) fixed bug when invoking tdedocker with options, which were not passed
to an existing instance 2) code restructure for tray label object 3) dockWhenLostFocus option is now saved/restored correctly 4) fixed issues with popup menu actions status Signed-off-by: Michele Calgaro <[email protected]>
Diffstat (limited to 'src/qtraylabel.cpp')
-rw-r--r--src/qtraylabel.cpp836
1 files changed, 0 insertions, 836 deletions
diff --git a/src/qtraylabel.cpp b/src/qtraylabel.cpp
deleted file mode 100644
index 13c020d..0000000
--- a/src/qtraylabel.cpp
+++ /dev/null
@@ -1,836 +0,0 @@
-/*
- * Copyright (C) 2004 Girish Ramakrishnan All Rights Reserved.
- *
- * This 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 of the License, or
- * (at your option) any later version.
- *
- * This software 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 this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-// $Id: qtraylabel.cpp,v 1.31 2005/06/21 10:04:36 cs19713 Exp $
-
-// Include all TQt includes before X
-#include <tqstring.h>
-#include <tqevent.h>
-#include <tqpoint.h>
-#include <tqtooltip.h>
-#include <tqtimer.h>
-#include <tqimage.h>
-#include <tqpixmap.h>
-#include <tqfileinfo.h>
-#include <tqapplication.h>
-#include "trace.h"
-#include <tdeconfig.h>
-
-#include <kiconloader.h>
-#include <tdeglobal.h>
-
-#include <X11/cursorfont.h>
-#include <X11/xpm.h>
-#include <X11/Xmu/WinUtil.h>
-
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include "util.h"
-
-#include "qtraylabel.h"
-
-void TQTrayLabel::initialize(void)
-{
- mDocked = false;
- mWithdrawn = true;
- mBalloonTimeout = 4000;
- mSkippingTaskbar = false;
- mDockWhenMinimized = true;
- mDesktop = 666; // setDockedWindow would set it a saner value
-
- // Balloon's properties are set to match a TQt tool tip (see TQt source)
- mBalloon = new TQLabel(0, "balloon", WType_TopLevel | WStyle_StaysOnTop |
- WStyle_Customize | WStyle_NoBorder |
- WStyle_Tool | WX11BypassWM);
- mBalloon->setFont(TQToolTip::font());
- mBalloon->setPalette(TQToolTip::palette());
- mBalloon->setAlignment(TQt::AlignLeft | TQt::AlignTop);
- mBalloon->setAutoMask(FALSE);
- mBalloon->setAutoResize(true);
- setAlignment(TQt::AlignCenter);
- setBackgroundMode(X11ParentRelative);
-
- connect(&mRealityMonitor, SIGNAL(timeout()), this, SLOT(realityCheck()));
- setDockedWindow(mDockedWindow);
-
- sysTrayStatus(TQPaintDevice::x11AppDisplay(), &mSysTray);
- // Subscribe to system tray window notifications
- if (mSysTray != None)
- subscribe(TQPaintDevice::x11AppDisplay(), mSysTray,
- StructureNotifyMask, true);
-}
-
-// Describe ourselves in a few words
-const char *TQTrayLabel::me(void) const
-{
- static char temp[100];
- snprintf(temp, sizeof(temp), "(%s,PID=%i,WID=0x%x)",
- appName().local8Bit().data(), mPid, (unsigned) mDockedWindow);
- return temp;
-}
-
-TQTrayLabel::TQTrayLabel(Window w, TQWidget* parent, const TQString& text)
- :TQLabel(parent, text.utf8(), WStyle_Customize | WStyle_NoBorder | WStyle_Tool),
- mDockedWindow(w), mPid(0)
-{
- initialize();
-}
-
-TQTrayLabel::TQTrayLabel(const TQStringList& pname, pid_t pid, TQWidget* parent)
- :TQLabel(parent, "TrayLabel", WStyle_Customize | WStyle_NoBorder | WStyle_Tool),
- mDockedWindow(None), mProgName(pname), mPid(pid)
-{
- if (pname[0].at(0) != '/' && pname[0].find('/', 1) > 0)
- {
- mProgName.push_front(TQFileInfo(pname[0]).absFilePath()); // convert to absolute
- }
- initialize();
-}
-
-TQTrayLabel::~TQTrayLabel()
-{
- TRACE("%s Goodbye", me());
- if (mDockedWindow == None) return;
- // Leave the docked window is some sane state
- mSkippingTaskbar = false;
- skipTaskbar();
- map();
-}
-
-void TQTrayLabel::setAppName(const TQString &prog)
-{
- if (mProgName.count() == 0)
- {
- mProgName.push_front(prog);
- }
- else
- {
- mProgName[0] = prog;
- }
-}
-
-/*
- * Scans the windows in the desktop and checks if a window exists that we might
- * be interested in
- */
-void TQTrayLabel::scanClients()
-{
- Window r, parent, *children;
- unsigned nchildren = 0;
- Display *display = TQPaintDevice::x11AppDisplay();
- TQString ename = TQFileInfo(appName()).fileName(); // strip out the path
-
- XQueryTree(display, tqt_xrootwin(), &r, &parent, &children, &nchildren);
- TRACE("%s nchildren=%i", me(), nchildren);
- for(unsigned i=0; i<nchildren; i++)
- {
- Window w = XmuClientWindow(display, children[i]);
- TRACE("\t%s checking(1) 0x%x", me(), (unsigned) w);
- if (!isNormalWindow(display, w)) continue;
- if (analyzeWindow(display, w, mPid, ename.local8Bit()))
- {
- TRACE("\t%s SOULMATE FOUND (1)", me());
- setDockedWindow(w);
- return;
- }
- }
-}
-
-/*
- * Do a reality check :). Note that this timer runs only when required. Does 3
- * things,
- * 1) If the system tray had disappeared, checks for arrival of new system tray
- * 2) Check root window subscription since it is overwritten by TQt (see below)
- * 3) Checks health of the process whose windows we are docking
- */
-void TQTrayLabel::realityCheck(void)
-{
- if (mSysTray == None)
- {
- // Check the system tray status if we were docked
- if (sysTrayStatus(TQPaintDevice::x11AppDisplay(), &mSysTray)
- != SysTrayPresent) return; // no luck
-
- TRACE("%s System tray present", me());
- dock();
- subscribe(TQPaintDevice::x11AppDisplay(), mSysTray,
- StructureNotifyMask, true);
- mRealityMonitor.stop();
- return;
- }
-
- /*
- * I am not sure when, but TQt at some point in time overwrites our
- * subscription (SubstructureNotifyMask) on the root window. So, we check
- * the status of root window subscription periodically. Now, from the time
- * TQt overwrote our subscription to the time we discovered it, the
- * window we are looking for could have been mapped and we would have never
- * been informed (since TQt overrwrote the subscription). So we have to
- * scan existing client list and dock. I have never seen this happen
- * but I see it likely to happen during session restoration
- */
- Display *display = TQPaintDevice::x11AppDisplay();
- XWindowAttributes attr;
- XGetWindowAttributes(display, tqt_xrootwin(), &attr);
-
- if (!(attr.your_event_mask & SubstructureNotifyMask))
- {
- subscribe(display, None, SubstructureNotifyMask, true);
- TRACE("%s rescanning clients since qt overrode mask", me());
- scanClients();
- }
-
- if (mPid)
- {
- // Check process health
- int status;
- if (waitpid(mPid, &status, WNOHANG) == 0) return; // still running
- TRACE("%s processDead", me());
- mPid = 0;
- processDead();
- }
-}
-
-/*
- * Sends a message to the WM to show this window on all the desktops
- */
-void TQTrayLabel::showOnAllDesktops(void)
-{
- TRACE("Showing on all desktops");
- Display *d = TQPaintDevice::x11AppDisplay();
- long l[5] = { -1, 0, 0, 0, 0 }; // -1 = all, 0 = Desktop1, 1 = Desktop2 ...
- sendMessage(d, tqt_xrootwin(), mDockedWindow, "_NET_WM_DESKTOP", 32,
- SubstructureNotifyMask | SubstructureRedirectMask, l, sizeof(l));
-}
-
-// System tray messages
-const long SYSTEM_TRAY_REQUEST_DOCK = 0;
-const long SYSTEM_TRAY_BEGIN_MESSAGE = 1;
-const long SYSTEM_TRAY_CANCEL_MESSAGE = 2;
-
-/*
- * Add the window to the system tray. Different WM require different hints to be
- * set. We support the following (Google for more information),
- * 1. GNOME - SYSTEM_TRAY_REQUEST_DOCK (freedesktop.org)
- * 2. KDE 3.x and above - _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR
- * 3. Older KDE - KWM_DOCKWINDOW (Untested)
- */
-void TQTrayLabel::dock(void)
-{
- TRACE("%s", me());
- mDocked = true;
- if (mDockedWindow == None) return; // nothing to add
-
- if (mSysTray == None) // no system tray yet
- {
- TRACE("%s starting reality monitor", me());
- mRealityMonitor.start(500);
- return;
- }
-
- Display *display = TQPaintDevice::x11AppDisplay();
- Window wid = winId();
-
- // 1. GNOME and NET WM Specification
- long l[5] = { CurrentTime, SYSTEM_TRAY_REQUEST_DOCK, wid, 0, 0 };
- sendMessage(display, mSysTray, mSysTray, "_NET_SYSTEM_TRAY_OPCODE",
- 32, 0L, l, sizeof(l));
-
- // 2. KDE 3.x and above
- Atom tray_atom =
- XInternAtom(display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False);
- XChangeProperty(display, wid, tray_atom, XA_WINDOW, 32,
- PropModeReplace, (unsigned char *) &wid, 1);
-
- // 3. All other KDEs
- tray_atom = XInternAtom(display, "KWM_DOCKWINDOW", False);
- XChangeProperty(display, wid, tray_atom, XA_WINDOW, 32,
- PropModeReplace, (unsigned char *) &wid, 1);
-
- TRACE("%s ", me());
-
- handleTitleChange();
- handleIconChange();
-
- if (mProgName.count() == 0) setAppName(mClass);
-
- /*
- * For Gnome, a delay is required before we do a show (dont ask me why)
- * If I do a show() without any delay, sometimes the icon has width=1 pixel
- * even though the minimumSizeHint = 24, 24. I have successfully got it
- * working with with a delay of as little as 50ms. But since I
- * dont understand why this delay is required, I am justifiably paranoid
- */
- TQTimer::singleShot(500, this, SLOT(show()));
-
- // let the world know
- emit docked(this);
- emit docked();
-}
-
-/*
- * Undocks. Removes us from the system tray. The spec doesnt say how an icon
- * can be removed from the tray. KDE Spec says XUnmapWindow or XWithdraw should
- * be used. It works but the system tray does not fill the void that we left
- * in the tray. Looks like the system tray will resize only for DestroyEvents
- */
-void TQTrayLabel::undock(void)
-{
- TRACE("%s stopping reality monitor", me());
- mRealityMonitor.stop();
- XUnmapWindow(TQPaintDevice::x11AppDisplay(), winId());
- emit undocked(this);
- emit undocked();
-}
-
-/*
- * Maps the window from the same place it was withdrawn from
- */
-void TQTrayLabel::map(void)
-{
- TRACE("%s", me());
- mWithdrawn = false;
- if (mDockedWindow == None) return;
-
- Display *display = TQPaintDevice::x11AppDisplay();
-
- if (mDesktop == -1)
- {
- /*
- * We track _NET_WM_DESKTOP changes in the x11EventFilter. Its used here.
- * _NET_WM_DESKTOP is set by the WM to the active desktop for newly
- * mapped windows (like this one) at some point in time. We give
- * the WM 200ms to do that. We will override that value to -1 (all
- * desktops) on showOnAllDesktops().
- */
- TQTimer::singleShot(200, this, SLOT(showOnAllDesktops()));
- }
-
- /*
- * A simple XMapWindow would not do. Some applications like xmms wont
- * redisplay its other windows (like the playlist, equalizer) since the
- * Withdrawn->Normal state change code does not map them. So we make the
- * window go through Withdrawn->Iconify->Normal state.
- */
- XWMHints *wm_hint = XGetWMHints(display, mDockedWindow);
- if (wm_hint)
- {
- wm_hint->initial_state = IconicState;
- XSetWMHints(display, mDockedWindow, wm_hint);
- XFree(wm_hint);
- }
-
- XMapWindow(display, mDockedWindow);
- mSizeHint.flags = USPosition; // Obsolete ?
- XSetWMNormalHints(display, mDockedWindow, &mSizeHint);
- // make it the active window
- long l[5] = { None, CurrentTime, None, 0, 0 };
- sendMessage(display, tqt_xrootwin(), mDockedWindow, "_NET_ACTIVE_WINDOW", 32,
- SubstructureNotifyMask | SubstructureRedirectMask, l, sizeof(l));
- // skipTaskbar modifies _NET_WM_STATE. Make sure we dont override WMs value
- TQTimer::singleShot(230, this, SLOT(skipTaskbar()));
- // disable docking when minized for some time (since we went to Iconic state)
- mDockWhenMinimized = !mDockWhenMinimized;
- TQTimer::singleShot(230, this, SLOT(toggleDockWhenMinimized()));
-}
-
-void TQTrayLabel::withdraw(void)
-{
- TRACE("%s", me());
- mWithdrawn = true;
- if (mDockedWindow == None) return;
-
- Display *display = TQPaintDevice::x11AppDisplay();
- int screen = DefaultScreen(display);
- long dummy;
-
- XGetWMNormalHints(display, mDockedWindow, &mSizeHint, &dummy);
-
- /*
- * A simple call to XWithdrawWindow wont do. Here is what we do:
- * 1. Iconify. This will make the application hide all its other windows. For
- * example, xmms would take off the playlist and equalizer window.
- * 2. Next tell the WM, that we would like to go to withdrawn state. Withdrawn
- * state will remove us from the taskbar.
- * Reference: ICCCM 4.1.4 Changing Window State
- */
- XIconifyWindow(display, mDockedWindow, screen); // good for effects too
- XUnmapWindow(display, mDockedWindow);
- XUnmapEvent ev;
- memset(&ev, 0, sizeof(ev));
- ev.type = UnmapNotify;
- ev.display = display;
- ev.event = tqt_xrootwin();
- ev.window = mDockedWindow;
- ev.from_configure = false;
- XSendEvent(display, tqt_xrootwin(), False,
- SubstructureRedirectMask|SubstructureNotifyMask, (XEvent *)&ev);
- XSync(display, False);
-}
-
-/*
- * Skipping the taskbar is a bit painful. Basically, NET_WM_STATE needs to
- * have _NET_WM_STATE_SKIP_TASKBAR. NET_WM_STATE needs to be updated
- * carefully since it is a set of states.
- */
-void TQTrayLabel::skipTaskbar(void)
-{
- Atom __attribute__ ((unused)) type;
- int __attribute__ ((unused)) format;
- unsigned long __attribute__ ((unused)) left;
- Atom *data = NULL;
- unsigned long nitems = 0, num_states = 0;
- Display *display = TQPaintDevice::x11AppDisplay();
-
- TRACE("%s", me());
- Atom _NET_WM_STATE = XInternAtom(display, "_NET_WM_STATE", True);
- Atom skip_atom = XInternAtom(display, "_NET_WM_STATE_SKIP_TASKBAR", False);
- int ret = XGetWindowProperty(display, mDockedWindow, _NET_WM_STATE, 0,
- 20, False, AnyPropertyType, &type, &format,
- &nitems, &left, (unsigned char **) &data);
- Atom *old_states = (Atom *) data;
- bool append = true, replace = false;
-
- if ((ret == Success) && data)
- {
- // Search for the skip_atom. Stop when found
- for (num_states = 0; num_states < nitems; num_states++)
- if (old_states[num_states] == skip_atom) break;
-
- if (mSkippingTaskbar)
- append = (num_states >= nitems);
- else
- {
- if (num_states < nitems)
- {
- replace = true; // need to remove skip_atom
- for (; num_states < nitems - 1; num_states++)
- old_states[num_states] = old_states[num_states + 1];
- }
- }
- XFree(data);
- }
-
- TRACE("%s SkippingTaskar=%i append=%i replace=%i", me(), mSkippingTaskbar,
- append, replace);
-
- if (mSkippingTaskbar)
- {
- if (append)
- XChangeProperty(display, mDockedWindow, _NET_WM_STATE, XA_ATOM, 32,
- PropModeAppend, (unsigned char *) &skip_atom, 1);
- }
- else if (replace)
- XChangeProperty(display, mDockedWindow, _NET_WM_STATE, XA_ATOM, 32,
- PropModeReplace, (unsigned char *) &old_states, nitems - 1);
-}
-
-void TQTrayLabel::setSkipTaskbar(bool skip)
-{
- TRACE("%s Skip=%i", me(), skip);
- mSkippingTaskbar = skip;
- if (mDockedWindow != None && !mWithdrawn) skipTaskbar();
-}
-
-/*
- * Closes a window by sending _NET_CLOSE_WINDOW. For reasons best unknown we
- * need to first map and then send the request.
- */
-void TQTrayLabel::close(void)
-{
- TRACE("%s", me());
- undock();
- Display *display = TQPaintDevice::x11AppDisplay();
- long l[5] = { 0, 0, 0, 0, 0 };
- map();
- sendMessage(display, tqt_xrootwin(), mDockedWindow, "_NET_CLOSE_WINDOW", 32,
- SubstructureNotifyMask | SubstructureRedirectMask,
- l, sizeof(l));
-}
-
-/*
- * Sets the tray icon. If the icon failed to load, we revert to application icon
- */
-void TQTrayLabel::setTrayIcon(const TQString& icon)
-{
- mCustomIcon = icon;
- if (TQPixmap(mCustomIcon).isNull()) mCustomIcon = TQString::null;
- TRACE("%s mCustomIcon=%s", me(), mCustomIcon.local8Bit());
- updateIcon();
-}
-
-/*
- * Sets the docked window to w.
- * A) Start/stop reality timer.
- * B) Subscribe/Unsubscribe for root/w notifications as appropriate
- * C) And of course, dock the window and apply some settings
- */
-void TQTrayLabel::setDockedWindow(Window w)
-{
- TRACE("%s %s reality monitor", me(),
- mDockedWindow==None ? "Starting" : "Stopping");
-
- // Check if we are allowed to dock this window (allows custom rules)
- if (w != None) mDockedWindow = canDockWindow(w) ? w : None;
- else mDockedWindow = None;
-
- if (mDockedWindow == None) mRealityMonitor.start(500); else mRealityMonitor.stop();
-
- Display *d = TQPaintDevice::x11AppDisplay();
-
- // Subscribe for window or root window events
- if (w == None) subscribe(d, None, SubstructureNotifyMask, true);
- else
- {
- if (canUnsubscribeFromRoot())
- subscribe(d, None, ~SubstructureNotifyMask, false);
- else subscribe(d, None, SubstructureNotifyMask, true);
-
- subscribe(d, w,
- StructureNotifyMask | PropertyChangeMask |
- VisibilityChangeMask | FocusChangeMask,
- true);
- }
-
- if (mDocked && w!=None)
- {
- // store the desktop on which the window is being shown
- getCardinalProperty(d, mDockedWindow,
- XInternAtom(d, "_NET_WM_DESKTOP", True), &mDesktop);
-
- if (mWithdrawn)
- // show the window for sometime before docking
- TQTimer::singleShot(1000, this, SLOT(withdraw()));
- else map();
- dock();
- }
-}
-
-/*
- * Balloon text. Overload this if you dont like the way things are ballooned
- */
-void TQTrayLabel::balloonText()
-{
- TRACE("%s BalloonText=%s ToolTipText=%s", me(),
- mBalloon->text().local8Bit(), TQToolTip::textFor(this).local8Bit());
-
- if (mBalloon->text() == TQToolTip::textFor(this)) return;
-#if 0 // I_GOT_NETWM_BALLOONING_TO_WORK
- // if you can get NET WM ballooning to work let me know
- static int id = 1;
- long l[5] = { CurrentTime, SYSTEM_TRAY_BEGIN_MESSAGE, 2000,
- mTitle.length(), id++
- };
- sendMessage(display, mSystemTray, winId(), "_NET_SYSTEM_TRAY_OPCODE", 32,
- SubstructureNotifyMask | SubstructureRedirectMask,
- l, sizeof(l));
- int length = mTitle.length();
- const char *data = mTitle.local8Bit();
- while (length > 0)
- {
- sendMessage(display, mSystemTray, winId(), "_NET_SYSTEM_TRAY_MESSAGE_DATA", 8,
- SubstructureNotifyMask | SubstructureRedirectMask,
- (void *) data, length > 20 ? 20 : length);
- length -= 20;
- data += 20;
- }
-#else
- // Manually do ballooning. See the TQt ToolTip code
- TQString oldText = mBalloon->text();
- mBalloon->setText(TQToolTip::textFor(this));
- if (oldText.isEmpty()) return; // dont tool tip the first time
- TQPoint p = mapToGlobal(TQPoint(0, -1 - mBalloon->height()));
- if (p.x() + mBalloon->width() > TQApplication::desktop()->width())
- p.setX(p.x() + width() - mBalloon->width());
-
- if (p.y() < 0) p.setY(height() + 1);
-
- mBalloon->move(p);
- mBalloon->show();
- TQTimer::singleShot(mBalloonTimeout, mBalloon, SLOT(hide()));
-#endif
-}
-
-/*
- * Update the title in the menu. Balloon the title change if necessary
- */
-void TQTrayLabel::handleTitleChange(void)
-{
- Display *display = TQPaintDevice::x11AppDisplay();
- char *window_name = NULL;
-
- XFetchName(display, mDockedWindow, &window_name);
- mTitle = window_name;
- TRACE("%s has title [%s]", me(), mTitle.local8Bit());
- if (window_name) XFree(window_name);
-
- XClassHint ch;
- if (XGetClassHint(display, mDockedWindow, &ch))
- {
- if (ch.res_class) mClass = TQString(ch.res_class);
- else if (ch.res_name) mClass = TQString(ch.res_name);
-
- if (ch.res_class) XFree(ch.res_class);
- if (ch.res_name) XFree(ch.res_name);
- }
-
- updateTitle();
- if (mBalloonTimeout) balloonText();
-}
-
-/*
- * Overload this if you want a tool tip format that is different from the one
- * below i.e "Title [Class]".
- */
-void TQTrayLabel::updateTitle()
-{
- TRACE("%s", me());
- TQString text = mTitle + " [" + mClass + "]";
- TQToolTip::remove(this);
- TQToolTip::add(this, text);
-
- if (mBalloonTimeout) balloonText();
-}
-
-void TQTrayLabel::handleIconChange(void)
-{
- char **window_icon = NULL;
-
- TRACE("%s", me());
- if (mDockedWindow == None) return;
-
- Display *display = TQPaintDevice::x11AppDisplay();
- XWMHints *wm_hints = XGetWMHints(display, mDockedWindow);
- if (wm_hints != NULL)
- {
- if (!(wm_hints->flags & IconMaskHint))
- wm_hints->icon_mask = None;
- /*
- * We act paranoid here. Progams like KSnake has a bug where
- * IconPixmapHint is set but no pixmap (Actually this happens with
- * quite a few KDE programs) X-(
- */
- if ((wm_hints->flags & IconPixmapHint) && (wm_hints->icon_pixmap))
- XpmCreateDataFromPixmap(display, &window_icon, wm_hints->icon_pixmap,
- wm_hints->icon_mask, NULL);
- XFree(wm_hints);
- }
- TQImage image;
- if (!window_icon)
- {
- image = TDEGlobal::iconLoader()->loadIcon("question", TDEIcon::NoGroup, TDEIcon::SizeMedium);
- }
- else image = TQPixmap((const char **) window_icon).convertToImage();
- if (window_icon) XpmFree(window_icon);
- mAppIcon = image.smoothScale(24, 24); // why?
- setMinimumSize(mAppIcon.size());
- setMaximumSize(mAppIcon.size());
-
- updateIcon();
-}
-
-/*
- * Overload this to possibly do operations on the pixmap before it is set
- */
-void TQTrayLabel::updateIcon()
-{
- TRACE("%s", me());
- setPixmap(mCustomIcon.isEmpty() ? mAppIcon : mCustomIcon);
- erase();
- TQPaintEvent pe(rect());
- paintEvent(&pe);
-}
-
-/*
- * Mouse activity on our label. RightClick = Menu. LeftClick = Toggle Map
- */
-void TQTrayLabel::mouseReleaseEvent(TQMouseEvent * ev)
-{
- emit clicked(ev->button(), ev->globalPos());
-}
-
-/*
- * Track drag event
- */
-void TQTrayLabel::dragEnterEvent(TQDragEnterEvent *ev)
-{
- ev->accept();
- map();
-}
-
-/*
- * Event dispatcher
- */
-bool TQTrayLabel::x11EventFilter(XEvent *ev)
-{
- XAnyEvent *event = (XAnyEvent *)ev;
-
- if (event->window == mSysTray)
- {
- if (event->type != DestroyNotify)
- {
- return false; // not interested in others
- }
- emit sysTrayDestroyed();
- mSysTray = None;
- TRACE("%s SystemTray disappeared. Starting timer", me());
- mRealityMonitor.start(500);
- return true;
- }
- else if (event->window == mDockedWindow)
- {
- if (event->type == DestroyNotify)
- destroyEvent();
- else if (event->type == PropertyNotify)
- propertyChangeEvent(((XPropertyEvent *)event)->atom);
- else if (event->type == VisibilityNotify)
- {
- if (((XVisibilityEvent *) event)->state == VisibilityFullyObscured)
- obscureEvent();
- }
- else if (event->type == MapNotify)
- {
- mWithdrawn = false;
- mapEvent();
- }
- else if (event->type == UnmapNotify)
- {
- mWithdrawn = true;
- unmapEvent();
- }
- else if (event->type == FocusOut)
- {
- focusLostEvent();
- }
- return true; // Dont process this again
- }
-
- if (mDockedWindow != None || event->type != MapNotify) return FALSE;
-
- TRACE("%s Will analyze window 0x%x", me(), (int)((XMapEvent *)event)->window);
- // Check if this window is the soulmate we are looking for
- Display *display = TQPaintDevice::x11AppDisplay();
- Window w = XmuClientWindow(display, ((XMapEvent *) event)->window);
- if (!isNormalWindow(display, w)) return FALSE;
- if (!analyzeWindow(display, w, mPid, TQFileInfo(appName()).fileName().local8Bit()))
- {
- return false;
- }
- // All right. Lets dock this baby
- setDockedWindow(w);
- return true;
-}
-
-void TQTrayLabel::minimizeEvent(void)
-{
- TRACE("minimizeEvent");
- if (mDockWhenMinimized) withdraw();
-}
-
-void TQTrayLabel::destroyEvent(void)
-{
- TRACE("%s destroyEvent", me());
- setDockedWindow(None);
- if (!mPid) undock();
-}
-
-void TQTrayLabel::propertyChangeEvent(Atom property)
-{
- Display *display = TQPaintDevice::x11AppDisplay();
- static Atom WM_NAME = XInternAtom(display, "WM_NAME", True);
- static Atom WM_ICON = XInternAtom(display, "WM_ICON", True);
- static Atom WM_STATE = XInternAtom(display, "WM_STATE", True);
- static Atom _NET_WM_STATE = XInternAtom(display, "_NET_WM_STATE", True);
- static Atom _NET_WM_DESKTOP = XInternAtom(display, "_NET_WM_DESKTOP", True);
-
- if (property == WM_NAME)
- handleTitleChange();
- else if (property == WM_ICON)
- handleIconChange();
- else if (property == _NET_WM_STATE)
- ; // skipTaskbar();
- else if (property == _NET_WM_DESKTOP)
- {
- TRACE("_NET_WM_DESKTOP changed");
- getCardinalProperty(display, mDockedWindow, _NET_WM_DESKTOP, &mDesktop);
- }
- else if (property == WM_STATE)
- {
- Atom type = None;
- int format;
- unsigned long nitems, after;
- unsigned char *data = NULL;
- int r = XGetWindowProperty(display, mDockedWindow, WM_STATE,
- 0, 1, False, AnyPropertyType, &type,
- &format, &nitems, &after, &data);
-
- if ((r == Success) && data && (*(long *) data == IconicState))
- {
- minimizeEvent();
- XFree(data);
- }
- }
-}
-
-// Session Management
-bool TQTrayLabel::saveState(TDEConfig *config)
-{
- if (appName().isEmpty())
- {
- return false;
- }
-
- TRACE("%s saving state", me());
- config->writeEntry("Application", mProgName.join(" "));
- config->writeEntry("BalloonTimeout", mBalloonTimeout);
- config->writeEntry("CustomIcon", mCustomIcon);
- config->writeEntry("DockWhenMinimized", mDockWhenMinimized);
- config->writeEntry("SkipTaskbar", mSkippingTaskbar);
- config->writeEntry("Withdraw", mWithdrawn);
- return true;
-}
-
-bool TQTrayLabel::restoreState(TDEConfig *config)
-{
- TRACE("%s restoring state", me());
- setBalloonTimeout(config->readNumEntry("BalloonTimeout", 4000));
- mCustomIcon = config->readEntry("CustomIcon", TQString::null);
- setDockWhenMinimized(config->readBoolEntry("DockWhenMinimized", false));
- setSkipTaskbar(config->readBoolEntry("SkipTaskbar", false));
- mWithdrawn = config->readBoolEntry("Withdraw", false);
-
- dock();
- scanClients(); // Grab window
- if (mWithdrawn)
- {
- withdraw();
- }
- else
- {
- map();
- }
- return true;
-}
-
-// End kicking butt
-
-
-#include "qtraylabel.moc"