Make wxEventLoop::AddSourceForFD() static.

Any event sources should be registered with all the event loops, including the
ones that will be started in the future, and not only the current (and
potentially not even existing yet) one. So make AddSourceForFD() method static.

To still allow it to do different things in console and GUI applications, as
it must, virtualize it via the new wxEventLoopSourcesManager class which has
different implementations in the two cases, returned via wxAppTraits as usual.

Notice that this required moving the implementation of this method from
src/osx/core/evtloop_cf.cpp to src/osx/core/utilsexc_cf.cpp as the former file
is base-only and didn't have access to wxGUIAppTraits.

See #10258.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74341 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2013-07-03 00:28:42 +00:00
parent 5e38246378
commit 71e9885be0
13 changed files with 222 additions and 150 deletions

View File

@@ -79,9 +79,9 @@ public:
#if wxUSE_EVENTLOOP_SOURCE
// create a new event loop source wrapping the given file descriptor and
// start monitoring it
virtual wxEventLoopSource *
AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags) = 0;
// monitor it for events occurring on this descriptor in all event loops
static wxEventLoopSource *
AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags);
#endif // wxUSE_EVENTLOOP_SOURCE
// dispatch&processing
@@ -296,19 +296,6 @@ public:
wxGUIEventLoop() { m_impl = NULL; }
virtual ~wxGUIEventLoop();
#if wxUSE_EVENTLOOP_SOURCE
// We need to define a base class pure virtual method but we can't provide
// a generic implementation for it so simply fail.
virtual wxEventLoopSource *
AddSourceForFD(int WXUNUSED(fd),
wxEventLoopSourceHandler * WXUNUSED(handler),
int WXUNUSED(flags))
{
wxFAIL_MSG( "support for event loop sources not implemented" );
return NULL;
}
#endif // wxUSE_EVENTLOOP_SOURCE
virtual void ScheduleExit(int rc = 0);
virtual bool Pending() const;
virtual bool Dispatch();

View File

@@ -29,11 +29,6 @@ public:
virtual void WakeUp();
virtual bool YieldFor(long eventsToProcess);
#if wxUSE_EVENTLOOP_SOURCE
virtual wxEventLoopSource *
AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags);
#endif // wxUSE_EVENTLOOP_SOURCE
void StoreGdkEventForLaterProcessing(GdkEvent* ev)
{ m_arrGdkEvents.Add(ev); }

View File

@@ -45,11 +45,6 @@ public:
virtual bool YieldFor(long eventsToProcess);
#if wxUSE_EVENTLOOP_SOURCE
virtual wxEventLoopSource *
AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags);
#endif // wxUSE_EVENTLOOP_SOURCE
bool ShouldProcessIdleEvents() const { return m_processIdleEvents ; }
#if wxUSE_UIACTIONSIMULATOR

View File

@@ -17,7 +17,7 @@ typedef struct __CFFileDescriptor *CFFileDescriptorRef;
// wxCFEventLoopSource: CoreFoundation-based wxEventLoopSource for OS X
// ----------------------------------------------------------------------------
class wxCFEventLoopSource : public wxEventLoopSource
class WXDLLIMPEXP_BASE wxCFEventLoopSource : public wxEventLoopSource
{
public:
wxCFEventLoopSource(wxEventLoopSourceHandler *handler, int flags)

View File

@@ -0,0 +1,26 @@
///////////////////////////////////////////////////////////////////////////////
// Name: wx/private/eventloopsourcesmanager.h
// Purpose: declares wxEventLoopSourcesManagerBase class
// Author: Rob Bresalier
// Created: 2013-06-19
// RCS-ID: $Id$
// Copyright: (c) 2013 Rob Bresalier
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_PRIVATE_EVENTLOOPSOURCESMANAGER_H_
#define _WX_PRIVATE_EVENTLOOPSOURCESMANAGER_H_
// For pulling in the value of wxUSE_EVENTLOOP_SOURCE
#include "wx/evtloop.h"
class WXDLLIMPEXP_BASE wxEventLoopSourcesManagerBase
{
public:
#if wxUSE_EVENTLOOP_SOURCE
virtual wxEventLoopSource*
AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags) = 0;
#endif
};
#endif // _WX_PRIVATE_EVENTLOOPSOURCESMANAGER_H_

