init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled

This commit is contained in:
allhaileris
2026-02-16 15:50:16 +03:00
commit afb81b8278
13816 changed files with 3689732 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
#ifndef _GI_CAIRO_SETUP_DEF_HPP_
#define _GI_CAIRO_SETUP_DEF_HPP_
// missing in GIR
#include <cairo/cairo-gobject.h>
#endif // _GI_CAIRO_SETUP_DEF_HPP_

View File

@@ -0,0 +1,9 @@
#ifndef _GI_GDKPIXBUF_GDKPIXBUF_SETUP_PRE_DEF_HPP_
#define _GI_GDKPIXBUF_GDKPIXBUF_SETUP_PRE_DEF_HPP_
/* some header parts are only conditionally considered */
#ifndef GDK_PIXBUF_ENABLE_BACKEND
#define GDK_PIXBUF_ENABLE_BACKEND
#endif
#endif

View File

@@ -0,0 +1,10 @@
#pragma once
#define G_SETTINGS_ENABLE_BACKEND 1
#include <gio/gsettingsbackend.h>
// now unconditionally part of <gio/gio.h>
// though (still) missing in some distro's release
#include <gio/gunixconnection.h>
#include <gio/gunixcredentialsmessage.h>
#include <gio/gunixsocketaddress.h>

View File

@@ -0,0 +1,43 @@
#ifndef _GI_GIO_SIMPLE_ACTION_EXTRA_DEF_HPP_
#define _GI_GIO_SIMPLE_ACTION_EXTRA_DEF_HPP_
namespace gi
{
namespace repository
{
namespace Gio
{
class SimpleAction;
namespace base
{
class SimpleActionExtra : public GI_GIO_SIMPLEACTION_BASE
{
typedef GI_GIO_SIMPLEACTION_BASE super;
public:
// clang-format off
// add some signals that are missing due to missing parameter type annotation
// (at least in older Gio)
gi::signal_proxy<void(Gio::SimpleAction, GLib::Variant)> signal_activate()
{ return gi::signal_proxy<void(Gio::SimpleAction, GLib::Variant)>(*this, "activate"); }
gi::signal_proxy<void(Gio::SimpleAction, GLib::Variant)> signal_change_state()
{ return gi::signal_proxy<void(Gio::SimpleAction, GLib::Variant)>(*this, "change-state"); }
// clang-format on
}; // class
#undef GI_GIO_SIMPLEACTION_BASE
#define GI_GIO_SIMPLEACTION_BASE base::SimpleActionExtra
} // namespace base
} // namespace Gio
} // namespace repository
} // namespace gi
#endif

View File

@@ -0,0 +1,73 @@
#ifndef _GI_GLIB_GLIB_EXTRA_DEF_HPP_
#define _GI_GLIB_GLIB_EXTRA_DEF_HPP_
namespace gi
{
namespace repository
{
namespace GLib
{
GI_INLINE_DECL gi::rv<guint>::type idle_add(GLib::SourceFunc function)
GI_NOEXCEPT_DECL(true);
GI_INLINE_DECL gi::rv<guint>::type idle_add_once(std::function<void()> function)
GI_NOEXCEPT_DECL(true);
GI_INLINE_DECL gi::rv<guint>::type timeout_add_seconds(
guint interval, GLib::SourceFunc function) GI_NOEXCEPT_DECL(true);
GI_INLINE_DECL gi::rv<guint>::type timeout_add_seconds_once(
guint interval, std::function<void()> function) GI_NOEXCEPT_DECL(true);
GI_INLINE_DECL gi::rv<guint>::type timeout_add(
guint interval, GLib::SourceFunc function) GI_NOEXCEPT_DECL(true);
GI_INLINE_DECL gi::rv<guint>::type timeout_add_once(
guint interval, std::function<void()> function) GI_NOEXCEPT_DECL(true);
// connection helpers
namespace internal
{
class SourceConnection : public detail::connection_impl
{
public:
using connection_impl::connection_impl;
void disconnect() { g_source_remove(id_); }
};
} // namespace internal
using SourceConnection = detail::connection<internal::SourceConnection>;
using SourceScopedConnection = detail::scoped_connection<SourceConnection>;
} // namespace GLib
template<>
struct declare_gtype_of<GLib::Variant>
{
// a get_type() member already exists in base class detail::VariantWrapper
// so get_type() should not be specified here
// otherwise traits::gtype<GLib::Variant> will have 2 ambiguous options
static GLib::Variant get_value(const GValue *val)
{
return wrap(g_value_dup_variant(val), transfer_full);
}
static void set_value(GValue *val, GLib::Variant v)
{
g_value_take_variant(val, v.gobj_copy_());
}
};
} // namespace repository
inline repository::GLib::SourceConnection
make_connection(gulong id, const repository::GLib::SourceFunc &func)
{
return repository::GLib::SourceConnection(id, func.connection());
}
} // namespace gi
#endif

View File

@@ -0,0 +1,61 @@
#ifndef _GI_GLIB_GLIB_EXTRA_DEF_IMPL_HPP_
#define _GI_GLIB_GLIB_EXTRA_DEF_IMPL_HPP_
namespace gi
{
namespace repository
{
namespace GLib
{
gi::rv<guint>::type
idle_add(GLib::SourceFunc function) GI_NOEXCEPT_DECL(true)
{
return idle_add(GLib::PRIORITY_DEFAULT_IDLE_, function);
}
gi::rv<guint>::type
idle_add_once(std::function<void()> function) GI_NOEXCEPT_DECL(true)
{
// clang-format off
return idle_add([=] { function(); return false; });
// clang-format on
}
gi::rv<guint>::type
timeout_add_seconds(guint interval, GLib::SourceFunc function)
GI_NOEXCEPT_DECL(true)
{
return timeout_add_seconds(GLib::PRIORITY_DEFAULT_, interval, function);
}
gi::rv<guint>::type
timeout_add_seconds_once(guint interval, std::function<void()> function)
GI_NOEXCEPT_DECL(true)
{
// clang-format off
return timeout_add_seconds(interval, [=] { function(); return false; });
// clang-format on
}
gi::rv<guint>::type
timeout_add(guint interval, GLib::SourceFunc function) GI_NOEXCEPT_DECL(true)
{
return timeout_add(GLib::PRIORITY_DEFAULT_, interval, function);
}
gi::rv<guint>::type
timeout_add_once(guint interval, std::function<void()> function)
GI_NOEXCEPT_DECL(true)
{
// clang-format off
return timeout_add(interval, [=] { function(); return false; });
// clang-format on
}
} // namespace GLib
} // namespace repository
} // namespace gi
#endif

