20 |
|
|
21 |
*****************************************************************************/ |
*****************************************************************************/ |
22 |
|
|
23 |
#include "qsamplerAbout.h" |
#include "qsampler.h" |
24 |
|
|
25 |
#include "qsamplerOptions.h" |
#include "qsamplerOptions.h" |
26 |
#include "qsamplerMainForm.h" |
#include "qsamplerMainForm.h" |
27 |
|
|
|
#include <QApplication> |
|
28 |
#include <QLibraryInfo> |
#include <QLibraryInfo> |
29 |
#include <QTranslator> |
#include <QTranslator> |
30 |
#include <QLocale> |
#include <QLocale> |
52 |
// Singleton application instance stuff (Qt/X11 only atm.) |
// Singleton application instance stuff (Qt/X11 only atm.) |
53 |
// |
// |
54 |
|
|
|
#if QT_VERSION < 0x050000 |
|
|
#if defined(Q_WS_X11) |
|
|
#define CONFIG_X11 |
|
|
#endif |
|
|
#else |
|
|
#if defined(QT_X11EXTRAS_LIB) |
|
|
#define CONFIG_X11 |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
55 |
#ifdef CONFIG_X11 |
#ifdef CONFIG_X11 |
56 |
#ifdef CONFIG_XUNIQUE |
#ifdef CONFIG_XUNIQUE |
57 |
|
|
58 |
#include <QX11Info> |
#include <unistd.h> /* for gethostname() */ |
59 |
|
|
60 |
#include <X11/Xatom.h> |
#include <X11/Xatom.h> |
61 |
#include <X11/Xlib.h> |
#include <X11/Xlib.h> |
69 |
|
|
70 |
#include <QAbstractNativeEventFilter> |
#include <QAbstractNativeEventFilter> |
71 |
|
|
|
class qsamplerApplication; |
|
|
|
|
72 |
class qsamplerXcbEventFilter : public QAbstractNativeEventFilter |
class qsamplerXcbEventFilter : public QAbstractNativeEventFilter |
73 |
{ |
{ |
74 |
public: |
public: |
78 |
: QAbstractNativeEventFilter(), m_pApp(pApp) {} |
: QAbstractNativeEventFilter(), m_pApp(pApp) {} |
79 |
|
|
80 |
// XCB event filter (virtual processor). |
// XCB event filter (virtual processor). |
81 |
bool nativeEventFilter(const QByteArray& eventType, void *message, long *); |
bool nativeEventFilter(const QByteArray& eventType, void *message, long *) |
82 |
|
{ |
83 |
|
if (eventType == "xcb_generic_event_t") { |
84 |
|
xcb_property_notify_event_t *pEv |
85 |
|
= static_cast<xcb_property_notify_event_t *> (message); |
86 |
|
if ((pEv->response_type & ~0x80) == XCB_PROPERTY_NOTIFY |
87 |
|
&& pEv->state == XCB_PROPERTY_NEW_VALUE) |
88 |
|
m_pApp->x11PropertyNotify(pEv->window); |
89 |
|
} |
90 |
|
return false; |
91 |
|
} |
92 |
|
|
93 |
private: |
private: |
94 |
|
|
102 |
#endif // CONFIG_X11 |
#endif // CONFIG_X11 |
103 |
|
|
104 |
|
|
105 |
class qsamplerApplication : public QApplication |
// Constructor. |
106 |
|
qsamplerApplication::qsamplerApplication ( int& argc, char **argv ) |
107 |
|
: QApplication(argc, argv), |
108 |
|
m_pQtTranslator(NULL), m_pMyTranslator(NULL), m_pWidget(NULL) |
109 |
{ |
{ |
110 |
public: |
// Load translation support. |
111 |
|
QLocale loc; |
112 |
// Constructor. |
if (loc.language() != QLocale::C) { |
113 |
qsamplerApplication(int& argc, char **argv) : QApplication(argc, argv), |
// Try own Qt translation... |
114 |
m_pQtTranslator(0), m_pMyTranslator(0), m_pWidget(0) |
m_pQtTranslator = new QTranslator(this); |
115 |
{ |
QString sLocName = "qt_" + loc.name(); |
116 |
// Load translation support. |
QString sLocPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); |
117 |
QLocale loc; |
if (m_pQtTranslator->load(sLocName, sLocPath)) { |
118 |
if (loc.language() != QLocale::C) { |
QApplication::installTranslator(m_pQtTranslator); |
119 |
// Try own Qt translation... |
} else { |
120 |
m_pQtTranslator = new QTranslator(this); |
#ifdef RELATIVE_LOCALE_DIR |
121 |
QString sLocName = "qt_" + loc.name(); |
sLocPath = QApplication::applicationDirPath() + RELATIVE_LOCALE_DIR; |
|
QString sLocPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); |
|
122 |
if (m_pQtTranslator->load(sLocName, sLocPath)) { |
if (m_pQtTranslator->load(sLocName, sLocPath)) { |
123 |
QApplication::installTranslator(m_pQtTranslator); |
QApplication::installTranslator(m_pQtTranslator); |
124 |
} else { |
} else { |
125 |
#ifdef RELATIVE_LOCALE_DIR |
#endif |
126 |
sLocPath = QApplication::applicationDirPath() + RELATIVE_LOCALE_DIR; |
delete m_pQtTranslator; |
127 |
if (m_pQtTranslator->load(sLocName, sLocPath)) { |
m_pQtTranslator = 0; |
128 |
QApplication::installTranslator(m_pQtTranslator); |
#ifdef CONFIG_DEBUG |
129 |
} else { |
qWarning("Warning: no translation found for '%s' locale: %s/%s.qm", |
130 |
#endif |
loc.name().toUtf8().constData(), |
131 |
delete m_pQtTranslator; |
sLocPath.toUtf8().constData(), |
132 |
m_pQtTranslator = 0; |
sLocName.toUtf8().constData()); |
133 |
|
#endif |
134 |
|
#ifdef RELATIVE_LOCALE_DIR |
135 |
|
} |
136 |
|
#endif |
137 |
|
} |
138 |
|
// Try own application translation... |
139 |
|
m_pMyTranslator = new QTranslator(this); |
140 |
|
sLocName = "qsampler_" + loc.name(); |
141 |
|
if (m_pMyTranslator->load(sLocName, sLocPath)) { |
142 |
|
QApplication::installTranslator(m_pMyTranslator); |
143 |
|
} else { |
144 |
|
#ifdef RELATIVE_LOCALE_DIR |
145 |
|
sLocPath = QApplication::applicationDirPath() + RELATIVE_LOCALE_DIR; |
146 |
|
#else |
147 |
|
sLocPath = CONFIG_DATADIR "/qsampler/translations"; |
148 |
|
#endif |
149 |
|
if (m_pMyTranslator->load(sLocName, sLocPath)) { |
150 |
|
QApplication::installTranslator(m_pMyTranslator); |
151 |
|
} else { |
152 |
|
delete m_pMyTranslator; |
153 |
|
m_pMyTranslator = 0; |
154 |
#ifdef CONFIG_DEBUG |
#ifdef CONFIG_DEBUG |
155 |
qWarning("Warning: no translation found for '%s' locale: %s/%s.qm", |
qWarning("Warning: no translation found for '%s' locale: %s/%s.qm", |
156 |
loc.name().toUtf8().constData(), |
loc.name().toUtf8().constData(), |
157 |
sLocPath.toUtf8().constData(), |
sLocPath.toUtf8().constData(), |
158 |
sLocName.toUtf8().constData()); |
sLocName.toUtf8().constData()); |
159 |
#endif |
#endif |
|
#ifdef RELATIVE_LOCALE_DIR |
|
|
} |
|
|
#endif |
|
|
} |
|
|
// Try own application translation... |
|
|
m_pMyTranslator = new QTranslator(this); |
|
|
sLocName = "qsampler_" + loc.name(); |
|
|
if (m_pMyTranslator->load(sLocName, sLocPath)) { |
|
|
QApplication::installTranslator(m_pMyTranslator); |
|
|
} else { |
|
|
#ifdef RELATIVE_LOCALE_DIR |
|
|
sLocPath = QApplication::applicationDirPath() + RELATIVE_LOCALE_DIR; |
|
|
#else |
|
|
sLocPath = CONFIG_DATADIR "/qsampler/translations"; |
|
|
#endif |
|
|
if (m_pMyTranslator->load(sLocName, sLocPath)) { |
|
|
QApplication::installTranslator(m_pMyTranslator); |
|
|
} else { |
|
|
delete m_pMyTranslator; |
|
|
m_pMyTranslator = 0; |
|
|
#ifdef CONFIG_DEBUG |
|
|
qWarning("Warning: no translation found for '%s' locale: %s/%s.qm", |
|
|
loc.name().toUtf8().constData(), |
|
|
sLocPath.toUtf8().constData(), |
|
|
sLocName.toUtf8().constData()); |
|
|
#endif |
|
|
} |
|
160 |
} |
} |
161 |
} |
} |
|
#ifdef CONFIG_X11 |
|
|
#ifdef CONFIG_XUNIQUE |
|
|
m_pDisplay = NULL; |
|
|
m_aUnique = 0; |
|
|
m_wOwner = 0; |
|
|
#if QT_VERSION >= 0x050100 |
|
|
m_pXcbEventFilter = new qsamplerXcbEventFilter(this); |
|
|
installNativeEventFilter(m_pXcbEventFilter); |
|
|
if (QX11Info::isPlatformX11()) { |
|
|
#endif |
|
|
// Instance uniqueness initialization... |
|
|
m_pDisplay = QX11Info::display(); |
|
|
m_aUnique = XInternAtom(m_pDisplay, QSAMPLER_XUNIQUE, false); |
|
|
XGrabServer(m_pDisplay); |
|
|
m_wOwner = XGetSelectionOwner(m_pDisplay, m_aUnique); |
|
|
XUngrabServer(m_pDisplay); |
|
|
#if QT_VERSION >= 0x050100 |
|
|
} |
|
|
#endif |
|
|
#endif // CONFIG_XUNIQUE |
|
|
#endif // CONFIG_X11 |
|
162 |
} |
} |
163 |
|
#ifdef CONFIG_X11 |
164 |
|
#ifdef CONFIG_XUNIQUE |
165 |
|
m_pDisplay = NULL; |
166 |
|
m_aUnique = 0; |
167 |
|
m_wOwner = 0; |
168 |
|
#if QT_VERSION >= 0x050100 |
169 |
|
m_pXcbEventFilter = new qsamplerXcbEventFilter(this); |
170 |
|
installNativeEventFilter(m_pXcbEventFilter); |
171 |
|
#endif |
172 |
|
#endif // CONFIG_XUNIQUE |
173 |
|
#endif // CONFIG_X11 |
174 |
|
} |
175 |
|
|
|
// Destructor. |
|
|
~qsamplerApplication() |
|
|
{ |
|
|
#ifdef CONFIG_X11 |
|
|
#ifdef CONFIG_XUNIQUE |
|
|
#if QT_VERSION >= 0x050100 |
|
|
removeNativeEventFilter(m_pXcbEventFilter); |
|
|
delete m_pXcbEventFilter; |
|
|
#endif |
|
|
#endif // CONFIG_XUNIQUE |
|
|
#endif // CONFIG_X11 |
|
|
if (m_pMyTranslator) delete m_pMyTranslator; |
|
|
if (m_pQtTranslator) delete m_pQtTranslator; |
|
|
} |
|
176 |
|
|
177 |
// Main application widget accessors. |
// Destructor. |
178 |
void setMainWidget(QWidget *pWidget) |
qsamplerApplication::~qsamplerApplication (void) |
179 |
{ |
{ |
180 |
m_pWidget = pWidget; |
#ifdef CONFIG_X11 |
181 |
#ifdef CONFIG_X11 |
#ifdef CONFIG_XUNIQUE |
182 |
#ifdef CONFIG_XUNIQUE |
#if QT_VERSION >= 0x050100 |
183 |
m_wOwner = m_pWidget->winId(); |
removeNativeEventFilter(m_pXcbEventFilter); |
184 |
if (m_pDisplay && m_wOwner) { |
delete m_pXcbEventFilter; |
185 |
XGrabServer(m_pDisplay); |
#endif |
186 |
XSetSelectionOwner(m_pDisplay, m_aUnique, m_wOwner, CurrentTime); |
#endif // CONFIG_XUNIQUE |
187 |
XUngrabServer(m_pDisplay); |
#endif // CONFIG_X11 |
188 |
} |
if (m_pMyTranslator) delete m_pMyTranslator; |
189 |
#endif // CONFIG_XUNIQUE |
if (m_pQtTranslator) delete m_pQtTranslator; |
190 |
#endif // CONFIG_X11 |
} |
191 |
|
|
192 |
|
|
193 |
|
// Main application widget accessors. |
194 |
|
void qsamplerApplication::setMainWidget ( QWidget *pWidget ) |
195 |
|
{ |
196 |
|
m_pWidget = pWidget; |
197 |
|
#ifdef CONFIG_X11 |
198 |
|
#ifdef CONFIG_XUNIQUE |
199 |
|
m_wOwner = m_pWidget->winId(); |
200 |
|
if (m_pDisplay && m_wOwner) { |
201 |
|
XGrabServer(m_pDisplay); |
202 |
|
XSetSelectionOwner(m_pDisplay, m_aUnique, m_wOwner, CurrentTime); |
203 |
|
XUngrabServer(m_pDisplay); |
204 |
} |
} |
205 |
|
#endif // CONFIG_XUNIQUE |
206 |
|
#endif // CONFIG_X11 |
207 |
|
} |
208 |
|
|
|
QWidget *mainWidget() const { return m_pWidget; } |
|
209 |
|
|
210 |
// Check if another instance is running, |
// Check if another instance is running, |
211 |
// and raise its proper main widget... |
// and raise its proper main widget... |
212 |
bool setup() |
bool qsamplerApplication::setup (void) |
213 |
{ |
{ |
214 |
#ifdef CONFIG_X11 |
#ifdef CONFIG_X11 |
215 |
#ifdef CONFIG_XUNIQUE |
#ifdef CONFIG_XUNIQUE |
216 |
if (m_pDisplay && m_wOwner != None) { |
#if QT_VERSION >= 0x050100 |
217 |
|
if (!QX11Info::isPlatformX11()) |
218 |
|
return false; |
219 |
|
#endif |
220 |
|
m_pDisplay = QX11Info::display(); |
221 |
|
if (m_pDisplay) { |
222 |
|
QString sUnique = QSAMPLER_XUNIQUE; |
223 |
|
char szHostName[255]; |
224 |
|
if (::gethostname(szHostName, sizeof(szHostName)) == 0) { |
225 |
|
sUnique += '@'; |
226 |
|
sUnique += szHostName; |
227 |
|
} |
228 |
|
m_aUnique = XInternAtom(m_pDisplay, sUnique.toUtf8().constData(), false); |
229 |
|
XGrabServer(m_pDisplay); |
230 |
|
m_wOwner = XGetSelectionOwner(m_pDisplay, m_aUnique); |
231 |
|
XUngrabServer(m_pDisplay); |
232 |
|
if (m_wOwner != None) { |
233 |
// First, notify any freedesktop.org WM |
// First, notify any freedesktop.org WM |
234 |
// that we're about to show the main widget... |
// that we're about to show the main widget... |
235 |
Screen *pScreen = XDefaultScreenOfDisplay(m_pDisplay); |
Screen *pScreen = XDefaultScreenOfDisplay(m_pDisplay); |
265 |
// Done. |
// Done. |
266 |
return true; |
return true; |
267 |
} |
} |
|
#endif // CONFIG_XUNIQUE |
|
|
#endif // CONFIG_X11 |
|
|
return false; |
|
|
} |
|
|
|
|
|
#ifdef CONFIG_X11 |
|
|
#ifdef CONFIG_XUNIQUE |
|
|
void x11PropertyNotify(Window w) |
|
|
{ |
|
|
if (m_pDisplay && m_pWidget && m_wOwner == w) { |
|
|
// Always check whether our property-flag is still around... |
|
|
Atom aType; |
|
|
int iFormat = 0; |
|
|
unsigned long iItems = 0; |
|
|
unsigned long iAfter = 0; |
|
|
unsigned char *pData = 0; |
|
|
if (XGetWindowProperty( |
|
|
m_pDisplay, |
|
|
m_wOwner, |
|
|
m_aUnique, |
|
|
0, 1024, |
|
|
false, |
|
|
m_aUnique, |
|
|
&aType, |
|
|
&iFormat, |
|
|
&iItems, |
|
|
&iAfter, |
|
|
&pData) == Success |
|
|
&& aType == m_aUnique && iItems > 0 && iAfter == 0) { |
|
|
// Avoid repeating it-self... |
|
|
XDeleteProperty(m_pDisplay, m_wOwner, m_aUnique); |
|
|
// Just make it always shows up fine... |
|
|
m_pWidget->show(); |
|
|
m_pWidget->raise(); |
|
|
m_pWidget->activateWindow(); |
|
|
} |
|
|
// Free any left-overs... |
|
|
if (iItems > 0 && pData) |
|
|
XFree(pData); |
|
|
} |
|
|
} |
|
|
#if QT_VERSION < 0x050000 |
|
|
bool x11EventFilter(XEvent *pEv) |
|
|
{ |
|
|
if (pEv->type == PropertyNotify |
|
|
&& pEv->xproperty.state == PropertyNewValue) |
|
|
x11PropertyNotify(pEv->xproperty.window); |
|
|
return QApplication::x11EventFilter(pEv); |
|
268 |
} |
} |
|
#endif |
|
269 |
#endif // CONFIG_XUNIQUE |
#endif // CONFIG_XUNIQUE |
270 |
#endif // CONFIG_X11 |
#endif // CONFIG_X11 |
271 |
|
return false; |
272 |
private: |
} |
|
|
|
|
// Translation support. |
|
|
QTranslator *m_pQtTranslator; |
|
|
QTranslator *m_pMyTranslator; |
|
273 |
|
|
|
// Instance variables. |
|
|
QWidget *m_pWidget; |
|
274 |
|
|
275 |
#ifdef CONFIG_X11 |
#ifdef CONFIG_X11 |
276 |
#ifdef CONFIG_XUNIQUE |
#ifdef CONFIG_XUNIQUE |
277 |
Display *m_pDisplay; |
void qsamplerApplication::x11PropertyNotify ( Window w ) |
278 |
Atom m_aUnique; |
{ |
279 |
Window m_wOwner; |
if (m_pDisplay && m_pWidget && m_wOwner == w) { |
280 |
#if QT_VERSION >= 0x050100 |
// Always check whether our property-flag is still around... |
281 |
qsamplerXcbEventFilter *m_pXcbEventFilter; |
Atom aType; |
282 |
#endif |
int iFormat = 0; |
283 |
#endif // CONFIG_XUNIQUE |
unsigned long iItems = 0; |
284 |
#endif // CONFIG_X11 |
unsigned long iAfter = 0; |
285 |
}; |
unsigned char *pData = 0; |
286 |
|
if (XGetWindowProperty( |
287 |
|
m_pDisplay, |
288 |
|
m_wOwner, |
289 |
|
m_aUnique, |
290 |
|
0, 1024, |
291 |
|
false, |
292 |
|
m_aUnique, |
293 |
|
&aType, |
294 |
|
&iFormat, |
295 |
|
&iItems, |
296 |
|
&iAfter, |
297 |
|
&pData) == Success |
298 |
|
&& aType == m_aUnique && iItems > 0 && iAfter == 0) { |
299 |
|
// Avoid repeating it-self... |
300 |
|
XDeleteProperty(m_pDisplay, m_wOwner, m_aUnique); |
301 |
|
// Just make it always shows up fine... |
302 |
|
m_pWidget->show(); |
303 |
|
m_pWidget->raise(); |
304 |
|
m_pWidget->activateWindow(); |
305 |
|
} |
306 |
|
// Free any left-overs... |
307 |
|
if (iItems > 0 && pData) |
308 |
|
XFree(pData); |
309 |
|
} |
310 |
|
} |
311 |
|
|
312 |
|
|
313 |
#ifdef CONFIG_X11 |
#if QT_VERSION < 0x050000 |
314 |
#ifdef CONFIG_XUNIQUE |
bool qsamplerApplication::x11EventFilter ( XEvent *pEv ) |
|
#if QT_VERSION >= 0x050100 |
|
|
// XCB Event filter (virtual processor). |
|
|
bool qsamplerXcbEventFilter::nativeEventFilter ( |
|
|
const QByteArray& eventType, void *message, long * ) |
|
315 |
{ |
{ |
316 |
if (eventType == "xcb_generic_event_t") { |
if (pEv->type == PropertyNotify |
317 |
xcb_property_notify_event_t *pEv |
&& pEv->xproperty.state == PropertyNewValue) |
318 |
= static_cast<xcb_property_notify_event_t *> (message); |
x11PropertyNotify(pEv->xproperty.window); |
319 |
if ((pEv->response_type & ~0x80) == XCB_PROPERTY_NOTIFY |
return QApplication::x11EventFilter(pEv); |
|
&& pEv->state == XCB_PROPERTY_NEW_VALUE) |
|
|
m_pApp->x11PropertyNotify(pEv->window); |
|
|
} |
|
|
return false; |
|
320 |
} |
} |
321 |
#endif |
#endif |
322 |
|
|
323 |
#endif // CONFIG_XUNIQUE |
#endif // CONFIG_XUNIQUE |
324 |
#endif // CONFIG_X11 |
#endif // CONFIG_X11 |
325 |
|
|