View File

@@ -15,6 +15,7 @@
struct wxEndProcessData;
struct wxExecuteData;
class wxFDIOManager;
class wxEventLoopSourcesManagerBase;
// ----------------------------------------------------------------------------
// wxAppTraits: the Unix version adds extra hooks needed by Unix code
@@ -56,6 +57,10 @@ public:
virtual wxFDIOManager *GetFDIOManager();
#endif // wxUSE_SOCKETS
// Return a non-NULL pointer to the object responsible for managing the
// event loop sources in this kind of application.
virtual wxEventLoopSourcesManagerBase* GetEventLoopSourcesManager();
protected:
// a helper for the implementation of WaitForChild() in wxGUIAppTraits:
// checks the streams used for redirected IO in execData and returns true

View File

@@ -88,6 +88,8 @@ public:
#endif
#endif // wxUSE_SOCKETS
virtual wxEventLoopSourcesManagerBase* GetEventLoopSourcesManager();
};
#endif // wxUSE_GUI

View File

@@ -41,11 +41,6 @@ public:
virtual bool IsOk() const { return m_dispatcher != NULL; }
virtual bool YieldFor(long WXUNUSED(eventsToProcess)) { return true; }
#if wxUSE_EVENTLOOP_SOURCE
virtual wxEventLoopSource *
AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags);
#endif // wxUSE_EVENTLOOP_SOURCE
protected:
virtual void OnNextIteration();

View File

@@ -23,6 +23,8 @@
#endif //WX_PRECOMP
#include "wx/scopeguard.h"
#include "wx/apptrait.h"
#include "wx/private/eventloopsourcesmanager.h"
// ----------------------------------------------------------------------------
// wxEventLoopBase
@@ -115,6 +117,29 @@ bool wxEventLoopBase::Yield(bool onlyIfNeeded)
return YieldFor(wxEVT_CATEGORY_ALL);
}
#if wxUSE_EVENTLOOP_SOURCE
wxEventLoopSource*
wxEventLoopBase::AddSourceForFD(int fd,
wxEventLoopSourceHandler *handler,
int flags)
{
// Ensure that we have some valid traits.
wxConsoleAppTraits traitsConsole;
wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
if ( !traits )
traits = &traitsConsole;
// And delegate to the event loop sources manager defined by it.
wxEventLoopSourcesManagerBase* const
manager = traits->GetEventLoopSourcesManager();
wxCHECK_MSG( manager, NULL, wxS("Must have wxEventLoopSourcesManager") );
return manager->AddSourceForFD(fd, handler, flags);
}
#endif // wxUSE_EVENTLOOP_SOURCE
// wxEventLoopManual is unused in the other ports
#if defined(__WINDOWS__) || defined(__WXDFB__) || ( ( defined(__UNIX__) && !defined(__WXOSX__) ) && wxUSE_BASE)

View File