View File

@@ -0,0 +1,30 @@
#ifndef _GI_GLIB_EXTRA_PRE_DEF_HPP_
#define _GI_GLIB_EXTRA_PRE_DEF_HPP_
namespace gi
{
namespace repository
{
// enable various ref-based boxed copy
GI_ENABLE_BOXED_COPY(GClosure)
GI_ENABLE_BOXED_COPY(GByteArray)
GI_ENABLE_BOXED_COPY(GBytes)
GI_ENABLE_BOXED_COPY(GRegex)
GI_ENABLE_BOXED_COPY(GMatchInfo)
GI_ENABLE_BOXED_COPY(GVariantBuilder)
GI_ENABLE_BOXED_COPY(GVariantDict)
GI_ENABLE_BOXED_COPY(GDateTime)
GI_ENABLE_BOXED_COPY(GTimeZone)
GI_ENABLE_BOXED_COPY(GKeyFile)
GI_ENABLE_BOXED_COPY(GMappedFile)
GI_ENABLE_BOXED_COPY(GMainLoop)
GI_ENABLE_BOXED_COPY(GMainContext)
GI_ENABLE_BOXED_COPY(GSource)
GI_ENABLE_BOXED_COPY(GMarkupParseContext)
GI_ENABLE_BOXED_COPY(GThread)
GI_ENABLE_BOXED_COPY(GOptionGroup)
} // namespace repository
} // namespace gi
#endif // _GI_GLIB_EXTRA_PRE_DEF_HPP_

View File

@@ -0,0 +1,19 @@
#ifndef _GI_GLIB_SETUP_DEF_HPP_
#define _GI_GLIB_SETUP_DEF_HPP_
// missing in GIR
// recent version re'define functions to system functions,
// but may not include suitable headers, so force fallback to wrapping
// in recent version, it may also be included by glib-unix below
// so do so before including that one
#ifdef G_OS_UNIX
#define G_STDIO_WRAP_ON_UNIX 1
#endif
#include <glib/gstdio.h>
#ifdef G_OS_UNIX
// missing in GIR
#include <glib-unix.h>
#endif
#endif // _GI_GLIB_SETUP_DEF_HPP_

View File

@@ -0,0 +1,37 @@
#ifndef _GI_GLIB_MAINLOOP_EXTRA_DEF_HPP_
#define _GI_GLIB_MAINLOOP_EXTRA_DEF_HPP_
namespace gi
{
namespace repository
{
namespace GLib
{
namespace base
{
class MainLoopExtra : public GI_GLIB_MAINLOOP_BASE
{
typedef GI_GLIB_MAINLOOP_BASE super;
public:
// preserve existing
using super::new_;
// add another convenience one
static GI_INLINE_DECL gi::rv<GLib::MainLoop>::type new_()
GI_NOEXCEPT_DECL(true);
}; // class
#undef GI_GLIB_MAINLOOP_BASE
#define GI_GLIB_MAINLOOP_BASE base::MainLoopExtra
} // namespace base
} // namespace GLib
} // namespace repository
} // namespace gi
#endif

View File

@@ -0,0 +1,26 @@
#ifndef _GI_GLIB_MAINLOOP_EXTRA_DEF_IMPL_HPP_
#define _GI_GLIB_MAINLOOP_EXTRA_DEF_IMPL_HPP_
namespace gi
{
namespace repository
{
namespace GLib
{
namespace base
{
gi::rv<GLib::MainLoop>::type
MainLoopExtra::new_() GI_NOEXCEPT_DECL(true)
{
return super::new_(nullptr, false);
}
} // namespace base
} // namespace GLib
} // namespace repository
} // namespace gi
#endif

View File

@@ -0,0 +1,35 @@
#ifndef _GI_GLIB_SOURCE_EXTRA_DEF_HPP_
#define _GI_GLIB_SOURCE_EXTRA_DEF_HPP_
namespace gi
{
namespace repository
{
namespace GLib
{
namespace base
{
class SourceExtra : public GI_GLIB_SOURCE_BASE
{
typedef GI_GLIB_SOURCE_BASE super_type;
public:
using super_type::super_type;
template<typename CallbackType>
void set_callback(CallbackType callback) noexcept;
}; // class
#undef GI_GLIB_SOURCE_BASE
#define GI_GLIB_SOURCE_BASE base::SourceExtra
} // namespace base
} // namespace GLib
} // namespace repository
} // namespace gi
#endif

View File

@@ -0,0 +1,30 @@
#ifndef _GI_GLIB_SOURCE_EXTRA_DEF_IMPL_HPP_
#define _GI_GLIB_SOURCE_EXTRA_DEF_IMPL_HPP_
namespace gi
{
namespace repository
{
namespace GLib
{
namespace base
{
template<typename CallbackType>
void
SourceExtra::set_callback(CallbackType callback) noexcept
{
auto callback_wrap_ = unwrap(std::move(callback), gi::scope_notified);
g_source_set_callback(this->gobj_(),
(GSourceFunc)(GCallback)&callback_wrap_->wrapper, callback_wrap_,
&callback_wrap_->destroy);
}
} // namespace base
} // namespace GLib
} // namespace repository
} // namespace gi
#endif

View File

