mirror of
https://github.com/php/php-gtk-src.git
synced 2026-03-24 01:02:08 +01:00
their constructor's run when used with libglade or gtkbuilder and that constructors ar never double constructed Also added signal example for using TYPE_PHP_VALUE
1798 lines
57 KiB
C
1798 lines
57 KiB
C
/*
|
|
* PHP-GTK - The PHP language bindings for GTK+
|
|
*
|
|
* Copyright (C) 2001-2008 Andrei Zmievski <andrei@php.net>
|
|
*
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include "php_gtk.h"
|
|
#include "zend_interfaces.h"
|
|
|
|
#if HAVE_PHP_GTK
|
|
|
|
/*
|
|
* GObject API and helper functions
|
|
*/
|
|
|
|
static GQuark gobject_wrapper_handle_key = 0;
|
|
static GQuark gobject_wrapper_handlers_key = 0;
|
|
static GQuark gobject_wrapper_owned_key = 0;
|
|
static GQuark gobject_wrapper_zts_key = 0;
|
|
|
|
PHP_GTK_API zend_object_handlers phpg_gobject_handlers;
|
|
|
|
HashTable phpg_prop_info;
|
|
|
|
/* {{{ static phpg_free_gobject_storage() */
|
|
static inline void phpg_free_gobject_storage(phpg_gobject_t *object, zend_object_handle handle TSRMLS_DC)
|
|
{
|
|
GSList *tmp;
|
|
|
|
zend_object_std_dtor(&object->zobj TSRMLS_CC);
|
|
|
|
/*
|
|
* Remove cached handle information, since the object wrapper is going away.
|
|
*/
|
|
/*
|
|
g_object_set_qdata(object->obj, gobject_wrapper_handle_key, NULL);
|
|
g_object_set_qdata(object->obj, gobject_wrapper_handlers_key, NULL);
|
|
*/
|
|
|
|
if (object->obj && object->dtor && !object->is_owned)
|
|
object->dtor(object->obj);
|
|
object->obj = NULL;
|
|
|
|
tmp = object->closures;
|
|
while (tmp) {
|
|
GClosure *closure = (GClosure *) tmp->data;
|
|
/*
|
|
* Save the pointer, because phpg_gobject_unwatch_closure() will remove
|
|
* the closure from the list.
|
|
*/
|
|
tmp = tmp->next;
|
|
g_closure_invalidate(closure);
|
|
}
|
|
object->closures = NULL;
|
|
|
|
efree(object);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ static phpg_sink_object() */
|
|
static inline void phpg_sink_object(GObject *obj)
|
|
{
|
|
/*
|
|
* For now, do a check for GTK_TYPE_OBJECT's and sink them. More generic
|
|
* system can be implemented later.
|
|
*/
|
|
if (g_type_is_a(G_OBJECT_TYPE(obj), GTK_TYPE_OBJECT)
|
|
&& GTK_OBJECT_FLOATING(obj)) {
|
|
g_object_ref(obj);
|
|
gtk_object_sink(GTK_OBJECT(obj));
|
|
return;
|
|
}
|
|
|
|
if (g_type_is_a(G_OBJECT_TYPE(obj), GTK_TYPE_WINDOW)
|
|
&& obj->ref_count == 1
|
|
&& GTK_WINDOW(obj)->has_user_ref_count) {
|
|
g_object_ref(obj);
|
|
return;
|
|
}
|
|
|
|
if (g_type_is_a(G_OBJECT_TYPE(obj), GTK_TYPE_INVISIBLE)
|
|
&& obj->ref_count == 1
|
|
&& GTK_INVISIBLE(obj)->has_user_ref_count) {
|
|
g_object_ref(obj);
|
|
return;
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ static phpg_unref_by_handle */
|
|
static void phpg_unref_by_handle(void *data)
|
|
{
|
|
zend_object_handle handle = (zend_object_handle) data;
|
|
zval zobj;
|
|
TSRMLS_FETCH();
|
|
|
|
Z_OBJ_HANDLE(zobj) = handle;
|
|
php_gtk_handlers.del_ref(&zobj TSRMLS_CC);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ phpg_gobject_del_ref */
|
|
void phpg_gobject_del_ref(zval *zobject TSRMLS_DC)
|
|
{
|
|
zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
|
|
struct _store_object *stored = &EG(objects_store).object_buckets[handle].bucket.obj;
|
|
phpg_gobject_t *pobj = (phpg_gobject_t *) stored->object;
|
|
|
|
if (EG(objects_store).object_buckets[handle].valid && stored->refcount == 1) {
|
|
if (pobj->obj && pobj->obj->ref_count > 1) {
|
|
pobj->is_owned = TRUE;
|
|
g_object_set_qdata_full(pobj->obj, gobject_wrapper_owned_key, (void *)handle, phpg_unref_by_handle);
|
|
g_object_unref(pobj->obj);
|
|
return;
|
|
}
|
|
}
|
|
|
|
php_gtk_handlers.del_ref(zobject TSRMLS_CC);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ PHP_GTK_API phpg_create_gobject() */
|
|
PHP_GTK_API zend_object_value phpg_create_gobject(zend_class_entry *ce TSRMLS_DC)
|
|
{
|
|
zend_object_value zov;
|
|
phpg_gobject_t *object;
|
|
|
|
object = emalloc(sizeof(phpg_gobject_t));
|
|
phpg_init_object(object, ce TSRMLS_CC);
|
|
|
|
object->obj = NULL;
|
|
object->dtor = NULL;
|
|
object->closures = NULL;
|
|
object->is_owned = FALSE;
|
|
|
|
zov.handlers = &phpg_gobject_handlers;
|
|
zov.handle = zend_objects_store_put(object, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) phpg_free_gobject_storage, NULL TSRMLS_CC);
|
|
|
|
return zov;
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ PHP_GTK_API phpg_gobject_set_wrapper() */
|
|
PHP_GTK_API void phpg_gobject_set_wrapper(zval *zobj, GObject *obj TSRMLS_DC)
|
|
{
|
|
phpg_gobject_t *pobj = NULL;
|
|
|
|
phpg_sink_object(obj);
|
|
pobj = (phpg_gobject_t *) zend_object_store_get_object(zobj TSRMLS_CC);
|
|
pobj->obj = obj;
|
|
pobj->dtor = (phpg_dtor_t) g_object_unref;
|
|
pobj->is_owned = FALSE;
|
|
g_object_set_qdata(pobj->obj, gobject_wrapper_handle_key, (void*)Z_OBJ_HANDLE_P(zobj));
|
|
g_object_set_qdata(pobj->obj, gobject_wrapper_handlers_key, (void*)Z_OBJ_HT_P(zobj));
|
|
#ifdef ZTS
|
|
g_object_set_qdata(pobj->obj, gobject_wrapper_zts_key, (void*)TSRMLS_C);
|
|
#endif
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ PHP_GTK_API phpg_gobject_new() */
|
|
PHP_GTK_API void phpg_gobject_new(zval **zobj, GObject *obj TSRMLS_DC)
|
|
{
|
|
zend_class_entry *ce = NULL;
|
|
phpg_gobject_t *pobj = NULL;
|
|
zend_object_handle handle;
|
|
zend_object_handlers *handlers;
|
|
|
|
assert(zobj != NULL);
|
|
if (*zobj == NULL) {
|
|
MAKE_STD_ZVAL(*zobj);
|
|
}
|
|
ZVAL_NULL(*zobj);
|
|
|
|
if (obj == NULL) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* 1. Lookup stored object handle based on wrapper key.
|
|
* 2. Make zval refer to this handle.
|
|
* 3. If not found, create new object and store it.
|
|
* 4. Install wrapper key.
|
|
*/
|
|
|
|
handle = (zend_object_handle) g_object_get_qdata(obj, gobject_wrapper_handle_key);
|
|
if ((void*)handle != NULL) {
|
|
phpg_gobject_t *pobj;
|
|
handlers = (zend_object_handlers*) g_object_get_qdata(obj, gobject_wrapper_handlers_key);
|
|
Z_TYPE_PP(zobj) = IS_OBJECT;
|
|
Z_OBJ_HANDLE_PP(zobj) = handle;
|
|
Z_OBJ_HT_PP(zobj) = handlers;
|
|
pobj = zend_object_store_get_object(*zobj TSRMLS_CC);
|
|
if (pobj->is_owned) {
|
|
pobj->is_owned = FALSE;
|
|
g_object_steal_qdata(pobj->obj, gobject_wrapper_owned_key);
|
|
g_object_ref(pobj->obj);
|
|
} else {
|
|
zend_objects_store_add_ref(*zobj TSRMLS_CC);
|
|
}
|
|
} else {
|
|
ce = phpg_class_from_gtype(G_OBJECT_TYPE(obj) TSRMLS_CC);
|
|
object_init_ex(*zobj, ce);
|
|
|
|
g_object_ref(obj);
|
|
phpg_sink_object(obj);
|
|
|
|
pobj = (phpg_gobject_t *) zend_object_store_get_object(*zobj TSRMLS_CC);
|
|
pobj->obj = obj;
|
|
pobj->dtor = (phpg_dtor_t) g_object_unref;
|
|
pobj->is_owned = FALSE;
|
|
g_object_set_qdata(obj, gobject_wrapper_handle_key, (void*)Z_OBJ_HANDLE_PP(zobj));
|
|
g_object_set_qdata(obj, gobject_wrapper_handlers_key, (void*)Z_OBJ_HT_PP(zobj));
|
|
#ifdef ZTS
|
|
g_object_set_qdata(obj, gobject_wrapper_zts_key, (void*)TSRMLS_C);
|
|
#endif
|
|
|
|
if (ce->type == ZEND_USER_CLASS) {
|
|
zend_call_method_with_0_params(zobj, ce, &ce->constructor, "__construct", NULL);
|
|
}
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ PHP_GTK_API phpg_gobject_watch_closure() */
|
|
static void phpg_gobject_unwatch_closure(gpointer data, GClosure *closure)
|
|
{
|
|
phpg_gobject_t *pobj = (phpg_gobject_t *) data;
|
|
|
|
pobj->closures = g_slist_remove(pobj->closures, closure);
|
|
}
|
|
|
|
PHP_GTK_API void phpg_gobject_watch_closure(zval *zobj, GClosure *closure TSRMLS_DC)
|
|
{
|
|
phpg_gobject_t *pobj = NULL;
|
|
|
|
phpg_return_if_fail(zobj != NULL);
|
|
phpg_return_if_fail(closure != NULL);
|
|
phpg_return_if_fail_quiet(Z_TYPE_P(zobj) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zobj), gobject_ce TSRMLS_CC));
|
|
|
|
pobj = zend_object_store_get_object(zobj TSRMLS_CC);
|
|
phpg_return_if_fail_quiet(g_slist_find(pobj->closures, closure) == NULL);
|
|
|
|
pobj->closures = g_slist_prepend(pobj->closures, closure);
|
|
g_closure_add_invalidate_notifier(closure, pobj, phpg_gobject_unwatch_closure);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ phpg_gobject_construct */
|
|
zend_bool phpg_gobject_construct(zval *this_ptr, GType object_type, zval *props TSRMLS_DC)
|
|
{
|
|
guint n_params = 0;
|
|
GParameter *params = NULL;
|
|
GObjectClass *klass;
|
|
GObject *obj;
|
|
char buf [128];
|
|
int i;
|
|
|
|
if (G_TYPE_IS_ABSTRACT(object_type)) {
|
|
snprintf(buf, 128, "Cannot instantiate abstract class %s", g_type_name(object_type));
|
|
PHPG_THROW_EXCEPTION_WITH_RETURN(phpg_construct_exception, buf, 0);
|
|
}
|
|
|
|
if ((klass = g_type_class_ref(object_type)) == NULL) {
|
|
PHPG_THROW_EXCEPTION_WITH_RETURN(phpg_construct_exception, "Could not get a reference to type class", 0);
|
|
}
|
|
|
|
if (props) {
|
|
int key_type;
|
|
char *key;
|
|
ulong num_key;
|
|
zval **value;
|
|
GParamSpec *pspec;
|
|
|
|
params = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(props)), sizeof(GParameter));
|
|
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(props));
|
|
zend_hash_get_current_data(Z_ARRVAL_P(props), (void**)&value) == SUCCESS;
|
|
zend_hash_move_forward(Z_ARRVAL_P(props))) {
|
|
|
|
key_type = zend_hash_get_current_key(Z_ARRVAL_P(props), &key, &num_key, 0);
|
|
if (key_type != HASH_KEY_IS_STRING) {
|
|
zend_throw_exception(phpg_construct_exception, "parameter names have to be keys", 0 TSRMLS_CC);
|
|
goto cleanup;
|
|
}
|
|
|
|
pspec = g_object_class_find_property(klass, key);
|
|
if (!pspec) {
|
|
snprintf(buf, 128, "Class %s does not support property '%s'", g_type_name(object_type), key);
|
|
zend_throw_exception(phpg_construct_exception, buf, 0 TSRMLS_CC);
|
|
goto cleanup;
|
|
}
|
|
|
|
g_value_init(¶ms[n_params].value, G_PARAM_SPEC_VALUE_TYPE(pspec));
|
|
if (phpg_gvalue_from_zval(¶ms[n_params].value, value, TRUE TSRMLS_CC) == FAILURE) {
|
|
snprintf(buf, 128, "Could not convert value for property '%s'", key);
|
|
zend_throw_exception(phpg_construct_exception, buf, 0 TSRMLS_CC);
|
|
goto cleanup;
|
|
}
|
|
|
|
params[n_params].name = estrdup(key);
|
|
|
|
n_params++;
|
|
}
|
|
}
|
|
|
|
obj = g_object_newv(object_type, n_params, params);
|
|
if (obj) {
|
|
phpg_gobject_set_wrapper(this_ptr, obj TSRMLS_CC);
|
|
} else {
|
|
snprintf(buf, 128, "Could not construct %s object", Z_OBJCE_P(this_ptr)->name);
|
|
zend_throw_exception(phpg_construct_exception, buf, 0 TSRMLS_CC);
|
|
}
|
|
|
|
cleanup:
|
|
if (params) {
|
|
for (i = 0; i < (int)n_params; i++) {
|
|
efree((void *)params[i].name);
|
|
g_value_unset(¶ms[i].value);
|
|
}
|
|
efree(params);
|
|
}
|
|
g_type_class_unref(klass);
|
|
|
|
return (obj) ? 1 : 0;
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
/*
|
|
* GObject PHP class definition
|
|
*/
|
|
|
|
PHP_GTK_EXPORT_CE(gobject_ce) = NULL;
|
|
|
|
/* {{{ GObject::__construct */
|
|
static PHP_METHOD(GObject, __construct)
|
|
{
|
|
GType my_type;
|
|
zval *php_type = NULL;
|
|
zval *php_props = NULL;
|
|
char buf[128];
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "|Va", &php_type, &php_props)) {
|
|
snprintf(buf, 128, "Could not construct %s object", Z_OBJCE_P(this_ptr)->name);
|
|
PHPG_THROW_EXCEPTION(phpg_construct_exception, buf);
|
|
}
|
|
|
|
if (php_type) {
|
|
my_type = phpg_gtype_from_zval(php_type TSRMLS_CC);
|
|
} else {
|
|
my_type = phpg_gtype_from_zval(this_ptr TSRMLS_CC);
|
|
}
|
|
|
|
phpg_gobject_construct(this_ptr, my_type, php_props TSRMLS_CC);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ GObject::__tostring() */
|
|
static PHP_METHOD(GObject, __tostring)
|
|
{
|
|
char buf[256];
|
|
GObject *obj = NULL;
|
|
int numc = 0;
|
|
|
|
NOT_STATIC_METHOD();
|
|
|
|
obj = PHPG_GOBJECT(this_ptr);
|
|
numc = snprintf(buf, sizeof(buf),
|
|
"[%s object (%s Gtk+ type)]", Z_OBJCE_P(this_ptr)->name,
|
|
obj ? G_OBJECT_TYPE_NAME(obj) : "uninitialized");
|
|
RETURN_STRINGL(buf, numc, 1);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ static phpg_signal_connect_impl() */
|
|
static void phpg_signal_connect_impl(INTERNAL_FUNCTION_PARAMETERS, int connect_type, zend_bool after)
|
|
{
|
|
char *signal = NULL;
|
|
zval *callback;
|
|
zval *extra = NULL;
|
|
GObject *obj = NULL;
|
|
guint signal_id, handler_id;
|
|
GQuark detail = 0;
|
|
GClosure *closure = NULL;
|
|
|
|
NOT_STATIC_METHOD();
|
|
|
|
if (!php_gtk_parse_varargs(ZEND_NUM_ARGS(), 2, &extra, "sV", &signal, &callback)) {
|
|
if (extra) {
|
|
zval_ptr_dtor(&extra);
|
|
}
|
|
return;
|
|
}
|
|
|
|
obj = PHPG_GOBJECT(this_ptr);
|
|
if (!g_signal_parse_name(signal, G_OBJECT_TYPE(obj), &signal_id, &detail, TRUE)) {
|
|
php_error(E_WARNING, "%s(): unknown signal name '%s'", get_active_function_name(TSRMLS_C), signal);
|
|
if (extra) zval_ptr_dtor(&extra);
|
|
return;
|
|
}
|
|
|
|
closure = phpg_closure_new(callback, extra, connect_type, NULL TSRMLS_CC);
|
|
if (extra) {
|
|
zval_ptr_dtor(&extra);
|
|
}
|
|
phpg_gobject_watch_closure(this_ptr, closure TSRMLS_CC);
|
|
handler_id = g_signal_connect_closure_by_id(obj, signal_id, detail, closure, after);
|
|
RETURN_LONG(handler_id);
|
|
}
|
|
/* }}} */
|
|
/* {{{ GObject::connect */
|
|
static PHP_METHOD(GObject, connect)
|
|
{
|
|
phpg_signal_connect_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHPG_CONNECT_NORMAL, FALSE);
|
|
}
|
|
/* }}} */
|
|
/* {{{ GObject::connect_after */
|
|
static PHP_METHOD(GObject, connect_after)
|
|
{
|
|
phpg_signal_connect_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHPG_CONNECT_NORMAL, TRUE);
|
|
}
|
|
/* }}} */
|
|
/* {{{ GObject::connect_simple */
|
|
static PHP_METHOD(GObject, connect_simple)
|
|
{
|
|
phpg_signal_connect_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHPG_CONNECT_SIMPLE, FALSE);
|
|
}
|
|
/* }}} */
|
|
/* {{{ GObject::connect_simple_after */
|
|
static PHP_METHOD(GObject, connect_simple_after)
|
|
{
|
|
phpg_signal_connect_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHPG_CONNECT_SIMPLE, TRUE);
|
|
}
|
|
/* }}} */
|
|
/* {{{ GObject::connect_object */
|
|
static PHP_METHOD(GObject, connect_object)
|
|
{
|
|
phpg_warn_deprecated("use connect() or connect_simple()" TSRMLS_CC);
|
|
phpg_signal_connect_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHPG_CONNECT_OBJECT, FALSE);
|
|
}
|
|
/* }}} */
|
|
/* {{{ GObject::connect_object_after */
|
|
static PHP_METHOD(GObject, connect_object_after)
|
|
{
|
|
phpg_warn_deprecated("use connect_after() or connect_simple_after()" TSRMLS_CC);
|
|
phpg_signal_connect_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHPG_CONNECT_OBJECT, TRUE);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ GObject::notify stuff */
|
|
static PHP_METHOD(GObject, notify)
|
|
{
|
|
char *property;
|
|
GParamSpec *pspec;
|
|
GObject *obj;
|
|
|
|
NOT_STATIC_METHOD();
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "s", &property))
|
|
return;
|
|
|
|
obj = PHPG_GOBJECT(this_ptr);
|
|
pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(obj), property);
|
|
if (pspec == NULL) {
|
|
php_error(E_WARNING, "Class '%s' does not support property '%s'",
|
|
g_type_name(G_TYPE_FROM_INSTANCE(obj)), property);
|
|
return;
|
|
}
|
|
|
|
g_object_notify(obj, property);
|
|
}
|
|
|
|
static PHP_METHOD(GObject, freeze_notify)
|
|
{
|
|
NOT_STATIC_METHOD();
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "")) {
|
|
return;
|
|
}
|
|
|
|
g_object_freeze_notify(PHPG_GOBJECT(this_ptr));
|
|
}
|
|
|
|
static PHP_METHOD(GObject, thaw_notify)
|
|
{
|
|
NOT_STATIC_METHOD();
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "")) {
|
|
return;
|
|
}
|
|
|
|
g_object_thaw_notify(PHPG_GOBJECT(this_ptr));
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ GObject::get/set_property */
|
|
static PHP_METHOD(GObject, get_property)
|
|
{
|
|
char *property;
|
|
GParamSpec *pspec;
|
|
GValue value = { 0, };
|
|
GObject *obj;
|
|
|
|
NOT_STATIC_METHOD();
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "s", &property))
|
|
return;
|
|
|
|
obj = PHPG_GOBJECT(this_ptr);
|
|
pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(obj), property);
|
|
if (pspec == NULL) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "class '%s' does not support property '%s'",
|
|
g_type_name(G_TYPE_FROM_INSTANCE(obj)), property);
|
|
return;
|
|
}
|
|
|
|
if (!(pspec->flags & G_PARAM_READABLE)) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "property '%s' is not readable", property);
|
|
return;
|
|
}
|
|
|
|
g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
|
|
g_object_get_property(obj, property, &value);
|
|
phpg_param_gvalue_to_zval(&value, &return_value, TRUE, pspec TSRMLS_CC);
|
|
g_value_unset(&value);
|
|
}
|
|
|
|
static PHP_METHOD(GObject, set_property)
|
|
{
|
|
char *property;
|
|
zval *php_value;
|
|
GParamSpec *pspec;
|
|
GValue value = { 0, };
|
|
GObject *obj;
|
|
|
|
NOT_STATIC_METHOD();
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "sV", &property, &php_value))
|
|
return;
|
|
|
|
obj = PHPG_GOBJECT(this_ptr);
|
|
pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(obj), property);
|
|
if (pspec == NULL) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "class '%s' does not support property '%s'",
|
|
g_type_name(G_TYPE_FROM_INSTANCE(obj)), property);
|
|
return;
|
|
}
|
|
|
|
if (!(pspec->flags & G_PARAM_WRITABLE)) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "property '%s' is not writable", property);
|
|
return;
|
|
}
|
|
|
|
g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
|
|
if (phpg_param_gvalue_from_zval(&value, &php_value, pspec TSRMLS_CC) == FAILURE) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not convert value to property type");
|
|
return;
|
|
}
|
|
g_object_set_property(obj, property, &value);
|
|
g_value_unset(&value);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ GObject::get/set_data */
|
|
static PHP_METHOD(GObject, get_data)
|
|
{
|
|
char *key;
|
|
zval *data;
|
|
GQuark quark;
|
|
|
|
NOT_STATIC_METHOD();
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "s", &key))
|
|
return;
|
|
|
|
quark = g_quark_from_string(key);
|
|
data = g_object_get_qdata(PHPG_GOBJECT(this_ptr), quark);
|
|
if (data) {
|
|
RETURN_ZVAL(data, 1, 0);
|
|
}
|
|
}
|
|
|
|
static PHP_METHOD(GObject, set_data)
|
|
{
|
|
char *key;
|
|
zval *data;
|
|
GQuark quark;
|
|
|
|
NOT_STATIC_METHOD();
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "sV", &key, &data))
|
|
return;
|
|
|
|
quark = g_quark_from_string(key);
|
|
zval_add_ref(&data);
|
|
g_object_set_qdata_full(PHPG_GOBJECT(this_ptr), quark, data, phpg_destroy_notify);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ GObject::handler_* */
|
|
static PHP_METHOD(GObject, block)
|
|
{
|
|
guint handler_id;
|
|
|
|
NOT_STATIC_METHOD();
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "i", &handler_id)) {
|
|
return;
|
|
}
|
|
|
|
g_signal_handler_block(PHPG_GOBJECT(this_ptr), handler_id);
|
|
}
|
|
|
|
static PHP_METHOD(GObject, unblock)
|
|
{
|
|
guint handler_id;
|
|
|
|
NOT_STATIC_METHOD();
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "i", &handler_id)) {
|
|
return;
|
|
}
|
|
|
|
g_signal_handler_unblock(PHPG_GOBJECT(this_ptr), handler_id);
|
|
}
|
|
|
|
static PHP_METHOD(GObject, disconnect)
|
|
{
|
|
guint handler_id;
|
|
|
|
NOT_STATIC_METHOD();
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "i", &handler_id)) {
|
|
return;
|
|
}
|
|
|
|
g_signal_handler_disconnect(PHPG_GOBJECT(this_ptr), handler_id);
|
|
}
|
|
|
|
static PHP_METHOD(GObject, is_connected)
|
|
{
|
|
guint handler_id;
|
|
|
|
NOT_STATIC_METHOD();
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "i", &handler_id)) {
|
|
return;
|
|
}
|
|
|
|
RETURN_BOOL(g_signal_handler_is_connected(PHPG_GOBJECT(this_ptr), handler_id));
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ GObject::stop_emission */
|
|
static PHP_METHOD(GObject, stop_emission)
|
|
{
|
|
char *signal;
|
|
guint signal_id;
|
|
GQuark detail;
|
|
GObject *obj;
|
|
|
|
NOT_STATIC_METHOD();
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "s", &signal)) {
|
|
return;
|
|
}
|
|
|
|
obj = PHPG_GOBJECT(this_ptr);
|
|
if (!g_signal_parse_name(signal, G_OBJECT_TYPE(obj), &signal_id, &detail, TRUE)) {
|
|
php_error(E_WARNING, "%s(): unknown signal name '%s'", get_active_function_name(TSRMLS_C), signal);
|
|
return;
|
|
}
|
|
|
|
g_signal_stop_emission(obj, signal_id, detail);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ GObject::emit */
|
|
static PHP_METHOD(GObject, emit)
|
|
{
|
|
char *signal;
|
|
zval *extra = NULL, **item;
|
|
guint signal_id;
|
|
GQuark detail;
|
|
GObject *obj;
|
|
GSignalQuery query;
|
|
GValue *params, ret = { 0, };
|
|
int i;
|
|
|
|
NOT_STATIC_METHOD();
|
|
|
|
if (!php_gtk_parse_varargs(ZEND_NUM_ARGS(), 1, &extra, "s", &signal)) {
|
|
return;
|
|
}
|
|
|
|
obj = PHPG_GOBJECT(this_ptr);
|
|
if (!g_signal_parse_name(signal, G_OBJECT_TYPE(obj), &signal_id, &detail, TRUE)) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown signal name '%s'", signal);
|
|
if (extra) zval_ptr_dtor(&extra);
|
|
return;
|
|
}
|
|
|
|
g_signal_query(signal_id, &query);
|
|
if (extra && zend_hash_num_elements(Z_ARRVAL_P(extra)) != (int)query.n_params) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%d parameters needed for signal '%s', %d given", query.n_params, signal, zend_hash_num_elements(Z_ARRVAL_P(extra)));
|
|
zval_ptr_dtor(&extra);
|
|
return;
|
|
}
|
|
|
|
params = ecalloc(query.n_params+1, sizeof(GValue));
|
|
g_value_init(¶ms[0], G_OBJECT_TYPE(obj));
|
|
g_value_set_object(¶ms[0], G_OBJECT(obj));
|
|
i = 1;
|
|
|
|
if (extra) {
|
|
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(extra));
|
|
zend_hash_get_current_data(Z_ARRVAL_P(extra), (void**) &item) == SUCCESS;
|
|
zend_hash_move_forward(Z_ARRVAL_P(extra)), i++)
|
|
{
|
|
g_value_init(¶ms[i], query.param_types[i-1] & ~G_SIGNAL_TYPE_STATIC_SCOPE);
|
|
|
|
if (phpg_gvalue_from_zval(¶ms[i], item, TRUE TSRMLS_CC) == FAILURE) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
|
"could not convert value to %s for parameter %d",
|
|
g_type_name(G_VALUE_TYPE(¶ms[i])), i);
|
|
goto cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (query.return_type != G_TYPE_NONE) {
|
|
g_value_init(&ret, query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
|
|
}
|
|
|
|
g_signal_emitv(params, signal_id, detail, &ret);
|
|
|
|
if ((query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE) != G_TYPE_NONE) {
|
|
phpg_gvalue_to_zval(&ret, &return_value, TRUE, TRUE TSRMLS_CC);
|
|
g_value_unset(&ret);
|
|
}
|
|
|
|
cleanup:
|
|
for (--i ; i >= 0; i--) {
|
|
g_value_unset(¶ms[i]);
|
|
}
|
|
efree(params);
|
|
if (extra) {
|
|
zval_ptr_dtor(&extra);
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ GObject::signal_list_ids/names */
|
|
static void phpg_signal_list_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool list_names)
|
|
{
|
|
zval *php_type;
|
|
GType type;
|
|
gpointer *klass;
|
|
guint *ids, i, n;
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "V", &php_type))
|
|
return;
|
|
|
|
type = phpg_gtype_from_zval(php_type TSRMLS_CC);
|
|
if (!type)
|
|
return;
|
|
|
|
if (!G_TYPE_IS_INSTANTIATABLE(type) && !G_TYPE_IS_INTERFACE(type)) {
|
|
php_error(E_WARNING, "%s::%s() requires the type to be instantiable or an interface", get_active_class_name(NULL TSRMLS_CC), get_active_function_name(TSRMLS_C));
|
|
return;
|
|
}
|
|
|
|
if (G_TYPE_IS_INTERFACE(type)) {
|
|
klass = g_type_default_interface_ref(type);
|
|
} else {
|
|
klass = g_type_class_ref(type);
|
|
}
|
|
if (!klass) {
|
|
php_error(E_WARNING, "%s::%s() could not get a reference to type class", get_active_class_name(NULL TSRMLS_CC), get_active_function_name(TSRMLS_C));
|
|
}
|
|
|
|
ids = g_signal_list_ids(type, &n);
|
|
|
|
array_init(return_value);
|
|
if (list_names) {
|
|
for (i = 0; i < n; i++) {
|
|
add_next_index_string(return_value, (char *)g_signal_name(ids[i]), 1);
|
|
}
|
|
} else {
|
|
for (i = 0; i < n; i++) {
|
|
add_next_index_long(return_value, ids[i]);
|
|
}
|
|
}
|
|
|
|
g_free(ids);
|
|
if (G_TYPE_IS_INTERFACE(type)) {
|
|
g_type_default_interface_unref(klass);
|
|
} else {
|
|
g_type_class_unref(klass);
|
|
}
|
|
}
|
|
|
|
static PHP_METHOD(GObject, signal_list_ids)
|
|
{
|
|
phpg_signal_list_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
|
|
}
|
|
|
|
static PHP_METHOD(GObject, signal_list_names)
|
|
{
|
|
phpg_signal_list_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ GObject::signal_query */
|
|
static PHP_METHOD(GObject, signal_query)
|
|
{
|
|
zval *php_type, *temp, *params;
|
|
GType gtype;
|
|
gpointer *klass = NULL;
|
|
GSignalQuery query;
|
|
char *signal_name = NULL;
|
|
guint signal_id = 0, i;
|
|
|
|
if (!php_gtk_parse_args_quiet(ZEND_NUM_ARGS(), "iV", &signal_id, &php_type) &&
|
|
!php_gtk_parse_args_quiet(ZEND_NUM_ARGS(), "sV", &signal_name, &php_type)) {
|
|
php_error(E_WARNING, "%s::%s() requires the arguments to be either a valid signal_id or a signal name, followed by the object type", get_active_class_name(NULL TSRMLS_CC), get_active_function_name(TSRMLS_C));
|
|
return;
|
|
}
|
|
|
|
gtype = phpg_gtype_from_zval(php_type TSRMLS_CC);
|
|
if (!gtype)
|
|
return;
|
|
|
|
if (!G_TYPE_IS_INSTANTIATABLE(gtype) && !G_TYPE_IS_INTERFACE(gtype)) {
|
|
php_error(E_WARNING, "%s::%s() requires the type to be instantiable or an interface", get_active_class_name(NULL TSRMLS_CC), get_active_function_name(TSRMLS_C));
|
|
return;
|
|
}
|
|
|
|
if (G_TYPE_IS_INTERFACE(gtype)) {
|
|
klass = g_type_default_interface_ref(gtype);
|
|
} else {
|
|
klass = g_type_class_ref(gtype);
|
|
}
|
|
if (!klass) {
|
|
php_error(E_WARNING, "%s::%s() could not get a reference to type class", get_active_class_name(NULL TSRMLS_CC), get_active_function_name(TSRMLS_C));
|
|
return;
|
|
}
|
|
|
|
if (signal_name) {
|
|
signal_id = g_signal_lookup(signal_name, gtype);
|
|
}
|
|
|
|
g_signal_query(signal_id, &query);
|
|
|
|
if (query.signal_id == 0) {
|
|
goto signal_query_done;
|
|
}
|
|
|
|
array_init(return_value);
|
|
|
|
add_next_index_long(return_value, query.signal_id);
|
|
add_next_index_string(return_value, (char *)query.signal_name, 1);
|
|
MAKE_STD_ZVAL(temp);
|
|
phpg_gtype_new(temp, query.itype TSRMLS_CC);
|
|
add_next_index_zval(return_value, temp);
|
|
add_next_index_long(return_value, query.signal_flags);
|
|
MAKE_STD_ZVAL(temp);
|
|
phpg_gtype_new(temp, query.return_type TSRMLS_CC);
|
|
add_next_index_zval(return_value, temp);
|
|
MAKE_STD_ZVAL(params);
|
|
array_init(params);
|
|
for (i = 0; i < query.n_params; i++) {
|
|
MAKE_STD_ZVAL(temp);
|
|
phpg_gtype_new(temp, query.param_types[i] TSRMLS_CC);
|
|
add_next_index_zval(params, temp);
|
|
}
|
|
add_next_index_zval(return_value, params);
|
|
|
|
signal_query_done:
|
|
if (G_TYPE_IS_INTERFACE(gtype)) {
|
|
g_type_default_interface_unref(klass);
|
|
} else {
|
|
g_type_class_unref(klass);
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
static PHP_METHOD(GObject, list_properties)
|
|
{
|
|
GParamSpec **specs;
|
|
guint n_specs;
|
|
zval *php_type;
|
|
GType type;
|
|
GObjectClass *oclass;
|
|
guint i;
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "V", &php_type)) {
|
|
return;
|
|
}
|
|
|
|
if ((type = phpg_gtype_from_zval(php_type TSRMLS_CC)) == 0) {
|
|
return;
|
|
}
|
|
|
|
if (!g_type_is_a(type, G_TYPE_OBJECT)) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "type must be derived from GObject");
|
|
return;
|
|
}
|
|
|
|
oclass = g_type_class_ref(type);
|
|
if (!oclass) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "couuld not get a reference to type class");
|
|
return;
|
|
}
|
|
|
|
specs = g_object_class_list_properties(oclass, &n_specs);
|
|
array_init(return_value);
|
|
for (i = 0; i < n_specs; i++) {
|
|
zval *item = NULL;
|
|
phpg_paramspec_new(&item, specs[i] TSRMLS_CC);
|
|
add_next_index_zval(return_value, item);
|
|
}
|
|
|
|
g_free(specs);
|
|
g_type_class_unref(oclass);
|
|
}
|
|
|
|
/* {{{ GObject::register_type */
|
|
|
|
static void phpg_object_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
|
|
{
|
|
zval *php_object = NULL;
|
|
zval *php_pspec = NULL;
|
|
zval *retval = NULL;
|
|
|
|
#ifdef ZTS
|
|
TSRMLS_D = g_object_get_qdata(object, gobject_wrapper_zts_key);
|
|
#endif
|
|
|
|
phpg_gobject_new(&php_object, object TSRMLS_CC);
|
|
phpg_paramspec_new(&php_pspec, pspec TSRMLS_CC);
|
|
|
|
zend_call_method_with_1_params(&php_object, Z_OBJCE_P(php_object), NULL, "__get_gproperty", &retval, php_pspec);
|
|
SEPARATE_ZVAL(&retval);
|
|
|
|
if (retval) {
|
|
if (phpg_gvalue_from_zval(value, &retval, TRUE TSRMLS_CC) == FAILURE) {
|
|
php_error(E_WARNING, "phpg_object_get_property: could not convert PHP value to GValue");
|
|
}
|
|
zval_ptr_dtor(&retval);
|
|
} else {
|
|
php_error(E_WARNING, "phpg_object_get_property: error invoking do_get_property");
|
|
}
|
|
zval_ptr_dtor(&php_object);
|
|
zval_ptr_dtor(&php_pspec);
|
|
}
|
|
|
|
static void phpg_object_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
|
{
|
|
zval *php_object = NULL;
|
|
zval *php_pspec = NULL;
|
|
zval *php_value = NULL;
|
|
zval *retval = NULL;
|
|
|
|
#ifdef ZTS
|
|
TSRMLS_D = g_object_get_qdata(object, gobject_wrapper_zts_key);
|
|
#endif
|
|
|
|
if (phpg_gvalue_to_zval(value, &php_value, TRUE, TRUE TSRMLS_CC) == FAILURE) {
|
|
php_error(E_WARNING, "phpg_object_set_property: could not convert GValue to PHP value");
|
|
zval_ptr_dtor(&php_value);
|
|
return;
|
|
}
|
|
|
|
phpg_gobject_new(&php_object, object TSRMLS_CC);
|
|
phpg_paramspec_new(&php_pspec, pspec TSRMLS_CC);
|
|
|
|
zend_call_method_with_2_params(&php_object, Z_OBJCE_P(php_object), NULL, "__set_gproperty", &retval, php_pspec, php_value);
|
|
|
|
if (retval) {
|
|
zval_ptr_dtor(&retval);
|
|
}
|
|
zval_ptr_dtor(&php_object);
|
|
zval_ptr_dtor(&php_pspec);
|
|
zval_ptr_dtor(&php_value);
|
|
}
|
|
|
|
static void phpg_object_class_init(GObjectClass *class, zend_class_entry *ce)
|
|
{
|
|
class->get_property = phpg_object_get_property;
|
|
class->set_property = phpg_object_set_property;
|
|
}
|
|
|
|
static GParamSpec* phpg_create_property(const char *prop_name, GType prop_type, const char *nick, const char *blurb, zval *type_args, GParamFlags flags TSRMLS_DC)
|
|
{
|
|
GParamSpec *pspec = NULL;
|
|
|
|
switch (G_TYPE_FUNDAMENTAL(prop_type)) {
|
|
case G_TYPE_CHAR:
|
|
{
|
|
gchar minimum, maximum, default_val;
|
|
if (!php_gtk_parse_args_hash(type_args, "ccc", &minimum, &maximum, &default_val)) {
|
|
return NULL;
|
|
}
|
|
pspec = g_param_spec_char(prop_name, nick, blurb, minimum, maximum, default_val, flags);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_UCHAR:
|
|
{
|
|
gchar minimum, maximum, default_val;
|
|
if (!php_gtk_parse_args_hash(type_args, "ccc", &minimum, &maximum, &default_val)) {
|
|
return NULL;
|
|
}
|
|
pspec = g_param_spec_uchar(prop_name, nick, blurb, minimum, maximum, default_val, flags);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_BOOLEAN:
|
|
{
|
|
zend_bool default_val;
|
|
if (!php_gtk_parse_args_hash(type_args, "b", &default_val)) {
|
|
return NULL;
|
|
}
|
|
pspec = g_param_spec_boolean(prop_name, nick, blurb, (gboolean)default_val, flags);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_INT:
|
|
{
|
|
int minimum, maximum, default_val;
|
|
if (!php_gtk_parse_args_hash(type_args, "iii", &minimum, &maximum, &default_val)) {
|
|
return NULL;
|
|
}
|
|
pspec = g_param_spec_int(prop_name, nick, blurb, (gint)minimum, (gint)maximum, (gint)default_val, flags);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_UINT:
|
|
{
|
|
int minimum, maximum, default_val;
|
|
if (!php_gtk_parse_args_hash(type_args, "iii", &minimum, &maximum, &default_val)) {
|
|
return NULL;
|
|
}
|
|
pspec = g_param_spec_uint(prop_name, nick, blurb, (guint)minimum, (guint)maximum, (guint)default_val, flags);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_LONG:
|
|
{
|
|
long minimum, maximum, default_val;
|
|
if (!php_gtk_parse_args_hash(type_args, "lll", &minimum, &maximum, &default_val)) {
|
|
return NULL;
|
|
}
|
|
pspec = g_param_spec_long(prop_name, nick, blurb, (glong)minimum, (glong)maximum, (glong)default_val, flags);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_ULONG:
|
|
{
|
|
long minimum, maximum, default_val;
|
|
if (!php_gtk_parse_args_hash(type_args, "lll", &minimum, &maximum, &default_val)) {
|
|
return NULL;
|
|
}
|
|
pspec = g_param_spec_ulong(prop_name, nick, blurb, (gulong)minimum, (gulong)maximum, (gulong)default_val, flags);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_ENUM:
|
|
{
|
|
long default_val;
|
|
if (!php_gtk_parse_args_hash(type_args, "l", &default_val)) {
|
|
return NULL;
|
|
}
|
|
pspec = g_param_spec_enum(prop_name, nick, blurb, prop_type, default_val, flags);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_FLAGS:
|
|
{
|
|
long default_val;
|
|
if (!php_gtk_parse_args_hash(type_args, "l", &default_val)) {
|
|
return NULL;
|
|
}
|
|
pspec = g_param_spec_flags(prop_name, nick, blurb, prop_type, default_val, flags);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_FLOAT:
|
|
{
|
|
double minimum, maximum, default_val;
|
|
if (!php_gtk_parse_args_hash(type_args, "ddd", &minimum, &maximum, &default_val)) {
|
|
return NULL;
|
|
}
|
|
pspec = g_param_spec_float(prop_name, nick, blurb, (float)minimum,
|
|
(float)maximum, (float)default_val, flags);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_DOUBLE:
|
|
{
|
|
double minimum, maximum, default_val;
|
|
if (!php_gtk_parse_args_hash(type_args, "ddd", &minimum, &maximum, &default_val)) {
|
|
return NULL;
|
|
}
|
|
pspec = g_param_spec_double(prop_name, nick, blurb, minimum, maximum, default_val, flags);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_STRING:
|
|
{
|
|
char *default_val;
|
|
zend_bool free_default_val = FALSE;
|
|
|
|
if (!php_gtk_parse_args_hash(type_args, "u", &default_val, &free_default_val)) {
|
|
return NULL;
|
|
}
|
|
pspec = g_param_spec_string(prop_name, nick, blurb, default_val, flags);
|
|
if (free_default_val) g_free(default_val);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_PARAM:
|
|
{
|
|
pspec = g_param_spec_param(prop_name, nick, blurb, prop_type, flags);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_BOXED:
|
|
{
|
|
pspec = g_param_spec_boxed(prop_name, nick, blurb, prop_type, flags);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_POINTER:
|
|
{
|
|
pspec = g_param_spec_pointer(prop_name, nick, blurb, flags);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_OBJECT:
|
|
{
|
|
pspec = g_param_spec_object(prop_name, nick, blurb, prop_type, flags);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
/* unhandled pspec type */
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not create param spec for type '%s'", g_type_name(prop_type));
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return pspec;
|
|
}
|
|
|
|
static int phpg_register_properties(GType type, zval *properties TSRMLS_DC)
|
|
{
|
|
GObjectClass *oclass;
|
|
GParamFlags flags;
|
|
GParamSpec *pspec;
|
|
GType prop_type;
|
|
char *str_key;
|
|
const char *nick, *blurb;
|
|
int data_len;
|
|
int retval = SUCCESS;
|
|
uint str_key_len;
|
|
ulong num_key;
|
|
zval **data;
|
|
zval *type_args = NULL;
|
|
zval *php_prop_type;
|
|
|
|
oclass = g_type_class_ref(type);
|
|
if (!oclass) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "couuld not get a reference to type class");
|
|
return FAILURE;
|
|
}
|
|
|
|
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(properties));
|
|
zend_hash_get_current_data(Z_ARRVAL_P(properties), (void**)&data) == SUCCESS;
|
|
zend_hash_move_forward(Z_ARRVAL_P(properties))) {
|
|
|
|
if (zend_hash_get_current_key_ex(Z_ARRVAL_P(properties), &str_key, &str_key_len,
|
|
&num_key, 0, NULL) != HASH_KEY_IS_STRING) {
|
|
continue;
|
|
}
|
|
|
|
if (Z_TYPE_PP(data) != IS_ARRAY) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "property specs have to be arrays");
|
|
retval = FAILURE;
|
|
break;
|
|
}
|
|
|
|
if ((data_len = zend_hash_num_elements(Z_ARRVAL_PP(data))) < 4) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "property specs must have at least 4 elements");
|
|
retval = FAILURE;
|
|
break;
|
|
}
|
|
|
|
if (!php_gtk_parse_varargs_hash(*data, 4, &type_args, "Vssi", &php_prop_type, &nick, &blurb, &flags)) {
|
|
retval = FAILURE;
|
|
break;
|
|
}
|
|
|
|
prop_type = phpg_gtype_from_zval(php_prop_type TSRMLS_CC);
|
|
if (prop_type == 0) {
|
|
retval = FAILURE;
|
|
break;
|
|
}
|
|
if (type_args == NULL &&
|
|
(prop_type != G_TYPE_PARAM &&
|
|
prop_type != G_TYPE_BOXED &&
|
|
prop_type != G_TYPE_POINTER &&
|
|
prop_type != G_TYPE_OBJECT)) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "property specs require type-specific args");
|
|
retval = FAILURE;
|
|
break;
|
|
}
|
|
|
|
pspec = phpg_create_property(str_key, prop_type, nick, blurb, type_args, flags TSRMLS_CC);
|
|
if (pspec) {
|
|
g_object_class_install_property(oclass, 1, pspec);
|
|
} else {
|
|
retval = FAILURE;
|
|
break;
|
|
}
|
|
|
|
if (type_args) {
|
|
zval_ptr_dtor(&type_args);
|
|
}
|
|
}
|
|
|
|
if (type_args) {
|
|
zval_ptr_dtor(&type_args);
|
|
}
|
|
g_type_class_unref(oclass);
|
|
return retval;
|
|
}
|
|
|
|
static int phpg_override_signal(GType type, const char *signal_name TSRMLS_DC)
|
|
{
|
|
guint signal_id;
|
|
|
|
signal_id = g_signal_lookup(signal_name, type);
|
|
if (!signal_id) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not find signal '%s'", signal_name);
|
|
return FAILURE;
|
|
}
|
|
|
|
g_signal_override_class_closure(signal_id, type, phpg_get_signal_class_closure(TSRMLS_C));
|
|
return SUCCESS;
|
|
}
|
|
|
|
static int phpg_create_signal(GType type, const char *signal_name, zval *data TSRMLS_DC)
|
|
{
|
|
long signal_flags;
|
|
zval *php_return_type;
|
|
zval *php_param_types;
|
|
GType return_type;
|
|
GType *param_types;
|
|
guint n_params, i, signal_id;
|
|
zval **item;
|
|
|
|
if (!php_gtk_parse_args_hash(data, "lVa", &signal_flags, &php_return_type, &php_param_types)) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "incorrect format for '%s' signal spec", signal_name);
|
|
return FAILURE;
|
|
}
|
|
|
|
return_type = phpg_gtype_from_zval(php_return_type TSRMLS_CC);
|
|
if (0 == return_type) {
|
|
return FAILURE;
|
|
}
|
|
|
|
n_params = zend_hash_num_elements(Z_ARRVAL_P(php_param_types));
|
|
param_types = safe_emalloc(n_params, sizeof(GType), 0);
|
|
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(php_param_types)), i = 0;
|
|
zend_hash_get_current_data(Z_ARRVAL_P(php_param_types), (void**)&item) == SUCCESS;
|
|
zend_hash_move_forward(Z_ARRVAL_P(php_param_types)), i++) {
|
|
|
|
param_types[i] = phpg_gtype_from_zval(*item TSRMLS_CC);
|
|
if (0 == param_types[i]) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not get type of param #%d gor signal '%s'", i+1, signal_name);
|
|
efree(param_types);
|
|
return FAILURE;
|
|
}
|
|
}
|
|
|
|
signal_id = g_signal_newv(signal_name, type, signal_flags, phpg_get_signal_class_closure(TSRMLS_C),
|
|
(GSignalAccumulator)0, NULL, (GSignalCMarshaller)0,
|
|
return_type, n_params, param_types);
|
|
efree(param_types);
|
|
|
|
if (0 == signal_id) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not create signal '%s'", signal_name);
|
|
return FAILURE;
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
static int phpg_register_signals(GType type, zval *signals TSRMLS_DC)
|
|
{
|
|
GObjectClass *oclass;
|
|
zval **data;
|
|
char *str_key;
|
|
uint str_key_len;
|
|
ulong num_key;
|
|
int retval = SUCCESS;
|
|
|
|
oclass = g_type_class_ref(type);
|
|
if (!oclass) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "couuld not get a reference to type class");
|
|
return FAILURE;
|
|
}
|
|
|
|
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(signals));
|
|
zend_hash_get_current_data(Z_ARRVAL_P(signals), (void**)&data) == SUCCESS;
|
|
zend_hash_move_forward(Z_ARRVAL_P(signals))) {
|
|
|
|
if (zend_hash_get_current_key_ex(Z_ARRVAL_P(signals), &str_key, &str_key_len,
|
|
&num_key, 0, NULL) != HASH_KEY_IS_STRING) {
|
|
continue;
|
|
}
|
|
|
|
if (Z_TYPE_PP(data) == IS_NULL ||
|
|
(Z_TYPE_PP(data) == IS_STRING &&
|
|
!strcmp(Z_STRVAL_PP(data), "override"))) {
|
|
retval = phpg_override_signal(type, str_key TSRMLS_CC);
|
|
} else {
|
|
retval = phpg_create_signal(type, str_key, *data TSRMLS_CC);
|
|
}
|
|
|
|
if (retval == FAILURE) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
g_type_class_unref(oclass);
|
|
return retval;
|
|
}
|
|
|
|
static PHP_METHOD(GObject, register_type)
|
|
{
|
|
zend_class_entry *ce = gobject_ce;
|
|
GType parent_type, new_type;
|
|
GTypeQuery query;
|
|
gchar *type_name;
|
|
gchar **split_name;
|
|
int free_name = 0;
|
|
|
|
#if PHP_VERSION_ID < 50399
|
|
zval **prop_decls, **signal_decls;
|
|
#else
|
|
zval *property = NULL;
|
|
zend_property_info *property_info_ptr;
|
|
ulong h_signals = zend_get_hash_value("__gsignals", sizeof("__gsignals"));
|
|
ulong h_properties = zend_get_hash_value("__gproperties", sizeof("__gproperties"));
|
|
#endif
|
|
|
|
GTypeInfo type_info = {
|
|
0, /* class_size */
|
|
|
|
(GBaseInitFunc) NULL,
|
|
(GBaseFinalizeFunc) NULL,
|
|
|
|
(GClassInitFunc) phpg_object_class_init,
|
|
(GClassFinalizeFunc) NULL,
|
|
NULL, /* class_data */
|
|
|
|
0, /* instance_size */
|
|
0, /* n_preallocs */
|
|
(GInstanceInitFunc) NULL
|
|
};
|
|
|
|
if (!php_gtk_parse_args(ZEND_NUM_ARGS(), "C", &ce)) {
|
|
return;
|
|
}
|
|
|
|
parent_type = phpg_gtype_from_class(ce TSRMLS_CC);
|
|
|
|
if (!parent_type) {
|
|
return;
|
|
}
|
|
|
|
type_name = ce->name;
|
|
|
|
/* If this is a namespaced class we will have issues
|
|
since \ is not allowed, so copy and replace \ with _ */
|
|
if ((split_name = g_strsplit(ce->name, "\\", 0))) {
|
|
free_name = 1;
|
|
type_name = g_strjoinv("__", split_name);
|
|
g_strfreev(split_name);
|
|
}
|
|
|
|
if (g_type_from_name(type_name) != 0) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "type '%s' already exists?", type_name);
|
|
|
|
if (free_name) {
|
|
g_free(type_name);
|
|
}
|
|
return;
|
|
}
|
|
|
|
type_info.class_data = ce;
|
|
g_type_query(parent_type, &query);
|
|
type_info.class_size = query.class_size;
|
|
type_info.instance_size = query.instance_size;
|
|
|
|
new_type = g_type_register_static(parent_type, type_name, &type_info, 0);
|
|
if (new_type == 0) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not create new GType");
|
|
|
|
if (free_name) {
|
|
g_free(type_name);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!phpg_class_key) {
|
|
phpg_class_key = g_quark_from_static_string(phpg_class_id);
|
|
}
|
|
|
|
g_type_set_qdata(new_type, phpg_class_key, ce);
|
|
zend_declare_class_constant_long(ce, "gtype", sizeof("gtype")-1, new_type TSRMLS_CC);
|
|
|
|
zend_update_class_constants(ce TSRMLS_CC);
|
|
|
|
#if PHP_VERSION_ID < 50399
|
|
/* register properties */
|
|
if (zend_hash_find(&ce->default_properties, "__gproperties", sizeof("__gproperties"), (void**)&prop_decls) == SUCCESS) {
|
|
if (Z_TYPE_PP(prop_decls) != IS_ARRAY) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "__gproperties variable has to be an array");
|
|
if (free_name) {
|
|
g_free(type_name);
|
|
}
|
|
return;
|
|
}
|
|
if (phpg_register_properties(new_type, *prop_decls TSRMLS_CC) == FAILURE) {
|
|
if (free_name) {
|
|
g_free(type_name);
|
|
}
|
|
return;
|
|
}
|
|
zend_hash_del(&ce->default_properties, "__gproperties", sizeof("__gproperties"));
|
|
}
|
|
|
|
/* register signals */
|
|
if (zend_hash_find(&ce->default_properties, "__gsignals", sizeof("__gsignals"), (void**)&signal_decls) == SUCCESS) {
|
|
if (Z_TYPE_PP(signal_decls) != IS_ARRAY) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "__gsignals variable has to be an array");
|
|
if (free_name) {
|
|
g_free(type_name);
|
|
}
|
|
return;
|
|
}
|
|
if (phpg_register_signals(new_type, *signal_decls TSRMLS_CC) == FAILURE) {
|
|
if (free_name) {
|
|
g_free(type_name);
|
|
}
|
|
return;
|
|
}
|
|
zend_hash_del(&ce->default_properties, "__gsignals", sizeof("__gsignals"));
|
|
}
|
|
#else
|
|
/* This is horribly painful in 5.4 */
|
|
|
|
if (zend_hash_quick_find(&ce->properties_info, "__gproperties", sizeof("__gproperties"),
|
|
h_properties, (void**)&property_info_ptr) == SUCCESS &&
|
|
(property_info_ptr->flags & ZEND_ACC_STATIC) == 0) {
|
|
|
|
property = ce->default_properties_table[property_info_ptr->offset];
|
|
if (Z_TYPE_P(property) != IS_ARRAY) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "__gproperties variable has to be an array");
|
|
if (free_name) {
|
|
g_free(type_name);
|
|
}
|
|
return;
|
|
}
|
|
if (phpg_register_properties(new_type, property TSRMLS_CC) == FAILURE) {
|
|
if (free_name) {
|
|
g_free(type_name);
|
|
}
|
|
return;
|
|
}
|
|
|
|
zend_hash_quick_del(&ce->properties_info, "__gproperties",
|
|
sizeof("__gproperties"), h_properties);
|
|
}
|
|
|
|
if (zend_hash_quick_find(&ce->properties_info, "__gsignals", sizeof("__gsignals"),
|
|
h_signals, (void**)&property_info_ptr) == SUCCESS &&
|
|
(property_info_ptr->flags & ZEND_ACC_STATIC) == 0) {
|
|
|
|
property = ce->default_properties_table[property_info_ptr->offset];
|
|
if (Z_TYPE_P(property) != IS_ARRAY) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "__gsignals variable has to be an array");
|
|
if (free_name) {
|
|
g_free(type_name);
|
|
}
|
|
return;
|
|
}
|
|
if (phpg_register_signals(new_type, property TSRMLS_CC) == FAILURE) {
|
|
if (free_name) {
|
|
g_free(type_name);
|
|
}
|
|
return;
|
|
}
|
|
|
|
zend_hash_quick_del(&ce->properties_info, "__gsignals",
|
|
sizeof("__gsignals"), h_signals);
|
|
}
|
|
#endif
|
|
if (free_name) {
|
|
g_free(type_name);
|
|
}
|
|
|
|
/*TODO interface registration */
|
|
#if 0
|
|
if (class->num_interfaces > 0) {
|
|
int i;
|
|
GType itype;
|
|
zend_classs_entry *iface;
|
|
const GInterfaceInfo *iinfo;
|
|
|
|
for (i = 0; i < class->num_interfaces; i++) {
|
|
|
|
/* TODO might have to create GInterface type and check if interface class
|
|
* inherits from it
|
|
*/
|
|
itype = phpg_gtype_from_class(class->interfaces[i]);
|
|
/* TODO get interface info */
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* run class init */
|
|
/* TODO virtual method stuff */
|
|
|
|
RETURN_TRUE;
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ GObject reflection info */
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO(arginfo_gobject_block, 0)
|
|
ZEND_ARG_INFO(0, handler_id)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_gobject_connect, 0, 0, 2)
|
|
ZEND_ARG_INFO(0, signal)
|
|
ZEND_ARG_INFO(0, callback)
|
|
ZEND_ARG_INFO(0, userparam)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_gobject_connect_after, 0, 0, 2)
|
|
ZEND_ARG_INFO(0, signal)
|
|
ZEND_ARG_INFO(0, callback)
|
|
ZEND_ARG_INFO(0, userparam)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_gobject_connect_simple, 0, 0, 2)
|
|
ZEND_ARG_INFO(0, signal)
|
|
ZEND_ARG_INFO(0, callback)
|
|
ZEND_ARG_INFO(0, userparam)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_gobject_connect_simple_after, 0, 0, 2)
|
|
ZEND_ARG_INFO(0, signal)
|
|
ZEND_ARG_INFO(0, callback)
|
|
ZEND_ARG_INFO(0, userparam)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_gobject_connect_object, 0, 0, 2)
|
|
ZEND_ARG_INFO(0, signal)
|
|
ZEND_ARG_INFO(0, callback)
|
|
ZEND_ARG_INFO(0, userparam)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_gobject_connect_object_after, 0, 0, 2)
|
|
ZEND_ARG_INFO(0, signal)
|
|
ZEND_ARG_INFO(0, callback)
|
|
ZEND_ARG_INFO(0, userparam)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO(arginfo_gobject_disconnect, 0)
|
|
ZEND_ARG_INFO(0, handler_id)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO(arginfo_gobject_notify, 0)
|
|
ZEND_ARG_INFO(0, property_name)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO(arginfo_gobject_get_property, 0)
|
|
ZEND_ARG_INFO(0, property_name)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO(arginfo_gobject_set_property, 0)
|
|
ZEND_ARG_INFO(0, property_name)
|
|
ZEND_ARG_INFO(0, value)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO(arginfo_gobject_get_data, 0)
|
|
ZEND_ARG_INFO(0, key)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO(arginfo_gobject_is_connected, 0)
|
|
ZEND_ARG_INFO(0, handler_id)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO(arginfo_gobject_set_data, 0)
|
|
ZEND_ARG_INFO(0, key)
|
|
ZEND_ARG_INFO(0, value)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO(arginfo_gobject_signal_list_ids, 0)
|
|
ZEND_ARG_INFO(0, gtype)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO(arginfo_gobject_signal_list_names, 0)
|
|
ZEND_ARG_INFO(0, gtype)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO(arginfo_gobject_signal_query, 0)
|
|
ZEND_ARG_INFO(0, signal)
|
|
ZEND_ARG_INFO(0, gtype)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO(arginfo_gobject_unblock, 0)
|
|
ZEND_ARG_INFO(0, handler_id)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO(arginfo_gobject_list_properties, 0)
|
|
ZEND_ARG_INFO(0, gtype)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO(arginfo_gobject_stop_emission, 0)
|
|
ZEND_ARG_INFO(0, signal)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
PHPGTK_ARG_INFO_STATIC
|
|
ZEND_BEGIN_ARG_INFO(arginfo_gobject_register_type, 0)
|
|
ZEND_ARG_INFO(0, class)
|
|
ZEND_END_ARG_INFO();
|
|
|
|
/* }}} */
|
|
|
|
static zend_function_entry gobject_methods[] = {
|
|
PHP_ME(GObject, __construct, NULL , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, __tostring, NULL , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, connect, arginfo_gobject_connect , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, connect_after, arginfo_gobject_connect_after , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, connect_object, arginfo_gobject_connect_object , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, connect_object_after, arginfo_gobject_connect_object_after , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, connect_simple, arginfo_gobject_connect_simple , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, connect_simple_after, arginfo_gobject_connect_simple_after , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, notify, arginfo_gobject_notify , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, freeze_notify, NULL , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, thaw_notify, NULL , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, get_property, arginfo_gobject_get_property , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, set_property, arginfo_gobject_set_property , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, get_data, arginfo_gobject_get_data , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, set_data, arginfo_gobject_set_data , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, emit, NULL , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, block, arginfo_gobject_block , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, unblock, arginfo_gobject_unblock , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, disconnect, arginfo_gobject_disconnect , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, is_connected, arginfo_gobject_is_connected , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, signal_query, arginfo_gobject_signal_query , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
|
PHP_ME(GObject, stop_emission, arginfo_gobject_stop_emission , ZEND_ACC_PUBLIC)
|
|
PHP_ME(GObject, register_type, arginfo_gobject_register_type , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
|
PHP_ME(GObject, list_properties, arginfo_gobject_list_properties , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
|
PHP_ME(GObject, signal_list_ids, arginfo_gobject_signal_list_ids , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
|
PHP_ME(GObject, signal_list_names, arginfo_gobject_signal_list_names , ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
|
PHP_MALIAS(GObject, emit_stop_by_name, stop_emission, arginfo_gobject_stop_emission, ZEND_ACC_PUBLIC)
|
|
{NULL, NULL, NULL}
|
|
};
|
|
|
|
|
|
PHPG_PROP_READER(GObject, gtype)
|
|
{
|
|
if (((phpg_gobject_t *)object)->obj == NULL) {
|
|
return FAILURE;
|
|
}
|
|
|
|
ZVAL_LONG(return_value, G_OBJECT_TYPE(((phpg_gobject_t *)object)->obj));
|
|
return SUCCESS;
|
|
}
|
|
|
|
static prop_info_t gobject_props_info[] = {
|
|
{ "gtype", PHPG_PROP_READ_FN(GObject, gtype), NULL },
|
|
{ NULL, NULL, NULL },
|
|
};
|
|
|
|
|
|
void phpg_gobject_register_self(TSRMLS_D)
|
|
{
|
|
if (gobject_ce) return;
|
|
|
|
gobject_wrapper_handle_key = g_quark_from_static_string("phpg-wrapper-handle");
|
|
gobject_wrapper_handlers_key = g_quark_from_static_string("phpg-wrapper-handlers");
|
|
gobject_wrapper_owned_key = g_quark_from_static_string("phpg-wrapper-owned");
|
|
#ifdef ZTS
|
|
gobject_wrapper_zts_key = g_quark_from_static_string("phpg-wrapper-zts");
|
|
#endif
|
|
|
|
phpg_gobject_handlers = php_gtk_handlers;
|
|
phpg_gobject_handlers.del_ref = phpg_gobject_del_ref;
|
|
|
|
gobject_ce = phpg_register_class("GObject", gobject_methods, NULL, 0, gobject_props_info, NULL, G_TYPE_OBJECT TSRMLS_CC);
|
|
phpg_register_int_constant(gobject_ce, "gtype", sizeof("gtype")-1, G_TYPE_OBJECT);
|
|
|
|
/* Fundamental GTypes */
|
|
phpg_register_int_constant(gobject_ce, "TYPE_INVALID", sizeof("TYPE_INVALID")-1, G_TYPE_INVALID);
|
|
phpg_register_int_constant(gobject_ce, "TYPE_NONE", sizeof("TYPE_NONE")-1, G_TYPE_NONE);
|
|
phpg_register_int_constant(gobject_ce, "TYPE_INTERFACE", sizeof("TYPE_INTERFACE")-1, G_TYPE_INTERFACE);
|
|
phpg_register_int_constant(gobject_ce, "TYPE_CHAR", sizeof("TYPE_CHAR")-1, G_TYPE_CHAR);
|
|
phpg_register_int_constant(gobject_ce, "TYPE_BOOLEAN", sizeof("TYPE_BOOLEAN")-1, G_TYPE_BOOLEAN);
|
|
phpg_register_int_constant(gobject_ce, "TYPE_LONG", sizeof("TYPE_LONG")-1, G_TYPE_LONG);
|
|
phpg_register_int_constant(gobject_ce, "TYPE_ENUM", sizeof("TYPE_ENUM")-1, G_TYPE_ENUM);
|
|
phpg_register_int_constant(gobject_ce, "TYPE_FLAGS", sizeof("TYPE_FLAGS")-1, G_TYPE_FLAGS);
|
|
phpg_register_int_constant(gobject_ce, "TYPE_DOUBLE", sizeof("TYPE_DOUBLE")-1, G_TYPE_DOUBLE);
|
|
phpg_register_int_constant(gobject_ce, "TYPE_STRING", sizeof("TYPE_STRING")-1, G_TYPE_STRING);
|
|
phpg_register_int_constant(gobject_ce, "TYPE_POINTER", sizeof("TYPE_POINTER")-1, G_TYPE_POINTER);
|
|
phpg_register_int_constant(gobject_ce, "TYPE_BOXED", sizeof("TYPE_BOXED")-1, G_TYPE_BOXED);
|
|
phpg_register_int_constant(gobject_ce, "TYPE_PARAM", sizeof("TYPE_PARAM")-1, G_TYPE_PARAM);
|
|
phpg_register_int_constant(gobject_ce, "TYPE_OBJECT", sizeof("TYPE_OBJECT")-1, G_TYPE_OBJECT);
|
|
phpg_register_int_constant(gobject_ce, "TYPE_PHP_VALUE", sizeof("TYPE_PHP_VALUE")-1, G_TYPE_PHP_VALUE);
|
|
|
|
/* Priority Constants */
|
|
phpg_register_int_constant(gobject_ce, "PRIORITY_HIGH", sizeof("PRIORITY_HIGH")-1, G_PRIORITY_HIGH);
|
|
phpg_register_int_constant(gobject_ce, "PRIORITY_DEFAULT", sizeof("PRIORITY_DEFAULT")-1, G_PRIORITY_DEFAULT);
|
|
phpg_register_int_constant(gobject_ce, "PRIORITY_HIGH_IDLE", sizeof("PRIORITY_HIGH_IDLE")-1, G_PRIORITY_HIGH_IDLE);
|
|
phpg_register_int_constant(gobject_ce, "PRIORITY_DEFAULT_IDLE", sizeof("PRIORITY_DEFAULT_IDLE")-1, G_PRIORITY_DEFAULT_IDLE);
|
|
phpg_register_int_constant(gobject_ce, "PRIORITY_LOW", sizeof("PRIORITY_LOW")-1, G_PRIORITY_LOW);
|
|
|
|
/* IO Condition Constants */
|
|
phpg_register_int_constant(gobject_ce, "IO_IN", sizeof("IO_IN")-1, G_IO_IN);
|
|
phpg_register_int_constant(gobject_ce, "IO_OUT", sizeof("IO_OUT")-1, G_IO_OUT);
|
|
phpg_register_int_constant(gobject_ce, "IO_PRI", sizeof("IO_PRI")-1, G_IO_PRI);
|
|
phpg_register_int_constant(gobject_ce, "IO_ERR", sizeof("IO_ERR")-1, G_IO_ERR);
|
|
phpg_register_int_constant(gobject_ce, "IO_HUP", sizeof("IO_HUP")-1, G_IO_HUP);
|
|
phpg_register_int_constant(gobject_ce, "IO_NVAL", sizeof("IO_NVAL")-1, G_IO_NVAL);
|
|
|
|
/* Signal type constants */
|
|
phpg_register_int_constant(gobject_ce, "SIGNAL_RUN_FIRST", sizeof("SIGNAL_RUN_FIRST")-1, G_SIGNAL_RUN_FIRST);
|
|
phpg_register_int_constant(gobject_ce, "SIGNAL_RUN_LAST", sizeof("SIGNAL_RUN_LAST")-1, G_SIGNAL_RUN_LAST);
|
|
phpg_register_int_constant(gobject_ce, "SIGNAL_RUN_CLEANUP", sizeof("SIGNAL_RUN_CLEANUP")-1, G_SIGNAL_RUN_CLEANUP);
|
|
phpg_register_int_constant(gobject_ce, "SIGNAL_NO_RECURSE", sizeof("SIGNAL_NO_RECURSE")-1, G_SIGNAL_NO_RECURSE);
|
|
phpg_register_int_constant(gobject_ce, "SIGNAL_DETAILED", sizeof("SIGNAL_DETAILED")-1, G_SIGNAL_DETAILED);
|
|
phpg_register_int_constant(gobject_ce, "SIGNAL_ACTION", sizeof("SIGNAL_ACTION")-1, G_SIGNAL_ACTION);
|
|
phpg_register_int_constant(gobject_ce, "SIGNAL_NO_HOOKS", sizeof("SIGNAL_NO_HOOKS")-1, G_SIGNAL_NO_HOOKS);
|
|
|
|
/* Paramspec constants */
|
|
phpg_register_int_constant(gobject_ce, "PARAM_READABLE", sizeof("PARAM_READABLE")-1, G_PARAM_READABLE);
|
|
phpg_register_int_constant(gobject_ce, "PARAM_WRITABLE", sizeof("PARAM_WRITABLE")-1, G_PARAM_WRITABLE);
|
|
phpg_register_int_constant(gobject_ce, "PARAM_CONSTRUCT", sizeof("PARAM_CONSTRUCT")-1, G_PARAM_CONSTRUCT);
|
|
phpg_register_int_constant(gobject_ce, "PARAM_CONSTRUCT_ONLY", sizeof("PARAM_CONSTRUCT_ONLY")-1, G_PARAM_CONSTRUCT_ONLY);
|
|
phpg_register_int_constant(gobject_ce, "PARAM_LAX_VALIDATION", sizeof("PARAM_LAX_VALIDATION")-1, G_PARAM_LAX_VALIDATION);
|
|
phpg_register_int_constant(gobject_ce, "PARAM_READWRITE", sizeof("PARAM_READWRITE")-1, G_PARAM_READWRITE);
|
|
}
|
|
|
|
#endif /* HAVE_PHP_GTK */
|
|
|
|
/* vim: set fdm=marker et sts=4: */
|