]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/unix/appunix.cpp
Fix horizontal mouse wheel scrolling in wxGTK.
[wxWidgets.git] / src / unix / appunix.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/unix/appunix.cpp
3// Purpose: wxAppConsole with wxMainLoop implementation
4// Author: Lukasz Michalski
5// Created: 28/01/2005
6// Copyright: (c) Lukasz Michalski
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10#include "wx/wxprec.h"
11
12#ifdef __BORLANDC__
13 #pragma hdrstop
14#endif
15
16#ifndef WX_PRECOMP
17 #include "wx/app.h"
18 #include "wx/log.h"
19#endif
20
21#include "wx/evtloop.h"
22#include "wx/scopedptr.h"
23#include "wx/unix/private/wakeuppipe.h"
24#include "wx/private/fdiodispatcher.h"
25#include "wx/private/fdioeventloopsourcehandler.h"
26
27#include <signal.h>
28#include <unistd.h>
29
30#ifndef SA_RESTART
31 // don't use for systems which don't define it (at least VMS and QNX)
32 #define SA_RESTART 0
33#endif
34
35// ----------------------------------------------------------------------------
36// Helper class calling CheckSignal() on wake up
37// ----------------------------------------------------------------------------
38
39namespace
40{
41
42class SignalsWakeUpPipe : public wxWakeUpPipe
43{
44public:
45 // Ctor automatically registers this pipe with the event loop.
46 SignalsWakeUpPipe()
47 {
48 m_source = wxEventLoopBase::AddSourceForFD
49 (
50 GetReadFd(),
51 this,
52 wxEVENT_SOURCE_INPUT
53 );
54 }
55
56 virtual void OnReadWaiting()
57 {
58 // The base class wxWakeUpPipe::OnReadWaiting() needs to be called in order
59 // to read the data out of the wake up pipe and clear it for next time.
60 wxWakeUpPipe::OnReadWaiting();
61
62 if ( wxTheApp )
63 wxTheApp->CheckSignal();
64 }
65
66 virtual ~SignalsWakeUpPipe()
67 {
68 delete m_source;
69 }
70
71private:
72 wxEventLoopSource* m_source;
73};
74
75} // anonymous namespace
76
77wxAppConsole::wxAppConsole()
78{
79 m_signalWakeUpPipe = NULL;
80}
81
82wxAppConsole::~wxAppConsole()
83{
84 delete m_signalWakeUpPipe;
85}
86
87// use unusual names for arg[cv] to avoid clashes with wxApp members with the
88// same names
89bool wxAppConsole::Initialize(int& argc_, wxChar** argv_)
90{
91 if ( !wxAppConsoleBase::Initialize(argc_, argv_) )
92 return false;
93
94 sigemptyset(&m_signalsCaught);
95
96 return true;
97}
98
99// The actual signal handler. It does as little as possible (because very few
100// things are safe to do from inside a signal handler) and just ensures that
101// CheckSignal() will be called later from SignalsWakeUpPipe::OnReadWaiting().
102void wxAppConsole::HandleSignal(int signal)
103{
104 wxAppConsole * const app = wxTheApp;
105 if ( !app )
106 return;
107
108 // Register the signal that is caught.
109 sigaddset(&(app->m_signalsCaught), signal);
110
111 // Wake up the application for handling the signal.
112 //
113 // Notice that we must have a valid wake up pipe here as we only install
114 // our signal handlers after allocating it.
115 app->m_signalWakeUpPipe->WakeUpNoLock();
116}
117
118void wxAppConsole::CheckSignal()
119{
120 for ( SignalHandlerHash::iterator it = m_signalHandlerHash.begin();
121 it != m_signalHandlerHash.end();
122 ++it )
123 {
124 int sig = it->first;
125 if ( sigismember(&m_signalsCaught, sig) )
126 {
127 sigdelset(&m_signalsCaught, sig);
128 (it->second)(sig);
129 }
130 }
131}
132
133wxFDIOHandler* wxAppConsole::RegisterSignalWakeUpPipe(wxFDIODispatcher& dispatcher)
134{
135 wxCHECK_MSG( m_signalWakeUpPipe, NULL, "Should be allocated" );
136
137 // we need a bridge to wxFDIODispatcher
138 //
139 // TODO: refactor the code so that only wxEventLoopSourceHandler is used
140 wxScopedPtr<wxFDIOHandler>
141 fdioHandler(new wxFDIOEventLoopSourceHandler(m_signalWakeUpPipe));
142
143 if ( !dispatcher.RegisterFD
144 (
145 m_signalWakeUpPipe->GetReadFd(),
146 fdioHandler.get(),
147 wxFDIO_INPUT
148 ) )
149 return NULL;
150
151 return fdioHandler.release();
152}
153
154// the type of the signal handlers we use is "void(*)(int)" while the real
155// signal handlers are extern "C" and so have incompatible type and at least
156// Sun CC warns about it, so use explicit casts to suppress these warnings as
157// they should be harmless
158extern "C"
159{
160 typedef void (*SignalHandler_t)(int);
161}
162
163bool wxAppConsole::SetSignalHandler(int signal, SignalHandler handler)
164{
165 const bool install = (SignalHandler_t)handler != SIG_DFL &&
166 (SignalHandler_t)handler != SIG_IGN;
167
168 if ( !m_signalWakeUpPipe )
169 {
170 // Create the pipe that the signal handler will use to cause the event
171 // loop to call wxAppConsole::CheckSignal().
172 m_signalWakeUpPipe = new SignalsWakeUpPipe();
173 }
174
175 struct sigaction sa;
176 memset(&sa, 0, sizeof(sa));
177 sa.sa_handler = (SignalHandler_t)&wxAppConsole::HandleSignal;
178 sa.sa_flags = SA_RESTART;
179 int res = sigaction(signal, &sa, 0);
180 if ( res != 0 )
181 {
182 wxLogSysError(_("Failed to install signal handler"));
183 return false;
184 }
185
186 if ( install )
187 m_signalHandlerHash[signal] = handler;
188 else
189 m_signalHandlerHash.erase(signal);
190
191 return true;
192}
193