@@ -0,0 +1,62 @@
#ifndef _GI_GOBJECT_CLOSURE_EXTRA_DEF_HPP_
#define _GI_GOBJECT_CLOSURE_EXTRA_DEF_HPP_
namespace gi
{
namespace repository
{
namespace GObject
{
class Closure;
namespace base
{
class ClosureExtra : public GI_GOBJECT_CLOSURE_BASE
{
typedef GI_GOBJECT_CLOSURE_BASE super;
public:
template<typename Wrapper>
static GClosure *from_wrapper(Wrapper *w)
{
auto closure = g_cclosure_new(
(GCallback)&w->wrapper, w, (GClosureNotify)(GCallback)&w->destroy);
g_closure_sink(g_closure_ref(closure));
g_closure_set_marshal(closure, g_cclosure_marshal_generic);
return closure;
}
// add some convenience helper to create a Closure
// Closure is incomplete type at this stage, so use Ret to avoid complaints
// Functor is a callable F = C++ signature
// where all arguments are implicitly assumed transfer_none
template<typename F, typename Functor, typename Ret = Closure>
static Ret from_functor(Functor &&f)
{
auto w =
new gi::detail::transform_signal_wrapper<F>(std::forward<Functor>(f));
return gi::wrap(from_wrapper(w), gi::transfer_full);
}
// Callback is a generated callback type
template<typename Callback, typename Ret = Closure>
static Ret from_callback(Callback &&cb)
{
auto w = gi::unwrap(cb, gi::scope_notified);
return gi::wrap(from_wrapper(w), gi::transfer_full);
}
}; // class
#undef GI_GOBJECT_CLOSURE_BASE
#define GI_GOBJECT_CLOSURE_BASE base::ClosureExtra
} // namespace base
} // namespace GObject
} // namespace repository
} // namespace gi
#endif

View File

@@ -0,0 +1,20 @@
#pragma once
// + typedef __m128 graphene_simd4f_t;
// so it comes with (vector) attributes
// + some functions return bool rather than gboolean
// so the reconstructed signature does not quite match
#define GI_INCLUDE_GRAPHENE_BEGIN \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wignored-attributes\"")
#define GI_INCLUDE_GRAPHENE_END _Pragma("GCC diagnostic pop")
#define GI_INCLUDE_IMPL_GRAPHENE_BEGIN \
GI_INCLUDE_GRAPHENE_BEGIN \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wcast-function-type\"")
#define GI_INCLUDE_IMPL_GRAPHENE_END \
GI_INCLUDE_GRAPHENE_END \
GI_INCLUDE_GRAPHENE_END

View File

@@ -0,0 +1,43 @@
#ifndef _GI_GST_BIN_EXTRA_DEF_HPP_
#define _GI_GST_BIN_EXTRA_DEF_HPP_
namespace gi
{
namespace repository
{
namespace Gst
{
namespace base
{
class BinExtra : public GI_GST_BIN_BASE
{
typedef GI_GST_BIN_BASE super;
public:
using super::add;
// Syntax sugar add with multiple arguments to reflect a non-introspectable gst_bin_add_many
template <typename ...Args>
GI_INLINE_DECL void add(Gst::Element arg0, Args ...args) GI_NOEXCEPT_DECL(true) {
super::add(gi::object_cast<Gst::Element>(arg0));
// We don't need extra code to stop the recursion because of `using
// super::add` above. When the number of arguments reaches 1, the base class
// `add` will be called.
add(args...);
}
}; // class
#undef GI_GST_BIN_BASE
#define GI_GST_BIN_BASE base::BinExtra
} // namespace base
} // namespace Gst
} // namespace repository
} // namespace gi
#endif

View File

@@ -0,0 +1,47 @@
#ifndef _GI_GST_ELEMENT_EXTRA_DEF_HPP_
#define _GI_GST_ELEMENT_EXTRA_DEF_HPP_
namespace gi
{
namespace repository
{
namespace Gst
{
namespace base
{
class ElementExtra : public GI_GST_ELEMENT_BASE
{
typedef GI_GST_ELEMENT_BASE super;
GI_INLINE_DECL bool link() GI_NOEXCEPT_DECL(true)
{
return true;
}
public:
// Syntax sugar link with multiple arguments to reflect a non-introspectable gst_element_link_many
template <typename Arg0, typename ...Args>
GI_INLINE_DECL bool link(Arg0 arg0, Args ...args) GI_NOEXCEPT_DECL(true)
{
if (super::link(gi::object_cast<Gst::Element>(arg0))) {
return arg0.link(args...);
} else {
return false;
}
}
}; // class
#undef GI_GST_ELEMENT_BASE
#define GI_GST_ELEMENT_BASE base::ElementExtra
} // namespace base
} // namespace Gst
} // namespace repository
} // namespace gi
#endif

View File

