znaczacy > comp.os.* > comp.os.linux.programowanie

szykcech (17.11.2018, 17:54)
Witam
Pisze wieloplatformowy edytor tekstu w Qt5.x. Starsze wersje chodzily pod Widnows, a nowa, lepsza wersja ma chodzic równiez pod Linux-em. Problem jest taki, ze chce umozliwic prace na wielu pulpitach. Stara wersja otwierala sobie gniazdko lokalne i nasluchiwala na nim listy plików z innych (pózniejszych) instancji. To bylo dobre pod Windows, jednak na Linuxie nie jest wystarczajace, bo bedac najpierw na pulpicie 0 otwieram sobie edytor, przechodze na pulpit 1 i chce otworzyc nowy plik a tu zonk! Plik otwiera sie w edytorze na pulpicie 0! Aby temuzaradzic musze znac numer biezacego pulpitu (lub jego unikalny identyfikator). Wtedy wystarczy dodac ten identyfikatordo sciezki gniazdka i juz mam unikalne gniazdko zwiazane z danym pulpitem.

Próbowalem nastepujacych sposobów:
1. Identyfikowac pulpit po wskazniku do QScreen (wiem, ze tonie mialo szansy dzialac, ale próbowalem):
MainWindow w;
reinterpret_cast<quint64>(w.windowHandle()->screen()
2. Odbierac liste wirtualnych pulpitów
QList<QScreen*> lScreens(w.windowHandle()->screen()->virtualSiblings());
for(QScreen* lScreen : lScreens)
qInfo() << "Detected screen: " << reinterpret_cast<quint64>(lScreen);
Ale zwraca zawsze tylko jeden wskaznik.
3. Podobnie jak w 1 ale z QApplication::primaryScreen()
4. QDesktopWidget::screenNumber()
Ale zawsze zwraca 0 (bez wzgledu na jakim pulpicie program jest uruchamiany).

Wie ktos jak uzyskac numer/id biezacego pulpitu?!?

dzieki i pozdro
Szyk Cech
szykcech (18.11.2018, 14:48)
> Wie ktos jak uzyskac numer/id biezacego pulpitu?!?

Juz wie! Oto rozwiaznie (choc nie w Qt):

#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
Display* lDisplay = XOpenDisplay(nullptr);
int lScreen = DefaultScreen(lDisplay);
Window lRootWindow = RootWindow(lDisplay, lScreen);
Atom lAtom(XInternAtom(lDisplay, "_NET_CURRENT_DESKTOP", True));
if(lAtom == None)
qFatal("no atom\n");

unsigned long nitems, leftover;
unsigned char *data = nullptr;
int actual_format;
Atom actual_type;

if(XGetWindowProperty(lDisplay, lRootWindow, lAtom, 0L, (long)200, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &leftover, &data) != Success)
qFatal("XGetWindowProperty failed!");

printf("ok\n");
printf("desktop = %d\n", (unsigned int)*data);
#endif
szykcech (18.11.2018, 17:12)
Moze beda to czytac male dzieci, które chca nauczyc sie programowac - wiec...

Dobra praktyka programistyczna jest wylaczanie specyficznego kodu do plików latwo identyfikowalnych. W tym przypadku mam takie pliki:
+ Application.h : z deklaracja kasy aplikacji sluzacej do obslugi gniazdka lokalnego i tlumaczen
+ Application.cpp : z definicja funkcji klas kodowanych niezaleznie od systemu operacyjnego.
+ Application.Linux.cpp : z definicja funkcji specyficznych dla systemu operacyjnego Linux (sa one wylaczone do osobnego, latwo zauwazalnego pliku - to jest wlasnie ta "dobra praktyka")
+ Application.Windows.cpp : funkcje zakodowane z uzyciem Api systemu Windows.

Kazdy nowy system jaki bym wspieral musi miec odpowiedni plik Application.XXX.cpp w mojej aplikacji (wynika to z tego, ze nie mam czegos takiego jak "domyslne zachowanie" w razie braku funkcji specyficznych).

W pliku pro dodaje sie wtedy dyrektywe kompilacji warunkowej:
linux: SOURCES += Src/Application.Linux.cpp
win32: SOURCES += Src/Application.Windows.cpp
(w innych systemach budowania sa podobne mozliwosci)

Natomiast mój plik Application.Linux.cpp wyglada tak:

#include "Application.h"
#include <X11/Xlib.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>

quint32 Application::currentDesktopNumber()
{
Display* lDisplay = XOpenDisplay(nullptr);
int lScreen = DefaultScreen(lDisplay);
Window lRootWindow = RootWindow(lDisplay, lScreen);
Atom lAtom(XInternAtom(lDisplay, "_NET_CURRENT_DESKTOP", True));
if(lAtom == None)
qFatal("no atom\n");

unsigned long nitems, leftover;
unsigned char* lData = nullptr;
int actual_format;
Atom actual_type;

// if(XGetWindowProperty(lDisplay, lRootWindow, lAtom, 0L, 8, False, AnyPropertyType, nullptr, nullptr, nullptr, nullptr, &lData) != Success)
if(XGetWindowProperty(lDisplay, lRootWindow, lAtom, 0L, 8, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &leftover, &lData) != Success)
qFatal("XGetWindowProperty failed!");

quint32 lResult = lData[0];
delete [] lData;

return lResult;
}

void Application::raiseAnotherInstance(quint32 /*aProcesId*/)
{
}
szykcech (18.11.2018, 17:18)
Zapomnialem:
1. W moim 3 poscie jest rozwiazanie z usuwaniem tablicy z wynikami zwracanymi (lData)
2. Powyzsze rozwiazanie oryginalnie zostalo podane przez d4rk74m4 2004-10-24 tu:
Podobne wątki