source: psi/trunk/src/psiapplication.cpp@ 113

Last change on this file since 113 was 84, checked in by dmik, 19 years ago

Psi: Added installation of the OS/2 System Exception handler (QtOS2SysXcptHandler) on the main thread.

File size: 7.6 KB
Line 
1/*
2 * psiapplication.cpp - subclass of QApplication to do some workarounds
3 * Copyright (C) 2003 Michail Pishchagin
4 *
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.
9 *
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.
14 *
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
18 *
19 */
20
21#include "psiapplication.h"
22
23#ifdef Q_WS_MAC
24#include<Carbon/Carbon.h>
25#endif
26
27#ifdef Q_WS_X11
28#include <time.h>
29#include <sys/time.h>
30
31#include <X11/Xlib.h>
32#include <X11/Xutil.h>
33#include <X11/Xatom.h>
34#include <X11/SM/SMlib.h>
35
36// Atoms required for monitoring the freedesktop.org notification area
37static Atom manager_atom = 0;
38static Atom tray_selection_atom = 0;
39Window root_window = 0;
40Window tray_owner = None;
41
42//static Atom atom_KdeNetUserTime;
43static Atom kde_net_wm_user_time = 0;
44
45//#if QT_VERSION > 0x030201
46//#warning "Possibly, now it's time to clean up some 'focus stealing prevention' workaround code"
47//#endif
48
49Time qt_x_last_input_time = CurrentTime;
50//extern Time qt_x_time;
51
52#ifdef KeyPress
53#ifndef FIXX11H_KeyPress
54#define FIXX11H_KeyPress
55const int XKeyPress = KeyPress;
56#undef KeyPress
57const int KeyPress = XKeyPress;
58#endif
59#undef KeyPress
60#endif
61#endif
62
63// mblsha:
64// currently this file contains some Anti-"focus steling prevention" code by
65// Lubos Lunak (l.lunak@kde.org)
66//
67// This should resolve all bugs with KWin3 and old Qt, but maybe it'll be useful for
68// other window managers?
69
70#ifdef Q_WS_X11
71//#undef Q_WS_X11
72#endif
73
74#ifdef Q_WS_X11
75void setTrayOwnerWindow(Display *dsp)
76{
77 /* This code is basically trying to mirror what happens in
78 * eggtrayicon.c:egg_tray_icon_update_manager_window()
79 */
80 // ignore events from the old tray owner
81 if (tray_owner != None)
82 {
83 XSelectInput(dsp, tray_owner, 0);
84 }
85
86 // obtain the Window handle for the new tray owner
87 XGrabServer(dsp);
88 tray_owner = XGetSelectionOwner(dsp, tray_selection_atom);
89
90 // we have to be able to spot DestroyNotify messages on the tray owner
91 if (tray_owner != None)
92 {
93 XSelectInput(dsp, tray_owner, StructureNotifyMask|PropertyChangeMask);
94 }
95 XUngrabServer(dsp);
96 XFlush(dsp);
97}
98
99#endif
100
101#ifdef Q_WS_PM
102// support for the Innotek Font Engine (Freetype 2) library
103// (so far, we use it directly here rather than making Qt/2 Freetype2-aware,
104// because ft2lib has some problems (e.g. font transformations) that makes it
105// dangerous to enable it globally in Qt)
106#include <qlibrary.h>
107typedef VOID (APIENTRY *Ft2EnableFontEngine_T)( BOOL fEnable );
108static Ft2EnableFontEngine_T Ft2EnableFontEngine = 0;
109static QLibrary ft2lib( "ft2lib.dll" );
110#endif
111
112//----------------------------------------------------------------------------
113// PsiApplication
114//----------------------------------------------------------------------------
115
116PsiApplication::PsiApplication(int &argc, char **argv, bool GUIenabled)
117: QApplication(argc, argv, GUIenabled)
118{
119 init(GUIenabled);
120}
121
122PsiApplication::~PsiApplication()
123{
124}
125
126void PsiApplication::init(bool GUIenabled)
127{
128 Q_UNUSED(GUIenabled);
129#ifdef Q_WS_PM
130 // enable ft2lib when appropriate
131 if ( GUIenabled ) {
132 Ft2EnableFontEngine =
133 (Ft2EnableFontEngine_T) ft2lib.resolve( "Ft2EnableFontEngine" );
134 if ( Ft2EnableFontEngine ) {
135 // enable Innotek Font Engine
136 Ft2EnableFontEngine( TRUE );
137 }
138 }
139#endif
140#ifdef Q_WS_X11
141 if ( GUIenabled ) {
142 const int max = 20;
143 Atom* atoms[max];
144 char* names[max];
145 Atom atoms_return[max];
146 int n = 0;
147
148 //atoms[n] = &atom_KdeNetUserTime;
149 //names[n++] = (char *) "_KDE_NET_USER_TIME";
150
151 atoms[n] = &kde_net_wm_user_time;
152 names[n++] = (char *) "_NET_WM_USER_TIME";
153 atoms[n] = &manager_atom;
154 names[n++] = (char *) "MANAGER";
155
156 Display *dsp = qt_xdisplay();
157
158 XInternAtoms( dsp, names, n, false, atoms_return );
159
160 for (int i = 0; i < n; i++ )
161 *atoms[i] = atoms_return[i];
162
163 // get the selection type we'll use to locate the notification tray
164 char buf[32];
165 snprintf(buf, sizeof(buf), "_NET_SYSTEM_TRAY_S%d", XScreenNumberOfScreen( XDefaultScreenOfDisplay(dsp) ));
166 tray_selection_atom = XInternAtom(dsp, buf, false);
167
168 // make a note of the window handle for the root window
169 root_window = QApplication::desktop()->winId();
170
171 XWindowAttributes attr;
172
173 // this is actually futile, since Qt overrides it at some
174 // unknown point in the near future.
175 XGetWindowAttributes(dsp, root_window, &attr);
176 XSelectInput(dsp, root_window, attr.your_event_mask | StructureNotifyMask);
177
178 setTrayOwnerWindow(dsp);
179 }
180#endif
181}
182
183bool PsiApplication::notify(QObject *receiver, QEvent *event)
184{
185#ifdef Q_WS_X11
186 if( event->type() == QEvent::Show && receiver->isWidgetType())
187 {
188 QWidget* w = static_cast< QWidget* >( receiver );
189 if( w->isTopLevel() && qt_x_last_input_time != CurrentTime ) // CurrentTime means no input event yet
190 XChangeProperty( qt_xdisplay(), w->winId(), kde_net_wm_user_time, XA_CARDINAL,
191 32, PropModeReplace, (unsigned char*)&qt_x_last_input_time, 1 );
192 }
193 if( event->type() == QEvent::Hide && receiver->isWidgetType())
194 {
195 QWidget* w = static_cast< QWidget* >( receiver );
196 if( w->isTopLevel() && w->winId() != 0 )
197 XDeleteProperty( qt_xdisplay(), w->winId(), kde_net_wm_user_time );
198 }
199#endif
200 return QApplication::notify(receiver, event);
201}
202
203#ifdef Q_WS_X11
204bool PsiApplication::x11EventFilter( XEvent *_event )
205{
206 switch ( _event->type ) {
207
208 case ClientMessage:
209 if (_event->xclient.window == root_window && _event->xclient.message_type == manager_atom)
210 {
211 // A new notification area application has
212 // announced its presence
213 setTrayOwnerWindow(_event->xclient.display);
214 newTrayOwner();
215 }
216 break;
217
218 case DestroyNotify:
219 if (_event->xdestroywindow.event == tray_owner)
220 {
221 // there is now no known notification area.
222 // We're still looking out for the MANAGER
223 // message sent to the root window, at which
224 // point we'll have another look to see
225 // whether a notification area is available.
226 tray_owner = 0;
227 trayOwnerDied();
228 }
229 break;
230
231 case ButtonPress:
232 case XKeyPress:
233 {
234 if( _event->type == ButtonPress )
235 qt_x_last_input_time = _event->xbutton.time;
236 else // KeyPress
237 qt_x_last_input_time = _event->xkey.time;
238 QWidget *w = activeWindow();
239 if( w ) {
240 XChangeProperty( qt_xdisplay(), w->winId(), kde_net_wm_user_time, XA_CARDINAL,
241 32, PropModeReplace, (unsigned char*)&qt_x_last_input_time, 1 );
242 /*timeval tv;
243 gettimeofday( &tv, NULL );
244 unsigned long now = tv.tv_sec * 10 + tv.tv_usec / 100000;
245 XChangeProperty(qt_xdisplay(), w->winId(),
246 atom_KdeNetUserTime, XA_CARDINAL,
247 32, PropModeReplace, (unsigned char *)&now, 1);*/
248 }
249 break;
250 }
251
252 default:
253 break;
254 }
255
256 // process the event normally
257 return false;
258}
259#endif
260
261#ifdef Q_WS_MAC
262bool PsiApplication::macEventFilter( EventHandlerCallRef, EventRef inEvent )
263{
264 UInt32 eclass = GetEventClass(inEvent);
265 int etype = GetEventKind(inEvent);
266 if(eclass == 'eppc' && etype == kEventAppleEvent) {
267 dockActivated();
268 }
269 return false;
270}
271#endif
272
Note: See TracBrowser for help on using the repository browser.