@@ -0,0 +1,398 @@
#ifndef _GI_GST_GST_EXTRA_DEF_HPP_
#define _GI_GST_GST_EXTRA_DEF_HPP_
#include <ios>
#include <iostream>
#include <iterator>
#include <limits>
namespace gi
{
namespace repository
{
namespace Gst
{
// connection helpers
namespace internal
{
class PadProbeConnection : public detail::connection_impl
{
public:
// using connection_impl::connection_impl;
PadProbeConnection(gulong id, detail::connection_status s, Pad pad)
: connection_impl(id, s), pad_(pad)
{}
void disconnect() { pad_.remove_probe(id_); }
private:
Pad pad_;
};
template<typename T, typename LimitT = T>
struct Range
{
T min;
T max;
explicit constexpr Range(T _min = std::numeric_limits<LimitT>::min(),
T _max = std::numeric_limits<LimitT>::max())
: min(_min), max(_max)
{}
constexpr bool operator==(const Range &other)
{
return min == other.min && max == other.max;
}
constexpr bool operator!=(const Range &other) { return !(*this == other); }
};
template<typename T>
struct StepRange : public Range<T>
{
T step;
explicit constexpr StepRange(T _min, T _max, T _step = 1)
: Range<T>(_min, _max), step(_step)
{}
constexpr bool operator==(const StepRange &other)
{
return Range<T>::operator==(*this, other) && step == other.step;
}
constexpr bool operator!=(const StepRange &other)
{
return !(*this == other);
}
};
class ios_flags_saver
{
std::ostream &out;
std::ios old;
public:
ios_flags_saver(std::ostream &_out) : out(_out), old(nullptr)
{
old.copyfmt(out);
}
~ios_flags_saver() { out.copyfmt(old); }
};
template<typename T, typename U>
inline std::ostream &
operator<<(std::ostream &out, const Range<T, U> &v)
{
return out << "Range(" << v.min << ", " << v.max << ')';
}
template<typename T>
inline std::ostream &
operator<<(std::ostream &out, const StepRange<T> &v)
{
return out << "Range(" << v.min << ", " << v.max << ", " << v.step << ')';
}
} // namespace internal
using PadProbeConnection = detail::connection<internal::PadProbeConnection>;
using PadProbeScopedConnection = detail::scoped_connection<PadProbeConnection>;
// make Rank a more convenient numeric
GI_ENUM_NUMERIC(Rank)
// iterator helper
template<typename T>
class IteratorAdapter
{
Iterator it_;
public:
IteratorAdapter(Iterator _it) : it_(std::move(_it)) {}
class iterator
{
private:
Iterator_Ref it_;
GObject::Value val_;
T value_{};
IteratorResult result_{IteratorResult::DONE_};
public:
// traits
typedef T difference_type;
typedef T value_type;
typedef T *pointer;
typedef T &reference;
typedef std::input_iterator_tag category;
iterator() {}
iterator(Iterator_Ref _it) : it_(_it) { ++(*this); }
// only prefix required
iterator &operator++()
{
if (it_) {
val_.unset();
result_ = it_.next(val_);
value_ = val_.get_value<T>();
// clear iterator when done to ensure end() comparison
if (result_ == IteratorResult::DONE_)
it_ = nullptr;
}
return *this;
}
T &operator*()
{
if (result_ != IteratorResult::OK_ && result_ != IteratorResult::DONE_)
detail::try_throw(std::runtime_error(
"GstIterator error result " + std::to_string((int)result_)));
return value_;
}
void operator->() { return &value_; }
bool operator==(const iterator &other) const
{
return other.it_ == it_ && other.result_ == result_;
}
bool operator!=(const iterator &other) const { return !(*this == other); }
};
iterator begin() const { return iterator(it_); }
iterator end() const { return iterator(); }
};
// GstValue helpers
struct Bitmask
{
guint64 mask;
constexpr Bitmask(guint64 _mask = 0) : mask(_mask) {}
constexpr operator guint64() const { return mask; }
};
inline std::ostream &
operator<<(std::ostream &out, const Bitmask &v)
{
internal::ios_flags_saver s(out);
return out << std::showbase << std::hex << "Bitmask(" << (guint64)v << ')';
}
struct FlagSet
{
guint flags;
guint mask;
explicit constexpr FlagSet(guint _flags, guint _mask)
: flags(_flags), mask(_mask)
{}
constexpr bool operator==(const FlagSet &other)
{
return flags == other.flags && mask == other.mask;
}
constexpr bool operator!=(const FlagSet &other) { return !(*this == other); }
};
inline std::ostream &
operator<<(std::ostream &out, const FlagSet &v)
{
internal::ios_flags_saver s(out);
return out << std::showbase << std::hex << "FlagSet(" << v.flags << " , "
<< v.mask << ')';
}
struct Fraction
{
gint num;
gint den;
constexpr Fraction(gint _num = 0, gint _den = 1) : num(_num), den(_den) {}
constexpr bool operator==(const Fraction &other)
{
return num == other.num && den == other.den;
}
constexpr bool operator!=(const Fraction &other) { return !(*this == other); }
Fraction operator*(const Fraction &other)
{
Fraction result;
if (gst_util_fraction_multiply(
num, den, other.num, other.den, &result.num, &result.den)) {
return result;
} else {
detail::try_throw(std::overflow_error("multiplying Fraction"));
}
}
Fraction operator/(const Fraction &other)
{
return *this * Fraction(other.den, other.num);
}
Fraction &operator*=(const Fraction &other)
{
*this = *this * other;
return *this;
}
Fraction &operator/=(const Fraction &other)
{
*this = *this / other;
return *this;
}
Fraction operator+(const Fraction &other)
{
Fraction result;
if (gst_util_fraction_add(
num, den, other.num, other.den, &result.num, &result.den)) {
return result;
} else {
detail::try_throw(std::overflow_error("adding Fraction"));
}
}
Fraction operator-(const Fraction &other)
{
return *this * Fraction(-other.num, other.den);
}
Fraction &operator+=(const Fraction &other)
{
*this = *this + other;
return *this;
}
Fraction &operator-=(const Fraction &other)
{
*this = *this - other;
return *this;
}
};
inline std::ostream &
operator<<(std::ostream &out, const Fraction &v)
{
return out << "Fraction(" << v.num << ", " << v.den << ')';
}
using DoubleRange = internal::Range<double>;
using IntRange = internal::StepRange<int>;
using Int64Range = internal::StepRange<gint64>;
using FractionRange = internal::Range<Fraction, int>;
} // namespace Gst
template<>
struct declare_gtype_of<Gst::Bitmask>
{
static GType get_type() { return GST_TYPE_BITMASK; }
static Gst::Bitmask get_value(const GValue *val)
{
return Gst::Bitmask(gst_value_get_bitmask(val));
}
static void set_value(GValue *val, const Gst::Bitmask &r)
{
gst_value_set_bitmask(val, r);
}
};
template<>
struct declare_gtype_of<Gst::FlagSet>
{
static GType get_type() { return GST_TYPE_FLAG_SET; }
static Gst::FlagSet get_value(const GValue *val)
{
return Gst::FlagSet(
gst_value_get_flagset_flags(val), gst_value_get_flagset_mask(val));
}
static void set_value(GValue *val, const Gst::FlagSet &r)
{
gst_value_set_flagset(val, r.flags, r.mask);
}
};
template<>
struct declare_gtype_of<Gst::Fraction>
{
static GType get_type() { return GST_TYPE_FRACTION; }
static Gst::Fraction get_value(const GValue *val)
{
return Gst::Fraction(gst_value_get_fraction_numerator(val),
gst_value_get_fraction_denominator(val));
}
static void set_value(GValue *val, const Gst::Fraction &f)
{
gst_value_set_fraction(val, f.num, f.den);
}
};
template<>
struct declare_gtype_of<Gst::FractionRange>
{
static GType get_type() { return GST_TYPE_FRACTION_RANGE; }
static Gst::FractionRange get_value(const GValue *val)
{
const GValue *vmin = gst_value_get_fraction_range_min(val);
const GValue *vmax = gst_value_get_fraction_range_max(val);
return Gst::FractionRange(
Gst::Fraction(gst_value_get_fraction_numerator(vmin),
gst_value_get_fraction_denominator(vmin)),
Gst::Fraction(gst_value_get_fraction_numerator(vmax),
gst_value_get_fraction_denominator(vmax)));
}
static void set_value(GValue *val, const Gst::FractionRange &f)
{
gst_value_set_fraction_range_full(
val, f.min.num, f.min.den, f.max.num, f.max.den);
}
};
template<>
struct declare_gtype_of<Gst::DoubleRange>
{
static GType get_type() { return GST_TYPE_DOUBLE_RANGE; }
static Gst::DoubleRange get_value(const GValue *val)
{
return Gst::DoubleRange(gst_value_get_double_range_min(val),
gst_value_get_double_range_max(val));
}
static void set_value(GValue *val, const Gst::DoubleRange &r)
{
gst_value_set_double_range(val, r.min, r.max);
}
};
template<>
struct declare_gtype_of<Gst::IntRange>
{
static GType get_type() { return GST_TYPE_INT_RANGE; }
static Gst::IntRange get_value(const GValue *val)
{
return Gst::IntRange(gst_value_get_int_range_min(val),
gst_value_get_int_range_max(val), gst_value_get_int_range_step(val));
}
static void set_value(GValue *val, const Gst::IntRange &r)
{
gst_value_set_int_range_step(val, r.min, r.max, r.step);
}
};
template<>
struct declare_gtype_of<Gst::Int64Range>
{
static GType get_type() { return GST_TYPE_INT64_RANGE; }
static Gst::Int64Range get_value(const GValue *val)
{
return Gst::Int64Range(gst_value_get_int64_range_min(val),
gst_value_get_int64_range_max(val),
gst_value_get_int64_range_step(val));
}
static void set_value(GValue *val, const Gst::Int64Range &r)
{
gst_value_set_int64_range_step(val, r.min, r.max, r.step);
}
};
} // namespace repository
inline repository::Gst::PadProbeConnection
make_connection(gulong id, const repository::GLib::SourceFunc &func,
repository::Gst::Pad pad)
{
return repository::Gst::PadProbeConnection(id, func.connection(), pad);
}
} // namespace gi
#endif

