[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-devel
Subject: Re: Bespin GlobalMenu with XBar Development, Please help me develop
From: Aaron Lewis <aaron.lewis1989 () gmail ! com>
Date: 2010-08-21 16:10:30
Message-ID: 4C6FFA76.8070902 () gmail ! com
[Download RAW message or body]
Hi Thoams ,
Very glad to hear from u , attached globalmenu.cpp , just replace it
with what you've downloaded from kde-apps.org.
>
> However
> a) "releaseFocus" should be sufficient (in contrast to "unregisterMenu" and
> complementing "requestFocus")
Exactly , works min clicking on task manager , means minimize it , top
menu restored.
But when you clicking on plasma desktop , it won't be restored ( e.g
open emacs , then clicking on somewhere blank on desktop , mine is a
folder view , holding all of the areas on desktop )
See my code:
void GlobalMenu::activeWindowChanged(WId wid)
{
if (!mMenu->isHidden()) {
mMenu->hide();
}
kDebug() << QString::number(wid,16);
QString ctxXML = mContextMap[wid];
if (!ctxXML.isEmpty()) {
bindGlobalShortcut(ctxXML);
mXBarIfce->requestFocus(wid);
} else {
qDebug() << "Released . ";
if ( lastWid )
mXBarIfce->releaseFocus(lastWid);
}
}
You compile and run it , qDebug() << "Released" always prints , when
clicking on blank areas or minimized , but clicking on blank areas just
don't work .. couldn't figure out.
> b) from the snippet it looks a bit as if you tried to release/unregister the
> function parameter WId - this is not gonna work since it's the WId of the just
> activcated window (the one w/o supported menu) - so you'd have to store the
> currently used WId in a variable and release that.
Yep , that's the problem , i released the wrong target.
I saved lastWid here ;-) by default it's -1 , and i'll check this value
before calling releaseFocus(Wid)
void GlobalMenu::windowChanged(WId wid)
{
// Ugly Implementation , Check If Menu is hidden()
if (!mMenu->isHidden()) {
mMenu->hide();
}
updateContextMap(wid);
lastWid = wid;
}
> For more information i'd have to see the actual sources, sorry :-(
Sorry , edio says it's a bug , i found it , so i falled back to last
good one.
> Ps:
> i don't use too many Gtk+ apps (mostly gimp & inkscape and they happen to be
> the only apps i'm using max'd as well ;-) but i could actually merge
> globalmenu support upstream.
But if we implemented it , everything goes up top menu , isn't that
useful , cool ?
>
> Pps:
> canonical apparently works on a global menu solution as well (shuttleworth's
> creating his personal mac clone anyway...). Iff this will be supported by Gtk+
> & Qt upstream this here will be superflous in a near future anyway (though I
> object the way both global menu as well as the canonical solution implement
> popups, since they're really nothing i'd post on X11 or dbus, that's client
> private stuff that triggers _real_ actions ...)
Can't be very soon , i think , i'd like to create the "world" somewhat.
>
> Ppps:
> Mozilla's toolkit is XUL, OOo uses UNO
Oh , yeah , you got it.
Thanks for reply !
--
Best Regards,
Aaron Lewis - PGP: 0x4A6D32A0
FingerPrint EA63 26B2 6C52 72EA A4A5 EB6B BDFE 35B0 4A6D 32A0
irc: A4R0NL3WI5 on freenode
["globalmenu.cpp" (text/x-c)]
/* Bespin mac-a-like GlobalMenu KDE4
Copyright (C) 2007 Thomas Luebking <thomas.luebking@web.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <Plasma/Containment>
#include <Plasma/Theme>
#include <KDebug>
#include <KWindowSystem>
#include <KAction>
#include <KSelectAction>
#include <KShortcut>
#include <QApplication>
#include <QAbstractEventDispatcher>
#include <QCursor>
#include <QDBusConnectionInterface>
#include <QDBusInterface>
#include <QDesktopWidget>
#include <QDomDocument>
#include <QDomElement>
#include <QDomNode>
#include <QGraphicsLinearLayout>
#include <QGraphicsScene>
#include <QGraphicsSceneWheelEvent>
#include <QGraphicsView>
#include <QMessageBox>
#include <QPaintEvent>
#include <QPainter>
#include <QRectF>
#include <QSettings>
#include <QStyle>
#include <QStyleOption>
#include <QTextCodec>
#include <QTimer>
#include <QX11Info>
#include <netwm.h>
#include "globalmenu.h"
#include "xbarclientadaptor.h"
#define MSG(_FNC_) QDBusMessage::createMethodCall( "org.kde.XBar", "/XBar", \
"org.kde.XBar", _FNC_ ) #define XBAR_SEND( _MSG_ ) \
QDBusConnection::sessionBus().send( _MSG_ )
static GlobalMenu *self = 0;
static const QString SERVICE_NAME = "org.kde.XBar-gtk";
static QString windowName(WId wid)
{
NETRootInfo rootInfo(QX11Info::display(), -1);
NETWinInfo winInfo(QX11Info::display(), wid, rootInfo.rootWindow(), -1);
QString name = QString::fromUtf8(winInfo.visibleIconName());
if (name.isEmpty()) {
name = QString::fromUtf8(winInfo.visibleName());
}
if (name.isEmpty()) {
name = QString::fromUtf8(winInfo.name());
}
if (name.isEmpty()) {
name = "unknown";
}
return name;
}
static QStringList topMenuList(const QString &source)
{
QDomDocument doc;
QDomElement docElem;
QDomNode rootNode;
QDomNodeList topNodes;
QString error;
QStringList result;
doc.setContent(source,false,&error);
rootNode = doc.firstChild();
for (QDomElement elem = rootNode.firstChildElement(); !elem.isNull(); elem = \
elem.nextSiblingElement()) { if (elem.attribute("visible") != "0") {
QString result_tmp = elem.attribute("label").replace("_","&");
result << result_tmp;
}
}
return result;
}
GlobalMenu::GlobalMenu(QWidget *parent)
: QWidget(parent),
mMenu(0),
mMapper(new QSignalMapper(this))
{
Q_ASSERT(self == 0);
self = this;
lastWid = -1;
QAbstractEventDispatcher::instance()->setEventFilter(x11EventFilter);
mCtxAtom = XInternAtom(QX11Info::display(),"_NET_GLOBALMENU_MENU_CONTEXT",FALSE);
mEvtAtom = XInternAtom(QX11Info::display(),"_NET_GLOBALMENU_MENU_EVENT",FALSE);
QDBusConnection conn = QDBusConnection::connectToBus(QDBusConnection::SessionBus, \
"globalmenu");
mXBarIfce = new OrgKdeXBarInterface("org.kde.XBar","/XBar",conn);
mMenu = new KMenu(parent);
connect(mMapper,SIGNAL(mapped(const QString &)),this,SLOT(triggered(const QString \
&)));
conn.registerService(SERVICE_NAME);
new XBarClientAdaptor(this);
conn.registerObject("/XBarClient", this);
connect(KWindowSystem::self(),SIGNAL(activeWindowChanged(WId)),
this,SLOT(activeWindowChanged(WId)));
connect(KWindowSystem::self(),SIGNAL(windowChanged(WId)),
this,SLOT(windowChanged(WId)));
connect(KWindowSystem::self(),SIGNAL(windowAdded(WId)),
this,SLOT(windowAdded(WId)));
connect(KWindowSystem::self(),SIGNAL(windowRemoved(WId)),
this,SLOT(windowRemoved(WId)));
}
GlobalMenu::~GlobalMenu()
{
Q_ASSERT(self);
self = 0;
}
void GlobalMenu::activate()
{
// qDebug() << "Activate Now !";
kDebug();
}
void GlobalMenu::deactivate()
{
// qDebug() << "Deactivate Now !";
kDebug();
}
void GlobalMenu::hover(qlonglong key, int idx, int x, int y)
{
if (mMenu->isVisible()) {
popup(key,idx,x,y);
}
}
void GlobalMenu::popDown(qlonglong key)
{
Q_UNUSED(key);
mMenu->hide();
}
void GlobalMenu::popup(qlonglong key, int idx, int x, int y)
{
QDomDocument doc;
QDomElement rootElem;
idx = idx+1;
if (doc.setContent(mContextMap[key],false)) {
for (QDomElement elem = doc.firstChildElement().firstChildElement(); \
!elem.isNull(); elem = elem.nextSiblingElement()) { if (elem.attribute("visible") != \
"0") { idx--;
}
if (idx == 0) {
rootElem = elem;
break;
}
}
//mMenu = new KMenu(rootElem.attribute("label"),0);
mMenu->clear();
mMenu->setWindowFlags(Qt::X11BypassWindowManagerHint);
buildChildMenu(mMenu,rootElem.firstChildElement("menu"),"/"+rootElem.attribute("id"));
mMenu->exec(QPoint(x,y));
}
}
void GlobalMenu::raise(qlonglong key)
{
Q_UNUSED(key);
kDebug();
}
void GlobalMenu::windowAdded(WId wid)
{
kDebug() << QString::number(wid,16);
XSelectInput(QX11Info::display(),wid,PropertyChangeMask);
qApp->syncX();
}
void GlobalMenu::windowRemoved(WId wid)
{
kDebug() << QString::number(wid,16);
// Restore to "plasma" top menu when window closed.
XBAR_SEND( MSG("unregisterMenu") << (qlonglong)wid );
}
void GlobalMenu::windowChanged(WId wid)
{
// Ugly Implementation , Check If Menu is hidden()
if (!mMenu->isHidden()) {
mMenu->hide();
}
updateContextMap(wid);
lastWid = wid;
}
void GlobalMenu::activeWindowChanged(WId wid)
{
if (!mMenu->isHidden()) {
mMenu->hide();
}
kDebug() << QString::number(wid,16);
QString ctxXML = mContextMap[wid];
if (!ctxXML.isEmpty()) {
bindGlobalShortcut(ctxXML);
mXBarIfce->requestFocus(wid);
} else {
qDebug() << "Released . ";
if ( lastWid )
mXBarIfce->releaseFocus(lastWid);
}
}
void GlobalMenu::updateContextMap(WId wid)
{
int list_count;
char **list_return;
QString ctxXML;
Display *display = QX11Info::display();
Status status;
XTextProperty tp;
status = XGetTextProperty(display, wid, &tp, mCtxAtom);
if (status) {
status = XTextPropertyToStringList(&tp,&list_return,&list_count);
if (status) {
if (list_count) {
// for ( int i = 0 ; i < list_count ; i ++ ) {
// qDebug() << "Register , I is " << i;
ctxXML = QString::fromUtf8(list_return[0]);
// if (ctxXML != mContextMap[wid]) {
// qDebug() << "Step 4";
kDebug() << ctxXML;
mContextMap.insert(wid,ctxXML);
mXBarIfce->registerMenu(SERVICE_NAME,wid,
windowName(wid),
topMenuList(ctxXML));
if (KWindowSystem::activeWindow() == wid) {
mXBarIfce->requestFocus(wid);
}
// break;
// }
// }
} else {
ctxXML.clear();
}
XFreeStringList(list_return);
}
} else {
ctxXML.clear();
}
}
void GlobalMenu::buildChildMenu(KMenu *topMenu,const QDomElement &elem, const QString \
&prefix) {
if (elem.isNull()) {
return;
}
KAction *action;
//KSelectAction *selectAction = 0;
for (QDomElement itemElem = elem.firstChildElement("item"); !itemElem.isNull();
itemElem = itemElem.nextSiblingElement("item")) {
if (itemElem.attribute("visible") == "0" ) {
continue;
} else if (itemElem.attribute("type") == "s") {
topMenu->addSeparator();
} else if (!itemElem.firstChildElement("menu").isNull() ) {
QString menu_tmp = itemElem.attribute("label").replace("_","&");
KMenu *childMenu = new KMenu(menu_tmp,topMenu);
buildChildMenu(childMenu,itemElem.firstChildElement("menu"),
\
QString("%1/%2").arg(prefix).arg(itemElem.attribute("id")));
topMenu->addMenu(childMenu);
continue;
} else if ( !itemElem.attribute("label").isEmpty() ) {
QString menu_tmp = itemElem.attribute("label").replace("_","&");
action = new KAction(menu_tmp,0);
mMapper->setMapping(action,QString("%1/%2").arg(prefix).arg(itemElem.attribute("id")));
connect(action,SIGNAL(triggered()),mMapper,SLOT(map()));
if (itemElem.attribute("sensible") == "0") {
action->setEnabled(false);
}
topMenu->addAction(action);
}
}
}
void GlobalMenu::triggered(const QString &id)
{
kDebug() << id;
mMenu->hide();
WId wid = KWindowSystem::activeWindow();
char *data = id.toUtf8().append("\0").data();
QString ctxXML;
Display *display = QX11Info::display();
XTextProperty tp;
XStringListToTextProperty(&data,1,&tp);
XSetTextProperty(display, wid, &tp, mEvtAtom);
}
bool GlobalMenu::processXEvent(XEvent *ev)
{
if (ev->type == PropertyNotify) {
if (ev->xproperty.atom == mCtxAtom) {
updateContextMap(ev->xproperty.window);
}
if (ev->xproperty.atom == mEvtAtom) {
kDebug() << "Evt:" << QString::number(ev->xproperty.window) << \
XGetAtomName(QX11Info::display(),ev->xproperty.atom); }
}
return false;
}
bool GlobalMenu::x11EventFilter(void *message)
{
return self->processXEvent(static_cast<XEvent *>(message));
}
void GlobalMenu::bindGlobalShortcut(const QString &source)
{
QDomDocument doc;
QDomElement docElem;
QDomElement rootElem;
QDomNodeList topNodes;
QString error;
QStringList result;
doc.setContent(source,false,&error);
rootElem = doc.firstChildElement();
for (QDomElement elem = rootElem.firstChildElement(); !elem.isNull(); elem = \
elem.nextSiblingElement()) { if (elem.attribute("visible") != "0") {
KShortcut shortcut(elem.attribute("accel"));
QString label = elem.attribute("label").replace("_","&");
KAction *action = new KAction(label,0);
mMapper->setMapping(action,QString("/%1").arg(elem.attribute("id")));
connect(action,SIGNAL(triggered()),mMapper,SLOT(map()));
action->setGlobalShortcut(shortcut);
result << label;
}
}
return;
}
#include "globalmenu.moc"
>> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to unsubscribe <<
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic