/* Copyright (C) 2007 The gtkmm Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ _CONFIGINCLUDE(giommconfig.h) #include #include #include #include #include #include #include #include #include #include #include _DEFS(giomm,gio) _PINCLUDE(glibmm/private/object_p.h) namespace Gio { /** Application - Core application class. * An Application is the foundation of an application, unique for a given * application identifier. The Application class wraps some low-level * platform-specific services and is intended to act as the foundation for * higher-level application classes such as Gtk::Application or MxApplication. * In general, you should not use this class outside of a higher level * framework. * * One of the core features that Application provides is process uniqueness, * in the context of a "session". The session concept is platform-dependent, * but corresponds roughly to a graphical desktop login. When your application * is launched again, its arguments are passed through platform communication * to the already running program. The already running instance of the program * is called the primary instance. * * Before using Application, you must choose an "application identifier". The * expected form of an application identifier is very close to that of of a * DBus * bus name. Examples include: "com.example.MyApp", * "org.example.internal-apps.Calculator". For details on valid application * identifiers, see id_is_valid(). * * Application provides convenient life cycle management by maintaining a * use count for the primary application instance. The use count can be * changed using hold() and release(). If it drops to zero, the application * exits. * * Application also implements the ActionGroup and ActionMap * interfaces and lets you easily export actions by adding them with * Gio::ActionMap::add_action(). When invoking an action by calling * Gio::ActionGroup::activate_action() on the application, it is always * invoked in the primary instance. * * There is a number of different entry points into an Application: * * - via 'Activate' (i.e. just starting the application) * - via 'Open' (i.e. opening some files) * - via activating an action * * The signal_startup() signal lets you handle the application initialization * for all of these in a single place. * * See the C API docs for an example. * * @newin{2,32} */ class GIOMM_API Application : public Glib::Object, public ActionGroup, public ActionMap { _CLASS_GOBJECT(Application, GApplication, G_APPLICATION, Glib::Object, GObject, , , GIOMM_API) _IMPLEMENTS_INTERFACE(ActionGroup) _IMPLEMENTS_INTERFACE(ActionMap) public: _WRAP_ENUM(Flags, GApplicationFlags, s#^FLAGS_##, decl_prefix GIOMM_API) protected: /** Constructs an application instance. * If no application ID is given then some features (most notably application uniqueness) will be disabled. * * @param application_id The application ID. * @param flags The application flags. */ explicit Application(const Glib::ustring& application_id = {}, Flags flags = Flags::NONE); _IGNORE(g_application_new) public: _CUSTOM_DTOR() // Application::OptionType wraps GOptionArg, but _WRAP_ENUM can't be used here. // GOptionArg is defined in glib_enums.defs, not in gio_enums.defs. /** The OptionType enum values determine the expected type of a command line option. * If an option expects an extra argument, it can be specified in several ways; * with a short option: "-x arg", with a long option: "--name arg" or combined * in a single argument: "--name=arg". All option types except OptionType::BOOL * expect an extra argument. OptionType::STRING_VECTOR and * OptionType::FILENAME_VECTOR accept more than one extra argument. * * The descriptions of the enum values show what type of Glib::Variant<> * is stored in a Glib::VariantDict. * * @newin{2,42} * * @ingroup glibmmEnums */ enum class OptionType { BOOL, ///< bool STRING, ///< Glib::ustring INT, ///< gint32 // CALLBACK, FILENAME = INT+2, ///< std::string STRING_VECTOR, ///< std::vector FILENAME_VECTOR, ///< std::vector DOUBLE, ///< double INT64 ///< gint64 }; /** Creates an application instance. * If no application ID is given then some features (most notably application uniqueness) will be disabled. * * @param application_id The application ID. * @param flags The application flags. */ _WRAP_CREATE(const Glib::ustring& application_id = {}, Flags flags = Flags::NONE) _WRAP_METHOD(static bool id_is_valid(const Glib::ustring& application_id), g_application_id_is_valid) _WRAP_METHOD(Glib::ustring get_id() const, g_application_get_application_id) _WRAP_METHOD(void set_id(const Glib::ustring& application_id), g_application_set_application_id) _WRAP_METHOD(Glib::RefPtr get_dbus_connection(), g_application_get_dbus_connection, refreturn) _WRAP_METHOD(Glib::RefPtr get_dbus_connection() const, g_application_get_dbus_connection, refreturn, constversion) _WRAP_METHOD(Glib::ustring get_dbus_object_path() const, g_application_get_dbus_object_path) _WRAP_METHOD(guint get_inactivity_timeout() const, g_application_get_inactivity_timeout) _WRAP_METHOD(void set_inactivity_timeout(guint inactivity_timeout), g_application_set_inactivity_timeout) _WRAP_METHOD(Flags get_flags() const, g_application_get_flags) _WRAP_METHOD(void set_flags(Flags flags), g_application_set_flags) _WRAP_METHOD(std::string get_resource_base_path() const, g_application_get_resource_base_path, newin "2,44") _WRAP_METHOD(void set_resource_base_path(const std::string& resource_path), g_application_set_resource_base_path, newin "2,44") /** Disable automatic resource loading functionality. * See set_resource_base_path(). * @newin{2,44} */ void unset_resource_base_path(); _IGNORE(g_application_set_action_group) //Note: We would like to add a group, not just some entries, //so we can do pre and post parsing. See https://bugzilla.gnome.org/show_bug.cgi?id=727602 //but instead we need to use the VariantDict passed to the handle_local_options signal //and provided by ApplicationCommandLine::get_options_dict() in on_command_line(). /** Adds a main option entry to be handled by the Application. * * This function is comparable to Glib::OptionGroup::add_entry() + * Glib::OptionContext::set_main_group(). * * After the commandline arguments are parsed, the * signal_handle_local_options() signal will be emitted. At this * point, the application can inspect the parsed values. * * Unlike OptionGroup + OptionContext, Application packs the arguments * into a Glib::VariantDict which is passed to the * signal_handle_local_options() handler, where it can be * inspected and modified. If Gio::Application::Flags::HANDLES_COMMAND_LINE is * set, then the resulting dictionary is sent to the primary instance, * where Gio::ApplicationCommandLine::get_options_dict() will return it. * This "packing" is done according to the type of the argument -- * booleans for normal flags, Glib::ustring's for strings, std::string's for * filenames, etc. The packing only occurs if the flag is given (ie: we * do not pack a "false" Variant in the case that a flag is missing). * * In general, it is recommended that all commandline arguments are * parsed locally. The options dictionary should then be used to * transmit the result of the parsing to the primary instance, where * Glib::VariantDict::lookup_value() can be used. For local options, it is * possible to consult (and potentially remove) the option from the options dictionary. * * This function is new in GLib 2.40. Before then, the only real choice * was to send all of the commandline arguments (options and all) to the * primary instance for handling. Application ignored them completely * on the local side. Calling this function "opts in" to the new * behaviour, and in particular, means that unrecognised options will be * treated as errors. Unrecognised options have never been ignored when * Gio::Application::Flags::HANDLES_COMMAND_LINE is unset. * * If signal_handle_local_options() needs to see the list of * filenames, then the use of G_OPTION_REMAINING as @a long_name is recommended. * G_OPTION_REMAINING can be used as a key into * the options dictionary. If you do use G_OPTION_REMAINING then you * need to handle these arguments for yourself because once they are * consumed, they will no longer be visible to the default handling * (which treats them as filenames to be opened). * * @newin{2,42} * * @param arg_type A Gio::Application::OptionType. * @param long_name The long name of an option can be used to specify it * in a commandline as `--long_name`. Every option must have a * long name. * @param short_name If an option has a short name, it can be specified * `-short_name` in a commandline. @a short_name must be a printable * ASCII character different from '-', or '\0' if the option has no * short name. * @param description The description for the option in `--help` output. * @param arg_description The placeholder to use for the extra argument parsed * by the option in `--help` output. * @param flags Flags from Glib::OptionEntry::Flags. Do not set OptionEntry::Flags::FILENAME. * Character encoding is chosen with @a arg_type. */ void add_main_option_entry(OptionType arg_type, const Glib::ustring& long_name, gchar short_name = '\0', const Glib::ustring& description = {}, const Glib::ustring& arg_description = {}, Glib::OptionEntry::Flags flags = Glib::OptionEntry::Flags::NONE); _IGNORE(g_application_add_main_option_entries, g_application_add_main_option) /** Adds a main option entry to be handled by the Application. * * Adds a string option entry, but lets the callback @a slot parse the extra * argument instead of having it packed in a Glib::VariantDict. * * If you create more than one Application instance (unusual), * one Application instance can't add an option with the same name as * another instance adds. This restriction does not apply to the * add_main_option_entry() that takes an OptionType parameter. * * @newin{2,42} * * @see add_main_option_entry(OptionType, const Glib::ustring&, * gchar, const Glib::ustring&, const Glib::ustring&, Glib::OptionEntry::Flags) */ void add_main_option_entry(const Glib::OptionGroup::SlotOptionArgString& slot, const Glib::ustring& long_name, gchar short_name = '\0', const Glib::ustring& description = {}, const Glib::ustring& arg_description = {}, Glib::OptionEntry::Flags flags = Glib::OptionEntry::Flags::NONE); /** Adds a main option entry to be handled by the Application. * * Adds a filename option entry, but lets the callback @a slot parse the extra * argument instead of having it packed in a Glib::VariantDict. * * If you create more than one Application instance (unusual), * one Application instance can't add an option with the same name as * another instance adds. This restriction does not apply to the * add_main_option_entry() that takes an OptionType parameter. * * @newin{2,42} * * @see add_main_option_entry(OptionType, const Glib::ustring&, * gchar, const Glib::ustring&, const Glib::ustring&, Glib::OptionEntry::Flags) */ void add_main_option_entry_filename(const Glib::OptionGroup::SlotOptionArgFilename& slot, const Glib::ustring& long_name, gchar short_name = '\0', const Glib::ustring& description = {}, const Glib::ustring& arg_description = {}, Glib::OptionEntry::Flags flags = Glib::OptionEntry::Flags::NONE); // GApplication takes ownership of the GOptionGroup, unrefing it later. #m4 _CONVERSION(`Glib::OptionGroup&',`GOptionGroup*',`($3).gobj_copy()') /** Adds a Glib::OptionGroup to the commandline handling of the application. * * This function is comparable to Glib::OptionContext::add_group(). * * Unlike add_main_option_entry(), this function never transmits options to the * primary instance. * * The reason for that is because, by the time the options arrive at the * primary instance, it is typically too late to do anything with them. * Taking the GTK option group as an example: GTK will already have been * initialised by the time the signal_command_line() handler runs. * In the case that this is not the first-running instance of the * application, the existing instance may already have been running for * a very long time. * * This means that the options from Glib::OptionGroup are only really usable * in the case that the instance of the application being run is the * first instance. Passing options like `--display=` or `--gdk-debug=` * on future runs will have no effect on the existing primary instance. * * Calling this function will cause the options in the supplied option * group to be parsed, but it does not cause you to be "opted in" to the * new functionality whereby unrecognised options are rejected even if * Gio::Application::Flags::HANDLES_COMMAND_LINE was given. * * @newin{2,62} * * @param group A Glib::OptionGroup. * @note The group will not be copied, so it should exist for as long as the application exists. */ _WRAP_METHOD(void add_option_group(Glib::OptionGroup& group), g_application_add_option_group) _WRAP_METHOD(void set_option_context_parameter_string(const Glib::ustring& parameter_string{NULL}), g_application_set_option_context_parameter_string) _WRAP_METHOD(void set_option_context_summary(const Glib::ustring& summary{NULL}), g_application_set_option_context_summary) _WRAP_METHOD(void set_option_context_description(const Glib::ustring& description{NULL}), g_application_set_option_context_description) _WRAP_METHOD(bool is_registered() const, g_application_get_is_registered) _WRAP_METHOD(bool is_remote() const, g_application_get_is_remote) //Renamed from register() because that is a C++ keyword. _WRAP_METHOD(bool register_application(const Glib::RefPtr& cancellable{?}), g_application_register, errthrow) _IGNORE(g_application_impl_register) _WRAP_METHOD(void hold(), g_application_hold) _WRAP_METHOD(void release(), g_application_release) _WRAP_METHOD(void activate(), g_application_activate) using type_vec_files = std::vector< Glib::RefPtr >; /* Opens the given files. * * In essence, this results in the open signal being emitted * in the primary instance. * * @a hint is simply passed through to the open signal. It is * intended to be used by applications that have multiple modes for * opening files (eg: "view" vs "edit", etc). * * The application must be registered before calling this method * and it must have the Application::Flags::HANDLES_OPEN flag set. * * @param files The files to open. This must be non-empty. * @param hint A hint. * * @newin{2,32} */ void open(const type_vec_files& files, const Glib::ustring& hint = {}); _IGNORE(g_application_open) /* Opens the given file. * * In essence, this results in the open signal being emitted * in the primary instance. * * @a hint is simply passed through to the open signal. It is * intended to be used by applications that have multiple modes for * opening files (eg: "view" vs "edit", etc). * * The application must be registered before calling this method * and it must have the Application::Flags::HANDLES_OPEN flag set. * * @param file The file to open. This must be non-empty. * @param hint A hint. * * @newin{2,32} */ void open(const Glib::RefPtr& file, const Glib::ustring& hint = {}); _WRAP_METHOD(int run(int argc, char** argv), g_application_run) _WRAP_METHOD(void quit(), g_application_quit) _WRAP_METHOD(static void set_default(const Glib::RefPtr& application), g_application_set_default) /// Unsets any existing default application. static void unset_default(); _WRAP_METHOD(static Glib::RefPtr get_default(), g_application_get_default, refreturn) _WRAP_METHOD(void mark_busy(), g_application_mark_busy) _WRAP_METHOD(void unmark_busy(), g_application_unmark_busy) _WRAP_METHOD(bool get_is_busy() const, g_application_get_is_busy) _WRAP_METHOD(void send_notification(const Glib::ustring& id{?}, const Glib::RefPtr& notification), g_application_send_notification) _WRAP_METHOD(void withdraw_notification(const Glib::ustring& id), g_application_withdraw_notification) //TODO: Glib::RefPtr, Glib::ObjectBase, or both? //#m4 _CONVERSION(`const Glib::RefPtr&', `gpointer', `($3)->gobj()') // _WRAP_METHOD(void bind_busy_property(const Glib::RefPtr& object, const Glib::ustring& property), g_application_bind_busy_property) // _WRAP_METHOD(void unbind_busy_property(const Glib::RefPtr& object, const Glib::ustring& property), g_application_unbind_busy_property) _IGNORE_PROPERTY("action-group") _WRAP_PROPERTY("application-id", Glib::ustring) _WRAP_PROPERTY("flags", Flags) _WRAP_PROPERTY("inactivity-timeout", guint) _WRAP_PROPERTY("is-registered", bool) _WRAP_PROPERTY("is-remote", bool) _WRAP_PROPERTY("resource-base-path", std::string, newin "2,44") _WRAP_PROPERTY("is-busy", bool) _WRAP_SIGNAL(void startup(), "startup") _WRAP_SIGNAL(void shutdown(), "shutdown", newin "2,46") _WRAP_SIGNAL(void activate(), "activate") //We wrap the open signal without _WRAP_SIGNAL(), because we need to change its parameters. //See bug https://bugzilla.gnome.org/show_bug.cgi?id=637457 Glib::SignalProxy signal_open(); _IGNORE_SIGNAL(open) #m4 _CONVERSION(`GApplicationCommandLine*', `const Glib::RefPtr&',`Glib::wrap($3, true)') _WRAP_SIGNAL(int command_line(const Glib::RefPtr& command_line), "command-line") //TODO: Avoid the use of the Variants in the VariantDict? //options must be non-const. The handler is meant to modify it. See the description //of add_main_option_entry(OptionType, ...). #m4 _CONVERSION(`GVariantDict*',`const Glib::RefPtr&',`Glib::wrap($3, true)') #m4 _CONVERSION(`const Glib::RefPtr&',`GVariantDict*',__CONVERT_REFPTR_TO_P) _WRAP_SIGNAL(int handle_local_options(const Glib::RefPtr& options), "handle-local-options") _WRAP_SIGNAL(bool name_lost(), "name-lost") protected: virtual void on_open(const type_vec_files& files, const Glib::ustring& hint); #m4begin _PUSH(SECTION_PCC_CLASS_INIT_DEFAULT_SIGNAL_HANDLERS) klass->open = &Application_signal_open_default_callback; Application_signal_open_funcptr = &open_callback; _SECTION(SECTION_PH_DEFAULT_SIGNAL_HANDLERS) static void open_callback(GApplication* self, GFile** files, gint n_files, const gchar* hint); _POP() #m4end #m4 _CONVERSION(`char**&', `gchar***',`&($3)') #m4 _CONVERSION(`gchar***', `char**&',`*($3)') _WRAP_VFUNC(bool local_command_line(char**& arguments, int& exit_status), local_command_line) #m4 _CONVERSION(`GVariant*',`const Glib::VariantBase&',`Glib::wrap($3,true)') _WRAP_VFUNC(void before_emit(const Glib::VariantBase& platform_data), "before_emit") _WRAP_VFUNC(void after_emit(const Glib::VariantBase& platform_data), "after_emit") //TODO: File a bug about GVariantBuilder not being registered with the GType system first: //_WRAP_VFUNC(void add_platform_data(Glib::VariantBuilder* builder), "add_platform_data") _WRAP_VFUNC(void quit_mainloop(), "quit_mainloop") _WRAP_VFUNC(void run_mainloop(), "run_mainloop") #m4 _CONVERSION(`GDBusConnection*', `const Glib::RefPtr&', `Glib::wrap($3, true)') #m4 _CONVERSION(`const Glib::RefPtr&',`GDBusConnection*',__CONVERT_REFPTR_TO_P) _WRAP_VFUNC(bool dbus_register(const Glib::RefPtr& connection, const Glib::ustring& object_path), "dbus_register", errthrow) _WRAP_VFUNC(void dbus_unregister(const Glib::RefPtr& connection, const Glib::ustring& object_path), "dbus_unregister") private: /** This is just a way to call Glib::init() before calling a Glib::Object ctor, * so that glibmm's GQuarks are created before they are used. */ const Glib::Class& custom_class_init(); // Code, common to the public add_main_option_entry*() methods with a callback slot. void add_main_option_entry_private(const gchar* long_name, gchar short_name, const gchar* description, const gchar* arg_description, Glib::OptionEntry::Flags flags); }; } // namespace Gio