View File

@@ -0,0 +1,11 @@
#ifndef _GI_GST_SETUP_PRE_DEF_HPP_
#define _GI_GST_SETUP_PRE_DEF_HPP_
// some static inline are marked skipped, but make it through wrapping
// however, that leads to a reference to TU-local from non-TU-local in module
#ifdef GI_MODULE_IN_INTERFACE
// slightly less efficient, but it is the module way ...
#define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS 1
#endif
#endif // _GI_GST_SETUP_PRE_DEF_HPP_

View File

@@ -0,0 +1,10 @@
#ifndef _GI_GST_GL_EGL_SETUP_PRE_DEF_HPP_
#define _GI_GST_GL_EGL_SETUP_PRE_DEF_HPP_
// missing G_BEGIN_DECLS / G_END_DECLS
// so wrap those around and pre-include
G_BEGIN_DECLS
#include <gst/gl/egl/gstegl.h>
G_END_DECLS
#endif // _GI_GST_GL_EGL_SETUP_PRE_DEF_HPP_

View File

@@ -0,0 +1,96 @@
#ifndef _GI_GTK_BUILDER_EXTRA_DEF_HPP_
#define _GI_GTK_BUILDER_EXTRA_DEF_HPP_
namespace gi
{
namespace repository
{
namespace Gtk
{
class Builder;
namespace base
{
class BuilderExtra : public GI_GTK_BUILDER_BASE
{
typedef GI_GTK_BUILDER_BASE super;
public:
using super::get_object;
// T must be object-side type (not impl type)
template<typename T>
T get_object(const gi::cstring_v name)
{
auto obj = super::get_object(name);
return gi::object_cast<T>(obj);
}
/*
* T_Derived should be a custom subclass of some widget/object BaseClass.
* It should have a constructor of following signature that delegates
* to use the latter's special constructor (see also gtk example);
*
* T_Derived(BaseClass::instance_type instance, Gtk::Builder) :
* BaseClass(instance, this) {}
*
* Of course, it may also have additional arguments, and specify some
* additional arguments to super class constructor, if needed.
* See also comments on the latter.
*
* Note that this function *should* be called at some stage for any created
* C++-type based widget to ensure full and proper "C++ side" setup.
* See also gtk example (for additional comments).
*/
template<typename T_Derived, typename... Args>
gi::ref_ptr<T_Derived> get_object_derived(
const gi::cstring_v name, Args &&...args)
{
// instance type of class that T_Derived is based on
// (Gtk::Window for Gtk::WindowClass)
using instance_type = typename T_Derived::instance_type;
auto obj = super::get_object(name);
if (!obj)
return {};
// should be of expected base type
auto wobj = gi::object_cast<instance_type>(obj);
if (!wobj) {
g_error("wrong type (%s)", name.c_str());
return {};
}
// perhaps wrapper already of suitable type
auto wrapper = detail::ObjectClass::instance(obj.gobj_());
auto wrapper_cast = dynamic_cast<T_Derived *>(wrapper);
if (wrapper && !wrapper_cast) {
g_error("wrong C++ instance type (%s)", name.c_str());
return {};
} else if (wrapper_cast) {
return ref_ptr<T_Derived>(wrapper_cast, false);
}
// obtain builder from this
// (Builder subclass not yet declared/defined at this stage)
auto &builder = *(Builder *)(this);
// make wrapper using suitable constructor signature
// which does not add ref on provided instance
// so ref_ptr needs to grab an extra one
return ref_ptr<T_Derived>(
new T_Derived(wobj, builder, std::forward<Args>(args)...), false);
}
}; // class
#undef GI_GTK_BUILDER_BASE
#define GI_GTK_BUILDER_BASE base::BuilderExtra
} // namespace base
} // namespace Gtk
} // namespace repository
} // namespace gi
#endif