@@ -32,6 +32,9 @@
#include "wx/log.h"
#endif // WX_PRECOMP
#include "wx/private/eventloopsourcesmanager.h"
#include "wx/apptrait.h"
#include <gtk/gtk.h>
#include <glib.h>
@@ -133,20 +136,21 @@ static gboolean wx_on_channel_event(GIOChannel *channel,
}
}
wxEventLoopSource *
wxGUIEventLoop::AddSourceForFD(int fd,
wxEventLoopSourceHandler *handler,
int flags)
class wxGUIEventLoopSourcesManager : public wxEventLoopSourcesManagerBase
{
public:
virtual wxEventLoopSource*
AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags)
{
wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" );
int condition = 0;
if ( flags & wxEVENT_SOURCE_INPUT )
condition |= G_IO_IN | G_IO_PRI;
condition |= G_IO_IN | G_IO_PRI | G_IO_HUP;
if ( flags & wxEVENT_SOURCE_OUTPUT )
condition |= G_IO_OUT;
if ( flags & wxEVENT_SOURCE_EXCEPTION )
condition |= G_IO_ERR | G_IO_HUP | G_IO_NVAL;
condition |= G_IO_ERR | G_IO_NVAL;
GIOChannel* channel = g_io_channel_unix_new(fd);
const unsigned sourceId = g_io_add_watch
@@ -169,6 +173,14 @@ wxGUIEventLoop::AddSourceForFD(int fd,
return new wxGTKEventLoopSource(sourceId, handler, flags);
}
};
wxEventLoopSourcesManagerBase* wxGUIAppTraits::GetEventLoopSourcesManager()
{
static wxGUIEventLoopSourcesManager s_eventLoopSourcesManager;
return &s_eventLoopSourcesManager;
}
wxGTKEventLoopSource::~wxGTKEventLoopSource()
{

View File

@@ -48,80 +48,6 @@
#if wxUSE_EVENTLOOP_SOURCE
namespace
{
void EnableDescriptorCallBacks(CFFileDescriptorRef cffd, int flags)
{
if ( flags & wxEVENT_SOURCE_INPUT )
CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorReadCallBack);
if ( flags & wxEVENT_SOURCE_OUTPUT )
CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorWriteCallBack);
}
void
wx_cffiledescriptor_callback(CFFileDescriptorRef cffd,
CFOptionFlags flags,
void *ctxData)
{
wxLogTrace(wxTRACE_EVT_SOURCE,
"CFFileDescriptor callback, flags=%d", flags);
wxCFEventLoopSource * const
source = static_cast<wxCFEventLoopSource *>(ctxData);
wxEventLoopSourceHandler * const
handler = source->GetHandler();
if ( flags & kCFFileDescriptorReadCallBack )
handler->OnReadWaiting();
if ( flags & kCFFileDescriptorWriteCallBack )
handler->OnWriteWaiting();
// we need to re-enable callbacks to be called again
EnableDescriptorCallBacks(cffd, source->GetFlags());
}
} // anonymous namespace
wxEventLoopSource *
wxCFEventLoop::AddSourceForFD(int fd,
wxEventLoopSourceHandler *handler,
int flags)
{
wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" );
wxScopedPtr<wxCFEventLoopSource>
source(new wxCFEventLoopSource(handler, flags));
CFFileDescriptorContext ctx = { 0, source.get(), NULL, NULL, NULL };
wxCFRef<CFFileDescriptorRef>
cffd(CFFileDescriptorCreate
(
kCFAllocatorDefault,
fd,
true, // close on invalidate
wx_cffiledescriptor_callback,
&ctx
));
if ( !cffd )
return NULL;
wxCFRef<CFRunLoopSourceRef>
cfsrc(CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, cffd, 0));
if ( !cfsrc )
return NULL;
CFRunLoopRef cfloop = CFGetCurrentRunLoop();
CFRunLoopAddSource(cfloop, cfsrc, kCFRunLoopDefaultMode);
// Enable the callbacks initially.
EnableDescriptorCallBacks(cffd, source->GetFlags());
source->SetFileDescriptor(cffd.release());
return source.release();
}
void wxCFEventLoopSource::SetFileDescriptor(CFFileDescriptorRef cffd)
{
wxASSERT_MSG( !m_cffd, "shouldn't be called more than once" );

View File

@@ -22,8 +22,13 @@
#include "wx/thread.h"
#include "wx/process.h"
#include "wx/evtloop.h"
#include "wx/evtloopsrc.h"
#include "wx/private/eventloopsourcesmanager.h"
#include <sys/wait.h>
#include <CoreFoundation/CFFileDescriptor.h>
#include <CoreFoundation/CFSocket.h>
/*!
@@ -104,6 +109,93 @@ int wxGUIAppTraits::AddProcessCallback(wxEndProcessData *proc_data, int fd)
return ++s_last_tag;
}
#if wxUSE_EVENTLOOP_SOURCE
namespace
{
void EnableDescriptorCallBacks(CFFileDescriptorRef cffd, int flags)
{
if ( flags & wxEVENT_SOURCE_INPUT )
CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorReadCallBack);
if ( flags & wxEVENT_SOURCE_OUTPUT )
CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorWriteCallBack);
}
void
wx_cffiledescriptor_callback(CFFileDescriptorRef cffd,
CFOptionFlags flags,
void *ctxData)
{
wxLogTrace(wxTRACE_EVT_SOURCE,
"CFFileDescriptor callback, flags=%d", flags);
wxCFEventLoopSource * const
source = static_cast<wxCFEventLoopSource *>(ctxData);
wxEventLoopSourceHandler * const
handler = source->GetHandler();
if ( flags & kCFFileDescriptorReadCallBack )
handler->OnReadWaiting();
if ( flags & kCFFileDescriptorWriteCallBack )
handler->OnWriteWaiting();
// we need to re-enable callbacks to be called again
EnableDescriptorCallBacks(cffd, source->GetFlags());
}
} // anonymous namespace
class wxCFEventLoopSourcesManager : public wxEventLoopSourcesManagerBase
{
public:
wxEventLoopSource *
AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags)
{
wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" );
wxScopedPtr<wxCFEventLoopSource>
source(new wxCFEventLoopSource(handler, flags));
CFFileDescriptorContext ctx = { 0, source.get(), NULL, NULL, NULL };
wxCFRef<CFFileDescriptorRef>
cffd(CFFileDescriptorCreate
(
kCFAllocatorDefault,
fd,
true, // close on invalidate
wx_cffiledescriptor_callback,
&ctx
));
if ( !cffd )
return NULL;
wxCFRef<CFRunLoopSourceRef>
cfsrc(CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, cffd, 0));
if ( !cfsrc )
return NULL;
CFRunLoopRef cfloop = CFRunLoopGetCurrent();
CFRunLoopAddSource(cfloop, cfsrc, kCFRunLoopDefaultMode);
// Enable the callbacks initially.
EnableDescriptorCallBacks(cffd, source->GetFlags());
source->SetFileDescriptor(cffd.release());
return source.release();
}
};
wxEventLoopSourcesManagerBase* wxGUIAppTraits::GetEventLoopSourcesManager()
{
static wxCFEventLoopSourcesManager s_eventLoopSourcesManager;
return &s_eventLoopSourcesManager;
}
#endif // wxUSE_EVENTLOOP_SOURCE
/////////////////////////////////////////////////////////////////////////////
// NOTE: This doesn't really belong here but this was a handy file to

View File

@@ -36,7 +36,9 @@
#include "wx/unix/private/epolldispatcher.h"
#include "wx/unix/private/wakeuppipe.h"
#include "wx/private/selectdispatcher.h"
#include "wx/private/eventloopsourcesmanager.h"
#include "wx/private/fdioeventloopsourcehandler.h"
#include "wx/private/eventloopsourcesmanager.h"
#if wxUSE_EVENTLOOP_SOURCE
#include "wx/evtloopsrc.h"
@@ -87,8 +89,10 @@ wxConsoleEventLoop::~wxConsoleEventLoop()
#if wxUSE_EVENTLOOP_SOURCE
wxEventLoopSource *
wxConsoleEventLoop::AddSourceForFD(int fd,
class wxConsoleEventLoopSourcesManager : public wxEventLoopSourcesManagerBase
{
public:
wxEventLoopSource* AddSourceForFD( int fd,
wxEventLoopSourceHandler *handler,
int flags)
{
@@ -103,12 +107,20 @@ wxConsoleEventLoop::AddSourceForFD(int fd,
wxScopedPtr<wxFDIOHandler>
fdioHandler(new wxFDIOEventLoopSourceHandler(handler));
if ( !m_dispatcher->RegisterFD(fd, fdioHandler.get(), flags) )
if ( !wxFDIODispatcher::Get()->RegisterFD(fd, fdioHandler.get(), flags) )
return NULL;
return new wxUnixEventLoopSource(m_dispatcher, fdioHandler.release(),
return new wxUnixEventLoopSource(wxFDIODispatcher::Get(), fdioHandler.release(),
fd, handler, flags);
}
};
wxEventLoopSourcesManagerBase* wxAppTraits::GetEventLoopSourcesManager()
{
static wxConsoleEventLoopSourcesManager s_eventLoopSourcesManager;
return &s_eventLoopSourcesManager;
}
wxUnixEventLoopSource::~wxUnixEventLoopSource()
{