1
/****************************************************************************
2
** common.cpp - contains all the common variables and functions for Psi
3
** Copyright (C) 2001, 2002 Justin Karneges
5
** This program is free software; you can redistribute it and/or
6
** modify it under the terms of the GNU General Public License
7
** as published by the Free Software Foundation; either version 2
8
** of the License, or (at your option) any later version.
10
** This program is distributed in the hope that it will be useful,
11
** but WITHOUT ANY WARRANTY; without even the implied warranty of
12
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
** GNU General Public License for more details.
15
** You should have received a copy of the GNU General Public License
16
** along with this program; if not, write to the Free Software
17
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
19
****************************************************************************/
2
* common.cpp - contains all the common variables and functions for Psi
3
* Copyright (C) 2001-2003 Justin Karneges
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this library; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23
#include"profiles.h"
24
28
QString PROG_NAME = "Psi";
25
QString PROG_VERSION = "0.8.5";
29
QString PROG_VERSION = "0.9.2";
36
#define LIBDIR "/usr/local/share/psi"
27
39
#include<qregexp.h>
30
42
#include<qapplication.h>
44
#include<qobjectlist.h>
35
50
#include<sys/types.h>
36
51
#include<sys/stat.h>
148
QString qstrquote(const QString &toquote, int width, bool quoteEmpty)
150
int ql = 0, col = 0, atstart = 1, ls=0;
152
QString quoted = "> "+toquote; // quote first line
153
QString rxs = quoteEmpty ? "\n" : "\n(?!\\s*\n)";
154
QRegExp rx(rxs); // quote following lines
155
quoted.replace(rx, "\n> ");
156
rx.setPattern("> +>"); // compress > > > > quotes to >>>>
157
quoted.replace(rx, ">>");
158
quoted.replace(rx, ">>");
159
quoted.replace(QRegExp(" +\n"), "\n"); // remove trailing spaces
163
quoted.replace(QRegExp("^>+\n"), "\n\n"); // unquote empty lines
164
quoted.replace(QRegExp("\n>+\n"), "\n\n");
168
for (int i=0;i<(int) quoted.length();i++)
171
if (atstart && quoted[i] == '>') ql++; else atstart=0;
173
switch(quoted[i].latin1())
175
case '\n': ql = col = 0; atstart = 1; break;
177
case '\t': ls = i; break;
180
if (quoted[i]=='\n') { ql=0; atstart = 1; }
186
ls = i; i = quoted.length();
187
while ((ls<i) && !quoted[ls].isSpace()) ls++;
190
if ((i<(int)quoted.length()) && (quoted[ls] != '\n'))
192
quoted.insert(ls, '\n');
194
quoted.insert(ls, QString().fill('>', ql));
200
quoted += "\n\n";// add two empty lines to quoted text - the cursor
201
// will be positioned at the end of those.
165
205
QString plain2rich(const QString &plain)
604
QString emoticonify(const QString &in)
607
while ( !p.atEnd() ) {
608
// returns us the first chunk as a plaintext string
609
QString str = p.next();
613
// find closest emoticon
617
int foundPos = -1, foundLen = -1;
619
QPtrListIterator<Iconset> iconsets(is->emoticons);
621
while ( (iconset = iconsets.current()) != 0 ) {
622
QPtrListIterator<Icon> it = iconset->iterator();
623
for ( ; it.current(); ++it) {
624
Icon *icon = it.current();
625
if ( icon->regExp().isEmpty() )
635
// find the closest match
636
const QRegExp &rx = icon->regExp();
637
int n = rx.search(str, iii);
641
if(ePos == -1 || n < ePos || (rx.matchedLength() > foundLen && n < ePos + foundLen)) {
642
// there must be whitespace at least on one side of the emoticon
644
( n+rx.matchedLength() == (int)str.length() ) ||
645
( n > 0 && str[n-1].isSpace() ) ||
646
( n+rx.matchedLength() < (int)str.length() && str[n+rx.matchedLength()].isSpace() ) )
652
foundLen = rx.matchedLength();
659
iii = n + rx.matchedLength();
660
} while ( searchAgain );
670
s = str.mid(i, ePos-i);
676
p.putRich( QString("<icon name=\"%1\" text=\"%2\">").arg(closest->name()).arg(str.mid(foundPos, foundLen)) );
677
i = foundPos + foundLen;
681
QString out = p.output();
683
//enable *bold* stuff
685
//out=out.replace(QRegExp("(^[^<>\\s]*|\\s[^<>\\s]*)\\*(\\S+)\\*([^<>\\s]*\\s|[^<>\\s]*$)"),"\\1<b>*\\2*</b>\\3");
686
//out=out.replace(QRegExp("(^[^<>\\s\\/]*|\\s[^<>\\s\\/]*)\\/([^\\/\\s]+)\\/([^<>\\s\\/]*\\s|[^<>\\s\\/]*$)"),"\\1<i>/\\2/</i>\\3");
687
//out=out.replace(QRegExp("(^[^<>\\s]*|\\s[^<>\\s]*)_(\\S+)_([^<>\\s]*\\s|[^<>\\s]*$)"),"\\1<u>_\\2_</u>\\3");
689
out=out.replace(QRegExp("(^_|\\s_)(\\S+)(_\\s|_$)"),"\\1<u>\\2</u>\\3");
690
out=out.replace(QRegExp("(^\\*|\\s\\*)(\\S+)(\\*\\s|\\*$)"),"\\1<b>\\2</b>\\3");
691
out=out.replace(QRegExp("(^\\/|\\s\\/)(\\S+)(\\/\\s|\\/$)"),"\\1<i>\\2</i>\\3");
463
696
QString encodePassword(const QString &pass, const QString &key)
506
QPixmap & status2pix(int status)
509
case STATUS_OFFLINE: return *pix_offline;
510
case STATUS_ONLINE: return *pix_online;
511
case STATUS_AWAY: return *pix_away;
512
case STATUS_XA: return *pix_xa;
513
case STATUS_DND: return *pix_dnd;
515
default: return *pix_online;
519
QImage & status2qim(int status)
522
case STATUS_OFFLINE: return *qim_offline;
523
case STATUS_ONLINE: return *qim_online;
524
case STATUS_AWAY: return *qim_away;
525
case STATUS_XA: return *qim_xa;
526
case STATUS_DND: return *qim_dnd;
528
default: return *qim_online;
532
739
QString status2txt(int status)
535
case STATUS_OFFLINE: return QObject::tr("Offline");
536
case STATUS_ONLINE: return QObject::tr("Online");
537
case STATUS_AWAY: return QObject::tr("Away");
538
case STATUS_XA: return QObject::tr("Not Available");
539
case STATUS_DND: return QObject::tr("Do not Disturb");
541
default: return QObject::tr("Online");
546
QString RecognizedTransportNames[] = {
553
const QString & transport2str(const QString &name)
555
QString service(name);
557
if(service.mid(0,4) == "icq.")
558
return RecognizedTransportNames[0];
559
else if(service.mid(0,4) == "aim.")
560
return RecognizedTransportNames[1];
561
else if(service.mid(0,4) == "msn.")
562
return RecognizedTransportNames[2];
563
else if(service.mid(0,6) == "yahoo.")
564
return RecognizedTransportNames[3];
569
QPixmap & transport2icon(const QString &jid, int status)
573
if(jid.mid(0,4) == "icq.")
575
else if(jid.mid(0,4) == "aim.")
577
else if(jid.mid(0,4) == "msn.")
579
else if(jid.mid(0,6) == "yahoo.")
585
case STATUS_OFFLINE: pix = 0; break;
586
case STATUS_ONLINE: pix = 1; break;
587
case STATUS_AWAY: pix = 2; break;
588
case STATUS_XA: pix = 3; break;
589
case STATUS_DND: pix = 4; break;
591
default: pix = 1; break;
594
if(!tic[trans].p[pix])
597
return *tic[trans].p[pix];
600
QPixmap *loadImage(const QString &fname, const QStringList &_dirs)
603
QStringList dirs = _dirs;
605
for(QStringList::Iterator it = dirs.begin(); it != dirs.end(); ++it) {
606
QString str = (*it) + "/" + fname;
607
if(image.load(str) == TRUE) {
608
QPixmap *p = new QPixmap;
609
// this is weird, but it gets the mask right on Windows
610
p->convertFromImage(image.copy(0,0,image.width(),image.height()));
618
char *loadImageData(const QString &fname, const QStringList &_dirs, int *size)
621
QStringList dirs = _dirs;
623
for(QStringList::Iterator it = dirs.begin(); it != dirs.end(); ++it) {
624
QString str = (*it) + "/" + fname;
629
if(!f.open(IO_ReadOnly))
631
QByteArray a = f.readAll();
632
p = new char[(*size)];
633
memcpy(p, a.data(), *size);
642
Anim *loadAnim(const QString &fname, const QStringList &dirs)
644
QPixmap *p = loadImage(fname, dirs);
648
Anim *a = new Anim(*p);
654
void bringToFront(QWidget *w)
658
w->setActiveWindow();
662
void win_raiseNoFocus(QWidget *w)
666
//SetWindowPos(w->winId(),HWND_TOP,0,0,0,0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
742
case STATUS_OFFLINE: return QObject::tr("Offline");
743
case STATUS_AWAY: return QObject::tr("Away");
744
case STATUS_XA: return QObject::tr("Not Available");
745
case STATUS_DND: return QObject::tr("Do not Disturb");
746
case STATUS_CHAT: return QObject::tr("Free for Chat");
747
case STATUS_INVISIBLE: return QObject::tr("Invisible");
750
default: return QObject::tr("Online");
754
Icon category2icon(const QString &category, const QString &type)
756
// TODO: update this to http://www.jabber.org/registrar/disco-categories.html#gateway
758
// still have to add more options...
759
if ( category == "service" || category == "gateway" ) {
764
else if (type == "icq")
766
else if (type == "msn")
768
else if (type == "yahoo")
770
else if (type == "gadugadu" || type == "x-gadugadu")
772
else if (type == "sms")
777
return is->transportStatus(trans, STATUS_ONLINE);
786
else if ( category == "conference" ) {
787
if (type == "public" || type == "private" || type == "text" || type == "irc")
788
return IconsetFactory::icon("psi/groupChat");
789
else if (type == "url")
790
return IconsetFactory::icon("psi/www");
795
else if ( category == "validate" ) {
797
return IconsetFactory::icon("psi/xml");
801
else if ( category == "user" || category == "client" ) {
807
return is->status(STATUS_ONLINE);
670
835
int hexChar2int(char c)
789
void unfinishedSoftware()
791
QMessageBox::information(0, CAP(QObject::tr("Warning")), QObject::tr(
792
"<h3>*** Warning! ***</h3>\n"
793
"This is unfinished software. It has been released so that interested users "
794
"can try it out and perhaps follow its development. It is not guaranteed to be "
795
"bugfree, although it is quite stable in my experience.<br><br>\n"
796
"One day it will be finished. Until then, don't count on every "
797
"Jabber feature to work. If you want to assist me in making this program "
798
"better, feel free to email me bugreports/patches/wishes.<br><br>\n"
799
"Note: quite a few options/features appear \"grayed out\". They "
800
"indicate planned features that are not in the program yet.<br><br>"
801
"Now that this is out of the way, enjoy Psi!\n"
805
bool loadPsiIconSet(const QString name)
808
QString subdir = "/iconsets/" + name;
810
dirs += "." + subdir;
811
dirs += g.pathHome + subdir;
812
dirs += g.pathBase + subdir;
813
dirs += g.pathBase + "/iconsets/stellar";
816
// load animations - this needs to be implemented better
817
anim_message = loadAnim("message.png", dirs);
818
anim_system = loadAnim("system.png", dirs);
819
anim_chat = loadAnim("chat.png", dirs);
820
anim_headline = loadAnim("headline.png", dirs);
821
if(!anim_message || !anim_system || !anim_chat || !anim_headline)
825
pix_online = loadImage("online.png", dirs);
826
pix_offline = loadImage("offline.png", dirs);
827
pix_away = loadImage("away.png", dirs);
828
pix_xa = loadImage("xa.png", dirs);
829
pix_dnd = loadImage("dnd.png", dirs);
830
pix_arrow[0] = loadImage("groupclose.png", dirs);
831
pix_arrow[1] = loadImage("groupopen.png", dirs);
832
pix_arrow[2] = loadImage("groupempty.png", dirs);
833
pix_add = loadImage("add.png", dirs);
834
pix_remove = loadImage("remove.png", dirs);
835
pix_send = loadImage("send.png", dirs);
836
pix_history = loadImage("history.png", dirs);
837
pix_info = loadImage("info.png", dirs);
838
pix_changeacc = loadImage("changeacc.png", dirs);
839
pix_url = loadImage("url.png", dirs);
841
if(!pix_online || !pix_offline || !pix_away || !pix_xa || !pix_dnd || !pix_arrow[0] ||
842
!pix_arrow[1] || !pix_arrow[2] || !pix_add || !pix_remove || !pix_send || !pix_history ||
843
!pix_info || !pix_changeacc || !pix_url)
846
qim_online = new QImage(pix_online->convertToImage());
847
qim_offline = new QImage(pix_offline->convertToImage());
848
qim_away = new QImage(pix_away->convertToImage());
849
qim_xa = new QImage(pix_xa->convertToImage());
850
qim_dnd = new QImage(pix_dnd->convertToImage());
855
void unloadPsiIconSet()
861
delete anim_headline;
875
delete pix_changeacc;
885
void getPsiIconSets(QStringList &names, QStringList &descriptions)
888
QString subdir = "/iconsets";
890
dirs += "." + subdir;
891
dirs += g.pathHome + subdir;
892
dirs += g.pathBase + subdir;
894
for(QStringList::Iterator it = dirs.begin(); it != dirs.end(); ++it) {
895
if(!QFile::exists(*it))
898
QStringList entries = d.entryList();
899
for(QStringList::Iterator it2 = entries.begin(); it2 != entries.end(); ++it2) {
900
// make sure we don't have it
902
for(QStringList::Iterator it3 = names.begin(); it3 != names.end(); ++it3) {
954
void qstringlistisort(QStringList &c)
956
if ( c.count() <= 1 )
959
QStringList::Iterator it;
960
uint size = c.count();
962
// first, make array that is easy (and quick) to manipulate
963
QString *heap = new QString[ size ];
966
for (it = c.begin(); it != c.end(); ++it)
970
for (uint tmp = 0; tmp < c.count(); tmp++) {
974
for (uint j = 1; j < size; j++) {
975
QString k = heap[j].lower();
978
for (i = j - 1; i >= 0; i--) {
979
if ( QString::compare(k, heap[i].lower()) > 0 )
911
QFile f(*it + "/" + *it2 + "/desc");
912
if(!f.open(IO_ReadOnly))
916
int n = f.readLine(line.data(), 255);
920
if(line.at(line.length()-1) == '\n')
921
line.at(line.length()-1) = 0;
923
QString desc = QString::fromUtf8(line);
926
descriptions += line;
989
// now, copy sorted data back to QStringList
991
for (i = 0; i < (int)size; i++)
932
997
void openURL(const QString &url)
934
999
//fprintf(stderr, "openURL: [%s]\n", url.latin1());
935
1000
bool useCustom = TRUE;
1002
int colon = url.find(':');
1005
QString service = url.left( colon );
1006
if ( service == "jabber" || service == "jid" ) {
938
1012
if(option.browser == 0)
939
1013
useCustom = FALSE;
942
if(option.browser == 0)
1016
if(option.browser == 0 || option.browser == 2)
943
1017
useCustom = FALSE;
1071
1133
s.truncate(s.length()-2);
1072
1134
timezone_offset = s.toInt();
1075
1137
strftime(str, 256, fmt, localtime(&x));
1076
1138
if(strcmp(fmt, str))
1077
1139
timezone_str = str;
1141
#if defined(Q_WS_X11)
1078
1142
struct utsname u;
1080
1144
os_str.sprintf("%s", u.sysname);
1081
#elif defined(Q_WS_WIN)
1146
// get description about os
1159
LinuxASP, // Russian Linux distros
1162
LinuxPLD, // Polish Linux distros
1179
{ LinuxMandrake, OsUseFile, "/etc/mandrake-release", "Mandrake Linux" },
1180
{ LinuxDebian, OsAppendFile, "/etc/debian_version", "Debian GNU/Linux" },
1181
{ LinuxGentoo, OsUseFile, "/etc/gentoo-release", "Gentoo Linux" },
1182
{ LinuxSlackware, OsAppendFile, "/etc/slackware-version", "Slackware Linux" },
1183
{ LinuxPLD, OsUseFile, "/etc/pld-release", "PLD Linux" },
1184
{ LinuxAurox, OsUseName, "/etc/aurox-release", "Aurox Linux" },
1185
{ LinuxArch, OsUseFile, "/etc/arch-release", "Arch Linux" },
1188
{ LinuxSuSE, OsUseFile, "/etc/SuSE-release", "SuSE Linux" },
1189
{ LinuxConectiva, OsUseFile, "/etc/conectiva-release", "Conectiva Linux" },
1190
{ LinuxCaldera, OsUseFile, "/etc/.installed", "Caldera Linux" },
1192
// many distros use the /etc/redhat-release for compatibility, so RedHat will be the last :)
1193
{ LinuxRedHat, OsUseFile, "/etc/redhat-release", "RedHat Linux" },
1195
{ LinuxNone, OsUseName, "", "" }
1198
for (int i = 0; osInfo[i].id != LinuxNone; i++) {
1199
QFileInfo fi( osInfo[i].file );
1200
if ( fi.exists() ) {
1203
QFile f( osInfo[i].file );
1204
f.open( IO_ReadOnly );
1205
f.readLine( desc, 128 );
1207
desc = desc.stripWhiteSpace ();
1209
switch ( osInfo[i].flags ) {
1214
os_str = osInfo[i].name;
1217
os_str = osInfo[i].name + " (" + desc + ")";
1224
#elif defined(Q_WS_MAC)
1228
#if defined(Q_WS_WIN)
1082
1229
TIME_ZONE_INFORMATION i;
1083
GetTimeZoneInformation(&i);
1084
timezone_offset = (-i.Bias) / 60;
1230
//GetTimeZoneInformation(&i);
1231
//timezone_offset = (-i.Bias) / 60;
1232
memset(&i, 0, sizeof(i));
1233
bool inDST = (GetTimeZoneInformation(&i) == TIME_ZONE_ID_DAYLIGHT);
1236
bias += i.DaylightBias;
1237
timezone_offset = (-bias) / 60;
1085
1238
timezone_str = "";
1086
1239
for(int n = 0; n < 32; ++n) {
1087
uint w = i.StandardName[n];
1240
uint w = inDST ? i.DaylightName[n] : i.StandardName[n];
1090
1243
timezone_str += QChar(w);
1474
void soundPlay(const QString &str)
1476
if(str == "!beep") {
1477
QApplication::beep();
1481
if(!QFile::exists(str))
1484
#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
1487
if(!option.player.isEmpty()) {
1489
args = QStringList::split(' ', option.player);
1493
wait3(NULL,WNOHANG,NULL);
1498
XMPP::Status makeStatus(int x, const QString &str)
1502
if(x == STATUS_OFFLINE)
1503
s.setIsAvailable(false);
1504
else if(x == STATUS_INVISIBLE)
1505
s.setIsInvisible(true);
1507
if(x == STATUS_AWAY)
1509
else if(x == STATUS_XA)
1511
else if(x == STATUS_DND)
1513
else if(x == STATUS_CHAT)
1520
int makeSTATUS(const XMPP::Status &s)
1522
int type = STATUS_ONLINE;
1523
if(!s.isAvailable())
1524
type = STATUS_OFFLINE;
1525
else if(s.isInvisible())
1526
type= STATUS_INVISIBLE;
1528
if(s.show() == "away")
1530
else if(s.show() == "xa")
1532
else if(s.show() == "dnd")
1534
else if(s.show() == "chat")
1541
QLayout *rw_recurseFindLayout(QLayout *lo, QWidget *w)
1543
//printf("scanning layout: %p\n", lo);
1544
QLayoutIterator it = lo->iterator();
1545
for(QLayoutItem *i; (i = it.current()); ++it) {
1546
//printf("found: %p,%p\n", i->layout(), i->widget());
1547
QLayout *slo = i->layout();
1549
QLayout *tlo = rw_recurseFindLayout(slo, w);
1553
else if(i->widget() == w)
1559
QLayout *rw_findLayoutOf(QWidget *w)
1561
return rw_recurseFindLayout(w->parentWidget()->layout(), w);
1564
void replaceWidget(QWidget *a, QWidget *b)
1569
QLayout *lo = rw_findLayoutOf(a);
1572
//printf("decided on this: %p\n", lo);
1574
if(lo->inherits("QBoxLayout")) {
1575
QBoxLayout *bo = (QBoxLayout *)lo;
1576
int n = bo->findWidget(a);
1577
bo->insertWidget(n+1, b);
1582
void closeDialogs(QWidget *w)
1584
// close qmessagebox?
1585
const QObjectList *list = w->children();
1587
QObjectListIt it(*list);
1588
QPtrList<QDialog> dialogs;
1589
for(QObject *o; (o = it.current()); ++it) {
1590
if(o->inherits("QDialog"))
1591
dialogs.append((QDialog *)o);
1593
QPtrListIterator<QDialog> dit(dialogs);
1594
for(QDialog *w; (w = dit.current()); ++dit)
1599
QString enc822jid(const QString &s)
1602
for(int n = 0; n < (int)s.length(); ++n) {
1603
if(s[n] == '\\' || s[n] == '<' || s[n] == '>') {
1605
hex.sprintf("\\x%02X", (unsigned char )s[n]);
1614
QString dec822jid(const QString &s)
1617
for(int n = 0; n < (int)s.length(); ++n) {
1618
if(s[n] == '\\' && n + 3 < (int)s.length()) {
1624
val += hexChar2int(s[x+1])*16;
1625
val += hexChar2int(s[x+2]);
1636
#include<X11/Xlib.h>
1637
#include<X11/Xutil.h> // needed for WM_CLASS hinting
1639
void x11wmClass(Display *dsp, WId wid, QString resName)
1641
char app_name[] = "psi";
1643
//Display *dsp = x11Display(); // get the display
1644
//WId win = winId(); // get the window
1645
XClassHint classhint; // class hints
1646
classhint.res_name = (char *)resName.latin1(); // res_name
1647
classhint.res_class = app_name; // res_class
1648
XSetClassHint(dsp, wid, &classhint); // set the class hints
1651
//>>>-- Nathaniel Gray -- Caltech Computer Science ------>
1652
//>>>-- Mojave Project -- http://mojave.cs.caltech.edu -->
1653
// Copied from http://www.nedit.org/archives/discuss/2002-Aug/0386.html
1656
bool getCardinal32Prop(Display *display, Window win, char *propName, long *value)
1658
Atom nameAtom, typeAtom, actual_type_return;
1659
int actual_format_return, result;
1660
unsigned long nitems_return, bytes_after_return;
1661
long *result_array=NULL;
1663
nameAtom = XInternAtom(display, propName, False);
1664
typeAtom = XInternAtom(display, "CARDINAL", False);
1665
if (nameAtom == None || typeAtom == None) {
1666
//qDebug("Atoms not interned!");
1671
// Try to get the property
1672
result = XGetWindowProperty(display, win, nameAtom, 0, 1, False,
1673
typeAtom, &actual_type_return, &actual_format_return,
1674
&nitems_return, &bytes_after_return,
1675
(unsigned char **)&result_array);
1677
if( result != Success ) {
1678
//qDebug("not Success");
1681
if( actual_type_return == None || actual_format_return == 0 ) {
1682
//qDebug("Prop not found");
1685
if( actual_type_return != typeAtom ) {
1686
//qDebug("Wrong type atom");
1688
*value = result_array[0];
1689
XFree(result_array);
1694
// Get the desktop number that a window is on
1695
bool desktopOfWindow(Window *window, long *desktop)
1697
Display *display = qt_xdisplay();
1698
bool result = getCardinal32Prop(display, *window, (char *)"_NET_WM_DESKTOP", desktop);
1700
// qDebug("Desktop: " + QString::number(*desktop));
1705
// Get the current desktop the WM is displaying
1706
bool currentDesktop(long *desktop)
1709
Display *display = qt_xdisplay();;
1712
rootWin = RootWindow(qt_xdisplay(), XDefaultScreen(qt_xdisplay()));
1713
result = getCardinal32Prop(display, rootWin, (char *)"_NET_CURRENT_DESKTOP", desktop);
1715
// qDebug("Current Desktop: " + QString::number(*desktop));
1720
void bringToFront(QWidget *w, bool)
1723
// If we're not on the current desktop, do the hide/show trick
1725
Window win = w->winId();
1726
if(desktopOfWindow(&win, &dsk) && currentDesktop(&curr_dsk)) {
1727
if(dsk != curr_dsk) {
1729
//qApp->processEvents();
1733
// FIXME: multi-desktop hacks for Win and Mac required
1737
if(w->isMinimized()) {
1739
if(w->isMaximized())
1745
// w->setActiveWindow();
1747
w->setActiveWindow();
1750
bool operator!=(const QMap<QString, QString> &m1, const QMap<QString, QString> &m2)
1752
if ( m1.size() != m2.size() )
1755
QMap<QString, QString>::ConstIterator it = m1.begin(), it2;
1756
for ( ; it != m1.end(); ++it) {
1757
it2 = m2.find( it.key() );
1758
if ( it2 == m2.end() )
1760
if ( it.data() != it2.data() )