View File

@@ -0,0 +1,412 @@
#ifndef _GI_GTK_GTK_EXTRA_DEF_HPP_
#define _GI_GTK_GTK_EXTRA_DEF_HPP_
#include <map>
#include <string>
namespace gi
{
namespace repository
{
namespace Gtk
{
namespace base
{
#ifdef _GI_GTK_LIST_STORE_EXTRA_DEF_HPP_
// deprecated (as of about 4.9.1)
// so only define implementation here if declaration has been included
template<typename... Args>
Gtk::ListStore
ListStoreExtra::new_type_() noexcept
{
GType columns[] = {traits::gtype<Args>::get_type()...};
return ListStoreBase::new_(G_N_ELEMENTS(columns), columns);
};
#endif
} // namespace base
// class generated parts are needed
#if !GTK_CHECK_VERSION(4, 0, 0) || GI_CLASS_IMPL
namespace impl
{
// gtk widget template helper
class WidgetTemplateHelper
{
public:
enum class ConnectObject { NONE, TAIL, HEAD };
protected:
using ConnectData =
std::map<GType, std::map<std::string, gi::repository::GObject::Closure>>;
// inner namespace
class Internal
{
template<typename TUPLE>
struct tuple_strip_last;
template<typename... T>
struct tuple_strip_last<std::tuple<T...>>
{
protected:
using Tuple = std::tuple<T...>;
template<typename W>
struct inner;
template<std::size_t... Index>
struct inner<std::index_sequence<Index...>>
{
using type = std::tuple<
typename std::tuple_element<Index, std::tuple<T...>>::type...>;
};
public:
using type =
typename inner<std::make_index_sequence<sizeof...(T) - 1>>::type;
};
public:
struct ProxyClosure
{
GClosure base;
// actual target closure
GObject::Closure actual;
// duplicated from actual, holds ownership
GCallback cb;
gpointer user_data;
// perhaps through a thunk call helper
GObject::Closure thunk;
// no ref, guarded by watch
::GObject *object;
gboolean swapped;
};
// FUNCTOR represents C helper that transforms to Cpp call
// so it has C-types of FUNCTOR follows by functor user_data
template<ConnectObject CONNECT, typename FUNCTOR>
struct make_thunk : public std::false_type
{
struct call_type
{
// call should accept (signal emit object, signal args, proxy user_data)
// and transform this to a call in FUNCTOR form
// (suitably adding extra tail object and optionally swapping)
static void call() {}
};
};
// essentially SWAPPED case
template<typename R, typename FirstArg, typename... Args>
struct make_thunk<ConnectObject::HEAD, R (*)(FirstArg, Args...)>
{
// ... so FirstArg is extra object
static_assert(std::is_pointer<FirstArg>::value, "");
// remove user data
using ArgsType = typename tuple_strip_last<std::tuple<Args...>>::type;
// signal emit object
using ObjectArgType =
typename std::tuple_element<sizeof...(Args) - 2, ArgsType>::type;
static_assert(std::is_pointer<ObjectArgType>::value, "");
using SignalArgsType = typename tuple_strip_last<ArgsType>::type;
template<typename T>
struct thunk;
template<typename... TArgs>
struct thunk<std::tuple<TArgs...>>
{
// transform to call to
// (extra object, signal args, signal emit object, functor user_data)
static R call(ObjectArgType arg, TArgs... args, gpointer user_data)
{
auto tdata = (ProxyClosure *)(user_data);
typedef R (*func_type)(
::GObject *, TArgs..., ObjectArgType, gpointer);
return ((func_type)(tdata->cb))(
tdata->object, args..., arg, tdata->user_data);
}
};
using call_type = thunk<SignalArgsType>;
};
// essentially non-SWAPPED case
template<typename R, typename... Args>
struct make_thunk<ConnectObject::TAIL, R (*)(Args...)>
{
// remove user data
using AllArgsType = typename tuple_strip_last<std::tuple<Args...>>::type;
// extra object
using ObjectArgType =
typename std::tuple_element<sizeof...(Args) - 2, AllArgsType>::type;
static_assert(std::is_pointer<ObjectArgType>::value, "");
template<typename T>
struct thunk;
template<typename... TArgs>
struct thunk<std::tuple<TArgs...>>
{
// transform to call to
// (signal emit object, signal args, extra object, functor user_data)
static R call(TArgs... args, gpointer user_data)
{
auto tdata = (ProxyClosure *)(user_data);
typedef R (*func_type)(TArgs..., ::GObject *, gpointer);
return ((func_type)(tdata->cb))(
args..., tdata->object, tdata->user_data);
}
};
using SignalArgsType = typename tuple_strip_last<AllArgsType>::type;
using call_type = thunk<SignalArgsType>;
};
static void proxy_marshal(GClosure *closure, GValue *return_value,
guint n_param_values, const GValue *param_values,
gpointer invocation_hint, gpointer marshal_data)
{
// should only be used internally in gclosure for class closure cases
g_return_if_fail(marshal_data == NULL);
// call actual target if one has been provided
auto pclosure = (ProxyClosure *)(closure);
if (pclosure->actual) {
// might have to go through thunk if extra object
g_assert(!!pclosure->thunk == !!pclosure->object);
auto tclosure = pclosure->thunk ? pclosure->thunk.gobj_()
: pclosure->actual.gobj_();
g_closure_invoke(tclosure, return_value, n_param_values, param_values,
invocation_hint);
}
}
static void proxy_finalize(gpointer, GClosure *closure)
{
auto pclosure = (ProxyClosure *)(closure);
pclosure->actual = nullptr;
pclosure->thunk = nullptr;
}
static GObject::Closure make_proxy_closure(
::GObject *object = nullptr, bool swapped = false)
{
auto closure = g_closure_new_simple(sizeof(ProxyClosure), nullptr);
g_closure_set_marshal(closure, proxy_marshal);
g_closure_sink(g_closure_ref(closure));
g_closure_add_finalize_notifier(closure, nullptr, proxy_finalize);
// extra tracking
auto pclosure = (ProxyClosure *)closure;
if (object) {
g_object_watch_closure(object, closure);
pclosure->object = object;
// only relevant if object
pclosure->swapped = swapped;
}
return gi::wrap(closure, gi::transfer_full);
}
// work-around missing inline support
static ConnectData *&get_connect_data()
{
thread_local ConnectData *connect_data;
return connect_data;
}
static GQuark get_template_quark()
{
static const char *KEY = "GIOBJECT_TEMPLATE";
static GQuark q = g_quark_from_static_string(KEY);
return q;
}
static void builder_connect_function(GtkBuilder *builder, ::GObject *object,
const gchar *signal_name, const gchar *handler_name,
::GObject *connect_object, GConnectFlags flags, gpointer user_data)
{
(void)builder;
(void)user_data;
auto closure = Internal::make_proxy_closure(
connect_object, flags & G_CONNECT_SWAPPED);
g_signal_connect_closure(
object, signal_name, closure.gobj_(), flags & G_CONNECT_AFTER);
auto connect_data = get_connect_data();
g_assert(connect_data);
if (connect_data) {
(*connect_data)[G_OBJECT_TYPE(object)][handler_name] = closure;
}
}
};
#if GTK_CHECK_VERSION(4, 0, 0)
class BuilderScope : public Gtk::impl::BuilderCScopeImpl
{
public:
BuilderScope() : Gtk::impl::BuilderCScopeImpl(this) {}
GObject::Closure create_closure_(Gtk::Builder builder,
const gi::cstring_v function_name, Gtk::BuilderClosureFlags flags,
GObject::Object object, GLib::Error *_error) override
{
(void)_error;
// current object is the template'd one being init'ed
// a direct call is used as a wrapped call might fiddle with refs
// while the object is still being init'ed, which does not end well
auto current = gtk_builder_get_current_object(builder.gobj_());
auto connect_data = current ? (ConnectData *)g_object_get_qdata(
current, Internal::get_template_quark())
: nullptr;
g_assert(connect_data);
if (connect_data) {
auto wrapped = Internal::make_proxy_closure(
object.gobj_(), (flags & Gtk::BuilderClosureFlags::SWAPPED_) ==
Gtk::BuilderClosureFlags::SWAPPED_);
(*connect_data)[G_OBJECT_TYPE(current)][function_name] = wrapped;
return wrapped;
}
return nullptr;
}
};
#endif
// owned by qdata
ConnectData *connect_data_;
public:
WidgetTemplateHelper(gi::repository::GObject::Object object)
{
if (object) {
connect_data_ = (ConnectData *)g_object_get_qdata(
object.gobj_(), Internal::get_template_quark());
g_assert(connect_data_);
}
}
template<GType (*typefunc)() = nullptr>
static void custom_class_init(gpointer klass, gpointer)
{
G_OBJECT_CLASS(klass)->dispose = custom_dispose<typefunc>;
#if GTK_CHECK_VERSION(4, 0, 0)
auto builder = gi::make_ref<BuilderScope>();
gtk_widget_class_set_template_scope(
GTK_WIDGET_CLASS(klass), GTK_BUILDER_SCOPE(builder->gobj_()));
#else
gtk_widget_class_set_connect_func(GTK_WIDGET_CLASS(klass),
Internal::builder_connect_function, nullptr, nullptr);
#endif
}
static void custom_init(GtkWidget *instance, gpointer)
{
// avoid namespace interference
using GObject = ::GObject;
auto tq = Internal::get_template_quark();
// prepare storage
// in case of multi-level subclassing, it is used for all
ConnectData *cdp;
if (!(cdp = (ConnectData *)g_object_get_qdata(G_OBJECT(instance), tq))) {
auto deleter = [](gpointer d) { delete (ConnectData *)d; };
auto cd = std::make_unique<ConnectData>();
cdp = cd.get();
g_object_set_qdata_full(G_OBJECT(instance), tq, cd.release(), deleter);
}
#if GTK_CHECK_VERSION(4, 0, 0)
(void)cdp;
gtk_widget_init_template(GTK_WIDGET(instance));
#else
// unfortunate API (which does not provide access to instance)
// make ConnectData instance active on this thread
Internal::get_connect_data() = cdp;
gtk_widget_init_template(GTK_WIDGET(instance));
// so we got all that during above _init call
Internal::get_connect_data() = nullptr;
#endif
}
template<GType (*typefunc)()>
static void custom_dispose(::GObject *gobject)
{
// this intermediate step avoids a -Waddress warning on recent gcc
auto tf = typefunc;
auto gtype = tf ? typefunc() : G_OBJECT_TYPE(gobject);
#if GTK_CHECK_VERSION(4, 8, 0)
gtk_widget_dispose_template(GTK_WIDGET(gobject), gtype);
#endif
// need to know our place in the type chain
// (in C, this is usually handled by the parent_class variable)
// fallback to the leaf type if all else fails, but that too may fail
G_OBJECT_CLASS(g_type_class_peek(g_type_parent(gtype)))->dispose(gobject);
}
template<typename F, ConnectObject c = ConnectObject::NONE, typename Functor>
bool set_handler(gi::cstring_v handler_name, Functor &&f, GType gtype = 0)
{
auto _cd = (ConnectData *)connect_data_;
if (!_cd) {
g_assert_not_reached();
return false;
}
auto cd = *_cd;
// find name in collected data
Internal::ProxyClosure *proxy{};
for (auto &e : cd) {
if (gtype != 0 && gtype != e.first)
continue;
auto it = e.second.find(handler_name);
if (it != e.second.end()) {
// perhaps found one already
if (proxy) {
g_warning("ambiguous template entry for %s", handler_name.c_str());
return false;
}
proxy = (Internal::ProxyClosure *)(it->second.gobj_());
// continue search to check for conflicts in case of wildcard type
if (gtype != 0)
break;
}
}
if (!proxy)
return false;
// sanity checks; provided parameters match UI data
g_return_val_if_fail(!!proxy->object == (c != ConnectObject::NONE), FALSE);
g_return_val_if_fail(
!proxy->object || proxy->swapped == (c == ConnectObject::HEAD), FALSE);
// go go
// standard closure, also owns functor data
auto w =
new gi::detail::transform_signal_wrapper<F>(std::forward<Functor>(f));
auto closure = g_cclosure_new(
(GCallback)&w->wrapper, w, (GClosureNotify)(GCallback)&w->destroy);
g_closure_sink(g_closure_ref(closure));
g_closure_set_marshal(closure, g_cclosure_marshal_generic);
proxy->cb = (GCallback)&w->wrapper;
proxy->user_data = w;
proxy->actual = gi::wrap(closure, gi::transfer_full);
proxy->thunk = nullptr;
// optional thunk closure to invoke helper thunk to handle object
if (proxy->object) {
auto cb_thunk = (GCallback)&Internal::make_thunk<c,
decltype(&w->wrapper)>::call_type::call;
auto thunk = g_cclosure_new(cb_thunk, proxy, nullptr);
g_closure_set_marshal(thunk, g_cclosure_marshal_generic);
g_closure_sink(g_closure_ref(thunk));
proxy->thunk = gi::wrap(thunk, gi::transfer_full);
}
return true;
}
};
} // namespace impl
#endif
} // namespace Gtk
} // namespace repository
} // namespace gi
#endif

