diff options
Diffstat (limited to 'glib/glibmm/main.h')
-rw-r--r-- | glib/glibmm/main.h | 549 |
1 files changed, 549 insertions, 0 deletions
diff --git a/glib/glibmm/main.h b/glib/glibmm/main.h new file mode 100644 index 00000000..078d9d9e --- /dev/null +++ b/glib/glibmm/main.h @@ -0,0 +1,549 @@ +// -*- c++ -*- +#ifndef _GLIBMM_MAIN_H +#define _GLIBMM_MAIN_H + +/* $Id$ */ + +/* Copyright (C) 2002 The gtkmm Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <glib/giochannel.h> +#include <glib/gmain.h> + +#include <vector> +#include <sigc++/sigc++.h> + +#include <glibmmconfig.h> +#include <glibmm/refptr.h> +#include <glibmm/timeval.h> + +GTKMM_USING_STD(vector) + + +namespace Glib +{ + +class Cond; +class Mutex; +class IOChannel; + + +/** @defgroup MainLoop The Main Event Loop + * Manages all available sources of events. + * @{ + */ + +enum +{ + /*! Use this for high priority event sources. It is not used within + * GLib or GTK+.<br><br> + */ + PRIORITY_HIGH = -100, + + /*! Use this for default priority event sources. In glibmm this + * priority is used by default when installing timeout handlers with + * SignalTimeout::connect(). In GDK this priority is used for events + * from the X server.<br><br> + */ + PRIORITY_DEFAULT = 0, + + /*! Use this for high priority idle functions. GTK+ uses + * <tt>PRIORITY_HIGH_IDLE + 10</tt> for resizing operations, and + * <tt>PRIORITY_HIGH_IDLE + 20</tt> for redrawing operations. + * (This is done to ensure that any pending resizes are processed before + * any pending redraws, so that widgets are not redrawn twice unnecessarily.) + * <br><br> + */ + PRIORITY_HIGH_IDLE = 100, + + /*! Use this for default priority idle functions. In glibmm this priority is + * used by default when installing idle handlers with SignalIdle::connect(). + * <br><br> + */ + PRIORITY_DEFAULT_IDLE = 200, + + /*! Use this for very low priority background tasks. It is not used within + * GLib or GTK+. + */ + PRIORITY_LOW = 300 +}; + + +/** A bitwise combination representing an I/O condition to watch for on an + * event source. + * The flags correspond to those used by the <tt>%poll()</tt> system call + * on UNIX (see <tt>man 2 poll</tt>). To test for individual flags, do + * something like this: + * @code + * if((condition & Glib::IO_OUT) != 0) + * do_some_output(); + * @endcode + * @par Bitwise operators: + * <tt>IOCondition operator|(IOCondition, IOCondition)</tt><br> + * <tt>IOCondition operator&(IOCondition, IOCondition)</tt><br> + * <tt>IOCondition operator^(IOCondition, IOCondition)</tt><br> + * <tt>IOCondition operator~(IOCondition)</tt><br> + * <tt>IOCondition& operator|=(IOCondition&, IOCondition)</tt><br> + * <tt>IOCondition& operator&=(IOCondition&, IOCondition)</tt><br> + * <tt>IOCondition& operator^=(IOCondition&, IOCondition)</tt><br> + */ +enum IOCondition +{ + IO_IN = G_IO_IN, /*!< @hideinitializer There is data to read. */ + IO_OUT = G_IO_OUT, /*!< @hideinitializer Data can be written (without blocking). */ + IO_PRI = G_IO_PRI, /*!< @hideinitializer There is urgent data to read. */ + IO_ERR = G_IO_ERR, /*!< @hideinitializer %Error condition. */ + IO_HUP = G_IO_HUP, /*!< @hideinitializer Hung up (the connection has been broken, + usually for pipes and sockets). */ + IO_NVAL = G_IO_NVAL /*!< @hideinitializer Invalid request. The file descriptor is not open. */ +}; + +inline IOCondition operator|(IOCondition lhs, IOCondition rhs) + { return static_cast<IOCondition>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs)); } + +inline IOCondition operator&(IOCondition lhs, IOCondition rhs) + { return static_cast<IOCondition>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs)); } + +inline IOCondition operator^(IOCondition lhs, IOCondition rhs) + { return static_cast<IOCondition>(static_cast<unsigned>(lhs) ^ static_cast<unsigned>(rhs)); } + +inline IOCondition operator~(IOCondition flags) + { return static_cast<IOCondition>(~static_cast<unsigned>(flags)); } + +inline IOCondition& operator|=(IOCondition& lhs, IOCondition rhs) + { return (lhs = static_cast<IOCondition>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs))); } + +inline IOCondition& operator&=(IOCondition& lhs, IOCondition rhs) + { return (lhs = static_cast<IOCondition>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs))); } + +inline IOCondition& operator^=(IOCondition& lhs, IOCondition rhs) + { return (lhs = static_cast<IOCondition>(static_cast<unsigned>(lhs) ^ static_cast<unsigned>(rhs))); } + + +class PollFD +{ +public: + PollFD(); + explicit PollFD(int fd); + PollFD(int fd, IOCondition events); + + void set_fd(int fd) { gobject_.fd = fd; } + int get_fd() const { return gobject_.fd; } + + void set_events(IOCondition events) { gobject_.events = events; } + IOCondition get_events() const { return static_cast<IOCondition>(gobject_.events); } + + void set_revents(IOCondition revents) { gobject_.revents = revents; } + IOCondition get_revents() const { return static_cast<IOCondition>(gobject_.revents); } + + GPollFD* gobj() { return &gobject_; } + const GPollFD* gobj() const { return &gobject_; } + +private: + GPollFD gobject_; +}; + + +class SignalTimeout +{ +public: +#ifndef DOXYGEN_SHOULD_SKIP_THIS + explicit inline SignalTimeout(GMainContext* context); +#endif + + /** Connects a timeout handler. + * @code + * Glib::signal_timeout().connect(SigC::slot(&timeout_handler), 1000); + * @endcode + * is equivalent to: + * @code + * const Glib::RefPtr<Glib::TimeoutSource> timeout_source = Glib::TimeoutSource::create(1000); + * timeout_source->connect(SigC::slot(&timeout_handler)); + * timeout_source->attach(Glib::MainContext::get_default()); + * @endcode + * @param slot A slot to call when @a interval elapsed. + * @param interval The timeout in milliseconds. + * @param priority The priority of the new event source. + * @return A connection handle, which can be used to disconnect the handler. + */ + SigC::Connection connect(const SigC::Slot0<bool>& slot, unsigned int interval, + int priority = PRIORITY_DEFAULT); +private: + GMainContext* context_; + + // no copy assignment + SignalTimeout& operator=(const SignalTimeout&); +}; + + +class SignalIdle +{ +public: +#ifndef DOXYGEN_SHOULD_SKIP_THIS + explicit inline SignalIdle(GMainContext* context); +#endif + + /** Connects an idle handler. + * @code + * Glib::signal_idle().connect(SigC::slot(&idle_handler)); + * @endcode + * is equivalent to: + * @code + * const Glib::RefPtr<Glib::IdleSource> idle_source = Glib::IdleSource::create(); + * idle_source->connect(SigC::slot(&idle_handler)); + * idle_source->attach(Glib::MainContext::get_default()); + * @endcode + * @param slot A slot to call when the main loop is idle. + * @param priority The priority of the new event source. + * @return A connection handle, which can be used to disconnect the handler. + */ + SigC::Connection connect(const SigC::Slot0<bool>& slot, int priority = PRIORITY_DEFAULT_IDLE); + +private: + GMainContext* context_; + + // no copy assignment + SignalIdle& operator=(const SignalIdle&); +}; + + +class SignalIO +{ +public: +#ifndef DOXYGEN_SHOULD_SKIP_THIS + explicit inline SignalIO(GMainContext* context); +#endif + + /** Connects an I/O handler. + * @code + * Glib::signal_io().connect(SigC::slot(&io_handler), fd, Glib::IO_IN | Glib::IO_HUP); + * @endcode + * is equivalent to: + * @code + * const Glib::RefPtr<Glib::IOSource> io_source = Glib::IOSource::create(fd, Glib::IO_IN | Glib::IO_HUP); + * io_source->connect(SigC::slot(&io_handler)); + * io_source->attach(Glib::MainContext::get_default()); + * @endcode + * @param slot A slot to call when polling @a fd results in an event that matches @a condition. + * The event will be passed as a parameter to @a slot. + * If @a io_handler returns <tt>false</tt> the signal is disconnected. + * @param fd The file descriptor (or a @c HANDLE on Win32 systems) to watch. + * @param condition The conditions to watch for. + * @param priority The priority of the new event source. + * @return A connection handle, which can be used to disconnect the handler. + */ + SigC::Connection connect(const SigC::Slot1<bool,IOCondition>& slot, int fd, + IOCondition condition, int priority = PRIORITY_DEFAULT); + + /** Connects an I/O channel. + * @code + * Glib::signal_io().connect(SigC::slot(&io_handler), channel, Glib::IO_IN | Glib::IO_HUP); + * @endcode + * is equivalent to: + * @code + * const Glib::RefPtr<Glib::IOSource> io_source = Glib::IOSource::create(channel, Glib::IO_IN | Glib::IO_HUP); + * io_source->connect(SigC::slot(&io_handler)); + * io_source->attach(Glib::MainContext::get_default()); + * @endcode + * @param slot A slot to call when polling @a fd results in an event that matches @a condition. + * The event will be passed as a parameter to @a slot. + * If @a io_handler returns <tt>false</tt> the signal is disconnected. + * @param channel The IOChannel object to watch. + * @param condition The conditions to watch for. + * @param priority The priority of the new event source. + * @return A connection handle, which can be used to disconnect the handler. + */ + SigC::Connection connect(const SigC::Slot1<bool,IOCondition>& slot, const Glib::RefPtr<IOChannel>& channel, + IOCondition condition, int priority = PRIORITY_DEFAULT); + +private: + GMainContext* context_; + + // no copy assignment + SignalIO& operator=(const SignalIO&); +}; + + +/** Convenience timeout signal. + * @return A signal proxy; you want to use SignalTimeout::connect(). + */ +SignalTimeout signal_timeout(); + +/** Convenience idle signal. + * @return A signal proxy; you want to use SignalIdle::connect(). + */ +SignalIdle signal_idle(); + +/** Convenience I/O signal. + * @return A signal proxy; you want to use SignalIO::connect(). + */ +SignalIO signal_io(); + + +/** Main context. + */ +class MainContext +{ +public: + typedef Glib::MainContext CppObjectType; + typedef GMainContext BaseObjectType; + + static Glib::RefPtr<MainContext> create(); + static Glib::RefPtr<MainContext> get_default(); + + bool iteration(bool may_block); + bool pending(); + void wakeup(); + + bool acquire(); + bool wait(Glib::Cond& cond, Glib::Mutex& mutex); + void release(); + + bool prepare(int& priority); + bool prepare(); + + void query(int max_priority, int& timeout, std::vector<PollFD>& fds); + bool check(int max_priority, std::vector<PollFD>& fds); + void dispatch(); + + void set_poll_func(GPollFunc poll_func); + GPollFunc get_poll_func(); + + void add_poll(PollFD& fd, int priority); + void remove_poll(PollFD& fd); + + /** Timeout signal, attached to this MainContext. + * @return A signal proxy; you want to use SignalTimeout::connect(). + */ + SignalTimeout signal_timeout(); + + /** Idle signal, attached to this MainContext. + * @return A signal proxy; you want to use SignalIdle::connect(). + */ + SignalIdle signal_idle(); + + /** I/O signal, attached to this MainContext. + * @return A signal proxy; you want to use SignalIO::connect(). + */ + SignalIO signal_io(); + + void reference() const; + void unreference() const; + + GMainContext* gobj(); + const GMainContext* gobj() const; + GMainContext* gobj_copy() const; + +private: + // Glib::MainContext can neither be constructed nor deleted. + MainContext(); + void operator delete(void*, size_t); + + // noncopyable + MainContext(const MainContext& other); + MainContext& operator=(const MainContext& other); + +}; + +/** @relates Glib::MainContext */ +Glib::RefPtr<MainContext> wrap(GMainContext* gobject, bool take_copy = false); + + +class MainLoop +{ +public: + typedef Glib::MainLoop CppObjectType; + typedef GMainLoop BaseObjectType; + + static Glib::RefPtr<MainLoop> create(bool is_running = false); + static Glib::RefPtr<MainLoop> create(const Glib::RefPtr<MainContext>& context, + bool is_running = false); + + void run(); + void quit(); + bool is_running(); + + Glib::RefPtr<MainContext> get_context(); + + void reference() const; + void unreference() const; + + GMainLoop* gobj(); + const GMainLoop* gobj() const; + GMainLoop* gobj_copy() const; + +private: + // Glib::MainLoop can neither be constructed nor deleted. + MainLoop(); + void operator delete(void*, size_t); + + MainLoop(const MainLoop&); + MainLoop& operator=(const MainLoop&); +}; + +/** @relates Glib::MainLoop */ +Glib::RefPtr<MainLoop> wrap(GMainLoop* gobject, bool take_copy = false); + + +class Source +{ +public: + typedef Glib::Source CppObjectType; + typedef GSource BaseObjectType; + + static Glib::RefPtr<Source> create() /* = 0 */; + + unsigned int attach(const Glib::RefPtr<MainContext>& context); + unsigned int attach(); + void destroy(); + + void set_priority(int priority); + int get_priority() const; + + void set_can_recurse(bool can_recurse); + bool get_can_recurse() const; + + unsigned int get_id() const; + Glib::RefPtr<MainContext> get_context(); + + GSource* gobj() { return gobject_; } + const GSource* gobj() const { return gobject_; } + GSource* gobj_copy() const; + + void reference() const; + void unreference() const; + +protected: + /** Construct an object that uses the virtual functions prepare(), check() and dispatch(). + */ + Source(); + + /** Wrap an existing GSource object and install the given callback function. + * The constructed object doesn't use the virtual functions prepare(), check() and dispatch(). + * This ctor is for use by derived types that need to wrap a GSource object. + * The callback function can be a static member function. But beware! + * Depending on the actual implementation of the GSource's virtual functions + * the expected type of the callback function can differ from GSourceFunc. + */ + Source(GSource* cast_item, GSourceFunc callback_func); + + virtual ~Source(); + + SigC::Connection connect_generic(const SigC::SlotBase& slot); + + void add_poll (PollFD& poll_fd); + void remove_poll(PollFD& poll_fd); + + void get_current_time(Glib::TimeVal& current_time); + + virtual bool prepare(int& timeout) = 0; + virtual bool check() = 0; + virtual bool dispatch(SigC::SlotNode* slot_data) = 0; + +private: + GSource* gobject_; + +#ifndef DOXGEN_SHOULD_SKIP_THIS + + static inline Source* get_wrapper(GSource* source); + + static const GSourceFuncs vfunc_table_; + + static gboolean prepare_vfunc(GSource* source, int* timeout); + static gboolean check_vfunc(GSource* source); + static gboolean dispatch_vfunc(GSource* source, GSourceFunc callback, void* user_data); +public: + static void destroy_notify_callback(void* data); +private: + +#endif /* DOXGEN_SHOULD_SKIP_THIS */ + + // noncopyable + Source(const Source&); + Source& operator=(const Source&); +}; + + +class TimeoutSource : public Glib::Source +{ +public: + typedef Glib::TimeoutSource CppObjectType; + + static Glib::RefPtr<TimeoutSource> create(unsigned int interval); + SigC::Connection connect(const SigC::Slot0<bool>& slot); + +protected: + explicit TimeoutSource(unsigned int interval); + virtual ~TimeoutSource(); + + virtual bool prepare(int& timeout); + virtual bool check(); + virtual bool dispatch(SigC::SlotNode* slot_data); + +private: + Glib::TimeVal expiration_; + unsigned int interval_; +}; + + +class IdleSource : public Glib::Source +{ +public: + typedef Glib::IdleSource CppObjectType; + + static Glib::RefPtr<IdleSource> create(); + SigC::Connection connect(const SigC::Slot0<bool>& slot); + +protected: + IdleSource(); + virtual ~IdleSource(); + + virtual bool prepare(int& timeout); + virtual bool check(); + virtual bool dispatch(SigC::SlotNode* slot_data); +}; + + +class IOSource : public Glib::Source +{ +public: + typedef Glib::IOSource CppObjectType; + + static Glib::RefPtr<IOSource> create(int fd, IOCondition condition); + static Glib::RefPtr<IOSource> create(const Glib::RefPtr<IOChannel>& channel, IOCondition condition); + SigC::Connection connect(const SigC::Slot1<bool,IOCondition>& slot); + +protected: + IOSource(int fd, IOCondition condition); + IOSource(const Glib::RefPtr<IOChannel>& channel, IOCondition condition); + virtual ~IOSource(); + + virtual bool prepare(int& timeout); + virtual bool check(); + virtual bool dispatch(SigC::SlotNode* slot_data); + +private: + PollFD poll_fd_; +}; + +/** @} group MainLoop */ + +} // namespace Glib + + +#endif /* _GLIBMM_MAIN_H */ + |