source: psi/vendor/affinix/current/src/psiapplication.cpp@ 2

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

Imported original Psi 0.10 sources from Affinix

File size: 6.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 ([email protected])
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//----------------------------------------------------------------------------
102// PsiApplication
103//----------------------------------------------------------------------------
104
105PsiApplication::PsiApplication(int &argc, char **argv, bool GUIenabled)
106: QApplication(argc, argv, GUIenabled)
107{
108 init(GUIenabled);
109}
110
111PsiApplication::~PsiApplication()
112{
113}
114
115void PsiApplication::init(bool GUIenabled)
116{
117 Q_UNUSED(GUIenabled);
118#ifdef Q_WS_X11
119 if ( GUIenabled ) {
120 const int max = 20;
121 Atom* atoms[max];
122 char* names[max];
123 Atom atoms_return[max];
124 int n = 0;
125
126 //atoms[n] = &atom_KdeNetUserTime;
127 //names[n++] = (char *) "_KDE_NET_USER_TIME";
128
129 atoms[n] = &kde_net_wm_user_time;
130 names[n++] = (char *) "_NET_WM_USER_TIME";
131 atoms[n] = &manager_atom;
132 names[n++] = (char *) "MANAGER";
133
134 Display *dsp = qt_xdisplay();
135
136 XInternAtoms( dsp, names, n, false, atoms_return );
137
138 for (int i = 0; i < n; i++ )
139 *atoms[i] = atoms_return[i];
140
141 // get the selection type we'll use to locate the notification tray
142 char buf[32];
143 snprintf(buf, sizeof(buf), "_NET_SYSTEM_TRAY_S%d", XScreenNumberOfScreen( XDefaultScreenOfDisplay(dsp) ));
144 tray_selection_atom = XInternAtom(dsp, buf, false);
145
146 // make a note of the window handle for the root window
147 root_window = QApplication::desktop()->winId();
148
149 XWindowAttributes attr;
150
151 // this is actually futile, since Qt overrides it at some
152 // unknown point in the near future.
153 XGetWindowAttributes(dsp, root_window, &attr);
154 XSelectInput(dsp, root_window, attr.your_event_mask | StructureNotifyMask);
155
156 setTrayOwnerWindow(dsp);
157 }
158#endif
159}
160
161bool PsiApplication::notify(QObject *receiver, QEvent *event)
162{
163#ifdef Q_WS_X11
164 if( event->type() == QEvent::Show && receiver->isWidgetType())
165 {
166 QWidget* w = static_cast< QWidget* >( receiver );
167 if( w->isTopLevel() && qt_x_last_input_time != CurrentTime ) // CurrentTime means no input event yet
168 XChangeProperty( qt_xdisplay(), w->winId(), kde_net_wm_user_time, XA_CARDINAL,
169 32, PropModeReplace, (unsigned char*)&qt_x_last_input_time, 1 );
170 }
171 if( event->type() == QEvent::Hide && receiver->isWidgetType())
172 {
173 QWidget* w = static_cast< QWidget* >( receiver );
174 if( w->isTopLevel() && w->winId() != 0 )
175 XDeleteProperty( qt_xdisplay(), w->winId(), kde_net_wm_user_time );
176 }
177#endif
178 return QApplication::notify(receiver, event);
179}
180
181#ifdef Q_WS_X11
182bool PsiApplication::x11EventFilter( XEvent *_event )
183{
184 switch ( _event->type ) {
185
186 case ClientMessage:
187 if (_event->xclient.window == root_window && _event->xclient.message_type == manager_atom)
188 {
189 // A new notification area application has
190 // announced its presence
191 setTrayOwnerWindow(_event->xclient.display);
192 newTrayOwner();
193 }
194 break;
195
196 case DestroyNotify:
197 if (_event->xdestroywindow.event == tray_owner)
198 {
199 // there is now no known notification area.
200 // We're still looking out for the MANAGER
201 // message sent to the root window, at which
202 // point we'll have another look to see
203 // whether a notification area is available.
204 tray_owner = 0;
205 trayOwnerDied();
206 }
207 break;
208
209 case ButtonPress:
210 case XKeyPress:
211 {
212 if( _event->type == ButtonPress )
213 qt_x_last_input_time = _event->xbutton.time;
214 else // KeyPress
215 qt_x_last_input_time = _event->xkey.time;
216 QWidget *w = activeWindow();
217 if( w ) {
218 XChangeProperty( qt_xdisplay(), w->winId(), kde_net_wm_user_time, XA_CARDINAL,
219 32, PropModeReplace, (unsigned char*)&qt_x_last_input_time, 1 );
220 /*timeval tv;
221 gettimeofday( &tv, NULL );
222 unsigned long now = tv.tv_sec * 10 + tv.tv_usec / 100000;
223 XChangeProperty(qt_xdisplay(), w->winId(),
224 atom_KdeNetUserTime, XA_CARDINAL,
225 32, PropModeReplace, (unsigned char *)&now, 1);*/
226 }
227 break;
228 }
229
230 default:
231 break;
232 }
233
234 // process the event normally
235 return false;
236}
237#endif
238
239#ifdef Q_WS_MAC
240bool PsiApplication::macEventFilter( EventHandlerCallRef, EventRef inEvent )
241{
242 UInt32 eclass = GetEventClass(inEvent);
243 int etype = GetEventKind(inEvent);
244 if(eclass == 'eppc' && etype == kEventAppleEvent) {
245 dockActivated();
246 }
247 return false;
248}
249#endif
250
Note: See TracBrowser for help on using the repository browser.