View File

@@ -0,0 +1,19 @@
#pragma once
// unfortunately gtk includes gtkx includes gdkx includes X11/X*.h
// where the latter brings in a whole slew of (evidently non-namespaced) define
// so try to undefine some of the more nasty ones that might likely conflict
#ifdef DestroyNotify
#undef DestroyNotify
#endif
#ifdef Status
#undef Status
#endif
// still part of GIR, but now not part of standard include (or pkg .pc)
#if GTK_CHECK_VERSION(4, 0, 0)
#ifdef G_OS_UNIX
// needs include path specified in gtk4-unix-print.pc
#include <gtk/gtkunixprint.h>
#endif
#endif

View File

@@ -0,0 +1,12 @@
#pragma once
#include <gtk/gtk.h>
#if !GTK_CHECK_VERSION(3, 99, 0)
#include <gtk/gtk-a11y.h>
#endif
// GtkSnapshot is alias for GdkSnapshot and its GIR does not specify c:type
// use a fairly opaque dummy type here to make things work out
// (since one ctype can not map to 2 cpp types (Gdk::Snapshot and Gtk::Snapshot,
// and since one pointer is much like another)
struct GI_PATCH_GtkSnapshot;

View File

@@ -0,0 +1,33 @@
#ifndef _GI_GTK_LIST_STORE_EXTRA_DEF_HPP_
#define _GI_GTK_LIST_STORE_EXTRA_DEF_HPP_
namespace gi
{
namespace repository
{
namespace Gtk
{
namespace base
{
class ListStoreExtra : public GI_GTK_LISTSTORE_BASE
{
typedef GI_GTK_LISTSTORE_BASE super;
public:
template<typename... Args>
static GI_INLINE_DECL Gtk::ListStore new_type_() noexcept;
}; // class
#undef GI_GTK_LISTSTORE_BASE
#define GI_GTK_LISTSTORE_BASE base::ListStoreExtra
} // namespace base
} // namespace Gtk
} // namespace repository
} // namespace gi
#endif

