~ubuntu-branches/ubuntu/jaunty/psi/jaunty

« back to all changes in this revision

Viewing changes to src/psiapplication.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2005-01-10 17:41:43 UTC
  • mfrom: (1.2.1 upstream) (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050110174143-ltocv5zapl6blf5d
Tags: 0.9.3-1
* New upstream release
* Cleaned up debian/rules (some things are done by upstream Makefiles now)
* Fixed some lintian warnings:
  - removed executable bit from some .png files
  - moved psi.desktop to /usr/share/applications
* Updated menu files

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
37
static Atom manager_atom = 0;
 
38
static Atom tray_selection_atom = 0;
 
39
Window root_window = 0;
 
40
Window tray_owner = None;
 
41
 
 
42
//static Atom atom_KdeNetUserTime;
 
43
static 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
 
 
49
Time   qt_x_last_input_time = CurrentTime;
 
50
//extern Time qt_x_time;
 
51
 
 
52
#ifdef KeyPress
 
53
#ifndef FIXX11H_KeyPress
 
54
#define FIXX11H_KeyPress
 
55
const int XKeyPress = KeyPress;
 
56
#undef KeyPress
 
57
const 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
 
75
void 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
//----------------------------------------------------------------------------
 
103
// PsiApplication
 
104
//----------------------------------------------------------------------------
 
105
 
 
106
PsiApplication::PsiApplication(int &argc, char **argv, bool GUIenabled)
 
107
: QApplication(argc, argv, GUIenabled)
 
108
{
 
109
        init(GUIenabled);
 
110
}
 
111
 
 
112
PsiApplication::~PsiApplication()
 
113
{
 
114
}
 
115
 
 
116
void PsiApplication::init(bool GUIenabled)
 
117
{
 
118
        Q_UNUSED(GUIenabled);
 
119
#ifdef Q_WS_X11
 
120
        if ( GUIenabled ) {
 
121
                const int max = 20;
 
122
                Atom* atoms[max];
 
123
                char* names[max];
 
124
                Atom atoms_return[max];
 
125
                int n = 0;
 
126
 
 
127
                //atoms[n] = &atom_KdeNetUserTime;
 
128
                //names[n++] = (char *) "_KDE_NET_USER_TIME";
 
129
 
 
130
                atoms[n] = &kde_net_wm_user_time;
 
131
                names[n++] = (char *) "_NET_WM_USER_TIME";
 
132
                atoms[n] = &manager_atom;
 
133
                names[n++] = (char *) "MANAGER";
 
134
 
 
135
                Display *dsp = qt_xdisplay();
 
136
 
 
137
                XInternAtoms( dsp, names, n, false, atoms_return );
 
138
 
 
139
                for (int i = 0; i < n; i++ )
 
140
                        *atoms[i] = atoms_return[i];
 
141
 
 
142
                // get the selection type we'll use to locate the notification tray
 
143
                char buf[32];
 
144
                snprintf(buf, sizeof(buf), "_NET_SYSTEM_TRAY_S%d", XScreenNumberOfScreen( XDefaultScreenOfDisplay(dsp) ));
 
145
                tray_selection_atom = XInternAtom(dsp, buf, false);
 
146
 
 
147
                // make a note of the window handle for the root window
 
148
                root_window = QApplication::desktop()->winId();
 
149
 
 
150
                XWindowAttributes attr;
 
151
 
 
152
                // this is actually futile, since Qt overrides it at some
 
153
                // unknown point in the near future.
 
154
                XGetWindowAttributes(dsp, root_window, &attr);
 
155
                XSelectInput(dsp, root_window, attr.your_event_mask | StructureNotifyMask);
 
156
 
 
157
                setTrayOwnerWindow(dsp);
 
158
        }
 
159
#endif
 
160
}
 
161
 
 
162
bool PsiApplication::notify(QObject *receiver, QEvent *event)
 
163
{
 
164
#ifdef Q_WS_X11
 
165
        if( event->type() == QEvent::Show && receiver->isWidgetType())
 
166
        {
 
167
                QWidget* w = static_cast< QWidget* >( receiver );
 
168
                if( w->isTopLevel() && qt_x_last_input_time != CurrentTime ) // CurrentTime means no input event yet
 
169
                        XChangeProperty( qt_xdisplay(), w->winId(), kde_net_wm_user_time, XA_CARDINAL,
 
170
                                         32, PropModeReplace, (unsigned char*)&qt_x_last_input_time, 1 );
 
171
        }
 
172
        if( event->type() == QEvent::Hide && receiver->isWidgetType())
 
173
        {
 
174
                QWidget* w = static_cast< QWidget* >( receiver );
 
175
                if( w->isTopLevel() && w->winId() != 0 )
 
176
                        XDeleteProperty( qt_xdisplay(), w->winId(), kde_net_wm_user_time );
 
177
        }
 
178
#endif
 
179
        return QApplication::notify(receiver, event);
 
180
}
 
181
 
 
182
#ifdef Q_WS_X11
 
183
bool PsiApplication::x11EventFilter( XEvent *_event )
 
184
{
 
185
        switch ( _event->type ) {
 
186
 
 
187
                case ClientMessage:
 
188
                        if (_event->xclient.window == root_window && _event->xclient.message_type == manager_atom)
 
189
                        {
 
190
                                // A new notification area application has
 
191
                                // announced its presence
 
192
                                setTrayOwnerWindow(_event->xclient.display);
 
193
                                newTrayOwner();
 
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
                                break;
 
207
                        }
 
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
 
240
bool 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