View File

@@ -0,0 +1,34 @@
#ifndef _GI_GTK_TREEVIEWCOLUMN_EXTRA_DEF_HPP_
#define _GI_GTK_TREEVIEWCOLUMN_EXTRA_DEF_HPP_
namespace gi
{
namespace repository
{
namespace Gtk
{
namespace base
{
class TreeViewColumnExtra : public GI_GTK_TREEVIEWCOLUMN_BASE
{
typedef GI_GTK_TREEVIEWCOLUMN_BASE super;
public:
static GI_INLINE_DECL Gtk::TreeViewColumn new_(const std::string title = "",
Gtk::CellRenderer = nullptr,
const std::map<std::string, int> = {}) noexcept;
}; // class
#undef GI_GTK_TREEVIEWCOLUMN_BASE
#define GI_GTK_TREEVIEWCOLUMN_BASE base::TreeViewColumnExtra
} // namespace base
} // namespace Gtk
} // namespace repository
} // namespace gi
#endif

View File

@@ -0,0 +1,35 @@
#ifndef _GI_GTK_TREEVIEWCOLUMN_EXTRA_DEF_IMPL_HPP_
#define _GI_GTK_TREEVIEWCOLUMN_EXTRA_DEF_IMPL_HPP_
namespace gi
{
namespace repository
{
namespace Gtk
{
namespace base
{
Gtk::TreeViewColumn
TreeViewColumnExtra::new_(const std::string title, Gtk::CellRenderer renderer,
const std::map<std::string, int> attribs) noexcept
{
auto result = TreeViewColumnBase::new_();
result.set_title(title);
if (renderer) {
result.pack_start(renderer, true);
for (auto &e : attribs) {
result.add_attribute(renderer, e.first, e.second);
}
}
return result;
}
} // namespace base
} // namespace Gtk
} // namespace repository
} // namespace gi
#endif

View File

@@ -0,0 +1,8 @@
#ifndef _GI_PANGO_PANGO_SETUP_DEF_HPP_
#define _GI_PANGO_PANGO_SETUP_DEF_HPP_
/* some header parts are only conditionally considered */
#define PANGO_ENABLE_BACKEND
#define PANGO_ENABLE_ENGINE
#endif