Mon, 06 Aug 2012 18:11:44 +0200
Merge validation feature for Request API
| README.MTN | file | annotate | diff | comparison | revisions | |
| configure.ac | file | annotate | diff | comparison | revisions |
--- a/COPYRIGHT Mon Aug 06 13:16:32 2012 +0200 +++ b/COPYRIGHT Mon Aug 06 18:11:44 2012 +0200 @@ -15,7 +15,7 @@ piece of code, then that code should be traced through our version control system to see from where it came and who has modified it. -Copyright (C) 1998-2011 by the following: +Copyright (C) 1998-2012 by the following: Saleem Abdulrasool Jakub Adam @@ -40,6 +40,7 @@ Chris Banal Luca Barbato Levi Bard +Mark Barfield Ryan Barrett Kevin Barry Lukas Barth
--- a/ChangeLog Mon Aug 06 13:16:32 2012 +0200 +++ b/ChangeLog Mon Aug 06 18:11:44 2012 +0200 @@ -47,6 +47,14 @@ * The Offline Message Emulation plugin now adds a note that the message was an offline message. (Flavius Anton) (#2497) + MSN: + * Fix a crash when removing a user before its icon is loaded. (Mark + Barfield) (#15217) + + Yahoo!: + * Fix a double-free in profile/picture loading code. (Mihai Serban) + (#15053) + version 2.10.6 (07/06/2012): Pidgin: * Fix a bug that requires a triple-click to open a conversation
--- a/README Mon Aug 06 13:16:32 2012 +0200 +++ b/README Mon Aug 06 18:11:44 2012 +0200 @@ -6,7 +6,7 @@ to write an IM client that connects to many IM networks. It supports AIM, ICQ, XMPP, MSN and Yahoo!, among others. -Pidgin is an graphical IM client written in C which uses the GTK+ +Pidgin is a graphical IM client written in C which uses the GTK+ toolkit. Finch is a text-based IM client written in C which uses the ncurses @@ -43,7 +43,7 @@ To get started, simply add a new account. -If you come across a bug, please report it at: http://pidgin.im +If you come across a bug, please report it at: http://developer.pidgin.im PLUGINS =======
--- a/README.MTN Mon Aug 06 13:16:32 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -If you plan to use Pidgin, Finch and libpurple from our Monotone repository, -PLEASE read this message in its entirety! - -Pidgin, Finch, and libpurple are a fast-moving project with a somewhat regular -release schedule. Due to the rate of development, the code in our Monotone -repository undergoes frequent bursts of massive changes, often leaving behind -brokenness and partial functionality while the responsible developers rewrite -some portion of code or seek to add new features. - -What this all boils down to is that the code in our Monotone repository _WILL_ -sometimes be broken. Because of this, we ask that users who are not interested -in personally tracking down bugs and fixing them (without a lot of -assistance from the developers!) use only released versions. Since releases -will be made often, this should not prevent anyone from using the newest, -shiniest features -- but it will prevent users from having to deal with ugly -development bugs that we already know about but haven't gotten around to fixing. - -If you are interested in hacking on Pidgin, Finch, and/or libpurple, please -check out the information available at: http://developer.pidgin.im - -By far the best documentation, however, is the documented code. If you have -doxygen, you can run "make docs" in the toplevel directory to generate pretty -documentation. Otherwise (or even if you do!), the header files for each -subsystem contain documentation for the functions they contain. For instance, -conversation.h contains documentation for the entire purple_conversation_* -API, and account.h contains documentation for the purple_account_* API. - -If you have questions, please feel free to contact the Pidgin, Finch, and -libpurple developers by email at devel@pidgin.im or on IRC at irc.freenode.net -in #pidgin. Please do as much homework as you can before contacting us; the -more you know about your question, the faster and more effectively we can help! - -Patches should be posted as Trac tickets at: http://developer.pidgin.im
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.hg Mon Aug 06 18:11:44 2012 +0200 @@ -0,0 +1,33 @@ +If you plan to use Pidgin, Finch and libpurple from our Mercurial repository, +PLEASE read this message in its entirety! + +Pidgin, Finch, and libpurple are a fast-moving project with a somewhat regular +release schedule. Due to the rate of development, the code in our Mercurial +repository undergoes frequent bursts of massive changes, often leaving behind +brokenness and partial functionality while the responsible developers rewrite +some portion of code or seek to add new features. + +What this all boils down to is that the code in our Mercurial repository _WILL_ +sometimes be broken. Because of this, we ask that users who are not interested +in personally tracking down bugs and fixing them (without a lot of +assistance from the developers!) use only released versions. Since releases +will be made often, this should not prevent anyone from using the newest, +shiniest features -- but it will prevent users from having to deal with ugly +development bugs that we already know about but haven't gotten around to fixing. + +If you are interested in hacking on Pidgin, Finch, and/or libpurple, please +check out the information available at: http://developer.pidgin.im + +By far the best documentation, however, is the documented code. If you have +doxygen, you can run "make docs" in the toplevel directory to generate pretty +documentation. Otherwise (or even if you do!), the header files for each +subsystem contain documentation for the functions they contain. For instance, +conversation.h contains documentation for the entire purple_conversation_* +API, and account.h contains documentation for the purple_account_* API. + +If you have questions, please feel free to contact the Pidgin, Finch, and +libpurple developers by email at devel@pidgin.im or on IRC at irc.freenode.net +in #pidgin. Please do as much homework as you can before contacting us; the +more you know about your question, the faster and more effectively we can help! + +Patches should be posted as Trac tickets at: http://developer.pidgin.im
--- a/README.mingw Mon Aug 06 13:16:32 2012 +0200 +++ b/README.mingw Mon Aug 06 18:11:44 2012 +0200 @@ -1,5 +1,5 @@ How to build Pidgin for Windows using MinGW -============================= +=========================================== For the latest build instructions, please refer to:
--- a/config.h.mingw Mon Aug 06 13:16:32 2012 +0200 +++ b/config.h.mingw Mon Aug 06 18:11:44 2012 +0200 @@ -180,9 +180,6 @@ /* Define to 1 if you have the `random' function. */ /* #define HAVE_RANDOM 1 */ -/* Define to 1 if you have the <regex.h> header file. */ -/* #define HAVE_REGEX_H 1 */ - /* Define to 1 if you have the `setlocale' function. */ #define HAVE_SETLOCALE 1
--- a/configure.ac Mon Aug 06 13:16:32 2012 +0200 +++ b/configure.ac Mon Aug 06 18:11:44 2012 +0200 @@ -123,7 +123,7 @@ dnl Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(arpa/nameser_compat.h fcntl.h sys/time.h unistd.h locale.h signal.h stdint.h regex.h) +AC_CHECK_HEADERS(arpa/nameser_compat.h fcntl.h sys/time.h unistd.h locale.h signal.h stdint.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -372,6 +372,9 @@ AC_ARG_ENABLE(gtkui, [AC_HELP_STRING([--disable-gtkui], [compile without GTK+ user interface])], enable_gtkui="$enableval", enable_gtkui="yes") +AC_ARG_WITH(gtk, [AC_HELP_STRING([--with-gtk=<version>], + [compile with GTK+ 2 or 3 user interface (default: auto)])], + with_gtk="$withval", with_gtk="auto") AC_ARG_ENABLE(consoleui, [AC_HELP_STRING([--disable-consoleui], [compile without console user interface])], [enable_consoleui=$enableval force_finch=$enableval], [enable_consoleui=yes force_finch=no]) @@ -428,15 +431,35 @@ fi if test "x$enable_gtkui" = "xyes" ; then - PKG_CHECK_MODULES(GTK, [gtk+-2.0 >= 2.10.0], , [ - AC_MSG_RESULT(no) - AC_MSG_ERROR([ - + if test "x$with_gtk" = "x3"; then + PKG_CHECK_MODULES(GTK, [gtk+-3.0 >= 3.0.0], , [ + AC_MSG_RESULT(no) + AC_MSG_ERROR([ +You must have GTK+ 3.0.0 or newer development headers installed to compile +Pidgin. If you want to build only Finch then specify --disable-gtkui when +running configure. +])]) + elif test "x$with_gtk" = "x2"; then + PKG_CHECK_MODULES(GTK, [gtk+-2.0 >= 2.10.0], , [ + AC_MSG_RESULT(no) + AC_MSG_ERROR([ You must have GTK+ 2.10.0 or newer development headers installed to compile Pidgin. If you want to build only Finch then specify --disable-gtkui when running configure. ])]) - + elif test "x$with_gtk" = "xauto"; then + PKG_CHECK_MODULES(GTK, [gtk+-3.0 >= 3.0.0], [with_gtk=3], [ + AC_MSG_RESULT(no) + PKG_CHECK_MODULES(GTK, [gtk+-2.0 >= 2.10.0], [with_gtk=2], [ + AC_MSG_RESULT(no) + AC_MSG_ERROR([ +You must have GTK+ 2.10.0 or newer development headers installed to compile +Pidgin. If you want to build only Finch then specify --disable-gtkui when +running configure. +])])]) + else + AC_MSG_ERROR([--with-gtk must specify one of 2, 3 or auto.]) + fi AC_SUBST(GTK_CFLAGS) AC_SUBST(GTK_LIBS) @@ -444,13 +467,24 @@ PKG_CHECK_MODULES(PANGO, [pango >= 1.4.0], AC_DEFINE(HAVE_PANGO14, 1, [Define if we have Pango 1.4 or newer.]),:) - PKG_CHECK_MODULES(WEBKIT, [webkit-1.0 >= 1.1.1], , [ - AC_MSG_RESULT(no) - AC_MSG_ERROR([ -You must have WebKit 1.1.1 or newer development headers installed to compile -Pidgin. If you want to build only Finch then specify --disable-gtkui when -running configure. + WEBKIT_VERSION=1.1.1 + if test "x$with_gtk" = "x3"; then + PKG_CHECK_MODULES(WEBKIT, [webkitgtk-3.0 >= $WEBKIT_VERSION], , [ + AC_MSG_RESULT(no) + AC_MSG_ERROR([ +You must have WebKit for GTK+3 $WEBKIT_VERSION or newer development headers +installed to compile Pidgin. If you want to build only Finch then specify +--disable-gtkui when running configure. ])]) + else + PKG_CHECK_MODULES(WEBKIT, [webkit-1.0 >= $WEBKIT_VERSION], , [ + AC_MSG_RESULT(no) + AC_MSG_ERROR([ +You must have WebKit for GTK+2 $WEBKIT_VERSION or newer development headers +installed to compile Pidgin. If you want to build only Finch then specify +--disable-gtkui when running configure. +])]) + fi AC_SUBST(WEBKIT_CFLAGS) AC_SUBST(WEBKIT_LIBS) @@ -565,6 +599,10 @@ dnl ####################################################################### dnl # Check for GtkSpell dnl ####################################################################### + dnl GtkSpell is not GTK+3 compatible yet + if test "x$with_gtk" = "x3"; then + enable_gtkspell="no" + fi if test "x$enable_gtkspell" = "xyes" ; then PKG_CHECK_MODULES(GTKSPELL, gtkspell-2.0 >= 2.0.2, , [ AC_MSG_RESULT(no) @@ -629,16 +667,29 @@ dnl # Check for GCR for its certificate widgets dnl ####################################################################### if test "x$enable_gcr" = "xyes"; then - PKG_CHECK_MODULES(GCR, gcr-0, [ - AC_DEFINE(ENABLE_GCR, 1, [Define to 1 if GCR is found.])], [ - AC_MSG_RESULT(no) - enable_gcr="no" - if test "x$force_deps" = "xyes" ; then - AC_MSG_ERROR([ -GCR development headers not found. + if test "x$with_gtk" = "x3"; then + PKG_CHECK_MODULES(GCR, gcr-3, [ + AC_DEFINE(ENABLE_GCR, 1, [Define to 1 if GCR is found.])], [ + AC_MSG_RESULT(no) + enable_gcr="no" + if test "x$force_deps" = "xyes" ; then + AC_MSG_ERROR([ +GCR for GTK+3 development headers not found. Use --disable-gcr if you do not need GCR certificate widgets. ]) - fi]) + fi]) + else + PKG_CHECK_MODULES(GCR, gcr-0, [ + AC_DEFINE(ENABLE_GCR, 1, [Define to 1 if GCR is found.])], [ + AC_MSG_RESULT(no) + enable_gcr="no" + if test "x$force_deps" = "xyes" ; then + AC_MSG_ERROR([ +GCR for GTK+2 development headers not found. +Use --disable-gcr if you do not need GCR certificate widgets. +]) + fi]) + fi fi @@ -2612,7 +2663,10 @@ echo $PACKAGE $VERSION echo -echo Build GTK+ 2.x UI............. : $enable_gtkui +echo Build GTK+ UI................. : $enable_gtkui +if test "x$enable_gtkui" = "xyes"; then + echo Build for GTK+ version........ : $with_gtk +fi echo Build console UI.............. : $enable_consoleui echo Build for X11................. : $with_x echo
--- a/doc/pidgin.1.in Mon Aug 06 13:16:32 2012 +0200 +++ b/doc/pidgin.1.in Mon Aug 06 18:11:44 2012 +0200 @@ -218,9 +218,7 @@ .TP .B Notify buddies that you are typing to them Some protocols allow clients to tell their buddies when they are typing. -This option enables this feature for protocols that supports it. For XMPP, -this also enables sending the "User has left the conversation" message -when ending the conversation. +This option enables this feature for protocols that supports it. .TP .B Default Formatting
--- a/finch/gntrequest.c Mon Aug 06 13:16:32 2012 +0200 +++ b/finch/gntrequest.c Mon Aug 06 18:11:44 2012 +0200 @@ -388,10 +388,11 @@ purple_notify_close_with_handle(button); if (!g_object_get_data(G_OBJECT(button), "cancellation-function") && - !purple_request_fields_all_required_filled(fields)) { + (!purple_request_fields_all_required_filled(fields) || + !purple_request_fields_all_valid(fields))) { purple_notify_error(button, _("Error"), - _("You must fill all the required fields."), - _("The required fields are underlined.")); + _("You must properly fill all the required fields."), + _("The required fields are underlined.")); return; }
--- a/libpurple/mediamanager.c Mon Aug 06 13:16:32 2012 +0200 +++ b/libpurple/mediamanager.c Mon Aug 06 18:11:44 2012 +0200 @@ -742,8 +742,13 @@ | G_SIGNAL_MATCH_DATA, 0, 0, NULL, window_id_cb, ow); - gst_x_overlay_set_xwindow_id(GST_X_OVERLAY( - GST_MESSAGE_SRC(msg)), ow->window_id); +#if GST_CHECK_VERSION(0,10,31) + gst_x_overlay_set_window_handle(GST_X_OVERLAY(GST_MESSAGE_SRC(msg)), + ow->window_id); +#else + gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC(msg)), + ow->window_id); +#endif } #endif
--- a/libpurple/protocols/msn/userlist.c Mon Aug 06 13:16:32 2012 +0200 +++ b/libpurple/protocols/msn/userlist.c Mon Aug 06 18:11:44 2012 +0200 @@ -263,6 +263,7 @@ msn_userlist_remove_user(MsnUserList *userlist, MsnUser *user) { userlist->users = g_list_remove(userlist->users, user); + g_queue_remove(userlist->buddy_icon_requests, user); msn_user_unref(user); }
--- a/libpurple/protocols/yahoo/yahoo_picture.c Mon Aug 06 13:16:32 2012 +0200 +++ b/libpurple/protocols/yahoo/yahoo_picture.c Mon Aug 06 18:11:44 2012 +0200 @@ -137,9 +137,6 @@ if (url_data != NULL) { yd = purple_connection_get_protocol_data(gc); yd->url_datas = g_slist_prepend(yd->url_datas, url_data); - } else { - g_free(data->who); - g_free(data); } } else if (who && send_icon_info) { yahoo_send_picture_info(gc, who);
--- a/libpurple/protocols/yahoo/yahoo_profile.c Mon Aug 06 13:16:32 2012 +0200 +++ b/libpurple/protocols/yahoo/yahoo_profile.c Mon Aug 06 18:11:44 2012 +0200 @@ -1278,10 +1278,6 @@ url_data = purple_util_fetch_url(url, TRUE, NULL, FALSE, -1, yahoo_got_info, data); if (url_data != NULL) yd->url_datas = g_slist_prepend(yd->url_datas, url_data); - else { - g_free(data->name); - g_free(data); - } g_free(url); }
--- a/libpurple/prpl.h Mon Aug 06 13:16:32 2012 +0200 +++ b/libpurple/prpl.h Mon Aug 06 18:11:44 2012 +0200 @@ -467,11 +467,20 @@ void (*convo_closed)(PurpleConnection *, const char *who); /** - * Convert the username @a who to its canonical form. (For example, - * AIM treats "fOo BaR" and "foobar" as the same user; this function - * should return the same normalized string for both of those.) + * Convert the username @a who to its canonical form. Also checks for + * validity. + * + * For example, AIM treats "fOo BaR" and "foobar" as the same user; this + * function should return the same normalized string for both of those. + * On the other hand, both of these are invalid for protocols with + * number-based usernames, so function should return NULL in such case. + * + * @param account The account, that username is related with. Can + * be NULL. + * @param who The username to convert. + * @return Normalized username, or NULL, if it's invalid. */ - const char *(*normalize)(const PurpleAccount *, const char *who); + const char *(*normalize)(const PurpleAccount *account, const char *who); /** * Set the buddy icon for the given connection to @a img. The prpl
--- a/libpurple/request.c Mon Aug 06 13:16:32 2012 +0200 +++ b/libpurple/request.c Mon Aug 06 18:11:44 2012 +0200 @@ -128,6 +128,9 @@ void *ui_data; char *tooltip; + + PurpleRequestFieldValidator validator; + void *validator_data; }; struct _PurpleRequestFields @@ -138,6 +141,8 @@ GList *required_fields; + GList *validated_fields; + void *ui_data; }; @@ -171,6 +176,7 @@ g_list_foreach(fields->groups, (GFunc)purple_request_field_group_destroy, NULL); g_list_free(fields->groups); g_list_free(fields->required_fields); + g_list_free(fields->validated_fields); g_hash_table_destroy(fields->fields); g_free(fields); } @@ -203,6 +209,11 @@ g_list_append(fields->required_fields, field); } + if (purple_request_field_is_validatable(field)) { + fields->validated_fields = + g_list_append(fields->validated_fields, field); + } + } } @@ -223,7 +234,7 @@ return (g_hash_table_lookup(fields->fields, id) != NULL); } -GList * +const GList * purple_request_fields_get_required(const PurpleRequestFields *fields) { g_return_val_if_fail(fields != NULL, NULL); @@ -231,6 +242,14 @@ return fields->required_fields; } +const GList * +purple_request_fields_get_validatable(const PurpleRequestFields *fields) +{ + g_return_val_if_fail(fields != NULL, NULL); + + return fields->validated_fields; +} + gboolean purple_request_fields_is_field_required(const PurpleRequestFields *fields, const char *id) @@ -274,18 +293,26 @@ { PurpleRequestField *field = (PurpleRequestField *)l->data; - switch (purple_request_field_get_type(field)) - { - case PURPLE_REQUEST_FIELD_STRING: - if (purple_request_field_string_get_value(field) == NULL || - *(purple_request_field_string_get_value(field)) == '\0') - return FALSE; + if (!purple_request_field_is_filled(field)) + return FALSE; + } + + return TRUE; +} - break; +gboolean +purple_request_fields_all_valid(const PurpleRequestFields *fields) +{ + GList *l; + + g_return_val_if_fail(fields != NULL, FALSE); - default: - break; - } + for (l = fields->validated_fields; l != NULL; l = l->next) + { + PurpleRequestField *field = (PurpleRequestField *)l->data; + + if (!purple_request_field_is_valid(field, NULL)) + return FALSE; } return TRUE; @@ -436,6 +463,12 @@ group->fields_list->required_fields = g_list_append(group->fields_list->required_fields, field); } + + if (purple_request_field_is_validatable(field)) + { + group->fields_list->validated_fields = + g_list_append(group->fields_list->validated_fields, field); + } } field->group = group; @@ -657,6 +690,73 @@ return field->required; } +gboolean +purple_request_field_is_filled(const PurpleRequestField *field) +{ + g_return_val_if_fail(field != NULL, FALSE); + + switch (purple_request_field_get_type(field)) + { + case PURPLE_REQUEST_FIELD_STRING: + return (purple_request_field_string_get_value(field) != NULL && + *(purple_request_field_string_get_value(field)) != '\0'); + default: + return TRUE; + } +} + +void +purple_request_field_set_validator(PurpleRequestField *field, + PurpleRequestFieldValidator validator, void *user_data) +{ + g_return_if_fail(field != NULL); + + field->validator = validator; + field->validator_data = validator ? user_data : NULL; + + if (field->group != NULL) + { + PurpleRequestFields *flist = field->group->fields_list; + flist->validated_fields = g_list_remove(flist->validated_fields, + field); + if (validator) + { + flist->validated_fields = g_list_append( + flist->validated_fields, field); + } + } +} + +gboolean +purple_request_field_is_validatable(PurpleRequestField *field) +{ + g_return_val_if_fail(field != NULL, FALSE); + + return field->validator != NULL; +} + +gboolean +purple_request_field_is_valid(PurpleRequestField *field, gchar **errmsg) +{ + gboolean valid; + + g_return_val_if_fail(field != NULL, FALSE); + + if (!field->validator) + return TRUE; + + if (!purple_request_field_is_required(field) && + !purple_request_field_is_filled(field)) + return TRUE; + + valid = field->validator(field, errmsg, field->validator_data); + + if (valid && errmsg) + *errmsg = NULL; + + return valid; +} + PurpleRequestField * purple_request_field_string_new(const char *id, const char *text, const char *default_value, gboolean multiline) @@ -1361,6 +1461,122 @@ /* -- */ +gboolean +purple_request_field_email_validator(PurpleRequestField *field, gchar **errmsg, + void *user_data) +{ + const char *value; + + g_return_val_if_fail(field != NULL, FALSE); + g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE); + + value = purple_request_field_string_get_value(field); + + if (value != NULL && purple_email_is_valid(value)) + return TRUE; + + if (errmsg) + *errmsg = g_strdup(_("Invalid email address")); + return FALSE; +} + +gboolean +purple_request_field_alphanumeric_validator(PurpleRequestField *field, + gchar **errmsg, void *allowed_characters) +{ + const char *value; + gchar invalid_char = '\0'; + + g_return_val_if_fail(field != NULL, FALSE); + g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING, FALSE); + + value = purple_request_field_string_get_value(field); + + g_return_val_if_fail(value != NULL, FALSE); + + if (allowed_characters) + { + gchar *value_r = g_strdup(value); + g_strcanon(value_r, allowed_characters, '\0'); + invalid_char = value[strlen(value_r)]; + g_free(value_r); + } + else + { + while (value) + { + if (!g_ascii_isalnum(*value)) + { + invalid_char = *value; + break; + } + value++; + } + } + if (!invalid_char) + return TRUE; + + if (errmsg) + *errmsg = g_strdup_printf(_("Invalid character '%c'"), + invalid_char); + return FALSE; +} + +gboolean purple_request_field_numeric_validator(PurpleRequestField *field, + gchar **errmsg, void *range_p) +{ + gboolean succ = TRUE; + int value = 0; + int *range = range_p; + + g_return_val_if_fail(field != NULL, FALSE); + g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_STRING || + field->type == PURPLE_REQUEST_FIELD_INTEGER, FALSE); + + if (field->type == PURPLE_REQUEST_FIELD_STRING) + { + const gchar *svalue, *it; + svalue = purple_request_field_string_get_value(field); + if (svalue == NULL || svalue[0] == '\0') + succ = FALSE; + it = svalue; + if (it[0] == '-') + it++; + while (succ && *it) + { + if (!g_ascii_isdigit(*it)) + succ = FALSE; + it++; + } + if (succ) + { + char *endptr; + value = strtol(svalue, &endptr, 10); + succ = (errno != ERANGE && endptr[0] == '\0'); + } + } + // TODO: integer fields doesn't seems to work, so this one needs testing + else if (field->type == PURPLE_REQUEST_FIELD_INTEGER) + value = purple_request_field_int_get_value(field); + else + g_return_val_if_reached(FALSE); + + if (succ && range) + succ = (value >= range[0] && value <= range[1]); + + if (succ) + return TRUE; + + if (errmsg && !range) + *errmsg = g_strdup(_("Invalid number")); + if (errmsg && range) + *errmsg = g_strdup_printf(_("Value is not between %d and %d"), + range[0], range[1]); + return FALSE; +} + +/* -- */ + void * purple_request_input(void *handle, const char *title, const char *primary, const char *secondary, const char *default_value,
--- a/libpurple/request.h Mon Aug 06 13:16:32 2012 +0200 +++ b/libpurple/request.h Mon Aug 06 18:11:44 2012 +0200 @@ -150,6 +150,9 @@ typedef void (*PurpleRequestInputCb)(void *, const char *); +typedef gboolean (*PurpleRequestFieldValidator)(PurpleRequestField *field, + gchar **errmsg, void *user_data); + /** The type of callbacks passed to purple_request_action(). The first * argument is the @a user_data parameter; the second is the index in the list * of actions of the one chosen. @@ -216,7 +219,18 @@ * * @constreturn The list of required fields. */ -GList *purple_request_fields_get_required(const PurpleRequestFields *fields); +const GList *purple_request_fields_get_required( + const PurpleRequestFields *fields); + +/** + * Returns a list of all validated fields. + * + * @param fields The fields list. + * + * @constreturn The list of validated fields. + */ +const GList *purple_request_fields_get_validatable( + const PurpleRequestFields *fields); /** * Returns whether or not a field with the specified ID is required. @@ -240,6 +254,15 @@ const PurpleRequestFields *fields); /** + * Returns whether or not all fields are valid. + * + * @param fields The fields list. + * + * @return TRUE if all fields are valid, or FALSE. + */ +gboolean purple_request_fields_all_valid(const PurpleRequestFields *fields); + +/** * Return the field with the specified ID. * * @param fields The fields list. @@ -534,6 +557,51 @@ gboolean purple_request_field_is_required(const PurpleRequestField *field); /** + * Checks, if specified field has value. + * + * @param field The field. + * + * @return TRUE if the field has value, or FALSE. + */ +gboolean purple_request_field_is_filled(const PurpleRequestField *field); + +/** + * Sets validator for a single field. + * + * @param field The field. + * @param validator The validator callback, NULL to disable validation. + * @param user_data The data to pass to the callback. + */ +void purple_request_field_set_validator(PurpleRequestField *field, + PurpleRequestFieldValidator validator, void *user_data); + +/** + * Returns whether or not field has validator set. + * + * @param field The field. + * + * @return TRUE if the field has validator, or FALSE. + */ +gboolean purple_request_field_is_validatable(PurpleRequestField *field); + +/** + * Checks, if specified field is valid. + * + * If detailed message about failure reason is needed, there is an option to + * return (via errmsg argument) pointer to newly allocated error message. + * It must be freed with g_free after use. + * + * Note: empty, not required fields are valid. + * + * @param field The field. + * @param errmsg If non-NULL, the memory area, where the pointer to validation + * failure message will be set. + * + * @return TRUE, if the field is valid, FALSE otherwise. + */ +gboolean purple_request_field_is_valid(PurpleRequestField *field, gchar **errmsg); + +/** * Returns the ui_data for a field. * * @param field The field. @@ -1201,6 +1269,56 @@ /*@}*/ /**************************************************************************/ +/** @name Validators for request fields. */ +/**************************************************************************/ +/*@{*/ + +/** + * Validates a field which should contain an email address. + * + * @see purple_request_field_set_validator + * + * @param field The field. + * @param errmsg (Optional) destination for error message. + * @param user_data Ignored. + * + * @return TRUE, if field contains valid email address. + */ +gboolean purple_request_field_email_validator(PurpleRequestField *field, + gchar **errmsg, void *user_data); + +/** + * Validates a field which should contain alphanumeric content. + * + * @see purple_request_field_set_validator + * + * @param field The field. + * @param errmsg (Optional) destination for error message. + * @param user_data (Optional) allowed character list (NULL-terminated string). + * + * @return TRUE, if field contains only alphanumeric characters. + */ +gboolean purple_request_field_alphanumeric_validator(PurpleRequestField *field, + gchar **errmsg, void *allowed_characters); + +/** + * Validates a field which should contain numeric content, within (optional) + * range. + * + * @see purple_request_field_set_validator + * + * @param field The field. + * @param errmsg (Optional) destination for error message. + * @param user_data (Optional) an int[2] array containing specified range. + * + * @return TRUE, if field contains only alphanumeric characters. + */ +gboolean purple_request_field_numeric_validator(PurpleRequestField *field, + gchar **errmsg, void *range); + +/*@}*/ + +/**************************************************************************/ /** @name Request API */ /**************************************************************************/ /*@{*/
--- a/libpurple/util.c Mon Aug 06 13:16:32 2012 +0200 +++ b/libpurple/util.c Mon Aug 06 18:11:44 2012 +0200 @@ -3487,6 +3487,28 @@ return buf; } +gboolean +purple_validate(const PurplePlugin *prpl, const char *str) +{ + PurplePluginProtocolInfo *prpl_info; + const char *normalized; + + g_return_val_if_fail(prpl != NULL, FALSE); + g_return_val_if_fail(str != NULL, FALSE); + + if (str[0] == '\0') + return FALSE; + + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + + if (!prpl_info->normalize) + return TRUE; + + normalized = prpl_info->normalize(NULL, str); + + return (NULL != normalized); +} + gchar * purple_strdup_withhtml(const gchar *src) {
--- a/libpurple/util.h Mon Aug 06 13:16:32 2012 +0200 +++ b/libpurple/util.h Mon Aug 06 18:11:44 2012 +0200 @@ -56,6 +56,7 @@ #include "signals.h" #include "xmlnode.h" #include "notify.h" +#include "plugin.h" typedef char *(*PurpleInfoFieldFormatCallback)(const char *field, size_t len); @@ -960,6 +961,16 @@ const char *purple_normalize_nocase(const PurpleAccount *account, const char *str); /** + * Checks, if a string is valid. + * + * @param prpl The protocol plugin the string belongs to. + * @param str The string to validate. + * + * @return TRUE, if string is valid, otherwise FALSE. + */ +gboolean purple_validate(const PurplePlugin *prpl, const char *str); + +/** * Compares two strings to see if the first contains the second as * a proper prefix. *
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/gtk3compat.h Mon Aug 06 18:11:44 2012 +0200 @@ -0,0 +1,172 @@ +/* pidgin + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef _PIDGINGTK3COMPAT_H_ +#define _PIDGINGTK3COMPAT_H_ + +/* This file is internal to Pidgin. Do not use! + * Also, any public API should not depend on this file. + */ + +#if !GTK_CHECK_VERSION(3,0,0) + +#define gdk_x11_window_get_xid GDK_WINDOW_XWINDOW + +#if !GTK_CHECK_VERSION(2,24,0) + +#define gdk_x11_set_sm_client_id gdk_set_sm_client_id +#define gdk_window_get_display gdk_drawable_get_display +#define GtkComboBoxText GtkComboBox +#define GTK_COMBO_BOX_TEXT GTK_COMBO_BOX +#define gtk_combo_box_text_new gtk_combo_box_new_text +#define gtk_combo_box_text_append_text gtk_combo_box_append_text +#define gtk_combo_box_text_get_active_text gtk_combo_box_get_active_text +#define gtk_combo_box_text_remove gtk_combo_box_remove_text + +static inline gint gdk_window_get_width(GdkWindow *x) +{ + gint w; + gdk_drawable_get_size(GDK_DRAWABLE(x), &w, NULL); + return w; +} + +static inline gint gdk_window_get_height(GdkWindow *x) +{ + gint h; + gdk_drawable_get_size(GDK_DRAWABLE(x), NULL, &h); + return h; +} + +#if !GTK_CHECK_VERSION(2,22,0) + +#define gdk_drag_context_get_actions(x) (x)->action +#define gdk_drag_context_get_suggested_action(x) (x)->suggested_action +#define gtk_text_view_get_vadjustment(x) (x)->vadjustment +#define gtk_font_selection_dialog_get_font_selection(x) (x)->fontsel + +#if !GTK_CHECK_VERSION(2,20,0) + +#define gtk_widget_get_mapped GTK_WIDGET_MAPPED +#define gtk_widget_set_mapped(x,y) do { \ + if (y) \ + GTK_WIDGET_SET_FLAGS(x, GTK_MAPPED); \ + else \ + GTK_WIDGET_UNSET_FLAGS(x, GTK_MAPPED); \ +} while(0) +#define gtk_widget_get_realized GTK_WIDGET_REALIZED +#define gtk_widget_set_realized(x,y) do { \ + if (y) \ + GTK_WIDGET_SET_FLAGS(x, GTK_REALIZED); \ + else \ + GTK_WIDGET_UNSET_FLAGS(x, GTK_REALIZED); \ +} while(0) + +#if !GTK_CHECK_VERSION(2,18,0) + +#define gtk_widget_get_state GTK_WIDGET_STATE +#define gtk_widget_is_drawable GTK_WIDGET_DRAWABLE +#define gtk_widget_get_visible GTK_WIDGET_VISIBLE +#define gtk_widget_has_focus GTK_WIDGET_HAS_FOCUS +#define gtk_widget_is_sensitive GTK_WIDGET_IS_SENSITIVE +#define gtk_widget_get_has_window(x) !GTK_WIDGET_NO_WINDOW(x) +#define gtk_widget_set_has_window(x,y) do { \ + if (!y) \ + GTK_WIDGET_SET_FLAGS(x, GTK_NO_WINDOW); \ + else \ + GTK_WIDGET_UNSET_FLAGS(x, GTK_NO_WINDOW); \ +} while(0) +#define gtk_widget_get_allocation(x,y) *(y) = (x)->allocation +#define gtk_widget_set_allocation(x,y) (x)->allocation = *(y) +#define gtk_widget_set_window(x,y) ((x)->window = (y)) +#define gtk_widget_set_can_default(w,y) do { \ + if (y) \ + GTK_WIDGET_SET_FLAGS((w), GTK_CAN_DEFAULT); \ + else \ + GTK_WIDGET_UNSET_FLAGS((w), GTK_CAN_DEFAULT); \ +} while (0) +#define gtk_widget_set_can_focus(x,y) do {\ + if (y) \ + GTK_WIDGET_SET_FLAGS(x, GTK_CAN_FOCUS); \ + else \ + GTK_WIDGET_UNSET_FLAGS(x, GTK_CAN_FOCUS); \ +} while(0) +#define gtk_cell_renderer_set_padding(x,y,z) do { \ + (x)->xpad = (y); \ + (x)->ypad = (z); \ +} while (0) +#define gtk_cell_renderer_get_padding(x,y,z) do { \ + *(y) = (x)->xpad; \ + *(z) = (x)->ypad; \ +} while (0) +#define gtk_cell_renderer_get_alignment(x,y,z) do { \ + *(y) = (x)->xalign; \ + *(z) = (x)->yalign; \ +} while (0) + +#if !GTK_CHECK_VERSION(2,16,0) + +#define gtk_status_icon_set_tooltip_text gtk_status_icon_set_tooltip + +#if !GTK_CHECK_VERSION(2,14,0) + +#define gtk_widget_get_window(x) (x)->window +#define gtk_widget_set_style(x,y) (x)->style = (y) +#define gtk_selection_data_get_data(x) (x)->data +#define gtk_selection_data_get_length(x) (x)->length +#define gtk_selection_data_get_format(x) (x)->format +#define gtk_selection_data_get_target(x) (x)->target +#define gtk_dialog_get_content_area(x) GTK_DIALOG(x)->vbox +#define gtk_dialog_get_action_area(x) GTK_DIALOG(x)->action_area +#define gtk_adjustment_get_page_size(x) (x)->page_size +#define gtk_adjustment_get_lower(x) (x)->lower +#define gtk_adjustment_get_upper(x) (x)->upper +#define gtk_font_selection_get_size_entry(x) (x)->size_entry +#define gtk_font_selection_get_family_list(x) (x)->family_list +#define gtk_font_selection_dialog_get_ok_button(x) (x)->ok_button +#define gtk_font_selection_dialog_get_cancel_button(x) (x)->cancel_button +#define gtk_color_selection_dialog_get_color_selection(x) (x)->colorsel +#define gtk_menu_item_get_accel_path(x) (x)->accel_path + +#if !GTK_CHECK_VERSION(2,12,0) + +#ifdef GTK_TOOLTIPS_VAR +#define gtk_widget_set_tooltip_text(w, t) gtk_tooltips_set_tip(GTK_TOOLTIPS_VAR, (w), (t), NULL) +#else +#define gtk_widget_set_tooltip_text(w, t) gtk_tooltips_set_tip(tooltips, (w), (t), NULL) +#endif + +#endif /* 2.12.0 */ + +#endif /* 2.14.0 */ + +#endif /* 2.16.0 */ + +#endif /* 2.18.0 */ + +#endif /* 2.20.0 */ + +#endif /* 2.22.0 */ + +#endif /* 2.24.0 */ + +#endif /* 3.0.0 */ + +#endif /* _PIDGINGTK3COMPAT_H_ */ +
--- a/pidgin/gtkaccount.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkaccount.c Mon Aug 06 18:11:44 2012 +0200 @@ -48,6 +48,8 @@ #include "pidginstock.h" #include "minidialog.h" +#include "gtk3compat.h" + enum { COLUMN_ICON, @@ -270,6 +272,11 @@ GHashTable *table; const char *label; + if (!dialog->prpl_info || ! PURPLE_PROTOCOL_PLUGIN_HAS_FUNC( + dialog->prpl_info, get_account_text_table)) { + return FALSE; + } + table = dialog->prpl_info->get_account_text_table(NULL); label = g_hash_table_lookup(table, "login_label"); @@ -286,9 +293,11 @@ static void username_changed_cb(GtkEntry *entry, AccountPrefsDialog *dialog) { - int opt_noscreenname = (dialog->prpl_info != NULL && + gboolean opt_noscreenname = (dialog->prpl_info != NULL && (dialog->prpl_info->options & OPT_PROTO_REGISTER_NOSCREENNAME)); - + gboolean username_valid = purple_validate(dialog->plugin, + gtk_entry_get_text(entry)); + if (dialog->ok_button) { if (opt_noscreenname && dialog->register_button && gtk_toggle_button_get_active( @@ -296,14 +305,15 @@ gtk_widget_set_sensitive(dialog->ok_button, TRUE); else gtk_widget_set_sensitive(dialog->ok_button, - *gtk_entry_get_text(entry) != '\0'); + username_valid); } + if (dialog->register_button) { if (opt_noscreenname) gtk_widget_set_sensitive(dialog->register_button, TRUE); else gtk_widget_set_sensitive(dialog->register_button, - *gtk_entry_get_text(entry) != '\0'); + username_valid); } } @@ -343,10 +353,10 @@ int opt_noscreenname = (dialog->prpl_info != NULL && (dialog->prpl_info->options & OPT_PROTO_REGISTER_NOSCREENNAME)); int register_noscreenname = (opt_noscreenname && register_checked); - - // get rid of login_label in username field + + /* get rid of login_label in username field */ username_focus_cb(dialog->username_entry, NULL, dialog); - + if (register_noscreenname) { gtk_entry_set_text(GTK_ENTRY(dialog->username_entry), ""); gtk_entry_set_text(GTK_ENTRY(dialog->password_entry), ""); @@ -355,14 +365,14 @@ gtk_widget_set_sensitive(dialog->username_entry, !register_noscreenname); gtk_widget_set_sensitive(dialog->password_entry, !register_noscreenname); gtk_widget_set_sensitive(dialog->remember_pass_check, !register_noscreenname); - + if (dialog->ok_button) { gtk_widget_set_sensitive(dialog->ok_button, (opt_noscreenname && register_checked) || *gtk_entry_get_text(GTK_ENTRY(dialog->username_entry)) != '\0'); } - + username_nofocus_cb(dialog->username_entry, NULL, dialog); } @@ -398,9 +408,11 @@ account_dnd_recv(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, GtkSelectionData *sd, guint info, guint t, AccountPrefsDialog *dialog) { - gchar *name = (gchar *)sd->data; - - if ((sd->length >= 0) && (sd->format == 8)) { + const gchar *name = (gchar *)gtk_selection_data_get_data(sd); + gint length = gtk_selection_data_get_length(sd); + gint format = gtk_selection_data_get_format(sd); + + if ((length >= 0) && (format == 8)) { /* Well, it looks like the drag event was cool. * Let's do something with it */ if (!g_ascii_strncasecmp(name, "file://", 7)) { @@ -473,11 +485,7 @@ if (dialog->protocol_menu != NULL) { -#if GTK_CHECK_VERSION(2,12,0) g_object_ref(G_OBJECT(dialog->protocol_menu)); -#else - gtk_widget_ref(dialog->protocol_menu); -#endif hbox = g_object_get_data(G_OBJECT(dialog->protocol_menu), "container"); gtk_container_remove(GTK_CONTAINER(hbox), dialog->protocol_menu); } @@ -504,21 +512,13 @@ { dialog->protocol_menu = pidgin_protocol_option_menu_new( dialog->protocol_id, G_CALLBACK(set_account_protocol_cb), dialog); -#if GTK_CHECK_VERSION(2,12,0) g_object_ref(G_OBJECT(dialog->protocol_menu)); -#else - gtk_widget_ref(dialog->protocol_menu); -#endif } hbox = add_pref_box(dialog, vbox, _("Pro_tocol:"), dialog->protocol_menu); g_object_set_data(G_OBJECT(dialog->protocol_menu), "container", hbox); -#if GTK_CHECK_VERSION(2,12,0) g_object_unref(G_OBJECT(dialog->protocol_menu)); -#else - gtk_widget_unref(dialog->protocol_menu); -#endif /* Username */ dialog->username_entry = gtk_entry_new(); @@ -1078,7 +1078,7 @@ dialog->new_proxy_type == PURPLE_PROXY_NONE || dialog->new_proxy_type == PURPLE_PROXY_USE_ENVVAR) { - gtk_widget_hide_all(dialog->proxy_vbox); + gtk_widget_hide(dialog->proxy_vbox); } else gtk_widget_show_all(dialog->proxy_vbox); @@ -1287,7 +1287,7 @@ { const PurpleSavedStatus *saved_status = purple_savedstatus_get_current(); purple_signal_emit(pidgin_account_get_handle(), "account-modified", account); - + if (saved_status != NULL && purple_account_get_remember_password(account)) { purple_savedstatus_activate_for_account(saved_status, account); purple_account_set_enabled(account, PIDGIN_UI, TRUE); @@ -1804,7 +1804,9 @@ GtkSelectionData *data, guint info, guint time, AccountsWindow *dialog) { - if (data->target == gdk_atom_intern("PURPLE_ACCOUNT", FALSE)) { + GdkAtom target = gtk_selection_data_get_target(data); + + if (target == gdk_atom_intern("PURPLE_ACCOUNT", FALSE)) { GtkTreeRowReference *ref; GtkTreePath *source_row; GtkTreeIter iter; @@ -1875,13 +1877,16 @@ guint x, guint y, GtkSelectionData *sd, guint info, guint t, AccountsWindow *dialog) { - if (sd->target == gdk_atom_intern("PURPLE_ACCOUNT", FALSE) && sd->data) { + GdkAtom target = gtk_selection_data_get_target(sd); + const guchar *data = gtk_selection_data_get_data(sd); + + if (target == gdk_atom_intern("PURPLE_ACCOUNT", FALSE) && data) { gint dest_index; PurpleAccount *a = NULL; GtkTreePath *path = NULL; GtkTreeViewDropPosition position; - memcpy(&a, sd->data, sizeof(a)); + memcpy(&a, data, sizeof(a)); if (gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), x, y, &path, &position)) { @@ -2384,7 +2389,11 @@ width = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/accounts/dialog/width"); height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/accounts/dialog/height"); +#if GTK_CHECK_VERSION(3,0,0) + dialog->window = win = pidgin_create_dialog(_("Accounts"), 0, "accounts", TRUE); +#else dialog->window = win = pidgin_create_dialog(_("Accounts"), PIDGIN_HIG_BORDER, "accounts", TRUE); +#endif gtk_window_set_default_size(GTK_WINDOW(win), width, height); g_signal_connect(G_OBJECT(win), "delete_event",
--- a/pidgin/gtkblist-theme-loader.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkblist-theme-loader.c Mon Aug 06 18:11:44 2012 +0200 @@ -65,7 +65,9 @@ GdkColor color; if (temp && gdk_color_parse(temp, &color)) { +#if !GTK_CHECK_VERSION(3,0,0) gdk_colormap_alloc_color(gdk_colormap_get_system(), &color, FALSE, TRUE); +#endif return gdk_color_copy(&color); } else { return NULL;
--- a/pidgin/gtkblist.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkblist.c Mon Aug 06 18:11:44 2012 +0200 @@ -71,6 +71,8 @@ #include <gtk/gtk.h> #include <gdk/gdk.h> +#include "gtk3compat.h" + typedef struct { PurpleAccount *account; @@ -120,15 +122,20 @@ PidginMiniDialog *signed_on_elsewhere; PidginBlistTheme *current_theme; + +#if !GTK_CHECK_VERSION(3,0,0) + GdkCursor *hand_cursor; /**< Hand cursor */ + GdkCursor *arrow_cursor; /**< Arrow cursor */ + gboolean changing_style; /**< True when changing GTK+ theme style */ +#endif + } PidginBuddyListPrivate; #define PIDGIN_BUDDY_LIST_GET_PRIVATE(list) \ ((PidginBuddyListPrivate *)((list)->priv)) -#if !GTK_CHECK_VERSION(2,18,0) -#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x) -#define gtk_widget_has_focus(x) GTK_WIDGET_HAS_FOCUS(x) -#endif +#define PIDGIN_WINDOW_ICONIFIED(x) \ + (gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(x))) & GDK_WINDOW_STATE_ICONIFIED) static GtkWidget *accountmenu = NULL; @@ -467,9 +474,9 @@ GList *tmp; /* First, we find the contact to merge the rest of the buddies into. - * This will be the contact with the most buddies in it; ties are broken - * by which contact is higher in the list - */ + * This will be the contact with the most buddies in it; ties are broken + * by which contact is higher in the list + */ for (tmp = merges; tmp; tmp = tmp->next) { PurpleBlistNode *node = tmp->data; PurpleBlistNode *b; @@ -898,7 +905,7 @@ * strings are empty then don't allow the user to click on "OK." */ static void -set_sensitive_if_input_cb(GtkWidget *entry, gpointer user_data) +set_sensitive_if_input_chat_cb(GtkWidget *entry, gpointer user_data) { PurplePluginProtocolInfo *prpl_info; PurpleConnection *gc; @@ -931,6 +938,21 @@ } static void +set_sensitive_if_input_buddy_cb(GtkWidget *entry, gpointer user_data) +{ + PurplePlugin *prpl; + PidginAddBuddyData *data = user_data; + const char *text; + + prpl = purple_find_prpl(purple_account_get_protocol_id( + data->rq_data.account)); + text = gtk_entry_get_text(GTK_ENTRY(entry)); + + gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window), + GTK_RESPONSE_OK, purple_validate(prpl, text)); +} + +static void pidgin_blist_update_privacy_cb(PurpleBuddy *buddy) { struct _pidgin_blist_node *ui_data = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy)); @@ -990,20 +1012,21 @@ gtkblist = PIDGIN_BLIST(purple_get_blist()); blist_window = gtkblist ? GTK_WINDOW(gtkblist->window) : NULL; - data->window = gtk_dialog_new_with_buttons(title, - blist_window, GTK_DIALOG_NO_SEPARATOR, - NULL); - + data->window = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(data->window), title); gtk_window_set_transient_for(GTK_WINDOW(data->window), blist_window); gtk_dialog_set_default_response(GTK_DIALOG(data->window), GTK_RESPONSE_OK); gtk_container_set_border_width(GTK_CONTAINER(data->window), PIDGIN_HIG_BOX_SPACE); gtk_window_set_resizable(GTK_WINDOW(data->window), FALSE); - gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(data->window)->vbox), PIDGIN_HIG_BORDER); - gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), PIDGIN_HIG_BOX_SPACE); + gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(data->window))), + PIDGIN_HIG_BORDER); + gtk_container_set_border_width(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(data->window))), + PIDGIN_HIG_BOX_SPACE); gtk_window_set_role(GTK_WINDOW(data->window), window_role); hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(data->window)->vbox), hbox); + gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(data->window))), + hbox); gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); gtk_misc_set_alignment(GTK_MISC(img), 0, 0); @@ -1068,10 +1091,11 @@ if (pce->is_int) { - GtkObject *adjust; - adjust = gtk_adjustment_new(pce->min, pce->min, pce->max, - 1, 10, 10); - input = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0); + GtkAdjustment *adjust; + adjust = GTK_ADJUSTMENT(gtk_adjustment_new(pce->min, + pce->min, pce->max, + 1, 10, 10)); + input = gtk_spin_button_new(adjust, 1, 0); gtk_widget_set_size_request(input, 50, -1); pidgin_add_widget_to_vbox(GTK_BOX(data->rq_data.vbox), pce->label, data->rq_data.sg, input, FALSE, NULL); } @@ -1093,7 +1117,7 @@ } pidgin_add_widget_to_vbox(data->rq_data.vbox, pce->label, data->rq_data.sg, input, TRUE, NULL); g_signal_connect(G_OBJECT(input), "changed", - G_CALLBACK(set_sensitive_if_input_cb), data); + G_CALLBACK(set_sensitive_if_input_chat_cb), data); } /* Do the following for any type of input widget */ @@ -1114,7 +1138,7 @@ g_hash_table_destroy(defaults); /* Set whether the "OK" button should be clickable initially */ - set_sensitive_if_input_cb(NULL, data); + set_sensitive_if_input_chat_cb(NULL, data); gtk_widget_show_all(GTK_WIDGET(data->rq_data.vbox)); } @@ -1564,7 +1588,7 @@ pidgin_append_blist_node_move_to_menu(menu, PURPLE_BLIST_NODE(contact)); if (node->parent && node->parent->child->next && - !sub && !contact_expanded) { + !sub && !contact_expanded) { pidgin_separator(menu); pidgin_append_blist_node_privacy_menu(menu, node); pidgin_new_item_from_stock(menu, _("_Alias..."), PIDGIN_STOCK_ALIAS, @@ -1613,11 +1637,11 @@ pidgin_retrieve_user_info(purple_account_get_connection(purple_buddy_get_account(buddy)), purple_buddy_get_name(buddy)); } else { switch (event->keyval) { - case GDK_F2: + case GDK_KEY_F2: gtk_blist_menu_alias_cb(tv, node); break; - case GDK_Left: + case GDK_KEY_Left: path = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(tv), path)) { /* Collapse the Group */ @@ -1639,7 +1663,7 @@ gtk_tree_path_free(path); break; - case GDK_Right: + case GDK_KEY_Right: path = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); if (!gtk_tree_view_row_expanded(GTK_TREE_VIEW(tv), path)) { /* Expand the Group */ @@ -2252,9 +2276,9 @@ guint time, gpointer null) { - - if (data->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE)) - { + GdkAtom target = gtk_selection_data_get_target(data); + + if (target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE)) { GtkTreeRowReference *ref = g_object_get_data(G_OBJECT(dc), "gtk-tree-view-source-row"); GtkTreePath *sourcerow = gtk_tree_row_reference_get_path(ref); GtkTreeIter iter; @@ -2270,9 +2294,7 @@ sizeof (node)); gtk_tree_path_free(sourcerow); - } - else if (data->target == gdk_atom_intern("application/x-im-contact", FALSE)) - { + } else if (target == gdk_atom_intern("application/x-im-contact", FALSE)) { GtkTreeRowReference *ref; GtkTreePath *sourcerow; GtkTreeIter iter; @@ -2350,16 +2372,19 @@ static void pidgin_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, GtkSelectionData *sd, guint info, guint t) { + GdkAtom target = gtk_selection_data_get_target(sd); + const guchar *data = gtk_selection_data_get_data(sd); + if (gtkblist->drag_timeout) { g_source_remove(gtkblist->drag_timeout); gtkblist->drag_timeout = 0; } - if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE) && sd->data) { + if (target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE) && data) { PurpleBlistNode *n = NULL; GtkTreePath *path = NULL; GtkTreeViewDropPosition position; - memcpy(&n, sd->data, sizeof(n)); + memcpy(&n, data, sizeof(n)); if(gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(widget), x, y, &path, &position)) { /* if we're here, I think it means the drop is ok */ GtkTreeIter iter; @@ -2495,12 +2520,10 @@ } gtk_tree_path_free(path); - gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); - } - } - else if (sd->target == gdk_atom_intern("application/x-im-contact", - FALSE) && sd->data) - { + gtk_drag_finish(dc, TRUE, (gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE), t); + } + } else if (target == gdk_atom_intern("application/x-im-contact", + FALSE) && data) { PurpleGroup *group = NULL; GtkTreePath *path = NULL; GtkTreeViewDropPosition position; @@ -2535,7 +2558,7 @@ } } - if (pidgin_parse_x_im_contact((const char *)sd->data, FALSE, &account, + if (pidgin_parse_x_im_contact((const char *)data, FALSE, &account, &protocol, &username, &alias)) { if (account == NULL) @@ -2559,9 +2582,10 @@ if (path != NULL) gtk_tree_path_free(path); - gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); - } - else if (sd->target == gdk_atom_intern("text/x-vcard", FALSE) && sd->data) + gtk_drag_finish(dc, TRUE, + gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); + } + else if (target == gdk_atom_intern("text/x-vcard", FALSE) && data) { gboolean result; PurpleGroup *group = NULL; @@ -2594,10 +2618,11 @@ } } - result = parse_vcard((const gchar *)sd->data, group); - - gtk_drag_finish(dc, result, (dc->action == GDK_ACTION_MOVE), t); - } else if (sd->target == gdk_atom_intern("text/uri-list", FALSE) && sd->data) { + result = parse_vcard((const gchar *)data, group); + + gtk_drag_finish(dc, result, + gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); + } else if (target == gdk_atom_intern("text/uri-list", FALSE) && data) { GtkTreePath *path = NULL; GtkTreeViewDropPosition position; @@ -2615,7 +2640,8 @@ if (PURPLE_BLIST_NODE_IS_BUDDY(node) || PURPLE_BLIST_NODE_IS_CONTACT(node)) { PurpleBuddy *b = PURPLE_BLIST_NODE_IS_BUDDY(node) ? PURPLE_BUDDY(node) : purple_contact_get_priority_buddy(PURPLE_CONTACT(node)); pidgin_dnd_file_manage(sd, purple_buddy_get_account(b), purple_buddy_get_name(b)); - gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); + gtk_drag_finish(dc, TRUE, + gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); } else { gtk_drag_finish(dc, FALSE, FALSE, t); } @@ -2937,10 +2963,9 @@ } static gboolean -pidgin_blist_paint_tip(GtkWidget *widget, gpointer null) +pidgin_blist_paint_tip(GtkWidget *widget, cairo_t *cr, gpointer null) { GtkStyle *style; - cairo_t *cr; int current_height, max_width; int max_text_width; int max_avatar_width; @@ -2952,7 +2977,7 @@ if(gtkblist->tooltipdata == NULL) return FALSE; - style = gtkblist->tipwindow->style; + style = gtk_widget_get_style(gtkblist->tipwindow); max_text_width = 0; max_avatar_width = 0; @@ -2974,7 +2999,6 @@ else prpl_col = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width - PRPL_SIZE; - cr = gdk_cairo_create(GDK_DRAWABLE(gtk_widget_get_window(gtkblist->tipwindow))); current_height = 12; for(l = gtkblist->tooltipdata; l; l = l->next) { @@ -2982,15 +3006,29 @@ if (td->avatar && pidgin_gdk_pixbuf_is_opaque(td->avatar)) { +#if GTK_CHECK_VERSION(3,0,0) + if (dir == GTK_TEXT_DIR_RTL) + gtk_paint_flat_box(style, cr, GTK_STATE_NORMAL, GTK_SHADOW_OUT, + gtkblist->tipwindow, "tooltip", + TOOLTIP_BORDER - 1, current_height - 1, + td->avatar_width + 2, td->avatar_height + 2); + else + gtk_paint_flat_box(style, cr, GTK_STATE_NORMAL, GTK_SHADOW_OUT, + gtkblist->tipwindow, "tooltip", + max_width - (td->avatar_width + TOOLTIP_BORDER) - 1, + current_height - 1, + td->avatar_width + 2, td->avatar_height + 2); +#else if (dir == GTK_TEXT_DIR_RTL) gtk_paint_flat_box(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, - NULL, gtkblist->tipwindow, "tooltip", - TOOLTIP_BORDER -1, current_height -1, td->avatar_width +2, td->avatar_height + 2); + NULL, gtkblist->tipwindow, "tooltip", + TOOLTIP_BORDER -1, current_height -1, td->avatar_width +2, td->avatar_height + 2); else gtk_paint_flat_box(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, - NULL, gtkblist->tipwindow, "tooltip", - max_width - (td->avatar_width+ TOOLTIP_BORDER)-1, - current_height-1,td->avatar_width+2, td->avatar_height+2); + NULL, gtkblist->tipwindow, "tooltip", + max_width - (td->avatar_width+ TOOLTIP_BORDER)-1, + current_height-1,td->avatar_width+2, td->avatar_height+2); +#endif } if (td->status_icon) { @@ -3006,7 +3044,7 @@ } } - if(td->avatar) { + if (td->avatar) { if (dir == GTK_TEXT_DIR_RTL) { gdk_cairo_set_source_pixbuf(cr, td->avatar, TOOLTIP_BORDER, current_height); @@ -3027,36 +3065,62 @@ } if (td->name_layout) { +#if GTK_CHECK_VERSION(3,0,0) + if (dir == GTK_TEXT_DIR_RTL) { + gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE, + gtkblist->tipwindow, "tooltip", + max_width - (TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000), + current_height, td->name_layout); + } else { + gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE, + gtkblist->tipwindow, "tooltip", + TOOLTIP_BORDER + status_size + SMALL_SPACE, current_height, td->name_layout); + } +#else if (dir == GTK_TEXT_DIR_RTL) { gtk_paint_layout(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE, - NULL, gtkblist->tipwindow, "tooltip", - max_width -(TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000), - current_height, td->name_layout); + NULL, gtkblist->tipwindow, "tooltip", + max_width -(TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000), + current_height, td->name_layout); } else { - gtk_paint_layout (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE, - NULL, gtkblist->tipwindow, "tooltip", - TOOLTIP_BORDER + status_size + SMALL_SPACE, current_height, td->name_layout); + gtk_paint_layout(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE, + NULL, gtkblist->tipwindow, "tooltip", + TOOLTIP_BORDER + status_size + SMALL_SPACE, current_height, td->name_layout); } +#endif } if (td->layout) { +#if GTK_CHECK_VERSION(3,0,0) if (dir != GTK_TEXT_DIR_RTL) { - gtk_paint_layout (style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE, - NULL, gtkblist->tipwindow, "tooltip", - TOOLTIP_BORDER + status_size + SMALL_SPACE, current_height + td->name_height, td->layout); + gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE, + gtkblist->tipwindow, "tooltip", + TOOLTIP_BORDER + status_size + SMALL_SPACE, current_height + td->name_height, td->layout); + } else { + gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE, + gtkblist->tipwindow, "tooltip", + max_width - (TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000), + current_height + td->name_height, + td->layout); + } +#else + if (dir != GTK_TEXT_DIR_RTL) { + gtk_paint_layout(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE, + NULL, gtkblist->tipwindow, "tooltip", + TOOLTIP_BORDER + status_size + SMALL_SPACE, current_height + td->name_height, td->layout); } else { gtk_paint_layout(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE, - NULL, gtkblist->tipwindow, "tooltip", - max_width - (TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000), - current_height + td->name_height, - td->layout); + NULL, gtkblist->tipwindow, "tooltip", + max_width - (TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000), + current_height + td->name_height, + td->layout); } +#endif } current_height += MAX(td->name_height + td->height, td->avatar_height) + td->padding; } - cairo_destroy(cr); return FALSE; } @@ -3205,7 +3269,8 @@ pidgin_blist_expand_contact_cb(NULL, node); gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, >kblist->contact_rect); - gdk_drawable_get_size(GDK_DRAWABLE(tv->window), &(gtkblist->contact_rect.width), NULL); + gtkblist->contact_rect.width = + gdk_window_get_width(gtk_widget_get_window(tv)); gtkblist->mouseover_contact = node; gtk_tree_path_down (path); while (gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &i, path)) { @@ -3602,11 +3667,11 @@ } purple_request_fields(gc, _("Edit User Mood"), _("Edit User Mood"), - NULL, fields, - _("OK"), G_CALLBACK(edit_mood_cb), - _("Cancel"), NULL, - gc ? purple_connection_get_account(gc) : NULL, - NULL, NULL, gc); + NULL, fields, + _("OK"), G_CALLBACK(edit_mood_cb), + _("Cancel"), NULL, + gc ? purple_connection_get_account(gc) : NULL, + NULL, NULL, gc); g_free(global_moods); } @@ -5000,25 +5065,33 @@ widget = gtk_window_get_focus(GTK_WINDOW(gtkblist->window)); if (GTK_IS_IMHTML(widget) || GTK_IS_ENTRY(widget)) { +#if GTK_CHECK_VERSION(3,0,0) + if (gtk_bindings_activate(G_OBJECT(widget), event->keyval, event->state)) +#else if (gtk_bindings_activate(GTK_OBJECT(widget), event->keyval, event->state)) +#endif return TRUE; } return FALSE; } +#if !GTK_CHECK_VERSION(3,0,0) +static gboolean +headline_box_enter_cb(GtkWidget *widget, GdkEventCrossing *event, + PidginBuddyListPrivate *priv) +{ + gdk_window_set_cursor(widget->window, priv->hand_cursor); + return FALSE; +} + static gboolean -headline_box_enter_cb(GtkWidget *widget, GdkEventCrossing *event, PidginBuddyList *gtkblist) -{ - gdk_window_set_cursor(widget->window, gtkblist->hand_cursor); +headline_box_leave_cb(GtkWidget *widget, GdkEventCrossing *event, + PidginBuddyListPrivate *priv) +{ + gdk_window_set_cursor(widget->window, priv->arrow_cursor); return FALSE; } - -static gboolean -headline_box_leave_cb(GtkWidget *widget, GdkEventCrossing *event, PidginBuddyList *gtkblist) -{ - gdk_window_set_cursor(widget->window, gtkblist->arrow_cursor); - return FALSE; -} +#endif static void reset_headline(PidginBuddyList *gtkblist) @@ -5038,17 +5111,54 @@ return FALSE; } +#if GTK_CHECK_VERSION(3,0,0) + +static gboolean +headline_response_cb(GtkInfoBar *infobar, int resp, PidginBuddyList *gtkblist) +{ + gtk_widget_hide(gtkblist->headline); + + if (resp == GTK_RESPONSE_OK) { + if (gtkblist->headline_callback) + g_idle_add(headline_click_callback, NULL); + else { + if (gtkblist->headline_destroy) + gtkblist->headline_destroy(gtkblist->headline_data); + reset_headline(gtkblist); + } + } + + return FALSE; +} + +static void +headline_realize_cb(GtkWidget *widget, gpointer data) +{ + GdkCursor *hand_cursor = gdk_cursor_new(GDK_HAND2); + gdk_window_set_cursor(gtk_widget_get_window(widget), hand_cursor); + gdk_cursor_unref(hand_cursor); +} + +static gboolean +headline_press_cb(GtkWidget *widget, GdkEventButton *event, GtkInfoBar *infobar) +{ + gtk_info_bar_response(infobar, GTK_RESPONSE_OK); + return TRUE; +} + +#else + static gboolean headline_close_press_cb(GtkButton *button, PidginBuddyList *gtkblist) { - gtk_widget_hide(gtkblist->headline_hbox); + gtk_widget_hide(gtkblist->headline); return FALSE; } static gboolean headline_box_press_cb(GtkWidget *widget, GdkEventButton *event, PidginBuddyList *gtkblist) { - gtk_widget_hide(gtkblist->headline_hbox); + gtk_widget_hide(gtkblist->headline); if (gtkblist->headline_callback) g_idle_add(headline_click_callback, NULL); else { @@ -5059,6 +5169,8 @@ return TRUE; } +#endif + /***********************************/ /* Connection error handling stuff */ /***********************************/ @@ -5150,7 +5262,7 @@ } static void -generic_error_destroy_cb(GtkObject *dialog, +generic_error_destroy_cb(GtkWidget *dialog, PurpleAccount *account) { /* If the error dialog is being destroyed in response to the @@ -5488,6 +5600,7 @@ } } +#if !GTK_CHECK_VERSION(3,0,0) static gboolean paint_headline_hbox (GtkWidget *widget, GdkEventExpose *event, @@ -5506,6 +5619,7 @@ widget->allocation.height - 2); return FALSE; } +#endif /* This assumes there are not things like groupless buddies or multi-leveled groups. * I'm sure other things in this code assumes that also. @@ -5523,15 +5637,17 @@ } } +#if !GTK_CHECK_VERSION(3,0,0) static void headline_style_set (GtkWidget *widget, GtkStyle *prev_style) { + PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); GtkStyle *style; #if GTK_CHECK_VERSION(2,12,0) GtkWidget *window; - if (gtkblist->changing_style) + if (priv->changing_style) return; /* This is a hack needed to use the tooltip background colour */ @@ -5540,13 +5656,13 @@ gtk_widget_ensure_style(window); style = gtk_widget_get_style(window); - gtkblist->changing_style = TRUE; - gtk_widget_set_style(gtkblist->headline_hbox, style); - gtkblist->changing_style = FALSE; + priv->changing_style = TRUE; + gtk_widget_set_style(gtkblist->headline, style); + priv->changing_style = FALSE; gtk_widget_destroy(window); - gtk_widget_queue_draw(gtkblist->headline_hbox); + gtk_widget_queue_draw(gtkblist->headline); #else GtkTooltips *tooltips; @@ -5560,13 +5676,14 @@ gtk_widget_ensure_style (tooltips->tip_window); style = gtk_widget_get_style (tooltips->tip_window); - gtkblist->changing_style = TRUE; - gtk_widget_set_style (gtkblist->headline_hbox, style); - gtkblist->changing_style = FALSE; + priv->changing_style = TRUE; + gtk_widget_set_style (gtkblist->headline, style); + priv->changing_style = FALSE; g_object_unref (tooltips); #endif } +#endif /******************************************/ /* End of connection error handling stuff */ @@ -5796,8 +5913,13 @@ void *handle; GtkTreeViewColumn *column; GtkWidget *menu; + GtkWidget *sep; +#if GTK_CHECK_VERSION(3,0,0) + GtkWidget *infobar; + GtkWidget *content_area; +#else GtkWidget *ebox; - GtkWidget *sep; +#endif GtkWidget *label; GtkWidget *close; char *pretty, *tmp; @@ -5839,7 +5961,11 @@ G_CALLBACK(blist_focus_cb), gtkblist); g_signal_connect(G_OBJECT(gtkblist->window), "focus-out-event", G_CALLBACK(blist_focus_cb), gtkblist); + + /* TODO: how is this done in gtk+ 3.0? */ +#if !GTK_CHECK_VERSION(3,0,0) GTK_WINDOW(gtkblist->window)->allow_shrink = TRUE; +#endif gtkblist->main_vbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(gtkblist->main_vbox); @@ -5913,7 +6039,6 @@ pretty = pidgin_make_pretty_arrows(tmp); g_free(tmp); label = gtk_label_new(NULL); - gtk_widget_set_size_request(label, purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width") - 12, -1); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.2); gtk_label_set_markup(GTK_LABEL(label), pretty); @@ -5924,46 +6049,86 @@ gtk_widget_show_all(gtkblist->notebook); pidgin_blist_select_notebook_page(gtkblist); + /****************************** Headline **********************************/ +#if GTK_CHECK_VERSION(3,0,0) + + gtkblist->headline = gtk_event_box_new(); + gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->headline, + FALSE, FALSE, 0); + infobar = gtk_info_bar_new(); + gtk_container_add(GTK_CONTAINER(gtkblist->headline), infobar); + gtk_info_bar_set_default_response(GTK_INFO_BAR(infobar), GTK_RESPONSE_OK); + gtk_info_bar_set_message_type(GTK_INFO_BAR(infobar), GTK_MESSAGE_INFO); + + content_area = gtk_info_bar_get_content_area(GTK_INFO_BAR(infobar)); + gtkblist->headline_image = gtk_image_new_from_pixbuf(NULL); + gtk_misc_set_alignment(GTK_MISC(gtkblist->headline_image), 0.5, 0.5); + gtkblist->headline_label = gtk_label_new(NULL); + gtk_label_set_line_wrap(GTK_LABEL(gtkblist->headline_label), TRUE); + gtk_box_pack_start(GTK_BOX(content_area), gtkblist->headline_image, + FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(content_area), gtkblist->headline_label, + TRUE, TRUE, 0); + + close = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); + close = pidgin_create_small_button(close); + gtk_widget_set_tooltip_text(close, _("Close")); + gtk_info_bar_add_action_widget(GTK_INFO_BAR(infobar), close, + GTK_RESPONSE_CLOSE); + + g_signal_connect(infobar, "response", G_CALLBACK(headline_response_cb), + gtkblist); + g_signal_connect(infobar, "close", G_CALLBACK(gtk_info_bar_response), + GINT_TO_POINTER(GTK_RESPONSE_CLOSE)); + g_signal_connect(gtkblist->headline, "realize", + G_CALLBACK(headline_realize_cb), NULL); + g_signal_connect(gtkblist->headline, "button-press-event", + G_CALLBACK(headline_press_cb), infobar); + +#else + ebox = gtk_event_box_new(); gtk_box_pack_start(GTK_BOX(gtkblist->vbox), ebox, FALSE, FALSE, 0); - gtkblist->headline_hbox = gtk_hbox_new(FALSE, 3); - gtk_container_set_border_width(GTK_CONTAINER(gtkblist->headline_hbox), 6); - gtk_container_add(GTK_CONTAINER(ebox), gtkblist->headline_hbox); + gtkblist->headline = gtk_hbox_new(FALSE, 3); + gtk_container_set_border_width(GTK_CONTAINER(gtkblist->headline), 6); + gtk_container_add(GTK_CONTAINER(ebox), gtkblist->headline); gtkblist->headline_image = gtk_image_new_from_pixbuf(NULL); gtk_misc_set_alignment(GTK_MISC(gtkblist->headline_image), 0.0, 0); gtkblist->headline_label = gtk_label_new(NULL); gtk_widget_set_size_request(gtkblist->headline_label, purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width")-25,-1); gtk_label_set_line_wrap(GTK_LABEL(gtkblist->headline_label), TRUE); - gtk_box_pack_start(GTK_BOX(gtkblist->headline_hbox), gtkblist->headline_image, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(gtkblist->headline_hbox), gtkblist->headline_label, TRUE, TRUE, 0); - g_signal_connect(gtkblist->headline_label, /* connecting on headline_hbox doesn't work, because + gtk_box_pack_start(GTK_BOX(gtkblist->headline), gtkblist->headline_image, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(gtkblist->headline), gtkblist->headline_label, TRUE, TRUE, 0); + g_signal_connect(gtkblist->headline_label, /* connecting on headline doesn't work, because the signal is not emitted when theme is changed */ "style-set", G_CALLBACK(headline_style_set), NULL); - g_signal_connect (gtkblist->headline_hbox, + g_signal_connect (gtkblist->headline, "expose_event", G_CALLBACK (paint_headline_hbox), NULL); - gtk_widget_set_name(gtkblist->headline_hbox, "gtk-tooltips"); - - gtkblist->hand_cursor = gdk_cursor_new (GDK_HAND2); - gtkblist->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); + gtk_widget_set_name(gtkblist->headline, "gtk-tooltips"); + + priv->hand_cursor = gdk_cursor_new (GDK_HAND2); + priv->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR); /* Close button. */ close = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); close = pidgin_create_small_button(close); - gtk_box_pack_start(GTK_BOX(gtkblist->headline_hbox), close, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(gtkblist->headline), close, FALSE, FALSE, 0); #if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(close, _("Close")); #endif g_signal_connect(close, "clicked", G_CALLBACK(headline_close_press_cb), gtkblist); - g_signal_connect(G_OBJECT(ebox), "enter-notify-event", G_CALLBACK(headline_box_enter_cb), gtkblist); - g_signal_connect(G_OBJECT(ebox), "leave-notify-event", G_CALLBACK(headline_box_leave_cb), gtkblist); + g_signal_connect(G_OBJECT(ebox), "enter-notify-event", G_CALLBACK(headline_box_enter_cb), priv); + g_signal_connect(G_OBJECT(ebox), "leave-notify-event", G_CALLBACK(headline_box_leave_cb), priv); g_signal_connect(G_OBJECT(ebox), "button-press-event", G_CALLBACK(headline_box_press_cb), gtkblist); +#endif + /****************************** GtkTreeView **********************************/ gtkblist->treemodel = gtk_tree_store_new(BLIST_COLUMNS, GDK_TYPE_PIXBUF, /* Status icon */ @@ -6062,7 +6227,9 @@ gtkblist->statusbox = pidgin_status_box_new(); gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->statusbox, FALSE, TRUE, 0); gtk_widget_set_name(gtkblist->statusbox, "pidgin_blist_statusbox"); +#if !GTK_CHECK_VERSION(3,0,0) gtk_container_set_border_width(GTK_CONTAINER(gtkblist->statusbox), 3); +#endif gtk_widget_show(gtkblist->statusbox); /* set the Show Offline Buddies option. must be done @@ -6173,7 +6340,7 @@ PURPLE_CALLBACK(conversation_created_cb), gtkblist); - gtk_widget_hide(gtkblist->headline_hbox); + gtk_widget_hide(gtkblist->headline); show_initial_account_errors(gtkblist); @@ -6963,12 +7130,15 @@ g_object_unref(G_OBJECT(gtkblist->ui)); g_object_unref(G_OBJECT(gtkblist->empty_avatar)); - gdk_cursor_unref(gtkblist->hand_cursor); - gdk_cursor_unref(gtkblist->arrow_cursor); - gtkblist->hand_cursor = NULL; - gtkblist->arrow_cursor = NULL; - priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); + +#if !GTK_CHECK_VERSION(3,0,0) + gdk_cursor_unref(priv->hand_cursor); + gdk_cursor_unref(priv->arrow_cursor); + priv->hand_cursor = NULL; + priv->arrow_cursor = NULL; +#endif + if (priv->current_theme) g_object_unref(priv->current_theme); g_free(priv); @@ -6985,7 +7155,8 @@ return; if (show) { - if(!PIDGIN_WINDOW_ICONIFIED(gtkblist->window) && !gtk_widget_get_visible(gtkblist->window)) + if(!PIDGIN_WINDOW_ICONIFIED(gtkblist->window) && + !gtk_widget_get_visible(gtkblist->window)) purple_signal_emit(pidgin_blist_get_handle(), "gtkblist-unhiding", gtkblist); pidgin_blist_restore_position(); gtk_window_present(GTK_WINDOW(gtkblist->window)); @@ -7054,6 +7225,7 @@ invite_enabled = FALSE; gtk_widget_set_sensitive(data->entry_for_invite, invite_enabled); + set_sensitive_if_input_buddy_cb(data->entry, data); } static void @@ -7179,8 +7351,8 @@ gtk_entry_set_activates_default (GTK_ENTRY(data->entry), TRUE); g_signal_connect(G_OBJECT(data->entry), "changed", - G_CALLBACK(pidgin_set_sensitive_if_input), - data->rq_data.window); + G_CALLBACK(set_sensitive_if_input_buddy_cb), + data); data->entry_for_alias = gtk_entry_new(); pidgin_add_widget_to_vbox(data->rq_data.vbox, _("(Optional) A_lias:"), @@ -7455,9 +7627,9 @@ gtkblist->headline_destroy = destroy; if (text != NULL || pixbuf != NULL) { set_urgent(); - gtk_widget_show_all(gtkblist->headline_hbox); + gtk_widget_show_all(gtkblist->headline); } else { - gtk_widget_hide(gtkblist->headline_hbox); + gtk_widget_hide(gtkblist->headline); } } @@ -7957,7 +8129,7 @@ if(PURPLE_BLIST_NODE_IS_CONTACT(n)) { for (n2 = n->child; n2; n2 = n2->next) { - buddy = (PurpleBuddy*)n2; + buddy = (PurpleBuddy*)n2; this_log_activity_score += purple_log_get_activity_score(PURPLE_LOG_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); } this_buddy_name = purple_contact_get_alias((PurpleContact*)n); @@ -7993,7 +8165,7 @@ } static void -plugin_act(GtkObject *obj, PurplePluginAction *pam) +plugin_act(GtkWidget *obj, PurplePluginAction *pam) { if (pam && pam->callback) pam->callback(pam);
--- a/pidgin/gtkblist.h Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkblist.h Mon Aug 06 18:11:44 2012 +0200 @@ -103,17 +103,13 @@ PurpleBlistNode *selected_node; /**< The currently selected node */ - GdkCursor *hand_cursor; /**< Hand cursor */ - GdkCursor *arrow_cursor; /**< Arrow cursor */ - GtkWidget *scrollbook; /**< Scrollbook for alerts */ - GtkWidget *headline_hbox; /**< Hbox for headline notification */ - GtkWidget *headline_label; /**< Label for headline notifications */ + GtkWidget *headline; /**< Widget for headline notifications */ + GtkWidget *headline_label; /**< Label for headline notifications */ GtkWidget *headline_image; /**< Image for headline notifications */ GCallback headline_callback; /**< Callback for headline notifications */ gpointer headline_data; /**< User data for headline notifications */ GDestroyNotify headline_destroy; /**< Callback to use for destroying the headline-data */ - gboolean changing_style; /**< True when changing GTK+ theme style */ GtkWidget *statusbox; /**< The status selector dropdown */ GdkPixbuf *empty_avatar; /**< A 32x32 transparent pixbuf */
--- a/pidgin/gtkcellrendererexpander.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkcellrendererexpander.c Mon Aug 06 18:11:44 2012 +0200 @@ -32,6 +32,14 @@ #include <gtk/gtk.h> #include "gtkcellrendererexpander.h" +#include "gtk3compat.h" + +#if GTK_CHECK_VERSION(3,0,0) +#define GTK3_CONST const +#else +#define GTK3_CONST +#endif + static void pidgin_cell_renderer_expander_get_property (GObject *object, guint param_id, GValue *value, @@ -44,24 +52,30 @@ static void pidgin_cell_renderer_expander_class_init (PidginCellRendererExpanderClass *class); static void pidgin_cell_renderer_expander_get_size (GtkCellRenderer *cell, GtkWidget *widget, - GdkRectangle *cell_area, + GTK3_CONST GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height); static void pidgin_cell_renderer_expander_render (GtkCellRenderer *cell, +#if GTK_CHECK_VERSION(3,0,0) + cairo_t *cr, +#else GdkWindow *window, +#endif GtkWidget *widget, - GdkRectangle *background_area, - GdkRectangle *cell_area, - GdkRectangle *expose_area, - guint flags); + GTK3_CONST GdkRectangle *background_area, + GTK3_CONST GdkRectangle *cell_area, +#if !GTK_CHECK_VERSION(3,0,0) + GdkRectangle *export_area, +#endif + GtkCellRendererState flags); static gboolean pidgin_cell_renderer_expander_activate (GtkCellRenderer *r, GdkEvent *event, GtkWidget *widget, const gchar *p, - GdkRectangle *bg, - GdkRectangle *cell, + GTK3_CONST GdkRectangle *bg, + GTK3_CONST GdkRectangle *cell, GtkCellRendererState flags); static void pidgin_cell_renderer_expander_finalize (GObject *gobject); @@ -108,9 +122,9 @@ static void pidgin_cell_renderer_expander_init (PidginCellRendererExpander *cellexpander) { - GTK_CELL_RENDERER(cellexpander)->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE; - GTK_CELL_RENDERER(cellexpander)->xpad = 0; - GTK_CELL_RENDERER(cellexpander)->ypad = 2; + g_object_set(G_OBJECT(cellexpander), "mode", + GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL); + gtk_cell_renderer_set_padding(GTK_CELL_RENDERER(cellexpander), 0, 2); } static void pidgin_cell_renderer_expander_class_init (PidginCellRendererExpanderClass *class) @@ -188,9 +202,10 @@ return g_object_new(PIDGIN_TYPE_GTK_CELL_RENDERER_EXPANDER, NULL); } -static void pidgin_cell_renderer_expander_get_size (GtkCellRenderer *cell, +static void +pidgin_cell_renderer_expander_get_size (GtkCellRenderer *cell, GtkWidget *widget, - GdkRectangle *cell_area, + GTK3_CONST GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, @@ -199,11 +214,17 @@ gint calc_width; gint calc_height; gint expander_size; + gint xpad; + gint ypad; + gfloat xalign; + gfloat yalign; gtk_widget_style_get(widget, "expander-size", &expander_size, NULL); - calc_width = (gint) cell->xpad * 2 + expander_size; - calc_height = (gint) cell->ypad * 2 + expander_size; + gtk_cell_renderer_get_padding(cell, &xpad, &ypad); + gtk_cell_renderer_get_alignment(cell, &xalign, &yalign); + calc_width = (gint) xpad * 2 + expander_size; + calc_height = (gint) ypad * 2 + expander_size; if (width) *width = calc_width; @@ -215,74 +236,101 @@ { if (x_offset) { - *x_offset = cell->xalign * (cell_area->width - calc_width); + *x_offset = xalign * (cell_area->width - calc_width); *x_offset = MAX (*x_offset, 0); } if (y_offset) { - *y_offset = cell->yalign * (cell_area->height - calc_height); + *y_offset = yalign * (cell_area->height - calc_height); *y_offset = MAX (*y_offset, 0); } } } -static void pidgin_cell_renderer_expander_render(GtkCellRenderer *cell, - GdkWindow *window, - GtkWidget *widget, - GdkRectangle *background_area, - GdkRectangle *cell_area, - GdkRectangle *expose_area, - guint flags) +static void +pidgin_cell_renderer_expander_render(GtkCellRenderer *cell, +#if GTK_CHECK_VERSION(3,0,0) + cairo_t *cr, +#else + GdkWindow *window, +#endif + GtkWidget *widget, + GTK3_CONST GdkRectangle *background_area, + GTK3_CONST GdkRectangle *cell_area, +#if !GTK_CHECK_VERSION(3,0,0) + GdkRectangle *expose_area, +#endif + GtkCellRendererState flags) { PidginCellRendererExpander *cellexpander = (PidginCellRendererExpander *) cell; gboolean set; gint width, height; GtkStateType state; + gint xpad; + gint ypad; + gboolean is_expanded; + GtkAllocation allocation; if (!cellexpander->is_expander) return; + gtk_cell_renderer_get_padding(cell, &xpad, &ypad); + g_object_get(G_OBJECT(cell), "is-expanded", &is_expanded, NULL); + width = cell_area->width; height = cell_area->height; - if (!cell->sensitive) + if (!gtk_widget_get_sensitive(widget)) state = GTK_STATE_INSENSITIVE; else if (flags & GTK_CELL_RENDERER_PRELIT) state = GTK_STATE_PRELIGHT; -#if GTK_CHECK_VERSION(2,18,0) - else if (gtk_widget_has_focus (widget) && flags & GTK_CELL_RENDERER_SELECTED) + else if (gtk_widget_has_focus(widget) && flags & GTK_CELL_RENDERER_SELECTED) state = GTK_STATE_ACTIVE; -#else - else if (GTK_WIDGET_HAS_FOCUS (widget) && flags & GTK_CELL_RENDERER_SELECTED) - state = GTK_STATE_ACTIVE; -#endif else state = GTK_STATE_NORMAL; - width -= cell->xpad*2; - height -= cell->ypad*2; + width -= xpad*2; + height -= ypad*2; - gtk_paint_expander (widget->style, - window, state, - NULL, widget, "treeview", - cell_area->x + cell->xpad + (width / 2), - cell_area->y + cell->ypad + (height / 2), - cell->is_expanded ? GTK_EXPANDER_EXPANDED : GTK_EXPANDER_COLLAPSED); +#if GTK_CHECK_VERSION(3,0,0) + gtk_paint_expander(gtk_widget_get_style(widget), + cr, state, + widget, "treeview", + cell_area->x + xpad + (width / 2), + cell_area->y + ypad + (height / 2), + is_expanded ? GTK_EXPANDER_EXPANDED : GTK_EXPANDER_COLLAPSED); +#else + gtk_paint_expander(gtk_widget_get_style(widget), + window, state, + NULL, widget, "treeview", + cell_area->x + cell->xpad + (width / 2), + cell_area->y + cell->ypad + (height / 2), + is_expanded ? GTK_EXPANDER_EXPANDED : GTK_EXPANDER_COLLAPSED); +#endif /* only draw the line if the color isn't set - this prevents a bug where the hline appears only under the expander */ g_object_get(cellexpander, "cell-background-set", &set, NULL); - if (cell->is_expanded && !set) - gtk_paint_hline (widget->style, window, state, NULL, widget, NULL, 0, - widget->allocation.width, cell_area->y + cell_area->height); + gtk_widget_get_allocation(widget, &allocation); + +#if GTK_CHECK_VERSION(3,0,0) + if (is_expanded && !set) + gtk_paint_hline(gtk_widget_get_style(widget), cr, state, widget, NULL, 0, + allocation.width, cell_area->y + cell_area->height); +#else + if (is_expanded && !set) + gtk_paint_hline(gtk_widget_get_style(widget), window, state, NULL, widget, NULL, 0, + allocation.width, cell_area->y + cell_area->height); +#endif } -static gboolean pidgin_cell_renderer_expander_activate(GtkCellRenderer *r, +static gboolean +pidgin_cell_renderer_expander_activate(GtkCellRenderer *r, GdkEvent *event, GtkWidget *widget, const gchar *p, - GdkRectangle *bg, - GdkRectangle *cell, + GTK3_CONST GdkRectangle *bg, + GTK3_CONST GdkRectangle *cell, GtkCellRendererState flags) { GtkTreePath *path = gtk_tree_path_new_from_string(p);
--- a/pidgin/gtkcertmgr.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkcertmgr.c Mon Aug 06 18:11:44 2012 +0200 @@ -613,7 +613,11 @@ win = dlg->window = pidgin_create_dialog(_("Certificate Manager"),/* Title */ +#if GTK_CHECK_VERSION(3,0,0) + 0, /*Window border*/ +#else PIDGIN_HIG_BORDER, /*Window border*/ +#endif "certmgr", /* Role */ TRUE); /* Allow resizing */ g_signal_connect(G_OBJECT(win), "delete_event",
--- a/pidgin/gtkconv.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkconv.c Mon Aug 06 18:11:44 2012 +0200 @@ -80,14 +80,8 @@ #include "gtknickcolors.h" -#if !GTK_CHECK_VERSION(2,20,0) -#define gtk_widget_get_realized(x) GTK_WIDGET_REALIZED(x) - -#if !GTK_CHECK_VERSION(2,18,0) -#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x) -#define gtk_widget_is_drawable(x) GTK_WIDGET_DRAWABLE(x) -#endif -#endif +#define GTK_TOOLTIPS_VAR gtkconv->tooltips +#include "gtk3compat.h" /** * A GTK+ Instant Message pane. @@ -168,6 +162,16 @@ static GdkColor *nick_colors = NULL; static guint nbr_nick_colors; +/* These probably won't conflict with any WebKit values. */ +#define PIDGIN_DRAG_BLIST_NODE (1337) +#define PIDGIN_DRAG_IM_CONTACT (31337) + +static const GtkTargetEntry dnd_targets[] = +{ + {"PURPLE_BLIST_NODE", GTK_TARGET_SAME_APP, PIDGIN_DRAG_BLIST_NODE}, + {"application/x-im-contact", 0, PIDGIN_DRAG_IM_CONTACT} +}; + typedef struct { GtkWidget *window; @@ -846,7 +850,7 @@ static void invite_dnd_recv(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, - GtkSelectionData *sd, guint inf, guint t, gpointer data) + GtkSelectionData *sd, guint dnd_info, guint t, gpointer data) { InviteBuddyInfo *info = (InviteBuddyInfo *)data; const char *convprotocol; @@ -854,12 +858,13 @@ convprotocol = purple_account_get_protocol_id(purple_conversation_get_account(info->conv)); - if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE)) + if (dnd_info == PIDGIN_DRAG_BLIST_NODE) { PurpleBlistNode *node = NULL; PurpleBuddy *buddy; - - memcpy(&node, sd->data, sizeof(node)); + const guchar *data = gtk_selection_data_get_data(sd); + + memcpy(&node, data, sizeof(node)); if (PURPLE_BLIST_NODE_IS_CONTACT(node)) buddy = purple_contact_get_priority_buddy((PurpleContact *)node); @@ -878,15 +883,16 @@ else gtk_entry_set_text(GTK_ENTRY(info->entry), purple_buddy_get_name(buddy)); - gtk_drag_finish(dc, success, (dc->action == GDK_ACTION_MOVE), t); - } - else if (sd->target == gdk_atom_intern("application/x-im-contact", FALSE)) + gtk_drag_finish(dc, success, + gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); + } + else if (dnd_info == PIDGIN_DRAG_IM_CONTACT) { char *protocol = NULL; char *username = NULL; PurpleAccount *account; - if (pidgin_parse_x_im_contact((const char *)sd->data, FALSE, &account, + if (pidgin_parse_x_im_contact((const char *) data, FALSE, &account, &protocol, &username, NULL)) { if (account == NULL) @@ -911,15 +917,10 @@ g_free(username); g_free(protocol); - gtk_drag_finish(dc, success, (dc->action == GDK_ACTION_MOVE), t); - } -} - -static const GtkTargetEntry dnd_targets[] = -{ - {"PURPLE_BLIST_NODE", GTK_TARGET_SAME_APP, 0}, - {"application/x-im-contact", 0, 1} -}; + gtk_drag_finish(dc, success, + gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); + } +} static void invite_cb(GtkWidget *widget, PidginConversation *gtkconv) @@ -953,14 +954,11 @@ GTK_RESPONSE_OK); gtk_container_set_border_width(GTK_CONTAINER(invite_dialog), PIDGIN_HIG_BOX_SPACE); gtk_window_set_resizable(GTK_WINDOW(invite_dialog), FALSE); -#if !GTK_CHECK_VERSION(2,22,0) - gtk_dialog_set_has_separator(GTK_DIALOG(invite_dialog), FALSE); -#endif info->window = GTK_WIDGET(invite_dialog); /* Setup the outside spacing. */ - vbox = GTK_DIALOG(invite_dialog)->vbox; + vbox = gtk_dialog_get_content_area(GTK_DIALOG(invite_dialog)); gtk_box_set_spacing(GTK_BOX(vbox), PIDGIN_HIG_BORDER); gtk_container_set_border_width(GTK_CONTAINER(vbox), PIDGIN_HIG_BOX_SPACE); @@ -1142,7 +1140,6 @@ PurpleConversation *conv; PurpleLogType type; PidginBuddyList *gtkblist; - GdkCursor *cursor; const char *name; PurpleAccount *account; GSList *buddies; @@ -1159,10 +1156,8 @@ gtkblist = pidgin_blist_get_default_gtk_blist(); - cursor = gdk_cursor_new(GDK_WATCH); - gdk_window_set_cursor(gtkblist->window->window, cursor); - gdk_window_set_cursor(win->window->window, cursor); - gdk_cursor_unref(cursor); + pidgin_set_cursor(gtkblist->window, GDK_WATCH); + pidgin_set_cursor(win->window, GDK_WATCH); name = purple_conversation_get_name(conv); account = purple_conversation_get_account(conv); @@ -1175,8 +1170,8 @@ { pidgin_log_show_contact((PurpleContact *)node->parent); g_slist_free(buddies); - gdk_window_set_cursor(gtkblist->window->window, NULL); - gdk_window_set_cursor(win->window->window, NULL); + pidgin_clear_cursor(gtkblist->window); + pidgin_clear_cursor(win->window); return; } } @@ -1184,8 +1179,8 @@ pidgin_log_show(type, name, account); - gdk_window_set_cursor(gtkblist->window->window, NULL); - gdk_window_set_cursor(win->window->window, NULL); + pidgin_clear_cursor(gtkblist->window); + pidgin_clear_cursor(win->window); } static void @@ -1975,8 +1970,8 @@ /* If CTRL was held down... */ if (event->state & GDK_CONTROL_MASK) { switch (event->keyval) { - case GDK_Page_Down: - case GDK_KP_Page_Down: + case GDK_KEY_Page_Down: + case GDK_KEY_KP_Page_Down: case ']': if (!pidgin_conv_window_get_gtkconv_at_index(win, curconv + 1)) gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 0); @@ -1985,8 +1980,8 @@ return TRUE; break; - case GDK_Page_Up: - case GDK_KP_Page_Up: + case GDK_KEY_Page_Up: + case GDK_KEY_KP_Page_Up: case '[': if (!pidgin_conv_window_get_gtkconv_at_index(win, curconv - 1)) gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), -1); @@ -1995,9 +1990,9 @@ return TRUE; break; - case GDK_Tab: - case GDK_KP_Tab: - case GDK_ISO_Left_Tab: + case GDK_KEY_Tab: + case GDK_KEY_KP_Tab: + case GDK_KEY_ISO_Left_Tab: if (event->state & GDK_SHIFT_MASK) { move_to_next_unread_tab(gtkconv, FALSE); } else { @@ -2007,20 +2002,20 @@ return TRUE; break; - case GDK_comma: + case GDK_KEY_comma: gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook), gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv), curconv - 1); return TRUE; break; - case GDK_period: + case GDK_KEY_period: gtk_notebook_reorder_child(GTK_NOTEBOOK(win->notebook), gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), curconv), (curconv + 1) % gtk_notebook_get_n_pages(GTK_NOTEBOOK(win->notebook))); return TRUE; break; - case GDK_F6: + case GDK_KEY_F6: if (gtkconv_cycle_focus(gtkconv, event->state & GDK_SHIFT_MASK ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD)) return TRUE; break; @@ -2044,13 +2039,13 @@ else { switch (event->keyval) { - case GDK_F2: + case GDK_KEY_F2: if (gtk_widget_is_focus(GTK_WIDGET(win->notebook))) { infopane_entry_activate(gtkconv); return TRUE; } break; - case GDK_F6: + case GDK_KEY_F6: if (gtkconv_cycle_focus(gtkconv, event->state & GDK_SHIFT_MASK ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD)) return TRUE; break; @@ -2074,7 +2069,7 @@ /* If CTRL was held down... */ if (event->state & GDK_CONTROL_MASK) { switch (event->keyval) { - case GDK_Up: + case GDK_KEY_Up: if (!gtkconv->send_history) break; @@ -2125,7 +2120,7 @@ return TRUE; break; - case GDK_Down: + case GDK_KEY_Down: if (!gtkconv->send_history) break; @@ -2178,9 +2173,9 @@ /* If neither CTRL nor ALT were held down... */ else { switch (event->keyval) { - case GDK_Tab: - case GDK_KP_Tab: - case GDK_ISO_Left_Tab: + case GDK_KEY_Tab: + case GDK_KEY_KP_Tab: + case GDK_KEY_ISO_Left_Tab: if (gtkconv->entry != entry) break; { @@ -2192,14 +2187,14 @@ } break; - case GDK_Page_Up: - case GDK_KP_Page_Up: + case GDK_KEY_Page_Up: + case GDK_KEY_KP_Page_Up: gtk_webview_page_up(GTK_WEBVIEW(gtkconv->webview)); return TRUE; break; - case GDK_Page_Down: - case GDK_KP_Page_Down: + case GDK_KEY_Page_Down: + case GDK_KEY_KP_Page_Down: gtk_webview_page_down(GTK_WEBVIEW(gtkconv->webview)); return TRUE; break; @@ -2243,26 +2238,26 @@ /* If we have a valid key for the conversation display, then exit */ if ((event->state & GDK_CONTROL_MASK) || - (event->keyval == GDK_F6) || - (event->keyval == GDK_F10) || - (event->keyval == GDK_Shift_L) || - (event->keyval == GDK_Shift_R) || - (event->keyval == GDK_Control_L) || - (event->keyval == GDK_Control_R) || - (event->keyval == GDK_Escape) || - (event->keyval == GDK_Up) || - (event->keyval == GDK_Down) || - (event->keyval == GDK_Left) || - (event->keyval == GDK_Right) || - (event->keyval == GDK_Page_Up) || - (event->keyval == GDK_KP_Page_Up) || - (event->keyval == GDK_Page_Down) || - (event->keyval == GDK_KP_Page_Down) || - (event->keyval == GDK_Home) || - (event->keyval == GDK_End) || - (event->keyval == GDK_Tab) || - (event->keyval == GDK_KP_Tab) || - (event->keyval == GDK_ISO_Left_Tab)) + (event->keyval == GDK_KEY_F6) || + (event->keyval == GDK_KEY_F10) || + (event->keyval == GDK_KEY_Shift_L) || + (event->keyval == GDK_KEY_Shift_R) || + (event->keyval == GDK_KEY_Control_L) || + (event->keyval == GDK_KEY_Control_R) || + (event->keyval == GDK_KEY_Escape) || + (event->keyval == GDK_KEY_Up) || + (event->keyval == GDK_KEY_Down) || + (event->keyval == GDK_KEY_Left) || + (event->keyval == GDK_KEY_Right) || + (event->keyval == GDK_KEY_Page_Up) || + (event->keyval == GDK_KEY_KP_Page_Up) || + (event->keyval == GDK_KEY_Page_Down) || + (event->keyval == GDK_KEY_KP_Page_Down) || + (event->keyval == GDK_KEY_Home) || + (event->keyval == GDK_KEY_End) || + (event->keyval == GDK_KEY_Tab) || + (event->keyval == GDK_KEY_KP_Tab) || + (event->keyval == GDK_KEY_ISO_Left_Tab)) { if (event->type == GDK_KEY_PRESS) return conv_keypress_common(gtkconv, event); @@ -2732,7 +2727,7 @@ } static void -start_anim(GtkObject *obj, PidginConversation *gtkconv) +start_anim(GtkWidget *widget, PidginConversation *gtkconv) { int delay; @@ -2905,7 +2900,7 @@ } static void -stop_anim(GtkObject *obj, PidginConversation *gtkconv) +stop_anim(GtkWidget *widget, PidginConversation *gtkconv) { if (gtkconv->u.im->icon_timer != 0) g_source_remove(gtkconv->u.im->icon_timer); @@ -2927,7 +2922,7 @@ } static gboolean -icon_menu(GtkObject *obj, GdkEventButton *e, PidginConversation *gtkconv) +icon_menu(GtkWidget *widget, GdkEventButton *e, PidginConversation *gtkconv) { static GtkWidget *menu = NULL; PurpleConversation *conv; @@ -3769,10 +3764,10 @@ break; } if (gtkwin->menu.typing_icon == NULL) { - gtkwin->menu.typing_icon = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_MENU); - pidgin_menu_tray_append(PIDGIN_MENU_TRAY(gtkwin->menu.tray), - gtkwin->menu.typing_icon, - _("User is typing...")); + gtkwin->menu.typing_icon = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_MENU); + pidgin_menu_tray_append(PIDGIN_MENU_TRAY(gtkwin->menu.tray), + gtkwin->menu.typing_icon, + _("User is typing...")); } else { gtk_image_set_from_stock(GTK_IMAGE(gtkwin->menu.typing_icon), stock_id, GTK_ICON_SIZE_MENU); } @@ -4745,12 +4740,21 @@ GdkRectangle oneline; int height, diff; int pad_top, pad_inside, pad_bottom; - int total_height = (gtkconv->webview->allocation.height + gtkconv->entry->allocation.height); - int max_height = total_height / 2; + int total_height; + int max_height; int min_lines = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines"); int min_height; gboolean interior_focus; int focus_width; + GtkAllocation webview_allocation; + GtkAllocation entry_allocation; + GtkAllocation lower_hbox_allocation; + + gtk_widget_get_allocation(gtkconv->webview, &webview_allocation); + gtk_widget_get_allocation(gtkconv->entry, &entry_allocation); + gtk_widget_get_allocation(gtkconv->lower_hbox, &lower_hbox_allocation); + total_height = webview_allocation.height + entry_allocation.height; + max_height = total_height / 2; pad_top = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(gtkconv->entry)); pad_bottom = gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(gtkconv->entry)); @@ -4784,12 +4788,15 @@ if (!interior_focus) height += 2 * focus_width; - diff = height - gtkconv->entry->allocation.height; + diff = height - entry_allocation.height; if (ABS(diff) < oneline.height / 2) return FALSE; + purple_debug_info("pidgin", "resizing to %d, %d lines, diff %d\n", + diff + lower_hbox_allocation.height, min_lines, diff); + gtk_widget_set_size_request(gtkconv->lower_hbox, -1, - diff + gtkconv->lower_hbox->allocation.height); + diff + lower_hbox_allocation.height); return FALSE; } @@ -4836,7 +4843,7 @@ if(prpl_info->set_chat_topic == NULL) { gtk_editable_set_editable(GTK_EDITABLE(gtkchat->topic_text), FALSE); } else { - g_signal_connect(GTK_OBJECT(gtkchat->topic_text), "activate", + g_signal_connect(G_OBJECT(gtkchat->topic_text), "activate", G_CALLBACK(topic_callback), gtkconv); } @@ -5007,7 +5014,7 @@ gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL); webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(gtkconv->webview)); - gtk_widget_hide_all(gtkconv->quickfind.container); + gtk_widget_hide(gtkconv->quickfind.container); gtk_widget_grab_focus(gtkconv->entry); return TRUE; @@ -5017,8 +5024,8 @@ quickfind_process_input(GtkWidget *entry, GdkEventKey *event, PidginConversation *gtkconv) { switch (event->keyval) { - case GDK_Return: - case GDK_KP_Enter: + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: if (webkit_web_view_search_text(WEBKIT_WEB_VIEW(gtkconv->webview), gtk_entry_get_text(GTK_ENTRY(entry)), FALSE, TRUE, TRUE)) { gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL); } else { @@ -5029,7 +5036,7 @@ gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, &col); } break; - case GDK_Escape: + case GDK_KEY_Escape: pidgin_conv_end_quickfind(gtkconv); break; default: @@ -5048,12 +5055,7 @@ close = pidgin_create_small_button(gtk_label_new("×")); gtk_box_pack_start(GTK_BOX(widget), close, FALSE, FALSE, 0); -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(close, _("Close Find bar")); -#else - gtk_tooltips_set_tip(gtkconv->tooltips, close, - _("Close Find bar"), NULL); -#endif label = gtk_label_new(_("Find:")); gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 10); @@ -5491,8 +5493,10 @@ PurpleAccount *convaccount = purple_conversation_get_account(conv); PurpleConnection *gc = purple_account_get_connection(convaccount); PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL; - - if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE)) + GdkAtom target = gtk_selection_data_get_target(sd); + const guchar *data = gtk_selection_data_get_data(sd); + + if (info == PIDGIN_DRAG_BLIST_NODE) { PurpleBlistNode *n = NULL; PurpleBuddy *b; @@ -5500,7 +5504,7 @@ PurpleAccount *buddyaccount; const char *buddyname; - n = *(PurpleBlistNode **)sd->data; + n = *(PurpleBlistNode **) data; if (PURPLE_BLIST_NODE_IS_CONTACT(n)) b = purple_contact_get_priority_buddy((PurpleContact*)n); @@ -5548,16 +5552,17 @@ pidgin_conv_window_switch_gtkconv(win, gtkconv); } - gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); - } - else if (sd->target == gdk_atom_intern("application/x-im-contact", FALSE)) + gtk_drag_finish(dc, TRUE, + gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); + } + else if (info == PIDGIN_DRAG_IM_CONTACT) { char *protocol = NULL; char *username = NULL; PurpleAccount *account; PidginConversation *gtkconv; - if (pidgin_parse_x_im_contact((const char *)sd->data, FALSE, &account, + if (pidgin_parse_x_im_contact((const char *) data, FALSE, &account, &protocol, &username, NULL)) { if (account == NULL) @@ -5588,12 +5593,14 @@ g_free(username); g_free(protocol); - gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); - } - else if (sd->target == gdk_atom_intern("text/uri-list", FALSE)) { + gtk_drag_finish(dc, TRUE, + gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); + } + else if (target == gdk_atom_intern("text/uri-list", FALSE)) { if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) pidgin_dnd_file_manage(sd, convaccount, purple_conversation_get_name(conv)); - gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); + gtk_drag_finish(dc, TRUE, + gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); } else gtk_drag_finish(dc, FALSE, FALSE, t); @@ -5603,8 +5610,8 @@ static const GtkTargetEntry te[] = { GTK_IMHTML_DND_TARGETS, - {"PURPLE_BLIST_NODE", GTK_TARGET_SAME_APP, GTK_IMHTML_DRAG_NUM}, - {"application/x-im-contact", 0, GTK_IMHTML_DRAG_NUM + 1} + {"PURPLE_BLIST_NODE", GTK_TARGET_SAME_APP, PIDGIN_DRAG_BLIST_NODE}, + {"application/x-im-contact", 0, PIDGIN_DRAG_IM_CONTACT} }; static PidginConversation * @@ -5784,12 +5791,13 @@ g_signal_connect(G_OBJECT(pane), "button_press_event", G_CALLBACK(ignore_middle_click), NULL); - g_signal_connect(G_OBJECT(pane), "drag_data_received", - G_CALLBACK(conv_dnd_recv), gtkconv); - g_signal_connect(G_OBJECT(gtkconv->webview), "drag_data_received", - G_CALLBACK(conv_dnd_recv), gtkconv); - g_signal_connect(G_OBJECT(gtkconv->entry), "drag_data_received", - G_CALLBACK(conv_dnd_recv), gtkconv); +// TODO: this crashes with webkit, fix it +// g_signal_connect(G_OBJECT(pane), "drag_data_received", +// G_CALLBACK(conv_dnd_recv), gtkconv); +// g_signal_connect(G_OBJECT(gtkconv->webview), "drag_data_received", +// G_CALLBACK(conv_dnd_recv), gtkconv); +// g_signal_connect(G_OBJECT(gtkconv->entry), "drag_data_received", +// G_CALLBACK(conv_dnd_recv), gtkconv); g_signal_connect(gtkconv->webview, "style-set", G_CALLBACK(set_typing_font), gtkconv); @@ -6006,33 +6014,37 @@ GdkEventButton *btn_event = (GdkEventButton*) event; PurpleConversation *conv = data; char *buddyname; + gchar *name; + + g_object_get(G_OBJECT(tag), "name", &name, NULL); /* strlen("BUDDY " or "HILIT ") == 6 */ - g_return_val_if_fail((tag->name != NULL) - && (strlen(tag->name) > 6), FALSE); - - buddyname = (tag->name) + 6; + g_return_val_if_fail((name != NULL) && (strlen(name) > 6), FALSE); + + buddyname = name + 6; /* emit chat-nick-clicked signal */ if (event->type == GDK_BUTTON_PRESS) { gint plugin_return = GPOINTER_TO_INT(purple_signal_emit_return_1( pidgin_conversations_get_handle(), "chat-nick-clicked", data, buddyname, btn_event->button)); - if (plugin_return) + if (plugin_return) { + g_free(name); return TRUE; - } - - if (btn_event->button == 1 && - event->type == GDK_2BUTTON_PRESS) { + } + } + + if (btn_event->button == 1 && event->type == GDK_2BUTTON_PRESS) { chat_do_im(PIDGIN_CONVERSATION(conv), buddyname); - return TRUE; - } else if (btn_event->button == 2 - && event->type == GDK_2BUTTON_PRESS) { - chat_do_info(PIDGIN_CONVERSATION(conv), buddyname); + g_free(name); return TRUE; - } else if (btn_event->button == 3 - && event->type == GDK_BUTTON_PRESS) { + } else if (btn_event->button == 2 && event->type == GDK_2BUTTON_PRESS) { + chat_do_info(PIDGIN_CONVERSATION(conv), buddyname); + g_free(name); + + return TRUE; + } else if (btn_event->button == 3 && event->type == GDK_BUTTON_PRESS) { GtkTextIter start, end; /* we shouldn't display the popup @@ -6051,10 +6063,14 @@ btn_event->button, btn_event->time); + g_free(name); + /* Don't propagate the event any further */ return TRUE; } } + + g_free(name); } return FALSE; @@ -7289,13 +7305,8 @@ topic = purple_conv_chat_get_topic(chat); gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text), topic ? topic : ""); -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(gtkchat->topic_text, topic ? topic : ""); -#else - gtk_tooltips_set_tip(gtkconv->tooltips, gtkchat->topic_text, - topic ? topic : "", NULL); -#endif } } @@ -7306,7 +7317,7 @@ if ((fields & PIDGIN_CONV_COLORIZE_TITLE) || (fields & PIDGIN_CONV_SET_TITLE) || - (fields & PIDGIN_CONV_TOPIC)) + (fields & PIDGIN_CONV_TOPIC)) { char *title; PurpleConvIm *im = NULL; @@ -7672,7 +7683,7 @@ gtk_container_add(GTK_CONTAINER(gtkconv->u.im->icon_container), event); gtk_event_box_set_visible_window(GTK_EVENT_BOX(event), FALSE); gtk_widget_add_events(event, - GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); + GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); g_signal_connect(G_OBJECT(event), "button-press-event", G_CALLBACK(icon_menu), gtkconv); @@ -7714,11 +7725,14 @@ { gint pane_x, pane_y, x_rel; PidginConversation *gtkconv; - - gdk_window_get_origin(win->notebook->window, &pane_x, &pane_y); + GtkAllocation allocation; + + gdk_window_get_origin(gtk_widget_get_window(win->notebook), + &pane_x, &pane_y); x_rel = x - pane_x; gtkconv = pidgin_conv_window_get_active_gtkconv(win); - return (x_rel > gtkconv->infopane->allocation.x + gtkconv->infopane->allocation.width / 2); + gtk_widget_get_allocation(gtkconv->infopane, &allocation); + return (x_rel > allocation.x + allocation.width / 2); } int @@ -7736,7 +7750,7 @@ notebook = GTK_NOTEBOOK(win->notebook); - gdk_window_get_origin(win->notebook->window, &nb_x, &nb_y); + gdk_window_get_origin(gtk_widget_get_window(win->notebook), &nb_x, &nb_y); x_rel = x - nb_x; y_rel = y - nb_y; @@ -7746,30 +7760,32 @@ count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook)); for (i = 0; i < count; i++) { + GtkAllocation allocation; page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), i); tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page); + gtk_widget_get_allocation(tab, &allocation); /* Make sure the tab is not hidden beyond an arrow */ if (!gtk_widget_is_drawable(tab) && gtk_notebook_get_show_tabs(notebook)) continue; if (horiz) { - if (x_rel >= tab->allocation.x - PIDGIN_HIG_BOX_SPACE && - x_rel <= tab->allocation.x + tab->allocation.width + PIDGIN_HIG_BOX_SPACE) { + if (x_rel >= allocation.x - PIDGIN_HIG_BOX_SPACE && + x_rel <= allocation.x + allocation.width + PIDGIN_HIG_BOX_SPACE) { page_num = i; - if (to_right && x_rel >= tab->allocation.x + tab->allocation.width/2) + if (to_right && x_rel >= allocation.x + allocation.width/2) *to_right = TRUE; break; } } else { - if (y_rel >= tab->allocation.y - PIDGIN_HIG_BOX_SPACE && - y_rel <= tab->allocation.y + tab->allocation.height + PIDGIN_HIG_BOX_SPACE) { + if (y_rel >= allocation.y - PIDGIN_HIG_BOX_SPACE && + y_rel <= allocation.y + allocation.height + PIDGIN_HIG_BOX_SPACE) { page_num = i; - if (to_right && y_rel >= tab->allocation.y + tab->allocation.height/2) + if (to_right && y_rel >= allocation.y + allocation.height/2) *to_right = TRUE; break; @@ -8506,7 +8522,7 @@ purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/blist/show_protocol_icons", show_protocol_icons_pref_cb, NULL); purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/conversations/im/hide_new", - hide_new_pref_cb, NULL); + hide_new_pref_cb, NULL); @@ -8663,7 +8679,7 @@ window_list = g_list_remove(window_list, hidden_convwin); purple_signal_connect(purple_accounts_get_handle(), "account-status-changed", - handle, PURPLE_CALLBACK(account_status_changed_cb), NULL); + handle, PURPLE_CALLBACK(account_status_changed_cb), NULL); /* Callbacks to update a conversation */ purple_signal_connect(blist_handle, "blist-node-added", handle, @@ -8852,12 +8868,9 @@ gtk_container_set_border_width(GTK_CONTAINER(warn_close_dialog), 6); gtk_window_set_resizable(GTK_WINDOW(warn_close_dialog), FALSE); -#if !GTK_CHECK_VERSION(2,22,0) - gtk_dialog_set_has_separator(GTK_DIALOG(warn_close_dialog), FALSE); -#endif /* Setup the outside spacing. */ - vbox = GTK_DIALOG(warn_close_dialog)->vbox; + vbox = gtk_dialog_get_content_area(GTK_DIALOG(warn_close_dialog)); gtk_box_set_spacing(GTK_BOX(vbox), 12); gtk_container_set_border_width(GTK_CONTAINER(vbox), 6); @@ -9011,7 +9024,7 @@ always be true after a button press. */ if (!gdk_pointer_is_grabbed()) #endif - gdk_pointer_grab(gtkwin->notebook->window, FALSE, + gdk_pointer_grab(gtk_widget_get_window(gtkwin->notebook), FALSE, GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, NULL, cursor, GDK_CURRENT_TIME); } @@ -9131,6 +9144,9 @@ if (e->button == 1) { int nb_x, nb_y; + GtkAllocation allocation; + + gtk_widget_get_allocation(gtkconv->infopane_hbox, &allocation); if (gtkconv->win->in_drag) return TRUE; @@ -9138,12 +9154,12 @@ gtkconv->win->in_predrag = TRUE; gtkconv->win->drag_tab = gtk_notebook_page_num(GTK_NOTEBOOK(gtkconv->win->notebook), gtkconv->tab_cont); - gdk_window_get_origin(gtkconv->infopane_hbox->window, &nb_x, &nb_y); - - gtkconv->win->drag_min_x = gtkconv->infopane_hbox->allocation.x + nb_x; - gtkconv->win->drag_min_y = gtkconv->infopane_hbox->allocation.y + nb_y; - gtkconv->win->drag_max_x = gtkconv->infopane_hbox->allocation.width + gtkconv->win->drag_min_x; - gtkconv->win->drag_max_y = gtkconv->infopane_hbox->allocation.height + gtkconv->win->drag_min_y; + gdk_window_get_origin(gtk_widget_get_window(gtkconv->infopane_hbox), &nb_x, &nb_y); + + gtkconv->win->drag_min_x = allocation.x + nb_x; + gtkconv->win->drag_min_y = allocation.y + nb_y; + gtkconv->win->drag_max_x = allocation.width + gtkconv->win->drag_min_x; + gtkconv->win->drag_max_y = allocation.height + gtkconv->win->drag_min_y; gtkconv->win->drag_motion_signal = g_signal_connect(G_OBJECT(gtkconv->win->notebook), "motion_notify_event", G_CALLBACK(notebook_motion_cb), gtkconv->win); @@ -9185,6 +9201,7 @@ int tab_clicked; GtkWidget *page; GtkWidget *tab; + GtkAllocation allocation; if (e->button == 2 && e->type == GDK_BUTTON_PRESS) { PidginConversation *gtkconv; @@ -9222,7 +9239,7 @@ * Get the relative position of the press event, with regards to * the position of the notebook. */ - gdk_window_get_origin(win->notebook->window, &nb_x, &nb_y); + gdk_window_get_origin(gtk_widget_get_window(win->notebook), &nb_x, &nb_y); /* Reset the min/max x/y */ win->drag_min_x = 0; @@ -9234,10 +9251,12 @@ page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(win->notebook), tab_clicked); tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(win->notebook), page); - win->drag_min_x = tab->allocation.x + nb_x; - win->drag_min_y = tab->allocation.y + nb_y; - win->drag_max_x = tab->allocation.width + win->drag_min_x; - win->drag_max_y = tab->allocation.height + win->drag_min_y; + gtk_widget_get_allocation(tab, &allocation); + + win->drag_min_x = allocation.x + nb_x; + win->drag_min_y = allocation.y + nb_y; + win->drag_max_x = allocation.width + win->drag_min_x; + win->drag_max_y = allocation.height + win->drag_min_y; /* Make sure the click occurred in the tab. */ if (e->x_root < win->drag_min_x || @@ -9245,8 +9264,8 @@ e->y_root < win->drag_min_y || e->y_root >= win->drag_max_y) { - return FALSE; - } + return FALSE; + } win->in_predrag = TRUE; win->drag_tab = tab_clicked; @@ -9409,6 +9428,7 @@ stop_anim(NULL, gtkconv); } + static void close_window(GtkWidget *w, PidginWindow *win) { @@ -9416,17 +9436,16 @@ } static void -detach_tab_cb(GtkWidget *w, GObject *menu) -{ - PidginWindow *win, *new_window; +detach_tab_cb(GtkWidget *w, PidginWindow *win) +{ + PidginWindow *new_window; PidginConversation *gtkconv; - gtkconv = g_object_get_data(menu, "clicked_tab"); + gtkconv = win->clicked_tab; if (!gtkconv) return; - win = pidgin_conv_get_window(gtkconv); /* Nothing to do if there's only one tab in the window */ if (pidgin_conv_window_get_gtkconv_count(win) == 1) return; @@ -9439,19 +9458,16 @@ } static void -close_others_cb(GtkWidget *w, GObject *menu) +close_others_cb(GtkWidget *w, PidginWindow *win) { GList *iter; PidginConversation *gtkconv; - PidginWindow *win; - - gtkconv = g_object_get_data(menu, "clicked_tab"); + + gtkconv = win->clicked_tab; if (!gtkconv) return; - win = pidgin_conv_get_window(gtkconv); - for (iter = pidgin_conv_window_get_gtkconvs(win); iter; ) { PidginConversation *gconv = iter->data; @@ -9464,20 +9480,100 @@ } } -static void close_tab_cb(GtkWidget *w, GObject *menu) +static void +close_tab_cb(GtkWidget *w, PidginWindow *win) { PidginConversation *gtkconv; - gtkconv = g_object_get_data(menu, "clicked_tab"); + gtkconv = win->clicked_tab; if (gtkconv) close_conv_cb(NULL, gtkconv); } +static void +notebook_menu_switch_cb(GtkWidget *item, GtkWidget *child) +{ + GtkNotebook *notebook; + int index; + + notebook = GTK_NOTEBOOK(gtk_widget_get_parent(child)); + index = gtk_notebook_page_num(notebook, child); + gtk_notebook_set_current_page(notebook, index); +} + +static void +notebook_menu_update_label_cb(GtkWidget *child, GParamSpec *pspec, + GtkNotebook *notebook) +{ + GtkWidget *item; + GtkWidget *label; + + item = g_object_get_data(G_OBJECT(child), "popup-menu-item"); + label = gtk_bin_get_child(GTK_BIN(item)); + if (label) + gtk_container_remove(GTK_CONTAINER(item), label); + + label = gtk_notebook_get_menu_label(notebook, child); + if (label) { + gtk_widget_show(label); + gtk_container_add(GTK_CONTAINER(item), label); + gtk_widget_show(item); + } else { + gtk_widget_hide(item); + } +} + +static void +notebook_add_tab_to_menu_cb(GtkNotebook *notebook, GtkWidget *child, + guint page_num, PidginWindow *win) +{ + GtkWidget *item; + GtkWidget *label; + + item = gtk_menu_item_new(); + label = gtk_notebook_get_menu_label(notebook, child); + if (label) { + gtk_widget_show(label); + gtk_container_add(GTK_CONTAINER(item), label); + gtk_widget_show(item); + } + + g_signal_connect(child, "child-notify::menu-label", + G_CALLBACK(notebook_menu_update_label_cb), notebook); + g_signal_connect(item, "activate", + G_CALLBACK(notebook_menu_switch_cb), child); + g_object_set_data(G_OBJECT(child), "popup-menu-item", item); + + gtk_menu_shell_insert(GTK_MENU_SHELL(win->notebook_menu), item, page_num); +} + +static void +notebook_remove_tab_from_menu_cb(GtkNotebook *notebook, GtkWidget *child, + guint page_num, PidginWindow *win) +{ + GtkWidget *item; + + item = g_object_get_data(G_OBJECT(child), "popup-menu-item"); + gtk_container_remove(GTK_CONTAINER(win->notebook_menu), item); +} + + +static void +notebook_reorder_tab_in_menu_cb(GtkNotebook *notebook, GtkWidget *child, + guint page_num, PidginWindow *win) +{ + GtkWidget *item; + + item = g_object_get_data(G_OBJECT(child), "popup-menu-item"); + gtk_menu_reorder_child(GTK_MENU(win->notebook_menu), item, page_num); +} + static gboolean -right_click_menu_cb(GtkNotebook *notebook, GdkEventButton *event, PidginWindow *win) -{ - GtkWidget *item, *menu; +notebook_right_click_menu_cb(GtkNotebook *notebook, GdkEventButton *event, + PidginWindow *win) +{ + GtkWidget *menu; PidginConversation *gtkconv; if (event->type != GDK_BUTTON_PRESS || event->button != 3) @@ -9486,44 +9582,13 @@ gtkconv = pidgin_conv_window_get_gtkconv_at_index(win, pidgin_conv_get_tab_at_xy(win, event->x_root, event->y_root, NULL)); - if (g_object_get_data(G_OBJECT(notebook->menu), "clicked_tab")) - { - g_object_set_data(G_OBJECT(notebook->menu), "clicked_tab", gtkconv); - return FALSE; - } - - g_object_set_data(G_OBJECT(notebook->menu), "clicked_tab", gtkconv); - - menu = notebook->menu; - pidgin_separator(GTK_WIDGET(menu)); - - item = gtk_menu_item_new_with_label(_("Close other tabs")); - gtk_widget_show(item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(close_others_cb), menu); - - item = gtk_menu_item_new_with_label(_("Close all tabs")); - gtk_widget_show(item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(close_window), win); - - pidgin_separator(menu); - - item = gtk_menu_item_new_with_label(_("Detach this tab")); - gtk_widget_show(item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(detach_tab_cb), menu); - - item = gtk_menu_item_new_with_label(_("Close this tab")); - gtk_widget_show(item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(close_tab_cb), menu); - - return FALSE; + win->clicked_tab = gtkconv; + + menu = win->notebook_menu; + + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, event->time); + + return TRUE; } static void @@ -9546,7 +9611,7 @@ static gboolean alias_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data) { - if (event->keyval == GDK_Escape) { + if (event->keyval == GDK_KEY_Escape) { remove_edit_entry(user_data, widget); return TRUE; } @@ -9573,8 +9638,7 @@ PurpleBuddy *buddy; buddy = purple_find_buddy(account, name); if (buddy != NULL) { - purple_blist_alias_buddy(buddy, - gtk_entry_get_text(entry)); + purple_blist_alias_buddy(buddy, gtk_entry_get_text(entry)); } serv_alias_buddy(buddy); } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { @@ -9717,14 +9781,18 @@ make_status_icon_list(const char *stock, GtkWidget *w) { GList *l = NULL; - l = g_list_append(l, gtk_widget_render_icon (w, stock, - gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), "GtkWindow")); - l = g_list_append(l, gtk_widget_render_icon (w, stock, - gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_SMALL), "GtkWindow")); - l = g_list_append(l, gtk_widget_render_icon (w, stock, - gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MEDIUM), "GtkWindow")); - l = g_list_append(l, gtk_widget_render_icon (w, stock, - gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_LARGE), "GtkWindow")); + l = g_list_append(l, + gtk_widget_render_icon(w, stock, + gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), "GtkWindow")); + l = g_list_append(l, + gtk_widget_render_icon(w, stock, + gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_SMALL), "GtkWindow")); + l = g_list_append(l, + gtk_widget_render_icon(w, stock, + gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MEDIUM), "GtkWindow")); + l = g_list_append(l, + gtk_widget_render_icon(w, stock, + gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_LARGE), "GtkWindow")); return l; } @@ -9755,7 +9823,7 @@ /* Workaround for GTK+ bug # 169811 - "configure_event" is fired * when the window is being maximized */ - if (gdk_window_get_state(w->window) & GDK_WINDOW_STATE_MAXIMIZED) + if (gdk_window_get_state(gtk_widget_get_window(w)) & GDK_WINDOW_STATE_MAXIMIZED) return FALSE; /* don't save off-screen positioning */ @@ -9780,8 +9848,8 @@ pidgin_conv_set_position_size(PidginWindow *win, int conv_x, int conv_y, int conv_width, int conv_height) { - /* if the window exists, is hidden, we're saving positions, and the - * position is sane... */ + /* if the window exists, is hidden, we're saving positions, and the + * position is sane... */ if (win && win->window && !gtk_widget_get_visible(win->window) && conv_width != 0) { @@ -9820,6 +9888,8 @@ GtkPositionType pos; GtkWidget *testidea; GtkWidget *menubar; + GtkWidget *menu; + GtkWidget *item; GdkModifierType state; win = g_malloc0(sizeof(PidginWindow)); @@ -9864,12 +9934,48 @@ #endif gtk_notebook_set_tab_pos(GTK_NOTEBOOK(win->notebook), pos); gtk_notebook_set_scrollable(GTK_NOTEBOOK(win->notebook), TRUE); - gtk_notebook_popup_enable(GTK_NOTEBOOK(win->notebook)); gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE); gtk_notebook_set_show_border(GTK_NOTEBOOK(win->notebook), TRUE); + menu = win->notebook_menu = gtk_menu_new(); + + pidgin_separator(GTK_WIDGET(menu)); + + item = gtk_menu_item_new_with_label(_("Close other tabs")); + gtk_widget_show(item); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + g_signal_connect(G_OBJECT(item), "activate", + G_CALLBACK(close_others_cb), win); + + item = gtk_menu_item_new_with_label(_("Close all tabs")); + gtk_widget_show(item); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + g_signal_connect(G_OBJECT(item), "activate", + G_CALLBACK(close_window), win); + + pidgin_separator(menu); + + item = gtk_menu_item_new_with_label(_("Detach this tab")); + gtk_widget_show(item); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + g_signal_connect(G_OBJECT(item), "activate", + G_CALLBACK(detach_tab_cb), win); + + item = gtk_menu_item_new_with_label(_("Close this tab")); + gtk_widget_show(item); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + g_signal_connect(G_OBJECT(item), "activate", + G_CALLBACK(close_tab_cb), win); + + g_signal_connect(G_OBJECT(win->notebook), "page-added", + G_CALLBACK(notebook_add_tab_to_menu_cb), win); + g_signal_connect(G_OBJECT(win->notebook), "page-removed", + G_CALLBACK(notebook_remove_tab_from_menu_cb), win); + g_signal_connect(G_OBJECT(win->notebook), "page-reordered", + G_CALLBACK(notebook_reorder_tab_in_menu_cb), win); + g_signal_connect(G_OBJECT(win->notebook), "button-press-event", - G_CALLBACK(right_click_menu_cb), win); + G_CALLBACK(notebook_right_click_menu_cb), win); gtk_widget_show(win->notebook); @@ -9932,6 +10038,7 @@ } return; } + gtk_widget_destroy(win->notebook_menu); gtk_widget_destroy(win->window); g_object_unref(G_OBJECT(win->menu.ui)); @@ -9957,7 +10064,7 @@ void pidgin_conv_window_raise(PidginWindow *win) { - gdk_window_raise(GDK_WINDOW(win->window->window)); + gdk_window_raise(GDK_WINDOW(gtk_widget_get_window(win->window))); } void @@ -9971,9 +10078,6 @@ static gboolean gtkconv_tab_set_tip(GtkWidget *widget, GdkEventCrossing *event, PidginConversation *gtkconv) { -#if GTK_CHECK_VERSION(2, 12, 0) -#define gtk_tooltips_set_tip(tips, w, l, p) gtk_widget_set_tooltip_text(w, l) -#endif /* PANGO_VERSION_CHECK macro was introduced in 1.15. So we need this double check. */ #ifndef PANGO_VERSION_CHECK #define pango_layout_is_ellipsized(l) TRUE @@ -9983,13 +10087,12 @@ PangoLayout *layout; layout = gtk_label_get_layout(GTK_LABEL(gtkconv->tab_label)); - gtk_tooltips_set_tip(gtkconv->tooltips, widget, - pango_layout_is_ellipsized(layout) ? gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)) : NULL, - NULL); + if (pango_layout_is_ellipsized(layout)) + gtk_widget_set_tooltip_text(widget, gtk_label_get_text(GTK_LABEL(gtkconv->tab_label))); + else + gtk_widget_set_tooltip_text(widget, NULL); + return FALSE; -#if GTK_CHECK_VERSION(2, 12, 0) -#undef gtk_tooltips_set_tip -#endif } void @@ -10012,12 +10115,7 @@ /* Close button. */ gtkconv->close = pidgin_create_small_button(gtk_label_new("×")); -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(gtkconv->close, _("Close conversation")); -#else - gtk_tooltips_set_tip(gtkconv->tooltips, gtkconv->close, - _("Close conversation"), NULL); -#endif g_signal_connect(gtkconv->close, "clicked", G_CALLBACK (close_conv_cb), gtkconv); @@ -10132,7 +10230,7 @@ g_signal_connect(G_OBJECT(ebox), "enter-notify-event", G_CALLBACK(gtkconv_tab_set_tip), gtkconv); - if (gtkconv->tab_label->parent == NULL) { + if (gtk_widget_get_parent(gtkconv->tab_label) == NULL) { /* Pack if it's a new widget */ gtk_box_pack_start(GTK_BOX(gtkconv->tabby), first, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(gtkconv->tabby), gtkconv->tab_label, TRUE, TRUE, 0); @@ -10262,7 +10360,7 @@ for (l = pidgin_conv_windows_get_list(); l != NULL; l = l->next) { win = l->data; - if (gdkwin == win->window->window) + if (gdkwin == gtk_widget_get_window(win->window)) return win; } @@ -10391,7 +10489,7 @@ /* Workaround for GTK+ bug # 169811 - "configure_event" is fired * when the window is being maximized */ - if (gdk_window_get_state(w->window) & GDK_WINDOW_STATE_MAXIMIZED) + if (gdk_window_get_state(gtk_widget_get_window(w)) & GDK_WINDOW_STATE_MAXIMIZED) return FALSE; /* don't save off-screen positioning */
--- a/pidgin/gtkconvwin.h Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkconvwin.h Mon Aug 06 18:11:44 2012 +0200 @@ -42,6 +42,8 @@ { GtkWidget *window; /**< The window. */ GtkWidget *notebook; /**< The notebook of conversations. */ + GtkWidget *notebook_menu; /**< The menu on the notebook. */ + PidginConversation *clicked_tab; /**< The menu currently clicked. */ GList *gtkconvs; struct
--- a/pidgin/gtkdebug.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkdebug.c Mon Aug 06 18:11:44 2012 +0200 @@ -33,72 +33,59 @@ #include "gtkdebug.h" #include "gtkdialogs.h" -#include "gtkimhtml.h" #include "gtkutils.h" +#include "gtkwebview.h" #include "pidginstock.h" -#ifdef HAVE_REGEX_H -# include <regex.h> -# define USE_REGEX 1 -#else -#if GLIB_CHECK_VERSION(2,14,0) -# define USE_REGEX 1 -#endif -#endif /* HAVE_REGEX_H */ +#include <gdk/gdkkeysyms.h> -#include <gdk/gdkkeysyms.h> +#include "gtk3compat.h" typedef struct { GtkWidget *window; GtkWidget *text; - - GtkListStore *store; + GtkWidget *filter; + GtkWidget *expression; + GtkWidget *filterlevel; gboolean paused; -#ifdef USE_REGEX - GtkWidget *filter; - GtkWidget *expression; - gboolean invert; gboolean highlight; - guint timer; -# ifdef HAVE_REGEX_H - regex_t regex; -# else GRegex *regex; -# endif /* HAVE_REGEX_H */ -#else - GtkWidget *find; -#endif /* USE_REGEX */ - GtkWidget *filterlevel; } DebugWindow; -static const char debug_fg_colors[][8] = { - "#000000", /**< All debug levels. */ - "#666666", /**< Misc. */ - "#000000", /**< Information. */ - "#660000", /**< Warnings. */ - "#FF0000", /**< Errors. */ - "#FF0000", /**< Fatal errors. */ -}; +#define EMPTY_HTML \ + "<html><head><style>" \ + "body{white-space:pre-wrap;}" \ + "div.l0{color:#000000;}" /* All debug levels. */ \ + "div.l1{color:#666666;}" /* Misc. */ \ + "div.l2{color:#000000;}" /* Information. */ \ + "div.l3{color:#660000;}" /* Warnings. */ \ + "div.l4{color:#FF0000;}" /* Errors. */ \ + "div.l5{color:#FF0000;font-weight:bold;}" /* Fatal errors. */ \ + /* Filter levels */ \ + "div#pause~div{display:none;}" \ + "body.l1 div.l0{display:none;}" \ + "body.l2 div.l0,body.l2 div.l1{display:none;}" \ + "body.l3 div.l0,body.l3 div.l1,body.l3 div.l2{display:none;}" \ + "body.l4 div.l0,body.l4 div.l1,body.l4 div.l2,body.l4 div.l3{display:none;}" \ + "body.l5 div.l0,body.l5 div.l1,body.l5 div.l2,body.l5 div.l3,body.l5 div.l4{display:none;}" \ + /* Regex */ \ + "div.hide{display:none;}" \ + "span.regex{background-color:#ffafaf;font-weight:bold;}" \ + "</style></head><body class=l%d></body></html>" static DebugWindow *debug_win = NULL; static guint debug_enabled_timer = 0; -#ifdef USE_REGEX -static void regex_filter_all(DebugWindow *win); -static void regex_show_all(DebugWindow *win); -#endif /* USE_REGEX */ - static gint debug_window_destroy(GtkWidget *w, GdkEvent *event, void *unused) { purple_prefs_disconnect_by_handle(pidgin_debug_get_handle()); -#ifdef USE_REGEX if(debug_win->timer != 0) { const gchar *text; @@ -107,12 +94,7 @@ text = gtk_entry_get_text(GTK_ENTRY(debug_win->expression)); purple_prefs_set_string(PIDGIN_PREFS_ROOT "/debug/regex", text); } -#ifdef HAVE_REGEX_H - regfree(&debug_win->regex); -#else g_regex_unref(debug_win->regex); -#endif /* HAVE_REGEX_H */ -#endif /* USE_REGEX */ /* If the "Save Log" dialog is open then close it */ purple_request_close_with_handle(debug_win); @@ -128,11 +110,7 @@ static gboolean configure_cb(GtkWidget *w, GdkEventConfigure *event, DebugWindow *win) { -#if GTK_CHECK_VERSION(2,18,0) if (gtk_widget_get_visible(w)) { -#else - if (GTK_WIDGET_VISIBLE(w)) { -#endif purple_prefs_set_int(PIDGIN_PREFS_ROOT "/debug/width", event->width); purple_prefs_set_int(PIDGIN_PREFS_ROOT "/debug/height", event->height); } @@ -140,91 +118,6 @@ return FALSE; } -#ifndef USE_REGEX -struct _find { - DebugWindow *window; - GtkWidget *entry; -}; - -static void -do_find_cb(GtkWidget *widget, gint response, struct _find *f) -{ - switch (response) { - case GTK_RESPONSE_OK: - gtk_imhtml_search_find(GTK_IMHTML(f->window->text), - gtk_entry_get_text(GTK_ENTRY(f->entry))); - break; - - case GTK_RESPONSE_DELETE_EVENT: - case GTK_RESPONSE_CLOSE: - gtk_imhtml_search_clear(GTK_IMHTML(f->window->text)); - gtk_widget_destroy(f->window->find); - f->window->find = NULL; - g_free(f); - break; - } -} - -static void -find_cb(GtkWidget *w, DebugWindow *win) -{ - GtkWidget *hbox, *img, *label; - struct _find *f; - - if(win->find) - { - gtk_window_present(GTK_WINDOW(win->find)); - return; - } - - f = g_malloc(sizeof(struct _find)); - f->window = win; - win->find = gtk_dialog_new_with_buttons(_("Find"), - GTK_WINDOW(win->window), GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, - GTK_STOCK_FIND, GTK_RESPONSE_OK, NULL); - gtk_dialog_set_default_response(GTK_DIALOG(win->find), - GTK_RESPONSE_OK); - g_signal_connect(G_OBJECT(win->find), "response", - G_CALLBACK(do_find_cb), f); - - gtk_container_set_border_width(GTK_CONTAINER(win->find), PIDGIN_HIG_BOX_SPACE); - gtk_window_set_resizable(GTK_WINDOW(win->find), FALSE); -#if !GTK_CHECK_VERSION(2,22,0) - gtk_dialog_set_has_separator(GTK_DIALOG(win->find), FALSE); -#endif - gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(win->find)->vbox), PIDGIN_HIG_BORDER); - gtk_container_set_border_width( - GTK_CONTAINER(GTK_DIALOG(win->find)->vbox), PIDGIN_HIG_BOX_SPACE); - - hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(win->find)->vbox), - hbox); - img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_QUESTION, - gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_HUGE)); - gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); - - gtk_misc_set_alignment(GTK_MISC(img), 0, 0); - gtk_dialog_set_response_sensitive(GTK_DIALOG(win->find), - GTK_RESPONSE_OK, FALSE); - - label = gtk_label_new(NULL); - gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("_Search for:")); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - f->entry = gtk_entry_new(); - gtk_entry_set_activates_default(GTK_ENTRY(f->entry), TRUE); - gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_WIDGET(f->entry)); - g_signal_connect(G_OBJECT(f->entry), "changed", - G_CALLBACK(pidgin_set_sensitive_if_input), - win->find); - gtk_box_pack_start(GTK_BOX(hbox), f->entry, FALSE, FALSE, 0); - - gtk_widget_show_all(win->find); - gtk_widget_grab_focus(f->entry); -} -#endif /* USE_REGEX */ - static void save_writefile_cb(void *user_data, const char *filename) { @@ -237,7 +130,7 @@ return; } - tmp = gtk_imhtml_get_text(GTK_IMHTML(win->text), NULL, NULL); + tmp = gtk_webview_get_body_text(GTK_WEBVIEW(win->text)); fprintf(fp, "Pidgin Debug Log : %s\n", purple_date_format_full(NULL)); fprintf(fp, "%s", tmp); g_free(tmp); @@ -257,11 +150,13 @@ static void clear_cb(GtkWidget *w, DebugWindow *win) { - gtk_imhtml_clear(GTK_IMHTML(win->text)); + char *tmp; + int level; -#ifdef USE_REGEX - gtk_list_store_clear(win->store); -#endif /* USE_REGEX */ + level = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/filterlevel"); + tmp = g_strdup_printf(EMPTY_HTML, level); + gtk_webview_load_html_string(GTK_WEBVIEW(win->text), tmp); + g_free(tmp); } static void @@ -269,20 +164,25 @@ { win->paused = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(w)); -#ifdef USE_REGEX - if(!win->paused) { - if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) - regex_filter_all(win); - else - regex_show_all(win); + if (win->paused) { + gtk_webview_append_html(GTK_WEBVIEW(win->text), "<div id=pause></div>"); + } else { + WebKitDOMDocument *dom; + WebKitDOMElement *pause; + + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(win->text)); + pause = webkit_dom_document_get_element_by_id(dom, "pause"); + if (pause) { + WebKitDOMNode *parent; + parent = webkit_dom_node_get_parent_node(WEBKIT_DOM_NODE(pause)); + webkit_dom_node_remove_child(parent, WEBKIT_DOM_NODE(pause), NULL); + } } -#endif /* USE_REGEX */ } /****************************************************************************** * regex stuff *****************************************************************************/ -#ifdef USE_REGEX static void regex_clear_color(GtkWidget *w) { gtk_widget_modify_base(w, GTK_STATE_NORMAL, NULL); @@ -300,28 +200,133 @@ } static void -regex_highlight_clear(DebugWindow *win) { - GtkIMHtml *imhtml = GTK_IMHTML(win->text); - GtkTextIter s, e; +regex_toggle_div(WebKitDOMNode *div) +{ + WebKitDOMDOMTokenList *classes; + + if (!WEBKIT_DOM_IS_HTML_ELEMENT(div)) + return; + + classes = webkit_dom_html_element_get_class_list(WEBKIT_DOM_HTML_ELEMENT(div)); + webkit_dom_dom_token_list_toggle(classes, "hide", NULL); +} + +static void +regex_highlight_clear(WebKitDOMDocument *dom) +{ + WebKitDOMNodeList *nodes; + gulong i; - gtk_text_buffer_get_start_iter(imhtml->text_buffer, &s); - gtk_text_buffer_get_end_iter(imhtml->text_buffer, &e); - gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "regex", &s, &e); + /* Remove highlighting SPANs */ + nodes = webkit_dom_document_get_elements_by_class_name(dom, "regex"); + i = webkit_dom_node_list_get_length(nodes); + while (i--) { + WebKitDOMNode *span, *parent; + char *content; + WebKitDOMText *text; + GError *err = NULL; + + span = webkit_dom_node_list_item(nodes, i); + parent = webkit_dom_node_get_parent_node(span); + + content = webkit_dom_node_get_text_content(span); + text = webkit_dom_document_create_text_node(dom, content); + g_free(content); + + webkit_dom_node_replace_child(parent, WEBKIT_DOM_NODE(text), span, &err); + } } static void -regex_match(DebugWindow *win, const gchar *text) { - GtkIMHtml *imhtml = GTK_IMHTML(win->text); -#ifdef HAVE_REGEX_H - regmatch_t matches[4]; /* adjust if necessary */ - size_t n_matches = sizeof(matches) / sizeof(matches[0]); - gint inverted; -#else +regex_highlight_text_nodes(WebKitDOMDocument *dom, WebKitDOMNode *div, + gint start_pos, gint end_pos) +{ + GSList *data = NULL; + WebKitDOMNode *node; + WebKitDOMRange *range; + WebKitDOMElement *span; + gint ind, end_ind; + gint this_start, this_end; + + ind = 0; + webkit_dom_node_normalize(div); + node = div; + + /* First, find the container nodes and offsets to apply highlighting. */ + do { + if (webkit_dom_node_get_node_type(node) == 3/*TEXT_NODE*/) { + /* The GObject model does not correctly reflect the type, hence the + regular cast. */ + end_ind = ind + webkit_dom_character_data_get_length((WebKitDOMCharacterData*)node); + + if (start_pos <= ind) + this_start = 0; + else if (start_pos < end_ind) + this_start = start_pos - ind; + else + this_start = -1; + + if (end_pos < end_ind) + this_end = end_pos - ind; + else + this_end = end_ind - ind; + + if (this_start != -1 && this_start < this_end) { + data = g_slist_prepend(data, GINT_TO_POINTER(this_end)); + data = g_slist_prepend(data, GINT_TO_POINTER(this_start)); + data = g_slist_prepend(data, node); + } + + ind = end_ind; + } + + if (webkit_dom_node_has_child_nodes(node)) { + node = webkit_dom_node_get_first_child(node); + } else { + while (node != div) { + WebKitDOMNode *next; + + next = webkit_dom_node_get_next_sibling(node); + if (next) { + node = next; + break; + } else { + node = webkit_dom_node_get_parent_node(node); + } + } + } + } while (node != div); + + /* Second, apply highlighting to saved sections. Changing the DOM is + automatically reflected in all WebKit API, so we have to do this after + finding the offsets, or things could get complicated. */ + while (data) { + node = WEBKIT_DOM_NODE(data->data); + data = g_slist_delete_link(data, data); + this_start = GPOINTER_TO_INT(data->data); + data = g_slist_delete_link(data, data); + this_end = GPOINTER_TO_INT(data->data); + data = g_slist_delete_link(data, data); + + range = webkit_dom_document_create_range(dom); + webkit_dom_range_set_start(range, node, this_start, NULL); + webkit_dom_range_set_end(range, node, this_end, NULL); + span = webkit_dom_document_create_element(dom, "span", NULL); + webkit_dom_html_element_set_class_name(WEBKIT_DOM_HTML_ELEMENT(span), + "regex"); + webkit_dom_range_surround_contents(range, WEBKIT_DOM_NODE(span), NULL); + } +} + +static void +regex_match(DebugWindow *win, WebKitDOMDocument *dom, WebKitDOMNode *div) +{ GMatchInfo *match_info; -#endif /* HAVE_REGEX_H */ + gchar *text; gchar *plaintext; - if(!text) + text = webkit_dom_node_get_text_content(div); + if (!text) return; /* I don't like having to do this, but we need it for highlighting. Plus @@ -329,193 +334,80 @@ */ plaintext = purple_markup_strip_html(text); - /* we do a first pass to see if it matches at all. If it does we append - * it, and work out the offsets to highlight. + /* We do a first pass to see if it matches at all. If it does we work out + * the offsets to highlight. */ -#ifdef HAVE_REGEX_H - inverted = (win->invert) ? REG_NOMATCH : 0; - if(regexec(&win->regex, plaintext, n_matches, matches, 0) == inverted) { -#else - if(g_regex_match(win->regex, plaintext, 0, &match_info) != win->invert) { -#endif /* HAVE_REGEX_H */ - gchar *p = plaintext; - GtkTextIter ins; - gint i, offset = 0; - - gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &ins, - gtk_text_buffer_get_insert(imhtml->text_buffer)); - i = gtk_text_iter_get_offset(&ins); - - gtk_imhtml_append_text(imhtml, text, 0); - + if (g_regex_match(win->regex, plaintext, 0, &match_info) != win->invert) { /* If we're not highlighting or the expression is inverted, we're * done and move on. */ - if(!win->highlight || win->invert) { + if (!win->highlight || win->invert) { g_free(plaintext); -#ifndef HAVE_REGEX_H g_match_info_free(match_info); -#endif return; } - /* we use a do-while to highlight the first match, and then continue - * if necessary... - */ -#ifdef HAVE_REGEX_H do { - size_t m; - - for(m = 0; m < n_matches; m++) { - GtkTextIter ms, me; - - if(matches[m].rm_eo == -1) - break; - - i += offset; - - gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &ms, - i + matches[m].rm_so); - gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &me, - i + matches[m].rm_eo); - gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "regex", - &ms, &me); - offset = matches[m].rm_eo; - } - - p += offset; - } while(regexec(&win->regex, p, n_matches, matches, REG_NOTBOL) == inverted); -#else - do - { - gint m; + gint m, count; gint start_pos, end_pos; - GtkTextIter ms, me; if (!g_match_info_matches(match_info)) break; - for (m = 0; m < g_match_info_get_match_count(match_info); m++) + count = g_match_info_get_match_count(match_info); + if (count == 1) + m = 0; + else + m = 1; + + for (; m < count; m++) { - if (m == 1) - continue; - g_match_info_fetch_pos(match_info, m, &start_pos, &end_pos); if (end_pos == -1) break; - gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &ms, - i + start_pos); - gtk_text_buffer_get_iter_at_offset(imhtml->text_buffer, &me, - i + end_pos); - gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "regex", - &ms, &me); - offset = end_pos; + regex_highlight_text_nodes(dom, div, start_pos, end_pos); } + } while (g_match_info_next(match_info, NULL)); - g_match_info_free(match_info); - p += offset; - i += offset; - } while (g_regex_match(win->regex, p, G_REGEX_MATCH_NOTBOL, &match_info) != win->invert); g_match_info_free(match_info); -#endif /* HAVE_REGEX_H */ + } else { + regex_toggle_div(div); } g_free(plaintext); -} - -static gboolean -regex_filter_all_cb(GtkTreeModel *m, GtkTreePath *p, GtkTreeIter *iter, - gpointer data) -{ - DebugWindow *win = (DebugWindow *)data; - gchar *text; - PurpleDebugLevel level; - - gtk_tree_model_get(m, iter, 0, &text, 1, &level, -1); - - if (level >= purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/filterlevel")) - regex_match(win, text); - g_free(text); - - return FALSE; } static void -regex_filter_all(DebugWindow *win) { - gtk_imhtml_clear(GTK_IMHTML(win->text)); - - if(win->highlight) - regex_highlight_clear(win); - - gtk_tree_model_foreach(GTK_TREE_MODEL(win->store), regex_filter_all_cb, - win); -} +regex_toggle_filter(DebugWindow *win, gboolean filter) +{ + WebKitDOMDocument *dom; + WebKitDOMNodeList *list; + gulong i; -static gboolean -regex_show_all_cb(GtkTreeModel *m, GtkTreePath *p, GtkTreeIter *iter, - gpointer data) -{ - DebugWindow *win = (DebugWindow *)data; - gchar *text; - PurpleDebugLevel level; - - gtk_tree_model_get(m, iter, 0, &text, 1, &level, -1); - if (level >= purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/filterlevel")) - gtk_imhtml_append_text(GTK_IMHTML(win->text), text, 0); - g_free(text); + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(win->text)); - return FALSE; -} - -static void -regex_show_all(DebugWindow *win) { - gtk_imhtml_clear(GTK_IMHTML(win->text)); - - if(win->highlight) - regex_highlight_clear(win); + if (win->highlight) + regex_highlight_clear(dom); - gtk_tree_model_foreach(GTK_TREE_MODEL(win->store), regex_show_all_cb, - win); -} - -static void -regex_compile(DebugWindow *win) { - const gchar *text; - - text = gtk_entry_get_text(GTK_ENTRY(win->expression)); - - if(text == NULL || *text == '\0') { - regex_clear_color(win->expression); - gtk_widget_set_sensitive(win->filter, FALSE); - return; + /* Re-show debug lines that didn't match regex */ + list = webkit_dom_document_get_elements_by_class_name(dom, "hide"); + i = webkit_dom_node_list_get_length(list); + while (i--) { + WebKitDOMNode *div = webkit_dom_node_list_item(list, i); + regex_toggle_div(div); } -#ifdef HAVE_REGEX_H - regfree(&win->regex); - if(regcomp(&win->regex, text, REG_EXTENDED | REG_ICASE) != 0) { -#else - if (win->regex) - g_regex_unref(win->regex); - win->regex = g_regex_new(text, G_REGEX_EXTENDED | G_REGEX_CASELESS, 0, NULL); - if(win->regex == NULL) { -#endif - /* failed to compile */ - regex_change_color(win->expression, 0xFFFF, 0xAFFF, 0xAFFF); - gtk_widget_set_sensitive(win->filter, FALSE); - } else { - /* compiled successfully */ - regex_change_color(win->expression, 0xAFFF, 0xFFFF, 0xAFFF); - gtk_widget_set_sensitive(win->filter, TRUE); + if (filter) { + list = webkit_dom_document_get_elements_by_tag_name(dom, "div"); + + for (i = 0; i < webkit_dom_node_list_get_length(list); i++) { + WebKitDOMNode *div = webkit_dom_node_list_item(list, i); + regex_match(win, dom, div); + } } - - /* we check if the filter is on in case it was only of the options that - * got changed, and not the expression. - */ - if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) - regex_filter_all(win); } static void @@ -525,11 +417,11 @@ DebugWindow *win = (DebugWindow *)data; gboolean active = GPOINTER_TO_INT(val), current; - if(!win || !win->window) + if (!win || !win->window) return; current = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter)); - if(active != current) + if (active != current) gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win->filter), active); } @@ -552,8 +444,8 @@ win->invert = active; - if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) - regex_filter_all(win); + if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) + regex_toggle_filter(win, TRUE); } static void @@ -565,40 +457,8 @@ win->highlight = active; - if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) - regex_filter_all(win); -} - -static void -regex_row_changed_cb(GtkTreeModel *model, GtkTreePath *path, - GtkTreeIter *iter, DebugWindow *win) -{ - gchar *text; - PurpleDebugLevel level; - - if(!win || !win->window) - return; - - /* If the debug window is paused, we just return since it's in the store. - * We don't call regex_match because it doesn't make sense to check the - * string if it's paused. When we unpause we clear the imhtml and - * reiterate over the store to handle matches that were outputted when - * we were paused. - */ - if(win->paused) - return; - - gtk_tree_model_get(model, iter, 0, &text, 1, &level, -1); - - if (level >= purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/filterlevel")) { - if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) { - regex_match(win, text); - } else { - gtk_imhtml_append_text(GTK_IMHTML(win->text), text, 0); - } - } - - g_free(text); + if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) + regex_toggle_filter(win, TRUE); } static gboolean @@ -615,25 +475,42 @@ static void regex_changed_cb(GtkWidget *w, DebugWindow *win) { - if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) { + const gchar *text; + + if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) { gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win->filter), FALSE); } - if(win->timer == 0) + if (win->timer == 0) win->timer = purple_timeout_add_seconds(5, (GSourceFunc)regex_timer_cb, win); - regex_compile(win); + text = gtk_entry_get_text(GTK_ENTRY(win->expression)); + + if (text == NULL || *text == '\0') { + regex_clear_color(win->expression); + gtk_widget_set_sensitive(win->filter, FALSE); + return; + } + + if (win->regex) + g_regex_unref(win->regex); + win->regex = g_regex_new(text, G_REGEX_CASELESS, 0, NULL); + if (win->regex == NULL) { + /* failed to compile */ + regex_change_color(win->expression, 0xFFFF, 0xAFFF, 0xAFFF); + gtk_widget_set_sensitive(win->filter, FALSE); + } else { + /* compiled successfully */ + regex_change_color(win->expression, 0xAFFF, 0xFFFF, 0xAFFF); + gtk_widget_set_sensitive(win->filter, TRUE); + } } static void regex_key_release_cb(GtkWidget *w, GdkEventKey *e, DebugWindow *win) { - if(e->keyval == GDK_Return && -#if GTK_CHECK_VERSION(2,18,0) + if(e->keyval == GDK_KEY_Return && gtk_widget_is_sensitive(win->filter) && -#else - GTK_WIDGET_IS_SENSITIVE(win->filter) && -#endif !gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) { gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win->filter), TRUE); @@ -661,35 +538,38 @@ } static void -regex_filter_toggled_cb(GtkToggleToolButton *button, DebugWindow *win) { +regex_filter_toggled_cb(GtkToggleToolButton *button, DebugWindow *win) +{ gboolean active; active = gtk_toggle_tool_button_get_active(button); purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/debug/filter", active); - if(!GTK_IS_IMHTML(win->text)) + if (!GTK_IS_WEBVIEW(win->text)) return; - if(active) - regex_filter_all(win); - else - regex_show_all(win); + regex_toggle_filter(win, active); } static void filter_level_pref_changed(const char *name, PurplePrefType type, gconstpointer value, gpointer data) { DebugWindow *win = data; + WebKitDOMDocument *dom; + WebKitDOMHTMLElement *body; + int level = GPOINTER_TO_INT(value); + char *tmp; - if (GPOINTER_TO_INT(value) != gtk_combo_box_get_active(GTK_COMBO_BOX(win->filterlevel))) - gtk_combo_box_set_active(GTK_COMBO_BOX(win->filterlevel), GPOINTER_TO_INT(value)); - if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) - regex_filter_all(win); - else - regex_show_all(win); + if (level != gtk_combo_box_get_active(GTK_COMBO_BOX(win->filterlevel))) + gtk_combo_box_set_active(GTK_COMBO_BOX(win->filterlevel), level); + + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(win->text)); + body = webkit_dom_document_get_body(dom); + tmp = g_strdup_printf("l%d", level); + webkit_dom_html_element_set_class_name(body, tmp); + g_free(tmp); } -#endif /* USE_REGEX */ static void filter_level_changed_cb(GtkWidget *combo, gpointer null) @@ -739,7 +619,7 @@ gtk_widget_show_all(menu); - gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, event->time); return FALSE; } @@ -775,20 +655,6 @@ handle = pidgin_debug_get_handle(); -#ifdef USE_REGEX - /* the list store for all the messages */ - win->store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT); - - /* row-changed gets called when we do gtk_list_store_set, and row-inserted - * gets called with gtk_list_store_append, which is a - * completely empty row. So we just ignore row-inserted, and deal with row - * changed. -Gary - */ - g_signal_connect(G_OBJECT(win->store), "row-changed", - G_CALLBACK(regex_row_changed_cb), win); - -#endif /* USE_REGEX */ - /* Setup the vbox */ vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(win->window), vbox); @@ -814,38 +680,17 @@ gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); -#ifndef USE_REGEX - /* Find button */ - item = gtk_tool_button_new_from_stock(GTK_STOCK_FIND); - gtk_tool_item_set_is_important(item, TRUE); -#if GTK_CHECK_VERSION(2,12,0) - gtk_tool_item_set_tooltip_text(item, _("Find")); -#else - gtk_tool_item_set_tooltip(item, tooltips, _("Find"), NULL); -#endif - g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(find_cb), win); - gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item)); -#endif /* USE_REGEX */ - /* Save */ item = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE); gtk_tool_item_set_is_important(item, TRUE); -#if GTK_CHECK_VERSION(2,12,0) gtk_tool_item_set_tooltip_text(item, _("Save")); -#else - gtk_tool_item_set_tooltip(item, tooltips, _("Save"), NULL); -#endif g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(save_cb), win); gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item)); /* Clear button */ item = gtk_tool_button_new_from_stock(GTK_STOCK_CLEAR); gtk_tool_item_set_is_important(item, TRUE); -#if GTK_CHECK_VERSION(2,12,0) gtk_tool_item_set_tooltip_text(item, _("Clear")); -#else - gtk_tool_item_set_tooltip(item, tooltips, _("Clear"), NULL); -#endif g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(clear_cb), win); gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item)); @@ -855,15 +700,10 @@ /* Pause */ item = gtk_toggle_tool_button_new_from_stock(PIDGIN_STOCK_PAUSE); gtk_tool_item_set_is_important(item, TRUE); -#if GTK_CHECK_VERSION(2,12,0) gtk_tool_item_set_tooltip_text(item, _("Pause")); -#else - gtk_tool_item_set_tooltip(item, tooltips, _("Pause"), NULL); -#endif g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(pause_cb), win); gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item)); -#ifdef USE_REGEX /* regex stuff */ item = gtk_separator_tool_item_new(); gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item)); @@ -873,11 +713,7 @@ gtk_tool_item_set_is_important(item, TRUE); win->filter = GTK_WIDGET(item); gtk_tool_button_set_label(GTK_TOOL_BUTTON(win->filter), _("Filter")); -#if GTK_CHECK_VERSION(2,12,0) gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(win->filter), _("Filter")); -#else - gtk_tooltips_set_tip(tooltips, win->filter, _("Filter"), NULL); -#endif g_signal_connect(G_OBJECT(win->filter), "clicked", G_CALLBACK(regex_filter_toggled_cb), win); gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(win->filter)); @@ -895,11 +731,7 @@ /* regex entry */ win->expression = gtk_entry_new(); item = gtk_tool_item_new(); -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(win->expression, _("Right click for more options.")); -#else - gtk_tooltips_set_tip(tooltips, win->expression, _("Right click for more options."), NULL); -#endif gtk_container_add(GTK_CONTAINER(item), GTK_WIDGET(win->expression)); gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item)); @@ -926,8 +758,6 @@ purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/debug/highlight", regex_pref_highlight_cb, win); -#endif /* USE_REGEX */ - item = gtk_separator_tool_item_new(); gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item)); @@ -935,46 +765,35 @@ gtk_container_add(GTK_CONTAINER(item), gtk_label_new(_("Level "))); gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item)); - win->filterlevel = gtk_combo_box_new_text(); + win->filterlevel = gtk_combo_box_text_new(); item = gtk_tool_item_new(); -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(win->filterlevel, _("Select the debug filter level.")); -#else - gtk_tooltips_set_tip(tooltips, win->filterlevel, _("Select the debug filter level."), NULL); -#endif gtk_container_add(GTK_CONTAINER(item), win->filterlevel); gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item)); - gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("All")); - gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Misc")); - gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Info")); - gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Warning")); - gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Error ")); - gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Fatal Error")); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("All")); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Misc")); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Info")); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Warning")); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Error ")); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->filterlevel), _("Fatal Error")); gtk_combo_box_set_active(GTK_COMBO_BOX(win->filterlevel), purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/filterlevel")); -#ifdef USE_REGEX + purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/debug/filterlevel", filter_level_pref_changed, win); -#endif g_signal_connect(G_OBJECT(win->filterlevel), "changed", G_CALLBACK(filter_level_changed_cb), NULL); } - /* Add the gtkimhtml */ - frame = pidgin_create_imhtml(FALSE, &win->text, NULL, NULL); - gtk_imhtml_set_format_functions(GTK_IMHTML(win->text), - GTK_IMHTML_ALL ^ GTK_IMHTML_SMILEY ^ GTK_IMHTML_IMAGE); + /* Add the gtkwebview */ + frame = pidgin_create_webview(FALSE, &win->text, NULL, NULL); + gtk_webview_set_format_functions(GTK_WEBVIEW(win->text), + GTK_WEBVIEW_ALL ^ GTK_WEBVIEW_SMILEY ^ GTK_WEBVIEW_IMAGE); gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); gtk_widget_show(frame); -#ifdef USE_REGEX - /* add the tag for regex highlighting */ - gtk_text_buffer_create_tag(GTK_IMHTML(win->text)->text_buffer, "regex", - "background", "#FFAFAF", - "weight", "bold", - NULL); -#endif /* USE_REGEX */ + clear_cb(NULL, win); gtk_widget_show_all(win->window); @@ -1075,13 +894,11 @@ purple_prefs_add_int(PIDGIN_PREFS_ROOT "/debug/width", 450); purple_prefs_add_int(PIDGIN_PREFS_ROOT "/debug/height", 250); -#ifdef USE_REGEX purple_prefs_add_string(PIDGIN_PREFS_ROOT "/debug/regex", ""); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/debug/filter", FALSE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/debug/invert", FALSE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/debug/case_insensitive", FALSE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/debug/highlight", FALSE); -#endif /* USE_REGEX */ purple_prefs_connect_callback(NULL, PIDGIN_PREFS_ROOT "/debug/enabled", debug_enabled_cb, NULL); @@ -1143,9 +960,6 @@ pidgin_debug_print(PurpleDebugLevel level, const char *category, const char *arg_s) { -#ifdef USE_REGEX - GtkTreeIter iter; -#endif /* USE_REGEX */ gchar *ts_s; gchar *esc_s, *cat_s, *tmp, *s; const char *mdate; @@ -1165,33 +979,42 @@ else cat_s = g_strdup_printf("<b>%s:</b> ", category); - esc_s = g_markup_escape_text(arg_s, -1); + tmp = purple_utf8_try_convert(arg_s); + esc_s = g_markup_escape_text(tmp, -1); - s = g_strdup_printf("<font color=\"%s\">%s%s%s</font>", - debug_fg_colors[level], ts_s, cat_s, esc_s); + s = g_strdup_printf("<div class=\"l%d\">%s%s%s</div>", + level, ts_s, cat_s, esc_s); g_free(ts_s); g_free(cat_s); g_free(esc_s); - - tmp = purple_utf8_try_convert(s); - g_free(s); - s = tmp; + g_free(tmp); - if (level == PURPLE_DEBUG_FATAL) { - tmp = g_strdup_printf("<b>%s</b>", s); - g_free(s); - s = tmp; + //XXX: gtk_webview_append_html does delayed insert of new div, which is + // needed by filtering below + //gtk_webview_append_html(GTK_WEBVIEW(debug_win->text), s); + { + WebKitDOMDocument *dom = NULL; + WebKitDOMHTMLElement *body = NULL; + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(debug_win->text)); + if (dom) + body = webkit_dom_document_get_body(dom); + if (body) + webkit_dom_html_element_insert_adjacent_html(body, "beforeend", s, NULL); } -#ifdef USE_REGEX - /* add the text to the list store */ - gtk_list_store_append(debug_win->store, &iter); - gtk_list_store_set(debug_win->store, &iter, 0, s, 1, level, -1); -#else /* USE_REGEX */ - if(!debug_win->paused && level >= purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/filterlevel")) - gtk_imhtml_append_text(GTK_IMHTML(debug_win->text), s, 0); -#endif /* !USE_REGEX */ + if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(debug_win->filter))) { + WebKitDOMDocument *dom = NULL; + WebKitDOMHTMLElement *body = NULL; + WebKitDOMNode *div = NULL; + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(debug_win->text)); + if (dom) + body = webkit_dom_document_get_body(dom); + if (body) + div = webkit_dom_node_get_last_child(WEBKIT_DOM_NODE(body)); + if (div) + regex_match(debug_win, dom, div); + } g_free(s); } @@ -1225,3 +1048,4 @@ return &handle; } +
--- a/pidgin/gtkdialogs.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkdialogs.c Mon Aug 06 18:11:44 2012 +0200 @@ -44,6 +44,8 @@ #include "gtkwebview.h" #include "pidginstock.h" +#include "gtk3compat.h" + static GList *dialogwindows = NULL; struct _PidginGroupMergeObject { @@ -435,9 +437,14 @@ AtkObject *obj; char *filename, *tmp; +#if GTK_CHECK_VERSION(3,0,0) + win = pidgin_create_dialog(title, 0, role, TRUE); + vbox = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(win), FALSE, 0); +#else win = pidgin_create_dialog(title, PIDGIN_HIG_BORDER, role, TRUE); vbox = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(win), FALSE, PIDGIN_HIG_BORDER); - gtk_window_set_default_size(GTK_WINDOW(win), 450, 450); +#endif + gtk_window_set_default_size(GTK_WINDOW(win), 475, 450); /* Generate a logo with a version number */ filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "logo.png", NULL); @@ -467,11 +474,7 @@ button = pidgin_dialog_add_button(GTK_DIALOG(win), GTK_STOCK_CLOSE, G_CALLBACK(destroy_win), win); -#if GTK_CHECK_VERSION(2,18,0) gtk_widget_set_can_default(button, TRUE); -#else - GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); -#endif gtk_widget_grab_default(button); gtk_widget_show_all(win); @@ -876,6 +879,28 @@ pidgin_dialogs_im_with_user(account, username); } +static gboolean +pidgin_dialogs_im_name_validator(PurpleRequestField *field, gchar **errmsg, + void *_fields) +{ + PurpleRequestFields *fields = _fields; + PurpleAccount *account; + PurplePlugin *prpl; + const char *username; + gboolean valid; + + account = purple_request_fields_get_account(fields, "account"); + prpl = purple_find_prpl(purple_account_get_protocol_id(account)); + username = purple_request_fields_get_string(fields, "screenname"); + + valid = purple_validate(prpl, username); + + if (errmsg && !valid) + *errmsg = g_strdup(_("Invalid username")); + + return valid; +} + void pidgin_dialogs_im(void) { @@ -891,6 +916,7 @@ field = purple_request_field_string_new("screenname", _("_Name"), NULL, FALSE); purple_request_field_set_type_hint(field, "screenname"); purple_request_field_set_required(field, TRUE); + purple_request_field_set_validator(field, pidgin_dialogs_im_name_validator, fields); purple_request_field_group_add_field(group, field); field = purple_request_field_account_new("account", _("_Account"), NULL); @@ -977,14 +1003,13 @@ gtk_container_set_border_width (GTK_CONTAINER(window), PIDGIN_HIG_BOX_SPACE); gtk_window_set_resizable(GTK_WINDOW(window), FALSE); -#if !GTK_CHECK_VERSION(2,22,0) - gtk_dialog_set_has_separator(GTK_DIALOG(window), FALSE); -#endif - gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(window)->vbox), PIDGIN_HIG_BORDER); - gtk_container_set_border_width (GTK_CONTAINER(GTK_DIALOG(window)->vbox), PIDGIN_HIG_BOX_SPACE); + gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(window))), + PIDGIN_HIG_BORDER); + gtk_container_set_border_width(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(window))), + PIDGIN_HIG_BOX_SPACE); hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window)->vbox), hbox); + gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(window))), hbox); img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_COOL, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_HUGE)); gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
--- a/pidgin/gtkdialogs.h Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkdialogs.h Mon Aug 06 18:11:44 2012 +0200 @@ -52,9 +52,6 @@ void pidgin_dialogs_remove_contact(PurpleContact *); void pidgin_dialogs_merge_groups(PurpleGroup *, const char *); -/* This macro should probably be moved elsewhere */ -#define PIDGIN_WINDOW_ICONIFIED(x) (gdk_window_get_state(GTK_WIDGET(x)->window) & GDK_WINDOW_STATE_ICONIFIED) - G_END_DECLS #endif /* _PIDGINDIALOGS_H_ */
--- a/pidgin/gtkdnd-hints.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkdnd-hints.c Mon Aug 06 18:11:44 2012 +0200 @@ -34,6 +34,8 @@ #include "win32dep.h" #endif +#include "gtk3compat.h" + typedef struct { GtkWidget *widget; @@ -54,6 +56,59 @@ { NULL, NULL, 0, 0 } }; +#if GTK_CHECK_VERSION(3,0,0) + +static void +dnd_hints_realized_cb(GtkWidget *window, GtkWidget *pix) +{ + GdkPixbuf *pixbuf; + cairo_surface_t *surface; + cairo_region_t *region; + cairo_t *cr; + + pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(pix)); + + surface = cairo_image_surface_create(CAIRO_FORMAT_A1, + gdk_pixbuf_get_width(pixbuf), + gdk_pixbuf_get_height(pixbuf)); + + cr = cairo_create(surface); + gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0); + cairo_paint(cr); + cairo_destroy(cr); + + region = gdk_cairo_region_create_from_surface(surface); + gtk_widget_shape_combine_region(window, region); + cairo_region_destroy(region); + + cairo_surface_destroy(surface); +} + +static GtkWidget * +dnd_hints_init_window(const gchar *fname) +{ + GdkPixbuf *pixbuf; + GtkWidget *pix; + GtkWidget *win; + + pixbuf = gdk_pixbuf_new_from_file(fname, NULL); + g_return_val_if_fail(pixbuf, NULL); + + win = gtk_window_new(GTK_WINDOW_POPUP); + pix = gtk_image_new_from_pixbuf(pixbuf); + gtk_container_add(GTK_CONTAINER(win), pix); + gtk_widget_show_all(pix); + + g_object_unref(G_OBJECT(pixbuf)); + + g_signal_connect(G_OBJECT(win), "realize", + G_CALLBACK(dnd_hints_realized_cb), pix); + + return win; +} + +#else + static GtkWidget * dnd_hints_init_window(const gchar *fname) { @@ -85,21 +140,29 @@ return win; } +#endif + static void get_widget_coords(GtkWidget *w, gint *x1, gint *y1, gint *x2, gint *y2) { gint ox, oy, width, height; + GtkWidget *parent = gtk_widget_get_parent(w); - if (w->parent && w->parent->window == w->window) + if (parent && gtk_widget_get_window(parent) == gtk_widget_get_window(w)) { - get_widget_coords(w->parent, &ox, &oy, NULL, NULL); - height = w->allocation.height; - width = w->allocation.width; + GtkAllocation allocation; + + gtk_widget_get_allocation(w, &allocation); + get_widget_coords(parent, &ox, &oy, NULL, NULL); + height = allocation.height; + width = allocation.width; } else { - gdk_window_get_origin(w->window, &ox, &oy); - gdk_drawable_get_size(w->window, &width, &height); + GdkWindow *win = gtk_widget_get_window(w); + gdk_window_get_origin(win, &ox, &oy); + width = gdk_window_get_width(win); + height = gdk_window_get_height(win); } if (x1) *x1 = ox; @@ -172,10 +235,13 @@ { gint x1, x2, y1, y2; gint x = 0, y = 0; + GtkAllocation allocation; + + gtk_widget_get_allocation(widget, &allocation); get_widget_coords(widget, &x1, &y1, &x2, &y2); - x1 += widget->allocation.x; x2 += widget->allocation.x; - y1 += widget->allocation.y; y2 += widget->allocation.y; + x1 += allocation.x; x2 += allocation.x; + y1 += allocation.y; y2 += allocation.y; switch (horiz) {
--- a/pidgin/gtkdocklet.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkdocklet.c Mon Aug 06 18:11:44 2012 +0200 @@ -45,6 +45,8 @@ #include "gtkdocklet.h" #include "gtkdialogs.h" +#include "gtk3compat.h" + #ifndef DOCKLET_TOOLTIP_LINE_LIMIT #define DOCKLET_TOOLTIP_LINE_LIMIT 5 #endif @@ -59,7 +61,6 @@ static gboolean pending = FALSE; static gboolean connecting = FALSE; static gboolean enable_join_chat = FALSE; -static guint docklet_blinking_timer = 0; static gboolean visible = FALSE; static gboolean visibility_manager = FALSE; @@ -105,32 +106,13 @@ gtk_status_icon_set_from_icon_name(docklet, icon_name); } +#if !GTK_CHECK_VERSION(3,0,0) if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink")) { gtk_status_icon_set_blinking(docklet, (pending && !connecting)); } else if (gtk_status_icon_get_blinking(docklet)) { gtk_status_icon_set_blinking(docklet, FALSE); } -} - -static gboolean -docklet_blink_icon(gpointer data) -{ - static gboolean blinked = FALSE; - gboolean ret = FALSE; /* by default, don't keep blinking */ - - blinked = !blinked; - - if(pending && !connecting) { - if (!blinked) { - docklet_gtk_status_update_icon(status, connecting, pending); - } - ret = TRUE; /* keep blinking */ - } else { - docklet_blinking_timer = 0; - blinked = FALSE; - } - - return ret; +#endif } static GList * @@ -218,7 +200,7 @@ if (tooltip_text->len > 0) tooltip_text = g_string_truncate(tooltip_text, tooltip_text->len - 1); - gtk_status_icon_set_tooltip(docklet, tooltip_text->str); + gtk_status_icon_set_tooltip_text(docklet, tooltip_text->str); g_string_free(tooltip_text, TRUE); g_list_free(convs); @@ -226,7 +208,7 @@ } else { char *tooltip_text = g_strconcat(PIDGIN_NAME, " - ", purple_savedstatus_get_title(saved_status), NULL); - gtk_status_icon_set_tooltip(docklet, tooltip_text); + gtk_status_icon_set_tooltip_text(docklet, tooltip_text); g_free(tooltip_text); } @@ -253,12 +235,6 @@ connecting = newconnecting; docklet_gtk_status_update_icon(status, connecting, pending); - - /* and schedule the blinker function if messages are pending */ - if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink") - && pending && !connecting && docklet_blinking_timer == 0) { - docklet_blinking_timer = g_timeout_add(500, docklet_blink_icon, NULL); - } } return FALSE; /* for when we're called by the glib idle handler */ @@ -356,19 +332,23 @@ static void docklet_toggle_mute(GtkWidget *toggle, void *data) { - purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/sound/mute", GTK_CHECK_MENU_ITEM(toggle)->active); + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/sound/mute", + gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(toggle))); } +#if !GTK_CHECK_VERSION(3,0,0) static void docklet_toggle_blink(GtkWidget *toggle, void *data) { - purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/blink", GTK_CHECK_MENU_ITEM(toggle)->active); + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/blink", + gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(toggle))); } +#endif static void docklet_toggle_blist(GtkWidget *toggle, void *data) { - purple_blist_set_visible(GTK_CHECK_MENU_ITEM(toggle)->active); + purple_blist_set_visible(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(toggle))); } #ifdef _WIN32 @@ -634,7 +614,7 @@ static void -plugin_act(GtkObject *obj, PurplePluginAction *pam) +plugin_act(GtkWidget *widget, PurplePluginAction *pam) { if (pam && pam->callback) pam->callback(pam); @@ -776,10 +756,12 @@ g_signal_connect(G_OBJECT(menuitem), "toggled", G_CALLBACK(docklet_toggle_mute), NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); +#if !GTK_CHECK_VERSION(3,0,0) menuitem = gtk_check_menu_item_new_with_mnemonic(_("_Blink on New Message")); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink")); g_signal_connect(G_OBJECT(menuitem), "toggled", G_CALLBACK(docklet_toggle_blink), NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); +#endif pidgin_separator(menu); @@ -841,10 +823,6 @@ pidgin_blist_visibility_manager_remove(); visibility_manager = FALSE; } - if (docklet_blinking_timer) { - g_source_remove(docklet_blinking_timer); - docklet_blinking_timer = 0; - } visible = FALSE; status = PURPLE_STATUS_OFFLINE; }
--- a/pidgin/gtkft.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkft.c Mon Aug 06 18:11:44 2012 +0200 @@ -701,7 +701,7 @@ { PidginXferDialog *dialog; GtkWidget *window; - GtkWidget *vbox1, *vbox2; + GtkWidget *vbox; GtkWidget *expander; GtkWidget *alignment; GtkWidget *table; @@ -715,24 +715,21 @@ purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/filetransfer/clear_finished"); /* Create the window. */ - dialog->window = window = pidgin_create_window(_("File Transfers"), PIDGIN_HIG_BORDER, "file transfer", TRUE); +#if GTK_CHECK_VERSION(3,0,0) + dialog->window = window = pidgin_create_dialog(_("File Transfers"), 0, "file transfer", TRUE); +#else + dialog->window = window = pidgin_create_dialog(_("File Transfers"), PIDGIN_HIG_BORDER, "file transfer", TRUE); +#endif gtk_window_set_default_size(GTK_WINDOW(window), 450, 250); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_win_cb), dialog); - /* Create the parent vbox for everything. */ - vbox1 = gtk_vbox_new(FALSE, 0); - gtk_widget_show(vbox1); - gtk_container_add(GTK_CONTAINER(window), vbox1); - /* Create the main vbox for top half of the window. */ - vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); - gtk_box_pack_start(GTK_BOX(vbox1), vbox2, TRUE, TRUE, 0); - gtk_widget_show(vbox2); + vbox = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(window), FALSE, PIDGIN_HIG_BORDER); /* Setup the listbox */ - gtk_box_pack_start(GTK_BOX(vbox2), + gtk_box_pack_start(GTK_BOX(vbox), pidgin_make_scrollable(setup_tree(dialog), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, 140), TRUE, TRUE, 0); @@ -743,7 +740,7 @@ !dialog->keep_open); g_signal_connect(G_OBJECT(checkbox), "toggled", G_CALLBACK(toggle_keep_open_cb), dialog); - gtk_box_pack_start(GTK_BOX(vbox2), checkbox, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), checkbox, FALSE, FALSE, 0); gtk_widget_show(checkbox); /* "Clear finished transfers" */ @@ -753,13 +750,13 @@ dialog->auto_clear); g_signal_connect(G_OBJECT(checkbox), "toggled", G_CALLBACK(toggle_clear_finished_cb), dialog); - gtk_box_pack_start(GTK_BOX(vbox2), checkbox, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), checkbox, FALSE, FALSE, 0); gtk_widget_show(checkbox); /* "Download Details" arrow */ expander = gtk_expander_new_with_mnemonic(_("File transfer _details")); dialog->expander = expander; - gtk_box_pack_start(GTK_BOX(vbox2), expander, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), expander, FALSE, FALSE, 0); gtk_widget_show(expander); gtk_widget_set_sensitive(expander, FALSE); @@ -775,11 +772,7 @@ gtk_container_add(GTK_CONTAINER(alignment), table); gtk_widget_show(table); - bbox = gtk_hbutton_box_new(); - gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); - gtk_box_set_spacing(GTK_BOX(bbox), PIDGIN_HIG_BOX_SPACE); - gtk_box_pack_end(GTK_BOX(vbox1), bbox, FALSE, TRUE, 0); - gtk_widget_show(bbox); + bbox = pidgin_dialog_get_action_area(GTK_DIALOG(window)); #define ADD_BUTTON(b, label, callback, callbackdata) do { \ GtkWidget *button = gtk_button_new_from_stock(label); \
--- a/pidgin/gtkimhtml.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkimhtml.c Mon Aug 06 18:11:44 2012 +0200 @@ -65,15 +65,7 @@ #define TOOLTIP_TIMEOUT 500 -#if !GTK_CHECK_VERSION(2,20,0) -#define gtk_widget_get_realized(x) GTK_WIDGET_REALIZED(x) - -#if !GTK_CHECK_VERSION(2,18,0) -#define gtk_widget_get_has_window(x) !GTK_WIDGET_NO_WINDOW(x) -#define gtk_widget_get_state(x) GTK_WIDGET_STATE(x) -#define gtk_widget_is_drawable(x) GTK_WIDGET_DRAWABLE(x) -#endif -#endif +#include "gtk3compat.h" static GtkTextViewClass *parent_class = NULL; @@ -553,21 +545,41 @@ } } +#if GTK_CHECK_VERSION(3,0,0) +static gboolean +gtk_imhtml_tip_paint(GtkIMHtml *imhtml, cairo_t *cr, GtkWidget *w) +#else static gint -gtk_imhtml_tip_paint (GtkIMHtml *imhtml) +gtk_imhtml_tip_paint(GtkIMHtml *imhtml, GdkEvent *event, GtkWidget *w) +#endif { PangoLayout *layout; + GtkStyle *style; g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); - - gtk_paint_flat_box (imhtml->tip_window->style, imhtml->tip_window->window, - GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, imhtml->tip_window, - "tooltip", 0, 0, -1, -1); - - gtk_paint_layout (imhtml->tip_window->style, imhtml->tip_window->window, GTK_STATE_NORMAL, - FALSE, NULL, imhtml->tip_window, NULL, 4, 4, layout); + style = gtk_widget_get_style(imhtml->tip_window); + +#if GTK_CHECK_VERSION(3,0,0) + gtk_paint_flat_box(style, cr, + GTK_STATE_NORMAL, GTK_SHADOW_OUT, + imhtml->tip_window, "tooltip", + 0, 0, -1, -1); + + gtk_paint_layout(style, cr, + GTK_STATE_NORMAL, TRUE, imhtml->tip_window, NULL, + 4, 4, layout); +#else + gtk_paint_flat_box(style, gtk_widget_get_window(imhtml->tip_window), + GTK_STATE_NORMAL, GTK_SHADOW_OUT, + NULL, imhtml->tip_window, + "tooltip", 0, 0, -1, -1); + + gtk_paint_layout(style, gtk_widget_get_window(imhtml->tip_window), + GTK_STATE_NORMAL, FALSE, NULL, imhtml->tip_window, NULL, + 4, 4, layout); +#endif g_object_unref(layout); return FALSE; @@ -580,12 +592,15 @@ PangoFontMetrics *font_metrics; PangoLayout *layout; PangoFont *font; - + GtkStyle *style = gtk_widget_get_style(imhtml->tip_window); + GtkAllocation allocation; gint gap, x, y, h, w, scr_w, baseline_skip; g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); - if (!imhtml->tip || !gtk_widget_is_drawable (GTK_WIDGET(imhtml))) { + gtk_widget_get_allocation(GTK_WIDGET(imhtml), &allocation); + + if (!imhtml->tip || !gtk_widget_is_drawable(GTK_WIDGET(imhtml))) { imhtml->tip_timer = 0; return FALSE; } @@ -603,17 +618,21 @@ gtk_widget_set_name (imhtml->tip_window, "gtk-tooltips"); gtk_window_set_type_hint (GTK_WINDOW (imhtml->tip_window), GDK_WINDOW_TYPE_HINT_TOOLTIP); - g_signal_connect_swapped (G_OBJECT (imhtml->tip_window), "expose_event", - G_CALLBACK (gtk_imhtml_tip_paint), imhtml); +#if GTK_CHECK_VERSION(3,0,0) + g_signal_connect_swapped(G_OBJECT(imhtml->tip_window), "draw", + G_CALLBACK(gtk_imhtml_tip_paint), imhtml); +#else + g_signal_connect_swapped(G_OBJECT(imhtml->tip_window), "expose_event", + G_CALLBACK(gtk_imhtml_tip_paint), imhtml); +#endif gtk_widget_ensure_style (imhtml->tip_window); layout = gtk_widget_create_pango_layout(imhtml->tip_window, imhtml->tip); font = pango_context_load_font(pango_layout_get_context(layout), - imhtml->tip_window->style->font_desc); + style->font_desc); if (font == NULL) { - char *tmp = pango_font_description_to_string( - imhtml->tip_window->style->font_desc); + char *tmp = pango_font_description_to_string(style->font_desc); purple_debug(PURPLE_DEBUG_ERROR, "gtk_imhtml_tip", "pango_context_load_font() couldn't load font: '%s'\n", @@ -638,8 +657,8 @@ h = 8 + baseline_skip; gdk_window_get_pointer (NULL, &x, &y, NULL); - if (!gtk_widget_get_has_window (GTK_WIDGET(imhtml))) - y += GTK_WIDGET(imhtml)->allocation.y; + if ((!gtk_widget_get_has_window(GTK_WIDGET(imhtml)))) + y += allocation.y; scr_w = gdk_screen_width(); @@ -679,7 +698,7 @@ oldprelit_tag = GTK_IMHTML(imhtml)->prelit_tag; - gdk_window_get_pointer(GTK_WIDGET(imhtml)->window, NULL, NULL, NULL); + gdk_window_get_pointer(gtk_widget_get_window(GTK_WIDGET(imhtml)), NULL, NULL, NULL); gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(imhtml), GTK_TEXT_WINDOW_WIDGET, event->x, event->y, &x, &y); gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(imhtml), &iter, x, y); @@ -807,6 +826,8 @@ return FALSE; } +/* TODO: I think this can be removed for GTK+ 3.0... */ +#if !GTK_CHECK_VERSION(3,0,0) static gint gtk_imhtml_expose_event (GtkWidget *widget, GdkEventExpose *event) @@ -834,7 +855,8 @@ gdk_color_parse(GTK_IMHTML(widget)->edit.background, &gcolor); gdk_cairo_set_source_color(cr, &gcolor); } else { - gdk_cairo_set_source_color(cr, &(widget->style->base[gtk_widget_get_state(widget)])); + gdk_cairo_set_source_color(cr, + &(gtk_widget_get_style(widget)->base[gtk_widget_get_state(widget)])); } cairo_rectangle(cr, @@ -940,6 +962,7 @@ return FALSE; } +#endif static void paste_unformatted_cb(GtkMenuItem *menu, GtkIMHtml *imhtml) @@ -1111,7 +1134,7 @@ } if (primary) /* This was allocated here */ g_free(text); - } +} static void gtk_imhtml_primary_clipboard_clear(GtkClipboard *clipboard, GtkIMHtml *imhtml) { @@ -1216,11 +1239,12 @@ { char *text; GtkIMHtml *imhtml = data; + gint length = gtk_selection_data_get_length(selection_data); if (!gtk_text_view_get_editable(GTK_TEXT_VIEW(imhtml))) return; - if (imhtml->wbfo || selection_data->length <= 0) { + if (imhtml->wbfo || length <= 0) { gtk_clipboard_request_text(clipboard, paste_plaintext_received_cb, imhtml); return; } else { @@ -1244,13 +1268,13 @@ } #endif - text = g_malloc(selection_data->length + 1); - memcpy(text, selection_data->data, selection_data->length); + text = g_malloc(length + 1); + memcpy(text, gtk_selection_data_get_data(selection_data), length); /* Make sure the paste data is null-terminated. Given that * we're passed length (but assume later that it is * null-terminated), this seems sensible to me. */ - text[selection_data->length] = '\0'; + text[length] = '\0'; } #ifdef _WIN32 @@ -1261,10 +1285,10 @@ } #endif - if (selection_data->length >= 2 && + if (length >= 2 && (*(guint16 *)text == 0xfeff || *(guint16 *)text == 0xfffe)) { /* This is UTF-16 */ - char *utf8 = utf16_to_utf8_with_bom_check(text, selection_data->length); + char *utf8 = utf16_to_utf8_with_bom_check(text, length); g_free(text); text = utf8; if (!text) { @@ -1379,7 +1403,7 @@ paste_received_cb, imhtml); return TRUE; - } + } return FALSE; } @@ -1625,7 +1649,10 @@ gobject_class->finalize = gtk_imhtml_finalize; widget_class->drag_motion = gtk_text_view_drag_motion; + /* TODO: I _think_ this should be removed for GTK+ 3.0 */ +#if !GTK_CHECK_VERSION(3,0,0) widget_class->expose_event = gtk_imhtml_expose_event; +#endif parent_size_allocate = widget_class->size_allocate; widget_class->size_allocate = gtk_imhtml_size_allocate; parent_style_set = widget_class->style_set; @@ -1687,20 +1714,20 @@ TRUE, G_PARAM_READABLE)); binding_set = gtk_binding_set_by_class (parent_class); - gtk_binding_entry_add_signal (binding_set, GDK_b, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_BOLD); - gtk_binding_entry_add_signal (binding_set, GDK_i, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_ITALIC); - gtk_binding_entry_add_signal (binding_set, GDK_u, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_UNDERLINE); - gtk_binding_entry_add_signal (binding_set, GDK_plus, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_GROW); - gtk_binding_entry_add_signal (binding_set, GDK_equal, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_GROW); - gtk_binding_entry_add_signal (binding_set, GDK_minus, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_SHRINK); + gtk_binding_entry_add_signal (binding_set, GDK_KEY_b, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_BOLD); + gtk_binding_entry_add_signal (binding_set, GDK_KEY_i, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_ITALIC); + gtk_binding_entry_add_signal (binding_set, GDK_KEY_u, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_UNDERLINE); + gtk_binding_entry_add_signal (binding_set, GDK_KEY_plus, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_GROW); + gtk_binding_entry_add_signal (binding_set, GDK_KEY_equal, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_GROW); + gtk_binding_entry_add_signal (binding_set, GDK_KEY_minus, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_SHRINK); binding_set = gtk_binding_set_by_class(klass); - gtk_binding_entry_add_signal (binding_set, GDK_r, GDK_CONTROL_MASK, "format_function_clear", 0); - gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "message_send", 0); - gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "message_send", 0); - gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK, "undo", 0); - gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "redo", 0); - gtk_binding_entry_add_signal (binding_set, GDK_F14, 0, "undo", 0); - gtk_binding_entry_add_signal(binding_set, GDK_v, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "paste", 1, G_TYPE_STRING, "text"); + gtk_binding_entry_add_signal (binding_set, GDK_KEY_r, GDK_CONTROL_MASK, "format_function_clear", 0); + gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0, "message_send", 0); + gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0, "message_send", 0); + gtk_binding_entry_add_signal (binding_set, GDK_KEY_z, GDK_CONTROL_MASK, "undo", 0); + gtk_binding_entry_add_signal (binding_set, GDK_KEY_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "redo", 0); + gtk_binding_entry_add_signal (binding_set, GDK_KEY_F14, 0, "undo", 0); + gtk_binding_entry_add_signal(binding_set, GDK_KEY_v, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "paste", 1, G_TYPE_STRING, "text"); } static void gtk_imhtml_init (GtkIMHtml *imhtml) @@ -1927,23 +1954,23 @@ /* can't accept any of the offered targets */ } else { GtkWidget *source_widget; - suggested_action = context->suggested_action; + suggested_action = gdk_drag_context_get_suggested_action(context); source_widget = gtk_drag_get_source_widget (context); if (source_widget == widget) { /* Default to MOVE, unless the user has * pressed ctrl or alt to affect available actions */ - if ((context->actions & GDK_ACTION_MOVE) != 0) + if ((gdk_drag_context_get_actions(context) & GDK_ACTION_MOVE) != 0) suggested_action = GDK_ACTION_MOVE; } } gdk_drag_status (context, suggested_action, time); - /* TRUE return means don't propagate the drag motion to parent - * widgets that may also be drop sites. - */ - return TRUE; + /* TRUE return means don't propagate the drag motion to parent + * widgets that may also be drop sites. + */ + return TRUE; } static void @@ -1965,21 +1992,22 @@ { gchar **links; gchar *link; - char *text = (char *)sd->data; + char *text = (char *) gtk_selection_data_get_data(sd); GtkTextMark *mark = gtk_text_buffer_get_insert(imhtml->text_buffer); GtkTextIter iter; gint i = 0; + gint length = gtk_selection_data_get_length(sd); gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter, mark); - if(gtk_imhtml_get_editable(imhtml) && sd->data){ + if (gtk_imhtml_get_editable(imhtml) && text) { switch (info) { case GTK_IMHTML_DRAG_URL: /* TODO: Is it really ok to change sd->data...? */ - purple_str_strip_char((char *)sd->data, '\r'); - - links = g_strsplit((char *)sd->data, "\n", 0); - while((link = links[i]) != NULL){ + purple_str_strip_char(text, '\r'); + + links = g_strsplit(text, "\n", 0); + while ((link = links[i]) != NULL) { if (gtk_imhtml_is_protocol(link)) { gchar *label; @@ -2001,7 +2029,7 @@ i++; } - g_strfreev(links); + g_strfreev(links); break; case GTK_IMHTML_DRAG_HTML: { @@ -2017,8 +2045,8 @@ * See also the comment on text/html here: * http://mail.gnome.org/archives/gtk-devel-list/2001-September/msg00114.html */ - if (sd->length >= 2 && !g_utf8_validate(text, sd->length - 1, NULL)) { - utf8 = utf16_to_utf8_with_bom_check(text, sd->length); + if (length >= 2 && !g_utf8_validate(text, length - 1, NULL)) { + utf8 = utf16_to_utf8_with_bom_check(text, length); if (!utf8) { purple_debug_warning("gtkimhtml", "g_convert from UTF-16 failed in drag_rcv_cb\n"); @@ -2047,7 +2075,8 @@ gtk_drag_finish(dc, FALSE, FALSE, t); return; } - gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); + gtk_drag_finish(dc, TRUE, + gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); } else { gtk_drag_finish(dc, FALSE, FALSE, t); } @@ -2578,8 +2607,8 @@ static gboolean smooth_scroll_cb(gpointer data) { GtkIMHtml *imhtml = data; - GtkAdjustment *adj = GTK_TEXT_VIEW(imhtml)->vadjustment; - gdouble max_val = adj->upper - adj->page_size; + GtkAdjustment *adj = gtk_text_view_get_vadjustment(GTK_TEXT_VIEW(imhtml)); + gdouble max_val = gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj); gdouble scroll_val = gtk_adjustment_get_value(adj) + ((max_val - gtk_adjustment_get_value(adj)) / 3); g_return_val_if_fail(imhtml->scroll_time != NULL, FALSE); @@ -2602,9 +2631,10 @@ static gboolean scroll_idle_cb(gpointer data) { GtkIMHtml *imhtml = data; - GtkAdjustment *adj = GTK_TEXT_VIEW(imhtml)->vadjustment; - if(adj) { - gtk_adjustment_set_value(adj, adj->upper - adj->page_size); + GtkAdjustment *adj = gtk_text_view_get_vadjustment(GTK_TEXT_VIEW(imhtml)); + if (adj) { + gtk_adjustment_set_value(adj, gtk_adjustment_get_upper(adj) - + gtk_adjustment_get_page_size(adj)); } imhtml->scroll_src = 0; return FALSE; @@ -4286,9 +4316,14 @@ for (l = tags; l; l = l->next) { GtkTextTag *tag = l->data; - - if (tag->name && !strncmp(tag->name, prefix, len)) + gchar *name = NULL; + + g_object_get(G_OBJECT(tag), "name", &name, NULL); + + if (name && !strncmp(name, prefix, len)) gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, i, e); + + g_free(name); } g_slist_free(tags); @@ -4304,9 +4339,14 @@ for (l = tags; l; l = l->next) { GtkTextTag *tag = l->data; - - if (tag->name && !strncmp(tag->name, prefix, len)) + gchar *name = NULL; + + g_object_get(G_OBJECT(tag), "name", &name, NULL); + + if (name && !strncmp(name, prefix, len)) gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, &iter, e); + + g_free(name); } g_slist_free(tags); @@ -4427,11 +4467,16 @@ gtk_text_iter_begins_tag(start, tag) && /* the tag starts with the selection */ (!gtk_text_iter_has_tag(end, tag) || /* the tag ends within the selection */ gtk_text_iter_ends_tag(end, tag))) { + gchar *name = NULL; + + g_object_get(G_OBJECT(tag), "name", &name, NULL); gtk_text_buffer_remove_tag(imhtml->text_buffer, tag, start, end); - if (tag->name && - strncmp(tag->name, "LINK ", 5) == 0 && imhtml->edit.link) { + + if (name && strncmp(name, "LINK ", 5) == 0 && imhtml->edit.link) { gtk_imhtml_toggle_link(imhtml, NULL); } + + g_free(name); } } g_slist_free(tags); @@ -4653,27 +4698,32 @@ for (l = tags; l != NULL; l = l->next) { GtkTextTag *tag = GTK_TEXT_TAG(l->data); - - if (tag->name) { - if (strcmp(tag->name, "BOLD") == 0) + gchar *name = NULL; + + g_object_get(G_OBJECT(tag), "name", &name, NULL); + + if (name) { + if (strcmp(name, "BOLD") == 0) imhtml->edit.bold = TRUE; - else if (strcmp(tag->name, "ITALICS") == 0) + else if (strcmp(name, "ITALICS") == 0) imhtml->edit.italic = TRUE; - else if (strcmp(tag->name, "UNDERLINE") == 0) + else if (strcmp(name, "UNDERLINE") == 0) imhtml->edit.underline = TRUE; - else if (strcmp(tag->name, "STRIKE") == 0) + else if (strcmp(name, "STRIKE") == 0) imhtml->edit.strike = TRUE; - else if (strncmp(tag->name, "FORECOLOR ", 10) == 0) - imhtml->edit.forecolor = g_strdup(&(tag->name)[10]); - else if (strncmp(tag->name, "BACKCOLOR ", 10) == 0) - imhtml->edit.backcolor = g_strdup(&(tag->name)[10]); - else if (strncmp(tag->name, "FONT FACE ", 10) == 0) - imhtml->edit.fontface = g_strdup(&(tag->name)[10]); - else if (strncmp(tag->name, "FONT SIZE ", 10) == 0) - imhtml->edit.fontsize = strtol(&(tag->name)[10], NULL, 10); - else if ((strncmp(tag->name, "LINK ", 5) == 0) && !gtk_text_iter_is_end(&iter)) + else if (strncmp(name, "FORECOLOR ", 10) == 0) + imhtml->edit.forecolor = g_strdup(&(name)[10]); + else if (strncmp(name, "BACKCOLOR ", 10) == 0) + imhtml->edit.backcolor = g_strdup(&(name)[10]); + else if (strncmp(name, "FONT FACE ", 10) == 0) + imhtml->edit.fontface = g_strdup(&(name)[10]); + else if (strncmp(name, "FONT SIZE ", 10) == 0) + imhtml->edit.fontsize = strtol(&(name)[10], NULL, 10); + else if ((strncmp(name, "LINK ", 5) == 0) && !gtk_text_iter_is_end(&iter)) imhtml->edit.link = tag; } + + g_free(name); } g_slist_free(tags); @@ -4964,6 +5014,8 @@ gtk_text_buffer_end_user_action(imhtml->text_buffer); } +/* TODO: I think this can be removed for GTK+ 3.0... */ +#if !GTK_CHECK_VERSION(3,0,0) static gboolean image_expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { @@ -4971,9 +5023,10 @@ return TRUE; } +#endif /* In case the smiley gets removed from the imhtml before it gets removed from the queue */ -static void animated_smiley_destroy_cb(GtkObject *widget, GtkIMHtml *imhtml) +static void animated_smiley_destroy_cb(GtkWidget *widget, GtkIMHtml *imhtml) { GList *l = imhtml->animations->head; while (l) { @@ -5068,7 +5121,7 @@ } } } else { - imhtml->num_animations++; + imhtml->num_animations++; } g_signal_connect(G_OBJECT(icon), "destroy", G_CALLBACK(animated_smiley_destroy_cb), imhtml); g_queue_push_tail(imhtml->animations, icon); @@ -5092,7 +5145,10 @@ * images, and ensures that they are handled by the image * itself, without propagating to the textview and causing * a complete refresh */ + /* TODO: I think this should be removed for GTK+ 3.0? */ +#if !GTK_CHECK_VERSION(3,0,0) g_signal_connect(G_OBJECT(icon), "expose-event", G_CALLBACK(image_expose), NULL); +#endif gtk_widget_show(icon); if (ebox) @@ -5186,22 +5242,29 @@ static const gchar *tag_to_html_start(GtkTextTag *tag) { - const gchar *name; static gchar buf[1024]; - - name = tag->name; + gchar *name = NULL; + + g_object_get(G_OBJECT(tag), "name", &name, NULL); g_return_val_if_fail(name != NULL, ""); if (strcmp(name, "BOLD") == 0) { + g_free(name); return "<b>"; } else if (strcmp(name, "ITALICS") == 0) { + g_free(name); return "<i>"; } else if (strcmp(name, "UNDERLINE") == 0) { + g_free(name); return "<u>"; } else if (strcmp(name, "STRIKE") == 0) { + g_free(name); return "<s>"; } else if (strncmp(name, "LINK ", 5) == 0) { char *tmp = g_object_get_data(G_OBJECT(tag), "link_url"); + + g_free(name); + if (tmp) { g_snprintf(buf, sizeof(buf), "<a href=\"%s\">", tmp); buf[sizeof(buf)-1] = '\0'; @@ -5211,18 +5274,29 @@ } } else if (strncmp(name, "FORECOLOR ", 10) == 0) { g_snprintf(buf, sizeof(buf), "<font color=\"%s\">", &name[10]); + + g_free(name); + return buf; } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { g_snprintf(buf, sizeof(buf), "<font back=\"%s\">", &name[10]); + g_free(name); + return buf; } else if (strncmp(name, "BACKGROUND ", 10) == 0) { g_snprintf(buf, sizeof(buf), "<body bgcolor=\"%s\">", &name[11]); + g_free(name); + return buf; } else if (strncmp(name, "FONT FACE ", 10) == 0) { g_snprintf(buf, sizeof(buf), "<font face=\"%s\">", &name[10]); + g_free(name); + return buf; } else if (strncmp(name, "FONT SIZE ", 10) == 0) { g_snprintf(buf, sizeof(buf), "<font size=\"%s\">", &name[10]); + g_free(name); + return buf; } else { char *str = buf; @@ -5285,6 +5359,7 @@ } g_snprintf(str, sizeof(buf) - (str - buf), "'>"); + g_free(name); return (empty ? "" : buf); } @@ -5292,30 +5367,40 @@ static const gchar *tag_to_html_end(GtkTextTag *tag) { - const gchar *name; - - name = tag->name; + gchar *name; + + g_object_get(G_OBJECT(tag), "name", &name, NULL); g_return_val_if_fail(name != NULL, ""); if (strcmp(name, "BOLD") == 0) { + g_free(name); return "</b>"; } else if (strcmp(name, "ITALICS") == 0) { + g_free(name); return "</i>"; } else if (strcmp(name, "UNDERLINE") == 0) { + g_free(name); return "</u>"; } else if (strcmp(name, "STRIKE") == 0) { + g_free(name); return "</s>"; } else if (strncmp(name, "LINK ", 5) == 0) { + g_free(name); return "</a>"; } else if (strncmp(name, "FORECOLOR ", 10) == 0) { + g_free(name); return "</font>"; } else if (strncmp(name, "BACKCOLOR ", 10) == 0) { + g_free(name); return "</font>"; } else if (strncmp(name, "BACKGROUND ", 10) == 0) { + g_free(name); return "</body>"; } else if (strncmp(name, "FONT FACE ", 10) == 0) { + g_free(name); return "</font>"; } else if (strncmp(name, "FONT SIZE ", 10) == 0) { + g_free(name); return "</font>"; } else { const char *props[] = {"weight-set", "foreground-set", "background-set", @@ -5328,6 +5413,8 @@ return "</span>"; } + g_free(name); + return ""; } }
--- a/pidgin/gtkimhtml.h Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkimhtml.h Mon Aug 06 18:11:44 2012 +0200 @@ -175,12 +175,12 @@ } GtkIMHtmlOptions; enum { - GTK_IMHTML_DRAG_URL = 0, - GTK_IMHTML_DRAG_HTML, + GTK_IMHTML_DRAG_HTML = 0, + GTK_IMHTML_DRAG_TEXT, GTK_IMHTML_DRAG_UTF8_STRING, + GTK_IMHTML_DRAG_URL, GTK_IMHTML_DRAG_COMPOUND_TEXT, GTK_IMHTML_DRAG_STRING, - GTK_IMHTML_DRAG_TEXT, GTK_IMHTML_DRAG_NUM };
--- a/pidgin/gtkimhtmltoolbar.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkimhtmltoolbar.c Mon Aug 06 18:11:44 2012 +0200 @@ -43,10 +43,8 @@ #include <gdk/gdkkeysyms.h> -#if !GTK_CHECK_VERSION(2,18,0) -#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x) -#define gtk_widget_is_sensitive(x) GTK_WIDGET_IS_SENSITIVE(x) -#endif +#define GTK_TOOLTIPS_VAR toolbar->tooltips +#include "gtk3compat.h" static GtkHBoxClass *parent_class = NULL; @@ -129,11 +127,15 @@ { GtkFontSelection *sel; - sel = GTK_FONT_SELECTION(GTK_FONT_SELECTION_DIALOG(toolbar->font_dialog)->fontsel); - gtk_widget_hide_all(gtk_widget_get_parent(sel->size_entry)); - gtk_widget_show_all(sel->family_list); - gtk_widget_show(gtk_widget_get_parent(sel->family_list)); - gtk_widget_show(gtk_widget_get_parent(gtk_widget_get_parent(sel->family_list))); + sel = GTK_FONT_SELECTION( + gtk_font_selection_dialog_get_font_selection(GTK_FONT_SELECTION_DIALOG(toolbar->font_dialog))); + gtk_widget_hide(gtk_widget_get_parent( + gtk_font_selection_get_size_entry(sel))); + gtk_widget_show_all(gtk_font_selection_get_family_list(sel)); + gtk_widget_show(gtk_widget_get_parent( + gtk_font_selection_get_family_list(sel))); + gtk_widget_show(gtk_widget_get_parent(gtk_widget_get_parent( + gtk_font_selection_get_family_list(sel)))); } static void @@ -196,10 +198,12 @@ g_signal_connect(G_OBJECT(toolbar->font_dialog), "delete_event", G_CALLBACK(destroy_toolbar_font), toolbar); - g_signal_connect(G_OBJECT(GTK_FONT_SELECTION_DIALOG(toolbar->font_dialog)->ok_button), "clicked", - G_CALLBACK(apply_font), toolbar->font_dialog); - g_signal_connect(G_OBJECT(GTK_FONT_SELECTION_DIALOG(toolbar->font_dialog)->cancel_button), "clicked", - G_CALLBACK(cancel_toolbar_font), toolbar); + g_signal_connect(G_OBJECT( + gtk_font_selection_dialog_get_ok_button(GTK_FONT_SELECTION_DIALOG(toolbar->font_dialog))), + "clicked", G_CALLBACK(apply_font), toolbar->font_dialog); + g_signal_connect(G_OBJECT( + gtk_font_selection_dialog_get_cancel_button(GTK_FONT_SELECTION_DIALOG(toolbar->font_dialog))), + "clicked", G_CALLBACK(cancel_toolbar_font), toolbar); g_signal_connect_after(G_OBJECT(toolbar->font_dialog), "realize", G_CALLBACK(realize_toolbar_font), toolbar); } @@ -258,9 +262,12 @@ char *color = gtk_imhtml_get_current_forecolor(GTK_IMHTML(toolbar->imhtml)); if (!toolbar->fgcolor_dialog) { + GtkWidget *ok_button; + GtkWidget *cancel_button; toolbar->fgcolor_dialog = gtk_color_selection_dialog_new(_("Select Text Color")); - colorsel = GTK_COLOR_SELECTION_DIALOG(toolbar->fgcolor_dialog)->colorsel; + colorsel = + gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(toolbar->fgcolor_dialog)); if (color) { gdk_color_parse(color, &fgcolor); gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(colorsel), &fgcolor); @@ -269,12 +276,13 @@ g_object_set_data(G_OBJECT(colorsel), "purple_toolbar", toolbar); + g_object_get(G_OBJECT(toolbar->fgcolor_dialog), "ok-button", &ok_button, NULL); + g_object_get(G_OBJECT(toolbar->fgcolor_dialog), "cancel-button", &cancel_button, NULL); g_signal_connect(G_OBJECT(toolbar->fgcolor_dialog), "delete_event", G_CALLBACK(destroy_toolbar_fgcolor), toolbar); - g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(toolbar->fgcolor_dialog)->ok_button), "clicked", - G_CALLBACK(do_fgcolor), colorsel); - g_signal_connect(G_OBJECT (GTK_COLOR_SELECTION_DIALOG(toolbar->fgcolor_dialog)->cancel_button), "clicked", - G_CALLBACK(cancel_toolbar_fgcolor), toolbar); + g_signal_connect(G_OBJECT(ok_button), "clicked", G_CALLBACK(do_fgcolor), colorsel); + g_signal_connect(G_OBJECT(cancel_button), "clicked", + G_CALLBACK(cancel_toolbar_fgcolor), toolbar); } gtk_window_present(GTK_WINDOW(toolbar->fgcolor_dialog)); } else { @@ -338,9 +346,13 @@ char *color = gtk_imhtml_get_current_backcolor(GTK_IMHTML(toolbar->imhtml)); if (!toolbar->bgcolor_dialog) { + GtkWidget *ok_button; + GtkWidget *cancel_button; toolbar->bgcolor_dialog = gtk_color_selection_dialog_new(_("Select Background Color")); - colorsel = GTK_COLOR_SELECTION_DIALOG(toolbar->bgcolor_dialog)->colorsel; + colorsel = + gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(toolbar->bgcolor_dialog)); + if (color) { gdk_color_parse(color, &bgcolor); gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(colorsel), &bgcolor); @@ -349,11 +361,14 @@ g_object_set_data(G_OBJECT(colorsel), "purple_toolbar", toolbar); + g_object_get(G_OBJECT(toolbar->bgcolor_dialog), "ok-button", &ok_button, NULL); + g_object_get(G_OBJECT(toolbar->bgcolor_dialog), "cancel-button", + &cancel_button, NULL); g_signal_connect(G_OBJECT(toolbar->bgcolor_dialog), "delete_event", G_CALLBACK(destroy_toolbar_bgcolor), toolbar); - g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(toolbar->bgcolor_dialog)->ok_button), "clicked", - G_CALLBACK(do_bgcolor), colorsel); - g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(toolbar->bgcolor_dialog)->cancel_button), "clicked", + g_signal_connect(G_OBJECT(ok_button), "clicked", + G_CALLBACK(do_bgcolor), colorsel); + g_signal_connect(G_OBJECT(cancel_button), "clicked", G_CALLBACK(cancel_toolbar_bgcolor), toolbar); } @@ -466,12 +481,12 @@ static void insert_hr_cb(GtkWidget *widget, GtkIMHtmlToolbar *toolbar) { - GtkTextIter iter; - GtkTextMark *ins; + GtkTextIter iter; + GtkTextMark *ins; GtkIMHtmlScalable *hr; - ins = gtk_text_buffer_get_insert(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->imhtml))); - gtk_text_buffer_get_iter_at_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->imhtml)), &iter, ins); + ins = gtk_text_buffer_get_insert(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->imhtml))); + gtk_text_buffer_get_iter_at_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->imhtml)), &iter, ins); hr = gtk_imhtml_hr_new(); gtk_imhtml_hr_add_to(hr, GTK_IMHTML(toolbar->imhtml), &iter); } @@ -663,11 +678,7 @@ g_object_set_data(G_OBJECT(button), "smiley_text", face); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(insert_smiley_text), toolbar); -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(button, face); -#else - gtk_tooltips_set_tip(toolbar->tooltips, button, face, NULL); -#endif /* these look really weird with borders */ gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); @@ -681,11 +692,7 @@ g_snprintf(tip, sizeof(tip), _("This smiley is disabled because a custom smiley exists for this shortcut:\n %s"), face); -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(button, tip); -#else - gtk_tooltips_set_tip(toolbar->tooltips, button, tip, NULL); -#endif gtk_widget_set_sensitive(button, FALSE); } else if (psmiley) { /* Remove the button if the smiley is destroyed */ @@ -727,7 +734,7 @@ static gboolean smiley_dialog_input_cb(GtkWidget *dialog, GdkEvent *event, GtkIMHtmlToolbar *toolbar) { - if ((event->type == GDK_KEY_PRESS && event->key.keyval == GDK_Escape) || + if ((event->type == GDK_KEY_PRESS && event->key.keyval == GDK_KEY_Escape) || (event->type == GDK_BUTTON_PRESS && event->button.button == 1)) { close_smiley_dialog(toolbar); @@ -1097,19 +1104,21 @@ { GtkWidget *widget = GTK_WIDGET(data); GtkRequisition menu_req; - gint ythickness = widget->style->ythickness; + GtkAllocation allocation; + gint ythickness = gtk_widget_get_style(widget)->ythickness; int savy; + gtk_widget_get_allocation(widget, &allocation); gtk_widget_size_request(GTK_WIDGET (menu), &menu_req); - gdk_window_get_origin(widget->window, x, y); - *x += widget->allocation.x; - *y += widget->allocation.y + widget->allocation.height; + gdk_window_get_origin(gtk_widget_get_window(widget), x, y); + *x += allocation.x; + *y += allocation.y + allocation.height; savy = *y; pidgin_menu_position_func_helper(menu, x, y, push_in, data); if (savy > *y + ythickness + 1) - *y -= widget->allocation.height; + *y -= allocation.height; } static gboolean @@ -1268,11 +1277,7 @@ g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(buttons[iter].callback), toolbar); *(buttons[iter].button) = button; -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(button, buttons[iter].tooltip); -#else - gtk_tooltips_set_tip(toolbar->tooltips, button, buttons[iter].tooltip, NULL); -#endif } else button = gtk_vseparator_new(); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); @@ -1294,7 +1299,7 @@ static void button_sensitiveness_changed(GtkWidget *button, gpointer dontcare, GtkWidget *item) { - gtk_widget_set_sensitive(item, gtk_widget_is_sensitive(button)); + gtk_widget_set_sensitive(item, gtk_widget_get_sensitive(button)); } static void @@ -1317,10 +1322,10 @@ gconstpointer value, gpointer toolbar) { if (value) { - gtk_widget_hide_all(g_object_get_data(G_OBJECT(toolbar), "lean-view")); + gtk_widget_hide(g_object_get_data(G_OBJECT(toolbar), "lean-view")); gtk_widget_show_all(g_object_get_data(G_OBJECT(toolbar), "wide-view")); } else { - gtk_widget_hide_all(g_object_get_data(G_OBJECT(toolbar), "wide-view")); + gtk_widget_hide(g_object_get_data(G_OBJECT(toolbar), "wide-view")); gtk_widget_show_all(g_object_get_data(G_OBJECT(toolbar), "lean-view")); } } @@ -1418,7 +1423,8 @@ g_signal_connect(G_OBJECT(font_button), "button-press-event", G_CALLBACK(button_activate_on_click), toolbar); g_signal_connect(G_OBJECT(font_button), "activate", G_CALLBACK(pidgin_menu_clicked), font_menu); - g_signal_connect(G_OBJECT(font_menu), "deactivate", G_CALLBACK(pidgin_menu_deactivate), font_button); + g_signal_connect_data(G_OBJECT(font_menu), "deactivate", G_CALLBACK(pidgin_menu_deactivate), + g_object_ref(font_button), (GClosureNotify)g_object_unref, 0); /* Sep */ sep = gtk_vseparator_new(); @@ -1463,7 +1469,8 @@ g_signal_connect(G_OBJECT(insert_button), "button-press-event", G_CALLBACK(button_activate_on_click), toolbar); g_signal_connect(G_OBJECT(insert_button), "activate", G_CALLBACK(pidgin_menu_clicked), insert_menu); - g_signal_connect(G_OBJECT(insert_menu), "deactivate", G_CALLBACK(pidgin_menu_deactivate), insert_button); + g_signal_connect_data(G_OBJECT(insert_menu), "deactivate", G_CALLBACK(pidgin_menu_deactivate), + g_object_ref(insert_button), (GClosureNotify)g_object_unref, 0); toolbar->sml = NULL; /* Sep */
--- a/pidgin/gtklog.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtklog.c Mon Aug 06 18:11:44 2012 +0200 @@ -39,6 +39,8 @@ #include "gtkutils.h" #include "gtkwebview.h" +#include "gtk3compat.h" + static GHashTable *log_viewers = NULL; static void populate_log_tree(PidginLogViewer *lv); static PidginLogViewer *syslog_viewer = NULL; @@ -583,10 +585,7 @@ gtk_dialog_add_button(GTK_DIALOG(lv->window), _("_Browse logs folder"), GTK_RESPONSE_HELP); #endif gtk_container_set_border_width (GTK_CONTAINER(lv->window), PIDGIN_HIG_BOX_SPACE); -#if !GTK_CHECK_VERSION(2,22,0) - gtk_dialog_set_has_separator(GTK_DIALOG(lv->window), FALSE); -#endif - gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(lv->window)->vbox), 0); + gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(lv->window))), 0); g_signal_connect(G_OBJECT(lv->window), "response", G_CALLBACK(destroy_cb), ht); gtk_window_set_role(GTK_WINDOW(lv->window), "log_viewer"); @@ -595,11 +594,12 @@ if (icon != NULL) { title_box = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); gtk_container_set_border_width(GTK_CONTAINER(title_box), PIDGIN_HIG_BOX_SPACE); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(lv->window)->vbox), title_box, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(lv->window))), + title_box, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(title_box), icon, FALSE, FALSE, 0); } else - title_box = GTK_DIALOG(lv->window)->vbox; + title_box = gtk_dialog_get_content_area(GTK_DIALOG(lv->window)); /* Label ************/ lv->label = gtk_label_new(NULL); @@ -614,7 +614,8 @@ /* Pane *************/ pane = gtk_hpaned_new(); gtk_container_set_border_width(GTK_CONTAINER(pane), PIDGIN_HIG_BOX_SPACE); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(lv->window)->vbox), pane, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(lv->window))), + pane, TRUE, TRUE, 0); /* List *************/ lv->treestore = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_POINTER); @@ -649,7 +650,8 @@ gtk_label_set_markup(GTK_LABEL(size_label), text); /* gtk_paned_add1(GTK_PANED(pane), size_label); */ gtk_misc_set_alignment(GTK_MISC(size_label), 0, 0); - gtk_box_pack_end(GTK_BOX(GTK_DIALOG(lv->window)->vbox), size_label, FALSE, FALSE, 0); + gtk_box_pack_end(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(lv->window))), + size_label, FALSE, FALSE, 0); g_free(sz_txt); g_free(text); }
--- a/pidgin/gtkmedia.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkmedia.c Mon Aug 06 18:11:44 2012 +0200 @@ -46,6 +46,8 @@ #include <gst/interfaces/xoverlay.h> +#include "gtk3compat.h" + #define PIDGIN_TYPE_MEDIA (pidgin_media_get_type()) #define PIDGIN_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PIDGIN_TYPE_MEDIA, PidginMedia)) #define PIDGIN_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PIDGIN_TYPE_MEDIA, PidginMediaClass)) @@ -540,20 +542,12 @@ GdkWindow *window = NULL; if (data->participant == NULL) -#if GTK_CHECK_VERSION(2, 14, 0) window = gtk_widget_get_window(priv->local_video); -#else - window = (priv->local_video)->window; -#endif else { GtkWidget *widget = pidgin_media_get_widget(data->gtkmedia, data->session_id, data->participant); if (widget) -#if GTK_CHECK_VERSION(2, 14, 0) window = gtk_widget_get_window(widget); -#else - window = widget->window; -#endif } if (window) { @@ -561,7 +555,7 @@ #ifdef _WIN32 window_id = GDK_WINDOW_HWND(window); #elif defined(HAVE_X11) - window_id = GDK_WINDOW_XWINDOW(window); + window_id = gdk_x11_window_get_xid(window); #elif defined(GDK_WINDOWING_QUARTZ) window_id = (gulong) gdk_quartz_window_get_nsview(window); #else
--- a/pidgin/gtkmenutray.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkmenutray.c Mon Aug 06 18:11:44 2012 +0200 @@ -23,6 +23,8 @@ #include <gtk/gtk.h> +#include "gtk3compat.h" + /****************************************************************************** * Enums *****************************************************************************/ @@ -35,20 +37,20 @@ * Globals *****************************************************************************/ static GObjectClass *parent_class = NULL; +#if !GTK_CHECK_VERSION(2,12,0) +static GtkTooltips *tooltips = NULL; +#endif /****************************************************************************** * Internal Stuff *****************************************************************************/ -#if !GTK_CHECK_VERSION(2,18,0) -#define gtk_widget_get_has_window(x) !GTK_WIDGET_NO_WINDOW(x) -#endif - /****************************************************************************** * Item Stuff *****************************************************************************/ +#if GTK_CHECK_VERSION(3,0,0) static void -pidgin_menu_tray_select(GtkItem *item) { +pidgin_menu_tray_select(GtkMenuItem *widget) { /* this may look like nothing, but it's really overriding the * GtkMenuItem's select function so that it doesn't get highlighted like * a normal menu item would. @@ -56,15 +58,40 @@ } static void -pidgin_menu_tray_deselect(GtkItem *item) { +pidgin_menu_tray_deselect(GtkMenuItem *widget) { /* Probably not necessary, but I'd rather be safe than sorry. We're * overridding the select, so it makes sense to override deselect as well. */ } +#else +static void +pidgin_menu_tray_select(GtkItem *widget) { + /* this may look like nothing, but it's really overriding the + * GtkMenuItem's select function so that it doesn't get highlighted like + * a normal menu item would. + */ +} +static void +pidgin_menu_tray_deselect(GtkItem *widget) { + /* Probably not necessary, but I'd rather be safe than sorry. We're + * overridding the select, so it makes sense to override deselect as well. + */ +} +#endif /****************************************************************************** * Widget Stuff *****************************************************************************/ +#if !GTK_CHECK_VERSION(2,12,0) +static void +tooltips_unref_cb(gpointer data, GObject *object, gboolean is_last_ref) +{ + if (is_last_ref) { + g_object_unref(tooltips); + tooltips = NULL; + } +} +#endif /****************************************************************************** * Object Stuff @@ -96,10 +123,9 @@ static void pidgin_menu_tray_finalize(GObject *obj) { -#if !GTK_CHECK_VERSION(2,12,0) +#if 0 PidginMenuTray *tray = PIDGIN_MENU_TRAY(obj); -#endif -#if 0 + /* This _might_ be leaking, but I have a sneaking suspicion that the widget is * getting destroyed in GtkContainer's finalize function. But if were are * leaking here, be sure to figure out why this causes a crash. @@ -110,19 +136,17 @@ gtk_widget_destroy(GTK_WIDGET(tray->tray)); #endif -#if !GTK_CHECK_VERSION(2,12,0) - if (tray->tooltips) { - gtk_object_sink(GTK_OBJECT(tray->tooltips)); - } -#endif - G_OBJECT_CLASS(parent_class)->finalize(obj); } static void pidgin_menu_tray_class_init(PidginMenuTrayClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); - GtkItemClass *item_class = GTK_ITEM_CLASS(klass); +#if GTK_CHECK_VERSION(3,0,0) + GtkMenuItemClass *menu_item_class = GTK_MENU_ITEM_CLASS(klass); +#else + GtkItemClass *menu_item_class = GTK_ITEM_CLASS(klass); +#endif GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); GParamSpec *pspec; @@ -131,8 +155,8 @@ object_class->finalize = pidgin_menu_tray_finalize; object_class->get_property = pidgin_menu_tray_get_property; - item_class->select = pidgin_menu_tray_select; - item_class->deselect = pidgin_menu_tray_deselect; + menu_item_class->select = pidgin_menu_tray_select; + menu_item_class->deselect = pidgin_menu_tray_deselect; widget_class->map = pidgin_menu_tray_map; @@ -247,8 +271,11 @@ pidgin_menu_tray_set_tooltip(PidginMenuTray *menu_tray, GtkWidget *widget, const char *tooltip) { #if !GTK_CHECK_VERSION(2,12,0) - if (!menu_tray->tooltips) - menu_tray->tooltips = gtk_tooltips_new(); + gboolean notify_tooltips = FALSE; + if (!tooltips) { + tooltips = gtk_tooltips_new(); + notify_tooltips = TRUE; + } #endif /* Should we check whether widget is a child of menu_tray? */ @@ -261,12 +288,15 @@ * not on the widget itself. */ if (!gtk_widget_get_has_window(widget)) - widget = widget->parent; + widget = gtk_widget_get_parent(widget); #if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(widget, tooltip); #else - gtk_tooltips_set_tip(menu_tray->tooltips, widget, tooltip, NULL); + gtk_tooltips_set_tip(tooltips, widget, tooltip, NULL); + + if (notify_tooltips) + g_object_add_toggle_ref(G_OBJECT(tooltips), tooltips_unref_cb, NULL); #endif }
--- a/pidgin/gtkmenutray.h Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkmenutray.h Mon Aug 06 18:11:44 2012 +0200 @@ -40,9 +40,6 @@ struct _PidginMenuTray { GtkMenuItem gparent; /**< The parent instance */ GtkWidget *tray; /**< The tray */ -#if !GTK_CHECK_VERSION(2,12,0) - GtkTooltips *tooltips; /**< Tooltips */ -#endif }; /** A PidginMenuTrayClass */
--- a/pidgin/gtknotify.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtknotify.c Mon Aug 06 18:11:44 2012 +0200 @@ -534,14 +534,14 @@ gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BORDER); gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); -#if !GTK_CHECK_VERSION(2,22,0) - gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); -#endif - gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER); - gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BOX_SPACE); + gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + PIDGIN_HIG_BORDER); + gtk_container_set_border_width(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + PIDGIN_HIG_BOX_SPACE); hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); + gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + hbox); if (img != NULL) gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); @@ -786,11 +786,7 @@ gtk_tree_selection_select_iter(sel, &iter); } -#if GTK_CHECK_VERSION(2,18,0) if (!gtk_widget_get_visible(mail_dialog->dialog)) { -#else - if (!GTK_WIDGET_VISIBLE(mail_dialog->dialog)) { -#endif GdkPixbuf *pixbuf = gtk_widget_render_icon(mail_dialog->dialog, PIDGIN_STOCK_DIALOG_MAIL, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), NULL); char *label_text = g_strdup_printf(ngettext("<b>%d new email.</b>", @@ -806,11 +802,7 @@ g_free(label_text); if (pixbuf) g_object_unref(pixbuf); -#if GTK_CHECK_VERSION(2,18,0) } else if (!gtk_widget_has_focus(mail_dialog->dialog)) -#else - } else if (!GTK_WIDGET_HAS_FOCUS(mail_dialog->dialog)) -#endif pidgin_set_urgent(GTK_WINDOW(mail_dialog->dialog), TRUE); return data; @@ -819,7 +811,7 @@ static gboolean formatted_input_cb(GtkWidget *win, GdkEventKey *event, gpointer data) { - if (event->keyval == GDK_Escape) + if (event->keyval == GDK_KEY_Escape) { purple_notify_close(PURPLE_NOTIFY_FORMATTED, win); @@ -844,14 +836,16 @@ window = gtk_dialog_new(); gtk_window_set_title(GTK_WINDOW(window), title); +#if !GTK_CHECK_VERSION(3,0,0) gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); +#endif gtk_window_set_resizable(GTK_WINDOW(window), TRUE); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(formatted_close_cb), NULL); /* Setup the main vbox */ - vbox = GTK_DIALOG(window)->vbox; + vbox = gtk_dialog_get_content_area(GTK_DIALOG(window)); /* Setup the descriptive label */ primary_esc = g_markup_escape_text(primary, -1); @@ -979,7 +973,7 @@ G_CALLBACK(searchresults_close_cb), data); /* Setup the main vbox */ - vbox = GTK_DIALOG(window)->vbox; + vbox = gtk_dialog_get_content_area(GTK_DIALOG(window)); /* Setup the descriptive label */ primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL; @@ -1510,16 +1504,13 @@ dialog = gtk_dialog_new(); + /* Vertical box */ + vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + /* Setup the dialog */ gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BOX_SPACE); - gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BOX_SPACE); -#if !GTK_CHECK_VERSION(2,22,0) - gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); -#endif - gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER); - - /* Vertical box */ - vbox = GTK_DIALOG(dialog)->vbox; + gtk_container_set_border_width(GTK_CONTAINER(vbox), PIDGIN_HIG_BOX_SPACE); + gtk_box_set_spacing(GTK_BOX(vbox), PIDGIN_HIG_BORDER); /* Golden ratio it up! */ gtk_widget_set_size_request(dialog, 550, 400);
--- a/pidgin/gtkplugin.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkplugin.c Mon Aug 06 18:11:44 2012 +0200 @@ -35,6 +35,8 @@ #include <string.h> +#include "gtk3compat.h" + #define PIDGIN_RESPONSE_CONFIGURE 98121 static void plugin_toggled_stage_two(PurplePlugin *plug, GtkTreeModel *model, @@ -518,7 +520,7 @@ break; dialog = gtk_dialog_new_with_buttons(PIDGIN_ALERT_TITLE, GTK_WINDOW(d), - GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); if (plugin_pref_dialogs == NULL) @@ -527,7 +529,7 @@ g_hash_table_insert(plugin_pref_dialogs, plug, dialog); g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(pref_dialog_response_cb), plug); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), box); + gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), box); gtk_window_set_role(GTK_WINDOW(dialog), "plugin_config"); gtk_window_set_title(GTK_WINDOW(dialog), _(purple_plugin_get_name(plug))); gtk_widget_show_all(dialog); @@ -559,12 +561,18 @@ } static gboolean -pidgin_plugins_paint_tooltip(GtkWidget *tipwindow, gpointer data) +pidgin_plugins_paint_tooltip(GtkWidget *tipwindow, cairo_t *cr, gpointer data) { PangoLayout *layout = g_object_get_data(G_OBJECT(tipwindow), "tooltip-plugin"); +#if GTK_CHECK_VERSION(3,0,0) + gtk_paint_layout(gtk_widget_get_style(tipwindow), cr, GTK_STATE_NORMAL, FALSE, + tipwindow, "tooltip", + 6, 6, layout); +#else gtk_paint_layout(tipwindow->style, tipwindow->window, GTK_STATE_NORMAL, FALSE, - NULL, tipwindow, "tooltip", - 6, 6, layout); + NULL, tipwindow, "tooltip", + 6, 6, layout); +#endif return TRUE; } @@ -717,10 +725,8 @@ return; } - plugin_dialog = gtk_dialog_new_with_buttons(_("Plugins"), - NULL, - GTK_DIALOG_NO_SEPARATOR, - NULL); + plugin_dialog = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(plugin_dialog), _("Plugins")); pref_button = gtk_dialog_add_button(GTK_DIALOG(plugin_dialog), _("Configure Pl_ugin"), PIDGIN_RESPONSE_CONFIGURE); gtk_dialog_add_button(GTK_DIALOG(plugin_dialog), @@ -772,7 +778,7 @@ gtk_tree_view_append_column (GTK_TREE_VIEW(event_view), col); gtk_tree_view_column_set_sort_column_id(col, 1); g_object_unref(G_OBJECT(ls)); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(plugin_dialog)->vbox), + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(plugin_dialog))), pidgin_make_scrollable(event_view, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, -1), TRUE, TRUE, 0); gtk_tree_view_set_search_column(GTK_TREE_VIEW(event_view), 1); @@ -788,8 +794,8 @@ gtk_expander_set_use_markup(GTK_EXPANDER(expander), TRUE); gtk_widget_set_sensitive(expander, FALSE); gtk_container_add(GTK_CONTAINER(expander), create_details()); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(plugin_dialog)->vbox), expander, - FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(plugin_dialog))), + expander, FALSE, FALSE, 0); g_signal_connect (G_OBJECT (sel), "changed", G_CALLBACK (prefs_plugin_sel), NULL);
--- a/pidgin/gtkpluginpref.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkpluginpref.c Mon Aug 06 18:11:44 2012 +0200 @@ -32,10 +32,10 @@ #include "pluginpref.h" #include "prefs.h" -#include "gtkimhtml.h" #include "gtkpluginpref.h" #include "gtkprefs.h" #include "gtkutils.h" +#include "gtkwebview.h" static gboolean entry_cb(GtkWidget *entry, gpointer data) { @@ -48,27 +48,20 @@ static void -imhtml_cb(GtkTextBuffer *buffer, gpointer data) +webview_cb(GtkWebView *webview, gpointer data) { char *pref; char *text; - GtkIMHtml *imhtml = data; - pref = g_object_get_data(G_OBJECT(imhtml), "pref-key"); + pref = g_object_get_data(G_OBJECT(webview), "pref-key"); g_return_if_fail(pref); - text = gtk_imhtml_get_markup(imhtml); + text = gtk_webview_get_body_html(webview); purple_prefs_set_string(pref, text); g_free(text); } static void -imhtml_format_cb(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons, gpointer data) -{ - imhtml_cb(gtk_text_view_get_buffer(GTK_TEXT_VIEW(imhtml)), data); -} - -static void make_string_pref(GtkWidget *parent, PurplePluginPref *pref, GtkSizeGroup *sg) { GtkWidget *box, *gtk_label, *entry; const gchar *pref_name; @@ -115,7 +108,7 @@ { GtkWidget *hbox; GtkWidget *spacer; - GtkWidget *imhtml; + GtkWidget *webview; GtkWidget *toolbar; GtkWidget *frame; @@ -140,19 +133,23 @@ gtk_box_pack_start(GTK_BOX(hbox), spacer, FALSE, FALSE, 0); gtk_widget_show(spacer); - frame = pidgin_create_imhtml(TRUE, &imhtml, &toolbar, NULL); + frame = pidgin_create_webview(TRUE, &webview, &toolbar, NULL); if (!(format & PURPLE_STRING_FORMAT_TYPE_HTML)) gtk_widget_destroy(toolbar); - gtk_imhtml_append_text(GTK_IMHTML(imhtml), purple_prefs_get_string(pref_name), - (format & PURPLE_STRING_FORMAT_TYPE_MULTILINE) ? 0 : GTK_IMHTML_NO_NEWLINE); - gtk_label_set_mnemonic_widget(GTK_LABEL(gtk_label), imhtml); + if (format & PURPLE_STRING_FORMAT_TYPE_MULTILINE) { + gchar *tmp = purple_strreplace(purple_prefs_get_string(pref_name), "\n", "<br>"); + gtk_webview_append_html(GTK_WEBVIEW(webview), tmp); + g_free(tmp); + } else + gtk_webview_append_html(GTK_WEBVIEW(webview), purple_prefs_get_string(pref_name)); + gtk_label_set_mnemonic_widget(GTK_LABEL(gtk_label), webview); gtk_widget_show_all(frame); - g_object_set_data(G_OBJECT(imhtml), "pref-key", (gpointer)pref_name); - g_signal_connect(G_OBJECT(gtk_text_view_get_buffer(GTK_TEXT_VIEW(imhtml))), - "changed", G_CALLBACK(imhtml_cb), imhtml); - g_signal_connect(G_OBJECT(imhtml), - "format_function_toggle", G_CALLBACK(imhtml_format_cb), imhtml); + g_object_set_data(G_OBJECT(webview), "pref-key", (gpointer)pref_name); + g_signal_connect(G_OBJECT(webview), "changed", + G_CALLBACK(webview_cb), NULL); + g_signal_connect(G_OBJECT(webview), "format-toggled", + G_CALLBACK(webview_cb), NULL); gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); } @@ -211,7 +208,9 @@ sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); parent = ret = gtk_vbox_new(FALSE, 16); +#if !GTK_CHECK_VERSION(3,0,0) gtk_container_set_border_width(GTK_CONTAINER(ret), PIDGIN_HIG_BORDER); +#endif gtk_widget_show(ret); for(pp = purple_plugin_pref_frame_get_prefs(frame);
--- a/pidgin/gtkpounce.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkpounce.c Mon Aug 06 18:11:44 2012 +0200 @@ -38,11 +38,13 @@ #include "gtkblist.h" #include "gtkdialogs.h" -#include "gtkimhtml.h" #include "gtkpounce.h" #include "gtknotify.h" #include "pidginstock.h" #include "gtkutils.h" +#include "gtkwebview.h" + +#include <gdk/gdkkeysyms.h> /** * These are used for the GtkTreeView when you're scrolling through @@ -304,7 +306,7 @@ events |= PURPLE_POUNCE_MESSAGE_RECEIVED; /* Data fields */ - message = gtk_imhtml_get_markup(GTK_IMHTML(dialog->send_msg_entry)); + message = gtk_webview_get_body_html(GTK_WEBVIEW(dialog->send_msg_entry)); command = gtk_entry_get_text(GTK_ENTRY(dialog->exec_cmd_entry)); sound = gtk_entry_get_text(GTK_ENTRY(dialog->play_sound_entry)); reason = gtk_entry_get_text(GTK_ENTRY(dialog->popup_entry)); @@ -378,6 +380,19 @@ delete_win_cb(NULL, NULL, dialog); } +static gboolean +entry_key_press_cb(GtkWidget *widget, GdkEventKey *event, + PidginPounceDialog *dialog) +{ + if ((event->keyval == GDK_KEY_Return) + || (event->keyval == GDK_KEY_KP_Enter)) { + save_pounce_cb(widget, dialog); + return TRUE; + } + + return FALSE; +} + static void pounce_choose_cb(GtkWidget *item, PurpleAccount *account, PidginPounceDialog *dialog) @@ -410,13 +425,15 @@ GtkSelectionData *sd, guint info, guint t, gpointer data) { PidginPounceDialog *dialog; + GdkAtom target = gtk_selection_data_get_target(sd); + const guchar *sd_data = gtk_selection_data_get_data(sd); - if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE)) + if (target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE)) { PurpleBlistNode *node = NULL; PurpleBuddy *buddy; - memcpy(&node, sd->data, sizeof(node)); + memcpy(&node, sd_data, sizeof(node)); if (PURPLE_BLIST_NODE_IS_CONTACT(node)) buddy = purple_contact_get_priority_buddy((PurpleContact *)node); @@ -431,15 +448,15 @@ dialog->account = purple_buddy_get_account(buddy); pidgin_account_option_menu_set_selected(dialog->account_menu, purple_buddy_get_account(buddy)); - gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); + gtk_drag_finish(dc, TRUE, (gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE), t); } - else if (sd->target == gdk_atom_intern("application/x-im-contact", FALSE)) + else if (target == gdk_atom_intern("application/x-im-contact", FALSE)) { char *protocol = NULL; char *username = NULL; PurpleAccount *account; - if (pidgin_parse_x_im_contact((const char *)sd->data, FALSE, &account, + if (pidgin_parse_x_im_contact((const char *)sd_data, FALSE, &account, &protocol, &username, NULL)) { if (account == NULL) @@ -461,7 +478,7 @@ g_free(username); g_free(protocol); - gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); + gtk_drag_finish(dc, TRUE, (gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE), t); } } @@ -475,7 +492,7 @@ reset_send_msg_entry(PidginPounceDialog *dialog, GtkWidget *dontcare) { PurpleAccount *account = pidgin_account_option_menu_get_selected(dialog->account_menu); - gtk_imhtml_setup_entry(GTK_IMHTML(dialog->send_msg_entry), + gtk_webview_setup_entry(GTK_WEBVIEW(dialog->send_msg_entry), (account && purple_account_get_connection(account)) ? purple_connection_get_flags(purple_account_get_connection(account)) : PURPLE_CONNECTION_HTML); } @@ -494,7 +511,7 @@ GtkSizeGroup *sg; GPtrArray *sound_widgets; GPtrArray *exec_widgets; - GtkWidget *send_msg_imhtml; + GtkWidget *send_msg_webview; g_return_if_fail((cur_pounce != NULL) || (account != NULL) || @@ -534,13 +551,15 @@ dialog->window = window = gtk_dialog_new(); gtk_window_set_title(GTK_WINDOW(window), (cur_pounce == NULL ? _("Add Buddy Pounce") : _("Modify Buddy Pounce"))); gtk_window_set_role(GTK_WINDOW(window), "buddy_pounce"); +#if !GTK_CHECK_VERSION(3,0,0) gtk_container_set_border_width(GTK_CONTAINER(dialog->window), PIDGIN_HIG_BORDER); +#endif g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_win_cb), dialog); - /* Create the parent vbox for everything. */ - vbox1 = GTK_DIALOG(window)->vbox; + /* Get the parent vbox for everything. */ + vbox1 = gtk_dialog_get_content_area(GTK_DIALOG(window)); /* Create the vbox that will contain all the prefs stuff. */ vbox2 = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); @@ -679,7 +698,7 @@ dialog->play_sound = gtk_check_button_new_with_mnemonic(_("P_lay a sound")); - send_msg_imhtml = pidgin_create_imhtml(TRUE, &dialog->send_msg_entry, NULL, NULL); + send_msg_webview = pidgin_create_webview(TRUE, &dialog->send_msg_entry, NULL, NULL); reset_send_msg_entry(dialog, NULL); dialog->exec_cmd_entry = gtk_entry_new(); dialog->popup_entry = gtk_entry_new(); @@ -691,7 +710,7 @@ dialog->play_sound_test = gtk_button_new_with_mnemonic(_("Pre_view")); dialog->play_sound_reset = gtk_button_new_with_mnemonic(_("Reset")); - gtk_widget_set_sensitive(send_msg_imhtml, FALSE); + gtk_widget_set_sensitive(send_msg_webview, FALSE); gtk_widget_set_sensitive(dialog->exec_cmd_entry, FALSE); gtk_widget_set_sensitive(dialog->popup_entry, FALSE); gtk_widget_set_sensitive(dialog->exec_cmd_browse, FALSE); @@ -726,7 +745,7 @@ GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), dialog->send_msg, 0, 5, 2, 3, GTK_FILL, 0, 0, 0); - gtk_table_attach(GTK_TABLE(table), send_msg_imhtml, 0, 5, 3, 4, + gtk_table_attach(GTK_TABLE(table), send_msg_webview, 0, 5, 3, 4, GTK_FILL, 0, 0, 0); gtk_table_attach(GTK_TABLE(table), dialog->exec_cmd, 0, 1, 4, 5, GTK_FILL, 0, 0, 0); @@ -751,7 +770,7 @@ gtk_widget_show(dialog->popup); gtk_widget_show(dialog->popup_entry); gtk_widget_show(dialog->send_msg); - gtk_widget_show(send_msg_imhtml); + gtk_widget_show(send_msg_webview); gtk_widget_show(dialog->exec_cmd); gtk_widget_show(dialog->exec_cmd_entry); gtk_widget_show(dialog->exec_cmd_browse); @@ -767,7 +786,7 @@ g_signal_connect(G_OBJECT(dialog->send_msg), "clicked", G_CALLBACK(pidgin_toggle_sensitive), - send_msg_imhtml); + send_msg_webview); g_signal_connect(G_OBJECT(dialog->popup), "clicked", G_CALLBACK(pidgin_toggle_sensitive), @@ -807,13 +826,13 @@ g_object_set_data_full(G_OBJECT(dialog->window), "sound-widgets", sound_widgets, (GDestroyNotify)g_ptr_array_free); - g_signal_connect_swapped(G_OBJECT(dialog->send_msg_entry), "format_function_clear", + g_signal_connect_swapped(G_OBJECT(dialog->send_msg_entry), "format-cleared", G_CALLBACK(reset_send_msg_entry), dialog); g_signal_connect_swapped(G_OBJECT(dialog->account_menu), "changed", G_CALLBACK(reset_send_msg_entry), dialog); - g_signal_connect(G_OBJECT(dialog->send_msg_entry), "message_send", - G_CALLBACK(save_pounce_cb), dialog); + g_signal_connect(G_OBJECT(dialog->send_msg_entry), "key-press-event", + G_CALLBACK(entry_key_press_cb), dialog); g_signal_connect(G_OBJECT(dialog->popup_entry), "activate", G_CALLBACK(save_pounce_cb), dialog); g_signal_connect(G_OBJECT(dialog->exec_cmd_entry), "activate", @@ -926,7 +945,7 @@ "send-message", "message")) != NULL) { - gtk_imhtml_append_text(GTK_IMHTML(dialog->send_msg_entry), value, 0); + gtk_webview_append_html(GTK_WEBVIEW(dialog->send_msg_entry), value); } if ((value = purple_pounce_action_get_attribute(cur_pounce, @@ -1018,11 +1037,7 @@ static gboolean pounces_manager_configure_cb(GtkWidget *widget, GdkEventConfigure *event, PouncesManager *dialog) { -#if GTK_CHECK_VERSION(2,18,0) if (gtk_widget_get_visible(widget)) { -#else - if (GTK_WIDGET_VISIBLE(widget)) { -#endif purple_prefs_set_int(PIDGIN_PREFS_ROOT "/pounces/dialog/width", event->width); purple_prefs_set_int(PIDGIN_PREFS_ROOT "/pounces/dialog/height", event->height); } @@ -1335,7 +1350,11 @@ width = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/pounces/dialog/width"); height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/pounces/dialog/height"); +#if GTK_CHECK_VERSION(3,0,0) + dialog->window = win = pidgin_create_dialog(_("Buddy Pounces"), 0, "pounces", TRUE); +#else dialog->window = win = pidgin_create_dialog(_("Buddy Pounces"), PIDGIN_HIG_BORDER, "pounces", TRUE); +#endif gtk_window_set_default_size(GTK_WINDOW(win), width, height); g_signal_connect(G_OBJECT(win), "delete_event",
--- a/pidgin/gtkprefs.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkprefs.c Mon Aug 06 18:11:44 2012 +0200 @@ -58,6 +58,8 @@ #include "gtkwebviewtoolbar.h" #include "pidginstock.h" +#include "gtk3compat.h" + #define PROXYHOST 0 #define PROXYPORT 1 #define PROXYUSER 2 @@ -123,13 +125,13 @@ const char *key, int min, int max, GtkSizeGroup *sg) { GtkWidget *spin; - GtkObject *adjust; + GtkAdjustment *adjust; int val; val = purple_prefs_get_int(key); - adjust = gtk_adjustment_new(val, min, max, 1, 1, 0); - spin = gtk_spin_button_new(GTK_ADJUSTMENT(adjust), 1, 0); + adjust = GTK_ADJUSTMENT(gtk_adjustment_new(val, min, max, 1, 1, 0)); + spin = gtk_spin_button_new(adjust, 1, 0); g_object_set_data(G_OBJECT(spin), "val", (char *)key); if (max < 10000) gtk_widget_set_size_request(spin, 50, -1); @@ -902,9 +904,10 @@ theme_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, GtkSelectionData *sd, guint info, guint t, gpointer user_data) { - gchar *name = g_strchomp((gchar *)sd->data); - - if ((sd->length >= 0) && (sd->format == 8)) { + gchar *name = g_strchomp((gchar *)gtk_selection_data_get_data(sd)); + + if ((gtk_selection_data_get_length(sd) >= 0) + && (gtk_selection_data_get_format(sd) == 8)) { /* Well, it looks like the drag event was cool. * Let's do something with it */ gchar *temp; @@ -2639,7 +2642,7 @@ sound_page(void) { GtkWidget *ret; - GtkWidget *vbox, *vbox2, *sw, *button; + GtkWidget *vbox, *vbox2, *sw, *button, *parent, *parent_parent, *parent_parent_parent; GtkSizeGroup *sg; GtkTreeIter iter; GtkWidget *event_view; @@ -2739,12 +2742,15 @@ /* The following is an ugly hack to make the frame expand so the * sound events list is big enough to be usable */ - gtk_box_set_child_packing(GTK_BOX(vbox->parent), vbox, TRUE, TRUE, 0, + parent = gtk_widget_get_parent(vbox); + parent_parent = gtk_widget_get_parent(parent); + parent_parent_parent = gtk_widget_get_parent(parent_parent); + gtk_box_set_child_packing(GTK_BOX(parent), vbox, TRUE, TRUE, 0, GTK_PACK_START); - gtk_box_set_child_packing(GTK_BOX(vbox->parent->parent), vbox->parent, TRUE, - TRUE, 0, GTK_PACK_START); - gtk_box_set_child_packing(GTK_BOX(vbox->parent->parent->parent), - vbox->parent->parent, TRUE, TRUE, 0, GTK_PACK_START); + gtk_box_set_child_packing(GTK_BOX(parent_parent), + parent, TRUE, TRUE, 0, GTK_PACK_START); + gtk_box_set_child_packing(GTK_BOX(parent_parent_parent), + parent_parent, TRUE, TRUE, 0, GTK_PACK_START); /* SOUND SELECTION */ event_store = gtk_list_store_new (4, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); @@ -2981,7 +2987,11 @@ /* Back to instant-apply! I win! BU-HAHAHA! */ /* Create the window */ +#if GTK_CHECK_VERSION(3,0,0) + prefs = pidgin_create_dialog(_("Preferences"), 0, "preferences", FALSE); +#else prefs = pidgin_create_dialog(_("Preferences"), PIDGIN_HIG_BORDER, "preferences", FALSE); +#endif g_signal_connect(G_OBJECT(prefs), "destroy", G_CALLBACK(delete_prefs), NULL);
--- a/pidgin/gtkprivacy.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkprivacy.c Mon Aug 06 18:11:44 2012 +0200 @@ -36,6 +36,8 @@ #include "gtkprivacy.h" #include "gtkutils.h" +#include "gtk3compat.h" + typedef struct { GtkWidget *win; @@ -235,7 +237,7 @@ gtk_widget_hide(dialog->allow_widget); gtk_widget_hide(dialog->block_widget); - gtk_widget_hide_all(dialog->button_box); + gtk_widget_hide(dialog->button_box); if (new_type == PURPLE_PRIVACY_ALLOW_USERS) { gtk_widget_show(dialog->allow_widget); @@ -363,12 +365,12 @@ dialog->account = pidgin_account_option_menu_get_selected(dropdown); /* Add the drop-down list with the allow/block types. */ - dialog->type_menu = gtk_combo_box_new_text(); + dialog->type_menu = gtk_combo_box_text_new(); gtk_box_pack_start(GTK_BOX(vbox), dialog->type_menu, FALSE, FALSE, 0); gtk_widget_show(dialog->type_menu); for (i = 0; i < menu_entry_count; i++) { - gtk_combo_box_append_text(GTK_COMBO_BOX(dialog->type_menu), + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(dialog->type_menu), _(menu_entries[i].text)); if (menu_entries[i].num == purple_account_get_privacy_type(dialog->account)) @@ -434,7 +436,7 @@ privacy_dialog = privacy_dialog_new(); gtk_widget_show(privacy_dialog->win); - gdk_window_raise(privacy_dialog->win->window); + gdk_window_raise(gtk_widget_get_window(privacy_dialog->win)); } void
--- a/pidgin/gtkrequest.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkrequest.c Mon Aug 06 18:11:44 2012 +0200 @@ -30,8 +30,7 @@ #include "prefs.h" #include "util.h" -#include "gtkimhtml.h" -#include "gtkimhtmltoolbar.h" +#include "gtkwebview.h" #include "gtkrequest.h" #include "gtkutils.h" #include "pidginstock.h" @@ -42,22 +41,16 @@ #ifdef ENABLE_GCR #define GCR_API_SUBJECT_TO_CHANGE #include <gcr/gcr.h> +#if !GTK_CHECK_VERSION(3,0,0) #include <gcr/gcr-simple-certificate.h> #endif +#endif -#if !GTK_CHECK_VERSION(2,18,0) -#define gtk_widget_set_can_default(x,y) do {\ - if (y) \ - GTK_WIDGET_SET_FLAGS(x, GTK_CAN_DEFAULT); \ - else \ - GTK_WIDGET_UNSET_FLAGS(x, GTK_CAN_DEFAULT); \ -} while(0) -#define gtk_widget_set_can_focus(x,y) do {\ - if (y) \ - GTK_WIDGET_SET_FLAGS(x, GTK_CAN_FOCUS); \ - else \ - GTK_WIDGET_UNSET_FLAGS(x, GTK_CAN_FOCUS); \ -} while(0) +#include "gtk3compat.h" + +#if !GTK_CHECK_VERSION(2,12,0) +#undef gtk_widget_set_tooltip_text +#define gtk_widget_set_tooltip_text(x,y) #endif static GtkWidget * create_account_field(PurpleRequestField *field); @@ -107,9 +100,6 @@ { GtkWidget *image; GdkPixbuf *pixbuf; -#if !GTK_CHECK_VERSION(2,12,0) - GtkTooltips *tips; -#endif if (!account) return; @@ -118,16 +108,13 @@ image = gtk_image_new_from_pixbuf(pixbuf); g_object_unref(G_OBJECT(pixbuf)); -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(image, purple_account_get_username(account)); -#else - tips = gtk_tooltips_new(); - gtk_tooltips_set_tip(tips, image, purple_account_get_username(account), NULL); -#endif if (GTK_IS_DIALOG(cont)) { - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(cont)->action_area), image, FALSE, TRUE, 0); - gtk_box_reorder_child(GTK_BOX(GTK_DIALOG(cont)->action_area), image, 0); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_action_area(GTK_DIALOG(cont))), + image, FALSE, TRUE, 0); + gtk_box_reorder_child(GTK_BOX(gtk_dialog_get_action_area(GTK_DIALOG(cont))), + image, 0); } else if (GTK_IS_HBOX(cont)) { gtk_misc_set_alignment(GTK_MISC(image), 0, 0); gtk_box_pack_end(GTK_BOX(cont), image, FALSE, TRUE, 0); @@ -161,7 +148,7 @@ gtk_text_buffer_get_end_iter(buffer, &end_iter); if ((data->u.input.hint != NULL) && (!strcmp(data->u.input.hint, "html"))) - multiline_value = gtk_imhtml_get_markup(GTK_IMHTML(data->u.input.entry)); + multiline_value = gtk_webview_get_body_html(GTK_WEBVIEW(data->u.input.entry)); else multiline_value = gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, FALSE); @@ -284,11 +271,7 @@ { generic_response_start(data); -#if GTK_CHECK_VERSION(2,18,0) if (!gtk_widget_has_focus(button)) -#else - if (!GTK_WIDGET_HAS_FOCUS(button)) -#endif gtk_widget_grab_focus(button); if (data->cbs[0] != NULL) @@ -341,11 +324,6 @@ return text; } -static void stop_emission_cb(GtkDialog *dialog, const gchar *signal_name) -{ - gtk_signal_emit_stop_by_name(GTK_OBJECT(dialog), signal_name); -} - static void * pidgin_request_input(const char *title, const char *primary, const char *secondary, const char *default_value, @@ -389,18 +367,18 @@ /* Setup the dialog */ gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BORDER/2); - gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER/2); + gtk_container_set_border_width(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + PIDGIN_HIG_BORDER / 2); if (!multiline) gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); -#if !GTK_CHECK_VERSION(2,22,0) - gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); -#endif gtk_dialog_set_default_response(GTK_DIALOG(dialog), 0); - gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER); + gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + PIDGIN_HIG_BORDER); /* Setup the main horizontal box */ hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); + gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + hbox); /* Dialog icon. */ img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_QUESTION, @@ -444,16 +422,14 @@ if ((data->u.input.hint != NULL) && (!strcmp(data->u.input.hint, "html"))) { GtkWidget *frame; - /* imhtml */ - frame = pidgin_create_imhtml(TRUE, &entry, &toolbar, NULL); + /* webview */ + frame = pidgin_create_webview(TRUE, &entry, &toolbar, NULL); gtk_widget_set_size_request(entry, 320, 130); - gtk_widget_set_name(entry, "pidgin_request_imhtml"); + gtk_widget_set_name(entry, "pidgin_request_webview"); if (default_value != NULL) - gtk_imhtml_append_text(GTK_IMHTML(entry), default_value, GTK_IMHTML_NO_SCROLL); + gtk_webview_append_html(GTK_WEBVIEW(entry), default_value); gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); gtk_widget_show(frame); - - gtk_imhtml_set_return_inserts_newline(GTK_IMHTML(entry)); } else { if (multiline) { @@ -558,16 +534,16 @@ /* Setup the dialog */ gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BORDER/2); - gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER/2); + gtk_container_set_border_width(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + PIDGIN_HIG_BORDER / 2); gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); -#if !GTK_CHECK_VERSION(2,22,0) - gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); -#endif - gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER); + gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + PIDGIN_HIG_BORDER); /* Setup the main horizontal box */ hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); + gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + hbox); /* Dialog icon. */ img = gtk_image_new_from_stock(PIDGIN_STOCK_DIALOG_QUESTION, @@ -660,8 +636,6 @@ data->dialog = dialog = gtk_dialog_new(); gtk_window_set_deletable(GTK_WINDOW(data->dialog), FALSE); - g_signal_connect(G_OBJECT(dialog), "close", - G_CALLBACK(stop_emission_cb), "close"); if (title != NULL) gtk_window_set_title(GTK_WINDOW(dialog), title); @@ -684,16 +658,16 @@ /* Setup the dialog */ gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BORDER/2); - gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER/2); + gtk_container_set_border_width(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + PIDGIN_HIG_BORDER / 2); gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); -#if !GTK_CHECK_VERSION(2,22,0) - gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); -#endif - gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER); + gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + PIDGIN_HIG_BORDER); /* Setup the main horizontal box */ hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox); + gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + hbox); /* Dialog icon. */ if (icon_data) { @@ -792,10 +766,6 @@ static void req_entry_field_changed_cb(GtkWidget *entry, PurpleRequestField *field) { - PurpleRequestFieldGroup *group; - PurpleRequestFields *fields; - PidginRequestData *req_data; - if (purple_request_field_string_is_multiline(field)) { char *text; @@ -814,13 +784,22 @@ text = gtk_entry_get_text(GTK_ENTRY(entry)); purple_request_field_string_set_value(field, (*text == '\0') ? NULL : text); } +} + +static void +req_field_changed_cb(GtkWidget *widget, PurpleRequestField *field) +{ + PurpleRequestFieldGroup *group; + PurpleRequestFields *fields; + PidginRequestData *req_data; group = purple_request_field_get_group(field); fields = purple_request_field_group_get_fields_list(group); req_data = purple_request_fields_get_ui_data(fields); gtk_widget_set_sensitive(req_data->ok_button, - purple_request_fields_all_required_filled(fields)); + purple_request_fields_all_required_filled(fields) && + purple_request_fields_all_valid(fields)); } static void @@ -830,11 +809,10 @@ gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); - if (purple_request_field_is_required(field)) - { - g_signal_connect(G_OBJECT(entry), "changed", - G_CALLBACK(req_entry_field_changed_cb), field); - } + g_signal_connect(G_OBJECT(entry), "changed", + G_CALLBACK(req_entry_field_changed_cb), field); + g_signal_connect(G_OBJECT(entry), "changed", + G_CALLBACK(req_field_changed_cb), field); if ((type_hint = purple_request_field_get_type_hint(field)) != NULL) { @@ -903,9 +881,7 @@ gtk_text_buffer_set_text(buffer, value, -1); } -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(textview, purple_request_field_get_tooltip(field)); -#endif gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), purple_request_field_string_is_editable(field)); @@ -931,9 +907,7 @@ if (value != NULL) gtk_entry_set_text(GTK_ENTRY(widget), value); -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field)); -#endif if (purple_request_field_string_is_masked(field)) { @@ -975,9 +949,7 @@ gtk_entry_set_text(GTK_ENTRY(widget), buf); } -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field)); -#endif g_signal_connect(G_OBJECT(widget), "focus-out-event", G_CALLBACK(field_int_focus_out_cb), field); @@ -993,15 +965,15 @@ widget = gtk_check_button_new_with_label( purple_request_field_get_label(field)); -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field)); -#endif gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), purple_request_field_bool_get_default_value(field)); g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(field_bool_cb), field); + g_signal_connect(widget, "toggled", + G_CALLBACK(req_field_changed_cb), field); return widget; } @@ -1016,20 +988,18 @@ if (num_labels > 5) { - widget = gtk_combo_box_new_text(); + widget = gtk_combo_box_text_new(); for (l = labels; l != NULL; l = l->next) { const char *text = l->data; - gtk_combo_box_append_text(GTK_COMBO_BOX(widget), text); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(widget), text); } gtk_combo_box_set_active(GTK_COMBO_BOX(widget), purple_request_field_choice_get_default_value(field)); -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field)); -#endif g_signal_connect(G_OBJECT(widget), "changed", G_CALLBACK(field_choice_menu_cb), field); @@ -1048,9 +1018,7 @@ widget = box; -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field)); -#endif for (l = labels, i = 0; l != NULL; l = l->next, i++) { @@ -1094,9 +1062,7 @@ g_object_unref(G_OBJECT(buf)); g_object_unref(G_OBJECT(scale)); -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field)); -#endif return widget; } @@ -1113,9 +1079,9 @@ purple_request_field_account_get_filter(field), field); -#if GTK_CHECK_VERSION(2,12,0) gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field)); -#endif + g_signal_connect(widget, "changed", + G_CALLBACK(req_field_changed_cb), field); return widget; } @@ -1626,6 +1592,9 @@ if (!purple_request_fields_all_required_filled(fields)) gtk_widget_set_sensitive(data->ok_button, FALSE); + if (!purple_request_fields_all_valid(fields)) + gtk_widget_set_sensitive(data->ok_button, FALSE); + pidgin_auto_parent_window(win); gtk_widget_show(win);
--- a/pidgin/gtkroomlist.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkroomlist.c Mon Aug 06 18:11:44 2012 +0200 @@ -352,7 +352,7 @@ #define TOOLTIP_BORDER 12 static gboolean -pidgin_roomlist_paint_tooltip(GtkWidget *widget, gpointer user_data) +pidgin_roomlist_paint_tooltip(GtkWidget *widget, cairo_t *cr, gpointer user_data) { PurpleRoomlist *list = user_data; PidginRoomlist *grl = purple_roomlist_get_ui_data(list); @@ -361,34 +361,69 @@ int max_text_width; GtkTextDirection dir = gtk_widget_get_direction(GTK_WIDGET(grl->tree)); - style = grl->tipwindow->style; + style = gtk_widget_get_style(grl->tipwindow); max_text_width = MAX(grl->tip_width, grl->tip_name_width); max_width = TOOLTIP_BORDER + SMALL_SPACE + max_text_width + TOOLTIP_BORDER; current_height = 12; +#if GTK_CHECK_VERSION(3,0,0) if (dir == GTK_TEXT_DIR_RTL) { - gtk_paint_layout(style, grl->tipwindow->window, GTK_STATE_NORMAL, FALSE, - NULL, grl->tipwindow, "tooltip", - max_width - (TOOLTIP_BORDER + SMALL_SPACE) - PANGO_PIXELS(600000), - current_height, grl->tip_name_layout); + gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE, + grl->tipwindow, "tooltip", + max_width - (TOOLTIP_BORDER + SMALL_SPACE) - PANGO_PIXELS(600000), + current_height, + grl->tip_name_layout); } else { - gtk_paint_layout (style, grl->tipwindow->window, GTK_STATE_NORMAL, FALSE, - NULL, grl->tipwindow, "tooltip", - TOOLTIP_BORDER + SMALL_SPACE, current_height, grl->tip_name_layout); + gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE, + grl->tipwindow, "tooltip", + TOOLTIP_BORDER + SMALL_SPACE, + current_height, + grl->tip_name_layout); } if (dir != GTK_TEXT_DIR_RTL) { - gtk_paint_layout (style, grl->tipwindow->window, GTK_STATE_NORMAL, FALSE, - NULL, grl->tipwindow, "tooltip", - TOOLTIP_BORDER + SMALL_SPACE, current_height + grl->tip_name_height, grl->tip_layout); + gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE, + grl->tipwindow, "tooltip", + TOOLTIP_BORDER + SMALL_SPACE, + current_height + grl->tip_name_height, + grl->tip_layout); + } else { + gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE, + grl->tipwindow, "tooltip", + max_width - (TOOLTIP_BORDER + SMALL_SPACE) - PANGO_PIXELS(600000), + current_height + grl->tip_name_height, + grl->tip_layout); + } +#else + if (dir == GTK_TEXT_DIR_RTL) { + gtk_paint_layout(style, grl->tipwindow->window, GTK_STATE_NORMAL, FALSE, + NULL, grl->tipwindow, "tooltip", + max_width - (TOOLTIP_BORDER + SMALL_SPACE) - PANGO_PIXELS(600000), + current_height, + grl->tip_name_layout); } else { gtk_paint_layout(style, grl->tipwindow->window, GTK_STATE_NORMAL, FALSE, - NULL, grl->tipwindow, "tooltip", - max_width - (TOOLTIP_BORDER + SMALL_SPACE) - PANGO_PIXELS(600000), - current_height + grl->tip_name_height, - grl->tip_layout); + NULL, grl->tipwindow, "tooltip", + TOOLTIP_BORDER + SMALL_SPACE, + current_height, + grl->tip_name_layout); } + if (dir != GTK_TEXT_DIR_RTL) { + gtk_paint_layout(style, grl->tipwindow->window, GTK_STATE_NORMAL, FALSE, + NULL, grl->tipwindow, "tooltip", + TOOLTIP_BORDER + SMALL_SPACE, + current_height + grl->tip_name_height, + grl->tip_layout); + } else { + gtk_paint_layout(style, grl->tipwindow->window, GTK_STATE_NORMAL, FALSE, + NULL, grl->tipwindow, "tooltip", + max_width - (TOOLTIP_BORDER + SMALL_SPACE) - PANGO_PIXELS(600000), + current_height + grl->tip_name_height, + grl->tip_layout); + } +#endif + return FALSE; } @@ -533,7 +568,11 @@ dialog->account = account; /* Create the window. */ +#if GTK_CHECK_VERSION(3,0,0) + dialog->window = window = pidgin_create_dialog(_("Room List"), 0, "room list", TRUE); +#else dialog->window = window = pidgin_create_dialog(_("Room List"), PIDGIN_HIG_BORDER, "room list", TRUE); +#endif g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_win_cb), dialog);
--- a/pidgin/gtksavedstatuses.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtksavedstatuses.c Mon Aug 06 18:11:44 2012 +0200 @@ -35,11 +35,13 @@ #include "gtkblist.h" #include "pidgin.h" -#include "gtkimhtml.h" -#include "gtkimhtmltoolbar.h" #include "gtksavedstatuses.h" #include "pidginstock.h" #include "gtkutils.h" +#include "gtkwebview.h" +#include "gtkwebviewtoolbar.h" + +#include "gtk3compat.h" /* * TODO: Should attach to the account-deleted and account-added signals @@ -118,7 +120,7 @@ gchar *original_title; GtkEntry *title; GtkComboBox *type; - GtkIMHtml *message; + GtkWebView *message; } StatusEditor; typedef struct @@ -129,8 +131,8 @@ GtkWidget *window; GtkListStore *model; GtkComboBox *box; - GtkIMHtml *message; - GtkIMHtmlToolbar *toolbar; + GtkWebView *message; + GtkWebViewToolbar *toolbar; } SubStatusEditor; static StatusWindow *status_window = NULL; @@ -524,11 +526,7 @@ static gboolean configure_cb(GtkWidget *widget, GdkEventConfigure *event, StatusWindow *dialog) { -#if GTK_CHECK_VERSION(2,18,0) if (gtk_widget_get_visible(widget)) -#else - if (GTK_WIDGET_VISIBLE(widget)) -#endif { purple_prefs_set_int(PIDGIN_PREFS_ROOT "/status/dialog/width", event->width); purple_prefs_set_int(PIDGIN_PREFS_ROOT "/status/dialog/height", event->height); @@ -735,7 +733,7 @@ } type = gtk_combo_box_get_active(dialog->type) + (PURPLE_STATUS_UNSET + 1); - message = gtk_imhtml_get_markup(dialog->message); + message = gtk_webview_get_body_html(dialog->message); unformatted = purple_markup_strip_html(message); /* @@ -1151,19 +1149,17 @@ pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Status:"), sg, dropdown, TRUE, NULL); /* Status message */ - frame = pidgin_create_imhtml(TRUE, &text, &toolbar, NULL); - dialog->message = GTK_IMHTML(text); + frame = pidgin_create_webview(TRUE, &text, &toolbar, NULL); + dialog->message = GTK_WEBVIEW(text); hbox = pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Message:"), sg, frame, TRUE, NULL); gtk_container_child_set(GTK_CONTAINER(vbox), hbox, "expand", TRUE, "fill", TRUE, NULL); focus_chain = g_list_prepend(focus_chain, dialog->message); gtk_container_set_focus_chain(GTK_CONTAINER(hbox), focus_chain); g_list_free(focus_chain); - gtk_imhtml_set_return_inserts_newline(dialog->message); - if ((saved_status != NULL) && (purple_savedstatus_get_message(saved_status) != NULL)) - gtk_imhtml_append_text(GTK_IMHTML(text), - purple_savedstatus_get_message(saved_status), 0); + gtk_webview_append_html(GTK_WEBVIEW(text), + purple_savedstatus_get_message(saved_status)); /* Different status message expander */ expander = gtk_expander_new_with_mnemonic(_("Use a _different status for some accounts")); @@ -1351,7 +1347,7 @@ -1); type = purple_account_get_status_type(dialog->account, id); if (purple_status_type_get_attr(type, "message") != NULL) - message = gtk_imhtml_get_markup(GTK_IMHTML(dialog->message)); + message = gtk_webview_get_body_html(GTK_WEBVIEW(dialog->message)); name = purple_status_type_get_name(type); stock = get_stock_icon_from_primitive(purple_status_type_get_primitive(type)); @@ -1471,9 +1467,9 @@ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_size_group_add_widget(sg, label); - frame = pidgin_create_imhtml(TRUE, &text, &toolbar, NULL); - dialog->message = GTK_IMHTML(text); - dialog->toolbar = GTK_IMHTMLTOOLBAR(toolbar); + frame = pidgin_create_webview(TRUE, &text, &toolbar, NULL); + dialog->message = GTK_WEBVIEW(text); + dialog->toolbar = GTK_WEBVIEWTOOLBAR(toolbar); gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); /* Cancel button */ @@ -1507,7 +1503,7 @@ /* TODO: Else get the generic status type from our parent */ if (message) - gtk_imhtml_append_text(dialog->message, message, 0); + gtk_webview_append_html(dialog->message, message); for (list = purple_account_get_status_types(account); list; list = list->next) {
--- a/pidgin/gtkscrollbook.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkscrollbook.c Mon Aug 06 18:11:44 2012 +0200 @@ -102,7 +102,7 @@ gtk_widget_show_all(GTK_WIDGET(scroll_book)); if (count < 1) - gtk_widget_hide_all(scroll_book->hbox); + gtk_widget_hide(scroll_book->hbox); else { gtk_widget_show_all(scroll_book->hbox); if (count == 1) { @@ -160,7 +160,7 @@ PidginScrollBook *scroll_book; g_return_if_fail(GTK_IS_WIDGET (widget)); - g_return_if_fail (widget->parent == NULL); + g_return_if_fail(gtk_widget_get_parent(widget) == NULL); scroll_book = PIDGIN_SCROLL_BOOK(container); scroll_book->children = g_list_append(scroll_book->children, widget);
--- a/pidgin/gtksession.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtksession.c Mon Aug 06 18:11:44 2012 +0200 @@ -39,6 +39,8 @@ #include <gdk/gdk.h> #include <gtk/gtk.h> +#include "gtk3compat.h" + #define ERROR_LENGTH 512 static IceIOErrorHandler ice_installed_io_error_handler; @@ -349,7 +351,7 @@ free(tmp); session_managed = TRUE; - gdk_set_sm_client_id(client_id); + gdk_x11_set_sm_client_id(client_id); tmp = g_get_current_dir(); session_set_string(session, SmCurrentDirectory, tmp);
--- a/pidgin/gtksmiley.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtksmiley.c Mon Aug 06 18:11:44 2012 +0200 @@ -37,6 +37,8 @@ #include "gtkutils.h" #include "pidginstock.h" +#include "gtk3compat.h" + #define PIDGIN_RESPONSE_MODIFY 1000 struct _PidginSmiley @@ -399,7 +401,7 @@ window = gtk_dialog_new_with_buttons(smiley ? _("Edit Smiley") : _("Add Smiley"), widget ? GTK_WINDOW(widget) : NULL, - GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, + GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, smiley ? GTK_STOCK_SAVE : GTK_STOCK_ADD, GTK_RESPONSE_ACCEPT, NULL); @@ -407,14 +409,17 @@ if (smiley) g_object_set_data(G_OBJECT(smiley), "edit-dialog", window); +#if !GTK_CHECK_VERSION(3,0,0) gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); +#endif gtk_dialog_set_default_response(GTK_DIALOG(window), GTK_RESPONSE_ACCEPT); g_signal_connect(window, "response", G_CALLBACK(do_add_select_cb), s); /* The vbox */ vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window)->vbox), vbox); + gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(window))), + vbox); gtk_widget_show(vbox); /* The hbox */ @@ -724,9 +729,10 @@ GtkSelectionData *sd, guint info, guint t, gpointer user_data) { SmileyManager *dialog = user_data; - gchar *name = g_strchomp((gchar *)sd->data); + gchar *name = g_strchomp((gchar *) gtk_selection_data_get_data(sd)); - if ((sd->length >= 0) && (sd->format == 8)) { + if ((gtk_selection_data_get_length(sd) >= 0) + && (gtk_selection_data_get_format(sd) == 8)) { /* Well, it looks like the drag event was cool. * Let's do something with it */ @@ -872,7 +878,9 @@ gtk_window_set_default_size(GTK_WINDOW(win), 50, 400); gtk_window_set_role(GTK_WINDOW(win), "custom_smiley_manager"); +#if !GTK_CHECK_VERSION(3,0,0) gtk_container_set_border_width(GTK_CONTAINER(win),PIDGIN_HIG_BORDER); +#endif gtk_dialog_set_response_sensitive(GTK_DIALOG(win), GTK_RESPONSE_NO, FALSE); gtk_dialog_set_response_sensitive(GTK_DIALOG(win), PIDGIN_RESPONSE_MODIFY, FALSE); @@ -881,9 +889,7 @@ dialog); /* The vbox */ - vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER); - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(win)->vbox), vbox); - gtk_widget_show(vbox); + vbox = gtk_dialog_get_content_area(GTK_DIALOG(win)); /* get the scrolled window with all stuff */ sw = smiley_list_create(dialog); @@ -892,3 +898,4 @@ gtk_widget_show(win); } +
--- a/pidgin/gtksourceundomanager.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtksourceundomanager.c Mon Aug 06 18:11:44 2012 +0200 @@ -532,7 +532,9 @@ um->priv->document, undo_action->action.insert_anchor.pos, undo_action->action.insert_anchor.pos + 1); +#if !GTK_CHECK_VERSION(3,0,0) undo_action->action.insert_anchor.anchor->segment = NULL; /* XXX: This may be a bug in GTK+ */ +#endif break; default: /* Unknown action type. */
--- a/pidgin/gtkstatusbox.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkstatusbox.c Mon Aug 06 18:11:44 2012 +0200 @@ -67,19 +67,11 @@ # endif #endif +#include "gtk3compat.h" + /* Timeout for typing notifications in seconds */ #define TYPING_TIMEOUT 4 -#if !GTK_CHECK_VERSION(2,18,0) -#define gtk_widget_is_sensitive(x) GTK_WIDGET_IS_SENSITIVE(x) -#define gtk_widget_set_has_window(x, y) do { \ - if (y) \ - GTK_WIDGET_UNSET_FLAGS(x, GTK_WIDGET_NO_WINDOW); \ - else \ - GTK_WIDGET_SET_FLAGS(x, GTK_WIDGET_NO_WINDOW); \ -} while (0) -#endif - static void imhtml_changed_cb(GtkTextBuffer *buffer, void *data); static void imhtml_format_changed_cb(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons, void *data); static void remove_typing_cb(PidginStatusBox *box); @@ -92,9 +84,15 @@ static void status_menu_refresh_iter(PidginStatusBox *status_box, gboolean status_changed); static void pidgin_status_box_regenerate(PidginStatusBox *status_box, gboolean status_changed); static void pidgin_status_box_changed(PidginStatusBox *box); +#if GTK_CHECK_VERSION(3,0,0) +static void pidgin_status_box_get_preferred_height (GtkWidget *widget, + gint *minimum_height, gint *natural_height); +static gboolean pidgin_status_box_draw (GtkWidget *widget, cairo_t *cr); +#else static void pidgin_status_box_size_request (GtkWidget *widget, GtkRequisition *requisition); +static gboolean pidgin_status_box_expose_event (GtkWidget *widget, GdkEventExpose *event); +#endif static void pidgin_status_box_size_allocate (GtkWidget *widget, GtkAllocation *allocation); -static gboolean pidgin_status_box_expose_event (GtkWidget *widget, GdkEventExpose *event); static void pidgin_status_box_redisplay_buddy_icon(PidginStatusBox *status_box); static void pidgin_status_box_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data); static void pidgin_status_box_popup(PidginStatusBox *box); @@ -292,7 +290,7 @@ if (!message || !*message) { - gtk_widget_hide_all(status_box->vbox); + gtk_widget_hide(status_box->vbox); status_box->imhtml_visible = FALSE; } else @@ -353,9 +351,10 @@ icon_box_dnd_cb(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, GtkSelectionData *sd, guint info, guint t, PidginStatusBox *box) { - gchar *name = (gchar *)sd->data; - - if ((sd->length >= 0) && (sd->format == 8)) { + gchar *name = (gchar *) gtk_selection_data_get_data(sd); + + if ((gtk_selection_data_get_length(sd) >= 0) + && (gtk_selection_data_get_format(sd) == 8)) { /* Well, it looks like the drag event was cool. * Let's do something with it */ if (!g_ascii_strncasecmp(name, "file://", 7)) { @@ -380,7 +379,7 @@ static void statusbox_got_url(PurpleUtilFetchUrlData *url_data, gpointer user_data, - const gchar *themedata, size_t len, const gchar *error_message) + const gchar *themedata, size_t len, const gchar *error_message) { FILE *f; gchar *path; @@ -429,7 +428,7 @@ static gboolean icon_box_enter_cb(GtkWidget *widget, GdkEventCrossing *event, PidginStatusBox *box) { - gdk_window_set_cursor(widget->window, box->hand_cursor); + gdk_window_set_cursor(gtk_widget_get_window(widget), box->hand_cursor); gtk_image_set_from_pixbuf(GTK_IMAGE(box->icon), box->buddy_icon_hover); return FALSE; } @@ -437,7 +436,7 @@ static gboolean icon_box_leave_cb(GtkWidget *widget, GdkEventCrossing *event, PidginStatusBox *box) { - gdk_window_set_cursor(widget->window, box->arrow_cursor); + gdk_window_set_cursor(gtk_widget_get_window(widget), box->arrow_cursor); gtk_image_set_from_pixbuf(GTK_IMAGE(box->icon), box->buddy_icon) ; return FALSE; } @@ -543,7 +542,7 @@ static void pidgin_status_box_set_property(GObject *object, guint param_id, - const GValue *value, GParamSpec *pspec) + const GValue *value, GParamSpec *pspec) { PidginStatusBox *statusbox = PIDGIN_STATUS_BOX(object); @@ -612,7 +611,7 @@ static GType pidgin_status_box_child_type (GtkContainer *container) { - return GTK_TYPE_WIDGET; + return GTK_TYPE_WIDGET; } static void @@ -625,9 +624,14 @@ parent_class = g_type_class_peek_parent(klass); widget_class = (GtkWidgetClass*)klass; +#if GTK_CHECK_VERSION(3,0,0) + widget_class->get_preferred_height = pidgin_status_box_get_preferred_height; + widget_class->draw = pidgin_status_box_draw; +#else widget_class->size_request = pidgin_status_box_size_request; + widget_class->expose_event = pidgin_status_box_expose_event; +#endif widget_class->size_allocate = pidgin_status_box_size_allocate; - widget_class->expose_event = pidgin_status_box_expose_event; container_class->child_type = pidgin_status_box_child_type; container_class->forall = pidgin_status_box_forall; @@ -941,7 +945,7 @@ if (!purple_savedstatus_is_transient(saved_status) || !message || !*message) { status_box->imhtml_visible = FALSE; - gtk_widget_hide_all(status_box->vbox); + gtk_widget_hide(status_box->vbox); } else { @@ -1130,7 +1134,7 @@ static gboolean combo_box_scroll_event_cb(GtkWidget *w, GdkEventScroll *event, GtkIMHtml *imhtml) { - pidgin_status_box_popup(PIDGIN_STATUS_BOX(w)); + pidgin_status_box_popup(PIDGIN_STATUS_BOX(w)); return TRUE; } @@ -1145,7 +1149,7 @@ static gboolean imhtml_remove_focus(GtkWidget *w, GdkEventKey *event, PidginStatusBox *status_box) { - if (event->keyval == GDK_Tab || event->keyval == GDK_KP_Tab || event->keyval == GDK_ISO_Left_Tab) + if (event->keyval == GDK_KEY_Tab || event->keyval == GDK_KEY_KP_Tab || event->keyval == GDK_KEY_ISO_Left_Tab) { /* If last inserted character is a tab, then remove the focus from here */ GtkWidget *top = gtk_widget_get_toplevel(w); @@ -1158,7 +1162,7 @@ return FALSE; /* Reset the status if Escape was pressed */ - if (event->keyval == GDK_Escape) + if (event->keyval == GDK_KEY_Escape) { purple_timeout_remove(status_box->typing); status_box->typing = 0; @@ -1304,88 +1308,88 @@ static void pidgin_status_box_list_position (PidginStatusBox *status_box, int *x, int *y, int *width, int *height) { - GdkScreen *screen; - gint monitor_num; - GdkRectangle monitor; - GtkRequisition popup_req; - GtkPolicyType hpolicy, vpolicy; - - gdk_window_get_origin (GTK_WIDGET(status_box)->window, x, y); - - *x += GTK_WIDGET(status_box)->allocation.x; - *y += GTK_WIDGET(status_box)->allocation.y; - - *width = GTK_WIDGET(status_box)->allocation.width; - - hpolicy = vpolicy = GTK_POLICY_NEVER; + GdkScreen *screen; + gint monitor_num; + GdkRectangle monitor; + GtkRequisition popup_req; + GtkPolicyType hpolicy, vpolicy; + GtkAllocation allocation; + + gtk_widget_get_allocation(GTK_WIDGET(status_box), &allocation); + gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(status_box)), x, y); + + *x += allocation.x; + *y += allocation.y; + + *width = allocation.width; + + hpolicy = vpolicy = GTK_POLICY_NEVER; g_object_set(G_OBJECT(status_box->scrolled_window), - "hscrollbar-policy", hpolicy, - "vscrollbar-policy", vpolicy, - NULL); - gtk_widget_size_request (status_box->popup_frame, &popup_req); - - if (popup_req.width > *width) - { - hpolicy = GTK_POLICY_ALWAYS; - g_object_set(G_OBJECT(status_box->scrolled_window), - "hscrollbar-policy", hpolicy, - "vscrollbar-policy", vpolicy, - NULL); - gtk_widget_size_request (status_box->popup_frame, &popup_req); - } - - *height = popup_req.height; - - screen = gtk_widget_get_screen (GTK_WIDGET (status_box)); - monitor_num = gdk_screen_get_monitor_at_window (screen, - GTK_WIDGET (status_box)->window); - gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); - - if (*x < monitor.x) - *x = monitor.x; - else if (*x + *width > monitor.x + monitor.width) - *x = monitor.x + monitor.width - *width; - - if (*y + GTK_WIDGET(status_box)->allocation.height + *height <= monitor.y + monitor.height) - *y += GTK_WIDGET(status_box)->allocation.height; - else if (*y - *height >= monitor.y) - *y -= *height; - else if (monitor.y + monitor.height - (*y + GTK_WIDGET(status_box)->allocation.height) > *y - monitor.y) - { - *y += GTK_WIDGET(status_box)->allocation.height; - *height = monitor.y + monitor.height - *y; - } - else - { - *height = *y - monitor.y; - *y = monitor.y; - } - - if (popup_req.height > *height) - { - vpolicy = GTK_POLICY_ALWAYS; - - g_object_set(G_OBJECT(status_box->scrolled_window), - "hscrollbar-policy", hpolicy, - "vscrollbar-policy", vpolicy, - NULL); - } + "hscrollbar-policy", hpolicy, + "vscrollbar-policy", vpolicy, + NULL); + gtk_widget_size_request(status_box->popup_frame, &popup_req); + + if (popup_req.width > *width) { + hpolicy = GTK_POLICY_ALWAYS; + g_object_set(G_OBJECT(status_box->scrolled_window), + "hscrollbar-policy", hpolicy, + "vscrollbar-policy", vpolicy, + NULL); + gtk_widget_size_request(status_box->popup_frame, &popup_req); + } + + *height = popup_req.height; + + screen = gtk_widget_get_screen(GTK_WIDGET(status_box)); + monitor_num = gdk_screen_get_monitor_at_window(screen, + gtk_widget_get_window(GTK_WIDGET(status_box))); + gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor); + + if (*x < monitor.x) + *x = monitor.x; + else if (*x + *width > monitor.x + monitor.width) + *x = monitor.x + monitor.width - *width; + + if (*y + allocation.height + *height <= monitor.y + monitor.height) + *y += allocation.height; + else if (*y - *height >= monitor.y) + *y -= *height; + else if (monitor.y + monitor.height - (*y + allocation.height) > *y - monitor.y) + { + *y += allocation.height; + *height = monitor.y + monitor.height - *y; + } + else + { + *height = *y - monitor.y; + *y = monitor.y; + } + + if (popup_req.height > *height) + { + vpolicy = GTK_POLICY_ALWAYS; + + g_object_set(G_OBJECT(status_box->scrolled_window), + "hscrollbar-policy", hpolicy, + "vscrollbar-policy", vpolicy, + NULL); + } } static gboolean popup_grab_on_window (GdkWindow *window, - guint32 activate_time, - gboolean grab_keyboard) + guint32 activate_time) { if ((gdk_pointer_grab (window, TRUE, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK, NULL, NULL, activate_time) == 0)) { - if (!grab_keyboard || gdk_keyboard_grab (window, TRUE, activate_time) == 0) + if (gdk_keyboard_grab (window, TRUE, activate_time) == 0) return TRUE; else { - gdk_display_pointer_ungrab (gdk_drawable_get_display (window), activate_time); + gdk_display_pointer_ungrab (gdk_window_get_display (window), activate_time); return FALSE; } } @@ -1404,8 +1408,8 @@ gtk_window_move (GTK_WINDOW (box->popup_window), x, y); gtk_widget_show(box->popup_window); gtk_widget_grab_focus (box->tree_view); - if (!popup_grab_on_window (box->popup_window->window, - GDK_CURRENT_TIME, TRUE)) { + if (!popup_grab_on_window (gtk_widget_get_window(box->popup_window), + GDK_CURRENT_TIME)) { gtk_widget_hide (box->popup_window); return; } @@ -1429,16 +1433,18 @@ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (box->toggle_button), FALSE); gtk_grab_remove (box->popup_window); + gdk_pointer_ungrab(GDK_CURRENT_TIME); + gdk_keyboard_ungrab(GDK_CURRENT_TIME); } static gboolean toggle_key_press_cb(GtkWidget *widget, GdkEventKey *event, PidginStatusBox *box) { switch (event->keyval) { - case GDK_Return: - case GDK_KP_Enter: - case GDK_KP_Space: - case GDK_space: + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + case GDK_KEY_KP_Space: + case GDK_KEY_space: if (!box->popup_in_progress) { pidgin_status_box_popup (box); box->popup_in_progress = TRUE; @@ -1670,7 +1676,7 @@ GdkEventKey *event, PidginStatusBox *box) { if (box->popup_in_progress) { - if (event->keyval == GDK_Escape) { + if (event->keyval == GDK_KEY_Escape) { pidgin_status_box_popdown(box); return TRUE; } else { @@ -1681,9 +1687,9 @@ if (gtk_tree_selection_get_selected(sel, NULL, &iter)) { gboolean ret = TRUE; path = gtk_tree_model_get_path(GTK_TREE_MODEL(box->dropdown_store), &iter); - if (event->keyval == GDK_Return) { + if (event->keyval == GDK_KEY_Return) { treeview_activate_current_selection(box, path); - } else if (event->keyval == GDK_Delete) { + } else if (event->keyval == GDK_KEY_Delete) { tree_view_delete_current_selection(box, path); } else ret = FALSE; @@ -1934,6 +1940,33 @@ } +#if GTK_CHECK_VERSION(3,0,0) +static void +pidgin_status_box_get_preferred_height(GtkWidget *widget, gint *minimum_height, + gint *natural_height) +{ + gint box_min_height, box_nat_height; + gint border_width = gtk_container_get_border_width(GTK_CONTAINER (widget)); + + gtk_widget_get_preferred_height(PIDGIN_STATUS_BOX(widget)->toggle_button, + minimum_height, natural_height); + + *minimum_height = MAX(*minimum_height, 34) + border_width * 2; + *natural_height = MAX(*natural_height, 34) + border_width * 2; + + /* If the gtkimhtml is visible, then add some additional padding */ + if (PIDGIN_STATUS_BOX(widget)->imhtml_visible) { + gtk_widget_get_preferred_height(PIDGIN_STATUS_BOX(widget)->vbox, + &box_min_height, &box_nat_height); + + if (box_min_height > 1) + *minimum_height += box_min_height + border_width * 2; + + if (box_nat_height > 1) + *natural_height += box_nat_height + border_width * 2; + } +} +#else static void pidgin_status_box_size_request(GtkWidget *widget, GtkRequisition *requisition) @@ -1948,12 +1981,15 @@ requisition->height += border_width * 2; /* If the gtkimhtml is visible, then add some additional padding */ - gtk_widget_size_request(PIDGIN_STATUS_BOX(widget)->vbox, &box_req); - if (box_req.height > 1) - requisition->height += box_req.height + border_width * 2; + if (PIDGIN_STATUS_BOX(widget)->imhtml_visible) { + gtk_widget_size_request(PIDGIN_STATUS_BOX(widget)->vbox, &box_req); + if (box_req.height > 1) + requisition->height += box_req.height + border_width * 2; + } requisition->width = 1; } +#endif /* From gnome-panel */ static void @@ -2002,7 +2038,7 @@ PidginStatusBox *status_box = PIDGIN_STATUS_BOX(widget); GtkRequisition req = {0,0}; GtkAllocation parent_alc, box_alc, icon_alc; - gint border_width = GTK_CONTAINER (widget)->border_width; + gint border_width = gtk_container_get_border_width(GTK_CONTAINER (widget)); gtk_widget_size_request(status_box->toggle_button, &req); /* Make this icon the same size as other buddy icons in the list; unless it already wants to be bigger */ @@ -2041,9 +2077,27 @@ gtk_widget_size_allocate(status_box->icon_box, &icon_alc); } gtk_widget_size_allocate(status_box->toggle_button, &parent_alc); - widget->allocation = *allocation; + gtk_widget_set_allocation(GTK_WIDGET(status_box), allocation); } +#if GTK_CHECK_VERSION(3,0,0) +static gboolean +pidgin_status_box_draw(GtkWidget *widget, cairo_t *cr) +{ + PidginStatusBox *status_box = PIDGIN_STATUS_BOX(widget); + gtk_widget_draw(status_box->toggle_button, cr); + + if (status_box->icon_box && status_box->icon_opaque) { + GtkAllocation allocation; + + gtk_widget_get_allocation(status_box->icon_box, &allocation); + gtk_paint_box(gtk_widget_get_style(widget), cr, GTK_STATE_NORMAL, GTK_SHADOW_OUT, + status_box->icon_box, "button", allocation.x-1, allocation.y-1, + 34, 34); + } + return FALSE; +} +#else static gboolean pidgin_status_box_expose_event(GtkWidget *widget, GdkEventExpose *event) @@ -2058,6 +2112,7 @@ } return FALSE; } +#endif static void pidgin_status_box_forall(GtkContainer *container, @@ -2363,7 +2418,7 @@ message = pidgin_status_box_get_message(status_box); if (!message || !*message) { - gtk_widget_hide_all(status_box->vbox); + gtk_widget_hide(status_box->vbox); status_box->imhtml_visible = FALSE; if (message != NULL) { @@ -2635,7 +2690,7 @@ purple_timeout_remove(status_box->typing); status_box->typing = 0; - if (gtk_widget_is_sensitive(GTK_WIDGET(status_box))) + if (gtk_widget_get_sensitive(GTK_WIDGET(status_box))) { if (type == PIDGIN_STATUS_BOX_TYPE_POPULAR || type == PIDGIN_STATUS_BOX_TYPE_SAVED_POPULAR) { @@ -2697,7 +2752,7 @@ } g_list_free(accounts); - if (gtk_widget_is_sensitive(GTK_WIDGET(status_box))) + if (gtk_widget_get_sensitive(GTK_WIDGET(status_box))) { if (status_box->imhtml_visible) { @@ -2717,7 +2772,7 @@ } else { - gtk_widget_hide_all(status_box->vbox); + gtk_widget_hide(status_box->vbox); activate_currently_selected_status(status_box); /* This is where we actually set the status */ } } @@ -2753,7 +2808,7 @@ static void imhtml_changed_cb(GtkTextBuffer *buffer, void *data) { PidginStatusBox *status_box = (PidginStatusBox*)data; - if (gtk_widget_is_sensitive(GTK_WIDGET(status_box))) + if (gtk_widget_get_sensitive(GTK_WIDGET(status_box))) { if (status_box->typing != 0) { pidgin_status_box_pulse_typing(status_box);
--- a/pidgin/gtkutils.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkutils.c Mon Aug 06 18:11:44 2012 +0200 @@ -71,10 +71,7 @@ #include "gtkwebviewtoolbar.h" #include "pidgin/minidialog.h" -#if !GTK_CHECK_VERSION(2,18,0) -#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x) -#define gtk_widget_is_sensitive(x) GTK_WIDGET_IS_SENSITIVE(x) -#endif +#include "gtk3compat.h" enum { AOP_ICON_COLUMN, @@ -100,9 +97,8 @@ } static gboolean -url_clicked_cb(GtkIMHtml *unused, GtkIMHtmlLink *link) +url_clicked_cb(GtkWebView *unused, const char *uri) { - const char *uri = gtk_imhtml_link_get_url(link); g_idle_add(url_clicked_idle_cb, g_strdup(uri)); return TRUE; } @@ -220,7 +216,6 @@ wnd = GTK_WINDOW(gtk_dialog_new()); pidgin_window_init(wnd, title, border_width, role, resizable); - g_object_set(G_OBJECT(wnd), "has-separator", FALSE, NULL); return GTK_WIDGET(wnd); } @@ -228,7 +223,7 @@ GtkWidget * pidgin_dialog_get_vbox_with_properties(GtkDialog *dialog, gboolean homogeneous, gint spacing) { - GtkBox *vbox = GTK_BOX(GTK_DIALOG(dialog)->vbox); + GtkBox *vbox = GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))); gtk_box_set_homogeneous(vbox, homogeneous); gtk_box_set_spacing(vbox, spacing); return GTK_WIDGET(vbox); @@ -236,12 +231,12 @@ GtkWidget *pidgin_dialog_get_vbox(GtkDialog *dialog) { - return GTK_DIALOG(dialog)->vbox; + return gtk_dialog_get_content_area(GTK_DIALOG(dialog)); } GtkWidget *pidgin_dialog_get_action_area(GtkDialog *dialog) { - return GTK_DIALOG(dialog)->action_area; + return gtk_dialog_get_action_area(GTK_DIALOG(dialog)); } GtkWidget *pidgin_dialog_add_button(GtkDialog *dialog, const char *label, @@ -391,7 +386,7 @@ if (to_toggle == NULL) return; - sensitivity = gtk_widget_is_sensitive(to_toggle); + sensitivity = gtk_widget_get_sensitive(to_toggle); gtk_widget_set_sensitive(to_toggle, !sensitivity); } @@ -408,7 +403,7 @@ if (element == NULL) continue; - sensitivity = gtk_widget_is_sensitive(element); + sensitivity = gtk_widget_get_sensitive(element); gtk_widget_set_sensitive(element, !sensitivity); } @@ -1294,8 +1289,8 @@ widget = GTK_WIDGET(menu); screen = gtk_widget_get_screen(widget); - xthickness = widget->style->xthickness; - ythickness = widget->style->ythickness; + xthickness = gtk_widget_get_style(widget)->xthickness; + ythickness = gtk_widget_get_style(widget)->ythickness; rtl = (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL); /* @@ -1433,9 +1428,9 @@ GtkTreePath *path; GtkTreeViewColumn *col; GdkRectangle rect; - gint ythickness = GTK_WIDGET(menu)->style->ythickness; - - gdk_window_get_origin (widget->window, x, y); + gint ythickness = gtk_widget_get_style(GTK_WIDGET(menu))->ythickness; + + gdk_window_get_origin (gtk_widget_get_window(widget), x, y); gtk_tree_view_get_cursor (tv, &path, &col); gtk_tree_view_get_cell_area (tv, path, col, &rect); @@ -1552,7 +1547,7 @@ pidgin_dnd_file_manage(GtkSelectionData *sd, PurpleAccount *account, const char *who) { GdkPixbuf *pb; - GList *files = purple_uri_list_extract_filenames((const gchar *)sd->data); + GList *files = purple_uri_list_extract_filenames((const gchar *) gtk_selection_data_get_data(sd)); PurpleConnection *gc = purple_account_get_connection(account); PurplePluginProtocolInfo *prpl_info = NULL; #ifndef _WIN32 @@ -1875,8 +1870,9 @@ group = gtk_menu_get_accel_group(GTK_MENU(menu)); if (group) { - char *path = g_strdup_printf("%s/%s", GTK_MENU_ITEM(menuitem)->accel_path, - purple_menu_action_get_label(act)); + char *path = g_strdup_printf("%s/%s", + gtk_menu_item_get_accel_path(GTK_MENU_ITEM(menuitem)), + purple_menu_action_get_label(act)); gtk_menu_set_accel_path(GTK_MENU(submenu), path); g_free(path); gtk_menu_set_accel_group(GTK_MENU(submenu), group); @@ -2204,23 +2200,23 @@ GdkCursor *cursor; g_return_if_fail(widget != NULL); - if (widget->window == NULL) + if (gtk_widget_get_window(widget) == NULL) return; cursor = gdk_cursor_new(cursor_type); - gdk_window_set_cursor(widget->window, cursor); + gdk_window_set_cursor(gtk_widget_get_window(widget), cursor); gdk_cursor_unref(cursor); - gdk_display_flush(gdk_drawable_get_display(GDK_DRAWABLE(widget->window))); + gdk_display_flush(gdk_window_get_display(gtk_widget_get_window(widget))); } void pidgin_clear_cursor(GtkWidget *widget) { g_return_if_fail(widget != NULL); - if (widget->window == NULL) + if (gtk_widget_get_window(widget) == NULL) return; - gdk_window_set_cursor(widget->window, NULL); + gdk_window_set_cursor(gtk_widget_get_window(widget), NULL); } struct _icon_chooser { @@ -2261,7 +2257,7 @@ gtk_widget_destroy(dialog->icon_filesel); g_free(filename); g_free(dialog); - } +} static void @@ -2880,7 +2876,7 @@ if (!widget) return "dim grey"; - style = gtk_widget_get_style(widget); + style = gtk_widget_get_style(widget); if (!style) return "dim grey"; @@ -2892,18 +2888,18 @@ } static void -combo_box_changed_cb(GtkComboBox *combo_box, GtkEntry *entry) +combo_box_changed_cb(GtkComboBoxText *combo_box, GtkEntry *entry) { - char *text = gtk_combo_box_get_active_text(combo_box); + char *text = gtk_combo_box_text_get_active_text(combo_box); gtk_entry_set_text(entry, text ? text : ""); g_free(text); } static gboolean -entry_key_pressed_cb(GtkWidget *entry, GdkEventKey *key, GtkComboBox *combo) +entry_key_pressed_cb(GtkWidget *entry, GdkEventKey *key, GtkComboBoxText *combo) { - if (key->keyval == GDK_Down || key->keyval == GDK_Up) { - gtk_combo_box_popup(combo); + if (key->keyval == GDK_KEY_Down || key->keyval == GDK_KEY_Up) { + gtk_combo_box_popup(GTK_COMBO_BOX(combo)); return TRUE; } return FALSE; @@ -2912,12 +2908,17 @@ GtkWidget * pidgin_text_combo_box_entry_new(const char *default_item, GList *items) { - GtkComboBox *ret = NULL; + GtkComboBoxText *ret = NULL; GtkWidget *the_entry = NULL; +#if GTK_CHECK_VERSION(2,24,0) + ret = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new_with_entry()); + the_entry = gtk_bin_get_child(GTK_BIN(ret)); +#else ret = GTK_COMBO_BOX(gtk_combo_box_entry_new_text()); the_entry = gtk_entry_new(); gtk_container_add(GTK_CONTAINER(ret), the_entry); +#endif if (default_item) gtk_entry_set_text(GTK_ENTRY(the_entry), default_item); @@ -2925,7 +2926,7 @@ for (; items != NULL ; items = items->next) { char *text = items->data; if (text && *text) - gtk_combo_box_append_text(ret, text); + gtk_combo_box_text_append_text(ret, text); } g_signal_connect(G_OBJECT(ret), "changed", (GCallback)combo_box_changed_cb, the_entry); @@ -2936,12 +2937,12 @@ const char *pidgin_text_combo_box_entry_get_text(GtkWidget *widget) { - return gtk_entry_get_text(GTK_ENTRY(GTK_BIN((widget))->child)); + return gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN((widget))))); } void pidgin_text_combo_box_entry_set_text(GtkWidget *widget, const char *text) { - gtk_entry_set_text(GTK_ENTRY(GTK_BIN((widget))->child), (text)); + gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN((widget)))), (text)); } GtkWidget * @@ -3067,7 +3068,7 @@ } if (gtk_window_has_toplevel_focus(GTK_WINDOW(window)) || - (menu && menu == window->window)) { + (menu && menu == gtk_widget_get_window(window))) { parent = window; break; } @@ -3213,7 +3214,8 @@ return pixbuf; } -static void url_copy(GtkWidget *w, gchar *url) +static void +url_copy(GtkWidget *w, gchar *url) { GtkClipboard *clipboard; @@ -3225,54 +3227,63 @@ } static gboolean -link_context_menu(GtkIMHtml *imhtml, GtkIMHtmlLink *link, GtkWidget *menu) +link_context_menu(GtkWebView *webview, WebKitDOMHTMLAnchorElement *link, GtkWidget *menu) { GtkWidget *img, *item; - const char *url; - - url = gtk_imhtml_link_get_url(link); + char *url; + + url = webkit_dom_html_anchor_element_get_href(link); /* Open Link */ img = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU); item = gtk_image_menu_item_new_with_mnemonic(_("_Open Link")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); - g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link); + g_signal_connect_swapped(G_OBJECT(item), "activate", + G_CALLBACK(gtk_webview_activate_anchor), link); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); /* Copy Link Location */ img = gtk_image_new_from_stock(GTK_STOCK_COPY, GTK_ICON_SIZE_MENU); item = gtk_image_menu_item_new_with_mnemonic(_("_Copy Link Location")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); - g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(url_copy), (gpointer)url); + /* The signal owns url now: */ + g_signal_connect_data(G_OBJECT(item), "activate", G_CALLBACK(url_copy), + (gpointer)url, (GClosureNotify)g_free, 0); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); return TRUE; } static gboolean -copy_email_address(GtkIMHtml *imhtml, GtkIMHtmlLink *link, GtkWidget *menu) +copy_email_address(GtkWebView *webview, WebKitDOMHTMLAnchorElement *link, GtkWidget *menu) { GtkWidget *img, *item; - const char *text; + char *text; char *address; #define MAILTOSIZE (sizeof("mailto:") - 1) - text = gtk_imhtml_link_get_url(link); - g_return_val_if_fail(text && strlen(text) > MAILTOSIZE, FALSE); - address = (char*)text + MAILTOSIZE; + text = webkit_dom_html_anchor_element_get_href(link); + if (!text || strlen(text) <= MAILTOSIZE) { + g_free(text); + return FALSE; + } + address = text + MAILTOSIZE; /* Copy Email Address */ img = gtk_image_new_from_stock(GTK_STOCK_COPY, GTK_ICON_SIZE_MENU); item = gtk_image_menu_item_new_with_mnemonic(_("_Copy Email Address")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); - g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(url_copy), address); + g_signal_connect_data(G_OBJECT(item), "activate", G_CALLBACK(url_copy), + g_strdup(address), (GClosureNotify)g_free, 0); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + g_free(text); + return TRUE; } static void -file_open_uri(GtkIMHtml *imhtml, const char *uri) +file_open_uri(GtkWebView *webview, const char *uri) { /* Copied from gtkft.c:open_button_cb */ #ifdef _WIN32 @@ -3344,7 +3355,7 @@ { tmp = g_strdup_printf(_("Error launching %s: %s"), uri, error->message); - purple_notify_error(imhtml, NULL, _("Unable to open file."), tmp); + purple_notify_error(webview, NULL, _("Unable to open file."), tmp); g_free(tmp); g_error_free(error); } @@ -3353,7 +3364,7 @@ char *primary = g_strdup_printf(_("Error running %s"), command); char *secondary = g_strdup_printf(_("Process returned error code %d"), exit_status); - purple_notify_error(imhtml, NULL, primary, secondary); + purple_notify_error(webview, NULL, primary, secondary); g_free(tmp); } } @@ -3362,43 +3373,45 @@ #define FILELINKSIZE (sizeof("file://") - 1) static gboolean -file_clicked_cb(GtkIMHtml *imhtml, GtkIMHtmlLink *link) +file_clicked_cb(GtkWebView *webview, const char *uri) { - const char *uri = gtk_imhtml_link_get_url(link) + FILELINKSIZE; - file_open_uri(imhtml, uri); + file_open_uri(webview, uri + FILELINKSIZE); return TRUE; } static gboolean -open_containing_cb(GtkIMHtml *imhtml, const char *url) +open_containing_cb(GtkWebView *webview, const char *uri) { - char *dir = g_path_get_dirname(url + FILELINKSIZE); - file_open_uri(imhtml, dir); + char *dir = g_path_get_dirname(uri + FILELINKSIZE); + file_open_uri(webview, dir); g_free(dir); return TRUE; } static gboolean -file_context_menu(GtkIMHtml *imhtml, GtkIMHtmlLink *link, GtkWidget *menu) +file_context_menu(GtkWebView *webview, WebKitDOMHTMLAnchorElement *link, GtkWidget *menu) { GtkWidget *img, *item; - const char *url; - - url = gtk_imhtml_link_get_url(link); + char *url; + + url = webkit_dom_html_anchor_element_get_href(link); /* Open File */ img = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU); item = gtk_image_menu_item_new_with_mnemonic(_("_Open File")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); - g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link); + g_signal_connect_swapped(G_OBJECT(item), "activate", + G_CALLBACK(gtk_webview_activate_anchor), link); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); /* Open Containing Directory */ img = gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU); item = gtk_image_menu_item_new_with_mnemonic(_("Open _Containing Directory")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); - - g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(open_containing_cb), (gpointer)url); + /* The signal owns url now: */ + g_signal_connect_data(G_OBJECT(item), "activate", + G_CALLBACK(open_containing_cb), (gpointer)url, + (GClosureNotify)g_free, 0); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); return TRUE; @@ -3406,14 +3419,12 @@ #define AUDIOLINKSIZE (sizeof("audio://") - 1) static gboolean -audio_clicked_cb(GtkIMHtml *imhtml, GtkIMHtmlLink *link) +audio_clicked_cb(GtkWebView *webview, const char *uri) { - const char *uri; - PidginConversation *conv = g_object_get_data(G_OBJECT(imhtml), "gtkconv"); + PidginConversation *conv = g_object_get_data(G_OBJECT(webview), "gtkconv"); if (!conv) /* no playback in debug window */ return TRUE; - uri = gtk_imhtml_link_get_url(link) + AUDIOLINKSIZE; - purple_sound_play_file(uri, NULL); + purple_sound_play_file(uri + AUDIOLINKSIZE, NULL); return TRUE; } @@ -3429,8 +3440,10 @@ purple_debug_error("gtkutils", "Unable to read contents of %s: %s\n", temp_file, error->message); g_error_free(error); + g_free(temp_file); return; } + g_free(temp_file); if (!purple_util_write_data_to_file_absolute(file, contents, length)) { purple_debug_error("gtkutils", "Unable to write contents to %s\n", @@ -3441,56 +3454,61 @@ static gboolean save_file_cb(GtkWidget *item, const char *url) { - PidginConversation *conv = g_object_get_data(G_OBJECT(item), "gtkconv"); - if (!conv) + PidginConversation *gtkconv = g_object_get_data(G_OBJECT(item), "gtkconv"); + PurpleConversation *conv; + if (!gtkconv) return TRUE; - purple_request_file(conv->active_conv, _("Save File"), NULL, TRUE, - G_CALLBACK(savefile_write_cb), NULL, - purple_conversation_get_account(conv->active_conv), NULL, conv->active_conv, - (void *)url); + conv = gtkconv->active_conv; + purple_request_file(conv, _("Save File"), NULL, TRUE, + G_CALLBACK(savefile_write_cb), G_CALLBACK(g_free), + purple_conversation_get_account(conv), NULL, conv, + (gpointer)g_strdup(url)); return TRUE; } static gboolean -audio_context_menu(GtkIMHtml *imhtml, GtkIMHtmlLink *link, GtkWidget *menu) +audio_context_menu(GtkWebView *webview, WebKitDOMHTMLAnchorElement *link, GtkWidget *menu) { GtkWidget *img, *item; - const char *url; - PidginConversation *conv = g_object_get_data(G_OBJECT(imhtml), "gtkconv"); + char *url; + PidginConversation *conv = g_object_get_data(G_OBJECT(webview), "gtkconv"); if (!conv) /* No menu in debug window */ return TRUE; - url = gtk_imhtml_link_get_url(link); + url = webkit_dom_html_anchor_element_get_href(link); /* Play Sound */ img = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU); item = gtk_image_menu_item_new_with_mnemonic(_("_Play Sound")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); - - g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link); + g_signal_connect_swapped(G_OBJECT(item), "activate", + G_CALLBACK(gtk_webview_activate_anchor), link); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); /* Save File */ img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU); item = gtk_image_menu_item_new_with_mnemonic(_("_Save File")); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img); - g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(save_file_cb), (gpointer)(url+AUDIOLINKSIZE)); + g_signal_connect_data(G_OBJECT(item), "activate", + G_CALLBACK(save_file_cb), g_strdup(url+AUDIOLINKSIZE), + (GClosureNotify)g_free, 0); g_object_set_data(G_OBJECT(item), "gtkconv", conv); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + g_free(url); + return TRUE; } /* XXX: The following two functions are for demonstration purposes only! */ static gboolean -open_dialog(GtkIMHtml *imhtml, GtkIMHtmlLink *link) +open_dialog(GtkWebView *webview, const char *url) { - const char *url; const char *str; - url = gtk_imhtml_link_get_url(link); - if (!url || strlen(url) < sizeof("open://")) + if (!url || strlen(url) < sizeof("open://")) { return FALSE; + } str = url + sizeof("open://") - 1; @@ -3504,7 +3522,7 @@ } static gboolean -dummy(GtkIMHtml *imhtml, GtkIMHtmlLink *link, GtkWidget *menu) +dummy(GtkWebView *webview, WebKitDOMHTMLAnchorElement *link, GtkWidget *menu) { return TRUE; } @@ -3569,7 +3587,7 @@ protocol = g_strdup_printf("%s:", start); registered_url_handlers = g_slist_prepend(registered_url_handlers, protocol); - gtk_imhtml_class_register_protocol(protocol, url_clicked_cb, link_context_menu); + gtk_webview_class_register_protocol(protocol, url_clicked_cb, link_context_menu); } start = c + 1; } @@ -3602,7 +3620,7 @@ g_free(utf8); registered_url_handlers = g_slist_prepend(registered_url_handlers, protocol); /* We still pass everything to the "http" "open" handler for security reasons */ - gtk_imhtml_class_register_protocol(protocol, url_clicked_cb, link_context_menu); + gtk_webview_class_register_protocol(protocol, url_clicked_cb, link_context_menu); } RegCloseKey(reg_key); } @@ -3628,7 +3646,11 @@ if (width != -1 || height != -1) gtk_widget_set_size_request(sw, width, height); if (child) { +#if GTK_CHECK_VERSION(3,0,0) + if (GTK_IS_SCROLLABLE(child)) +#else if (GTK_WIDGET_GET_CLASS(child)->set_scroll_adjustments_signal) +#endif gtk_container_add(GTK_CONTAINER(sw), child); else gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), child); @@ -3641,17 +3663,17 @@ void pidgin_utils_init(void) { - gtk_imhtml_class_register_protocol("http://", url_clicked_cb, link_context_menu); - gtk_imhtml_class_register_protocol("https://", url_clicked_cb, link_context_menu); - gtk_imhtml_class_register_protocol("ftp://", url_clicked_cb, link_context_menu); - gtk_imhtml_class_register_protocol("gopher://", url_clicked_cb, link_context_menu); - gtk_imhtml_class_register_protocol("mailto:", url_clicked_cb, copy_email_address); - - gtk_imhtml_class_register_protocol("file://", file_clicked_cb, file_context_menu); - gtk_imhtml_class_register_protocol("audio://", audio_clicked_cb, audio_context_menu); + gtk_webview_class_register_protocol("http://", url_clicked_cb, link_context_menu); + gtk_webview_class_register_protocol("https://", url_clicked_cb, link_context_menu); + gtk_webview_class_register_protocol("ftp://", url_clicked_cb, link_context_menu); + gtk_webview_class_register_protocol("gopher://", url_clicked_cb, link_context_menu); + gtk_webview_class_register_protocol("mailto:", url_clicked_cb, copy_email_address); + + gtk_webview_class_register_protocol("file://", file_clicked_cb, file_context_menu); + gtk_webview_class_register_protocol("audio://", audio_clicked_cb, audio_context_menu); /* Example custom URL handler. */ - gtk_imhtml_class_register_protocol("open://", open_dialog, dummy); + gtk_webview_class_register_protocol("open://", open_dialog, dummy); /* If we're under GNOME, try registering the system URL handlers. */ if (purple_running_gnome()) @@ -3678,7 +3700,7 @@ void pidgin_utils_uninit(void) { - gtk_imhtml_class_register_protocol("open://", NULL, NULL); + gtk_webview_class_register_protocol("open://", NULL, NULL); /* If we have GNOME handlers registered, unregister them. */ if (registered_url_handlers) @@ -3686,7 +3708,7 @@ GSList *l; for (l = registered_url_handlers; l; l = l->next) { - gtk_imhtml_class_register_protocol((char *)l->data, NULL, NULL); + gtk_webview_class_register_protocol((char *)l->data, NULL, NULL); g_free(l->data); } g_slist_free(registered_url_handlers); @@ -3694,12 +3716,12 @@ return; } - gtk_imhtml_class_register_protocol("audio://", NULL, NULL); - gtk_imhtml_class_register_protocol("file://", NULL, NULL); - - gtk_imhtml_class_register_protocol("http://", NULL, NULL); - gtk_imhtml_class_register_protocol("https://", NULL, NULL); - gtk_imhtml_class_register_protocol("ftp://", NULL, NULL); - gtk_imhtml_class_register_protocol("mailto:", NULL, NULL); - gtk_imhtml_class_register_protocol("gopher://", NULL, NULL); + gtk_webview_class_register_protocol("audio://", NULL, NULL); + gtk_webview_class_register_protocol("file://", NULL, NULL); + + gtk_webview_class_register_protocol("http://", NULL, NULL); + gtk_webview_class_register_protocol("https://", NULL, NULL); + gtk_webview_class_register_protocol("ftp://", NULL, NULL); + gtk_webview_class_register_protocol("mailto:", NULL, NULL); + gtk_webview_class_register_protocol("gopher://", NULL, NULL); }
--- a/pidgin/gtkutils.h Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkutils.h Mon Aug 06 18:11:44 2012 +0200 @@ -118,7 +118,6 @@ * Create an GtkWebView widget and associated GtkIMHtmlToolbar widget. This * function puts both widgets in a nice GtkFrame. They're separated by an * attractive GtkSeparator. - * TODO WEBKIT: editable isn't supported yet * * @param editable @c TRUE if this webview should be editable. If this is * @c FALSE, then the toolbar will NOT be created. If this webview
--- a/pidgin/gtkwebview.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkwebview.c Mon Aug 06 18:11:44 2012 +0200 @@ -26,11 +26,15 @@ */ #include "internal.h" +#include "debug.h" #include "pidgin.h" #include <gdk/gdkkeysyms.h> +#include "gtkutils.h" #include "gtkwebview.h" +#include "gtk3compat.h" + #define MAX_FONT_SIZE 7 #define MAX_SCROLL_TIME 0.4 /* seconds */ #define SCROLL_DELAY 33 /* milliseconds */ @@ -39,6 +43,11 @@ (G_TYPE_INSTANCE_GET_PRIVATE((obj), GTK_TYPE_WEBVIEW, GtkWebViewPriv)) enum { + LOAD_HTML, + LOAD_JS +}; + +enum { BUTTONS_UPDATE, TOGGLE_FORMAT, CLEAR_FORMAT, @@ -52,12 +61,19 @@ * Structs *****************************************************************************/ -typedef struct _GtkWebViewPriv { - gboolean empty; /**< whether anything has been appended **/ +typedef struct { + char *name; + int length; - /* JS execute queue */ - GQueue *js_queue; + gboolean (*activate)(GtkWebView *webview, const char *uri); + gboolean (*context_menu)(GtkWebView *webview, WebKitDOMHTMLAnchorElement *link, GtkWidget *menu); +} GtkWebViewProtocol; + +typedef struct _GtkWebViewPriv { + /* Processing queues */ gboolean is_loading; + GQueue *load_queue; + guint loader; /* Scroll adjustments */ GtkAdjustment *vadj; @@ -124,21 +140,47 @@ } static gboolean -process_js_script_queue(GtkWebView *webview) +process_load_queue(GtkWebView *webview) { GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); - char *script; + int type; + char *str; + WebKitDOMDocument *doc; + WebKitDOMHTMLElement *body; + + if (priv->is_loading) { + priv->loader = 0; + return FALSE; + } + if (!priv->load_queue || g_queue_is_empty(priv->load_queue)) { + priv->loader = 0; + return FALSE; + } + + type = GPOINTER_TO_INT(g_queue_pop_head(priv->load_queue)); + str = g_queue_pop_head(priv->load_queue); - if (priv->is_loading) - return FALSE; /* we will be called when loaded */ - if (!priv->js_queue || g_queue_is_empty(priv->js_queue)) - return FALSE; /* nothing to do! */ + switch (type) { + case LOAD_HTML: + doc = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + body = webkit_dom_document_get_body(doc); + webkit_dom_html_element_insert_adjacent_html(body, "beforeend", + str, NULL); + break; - script = g_queue_pop_head(priv->js_queue); - webkit_web_view_execute_script(WEBKIT_WEB_VIEW(webview), script); - g_free(script); + case LOAD_JS: + webkit_web_view_execute_script(WEBKIT_WEB_VIEW(webview), str); + break; - return TRUE; /* there may be more for now */ + default: + purple_debug_error("webview", + "Got unknown loading queue type: %d\n", type); + break; + } + + g_free(str); + + return TRUE; } static void @@ -158,16 +200,38 @@ GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); priv->is_loading = FALSE; - g_idle_add((GSourceFunc)process_js_script_queue, webview); + if (priv->loader == 0) + priv->loader = g_idle_add((GSourceFunc)process_load_queue, webview); +} + +static GtkWebViewProtocol * +webview_find_protocol(const char *url, gboolean reverse) +{ + GtkWebViewClass *klass; + GList *iter; + GtkWebViewProtocol *proto = NULL; + int length = reverse ? strlen(url) : -1; + + klass = g_type_class_ref(GTK_TYPE_WEBVIEW); + for (iter = klass->protocols; iter; iter = iter->next) { + proto = iter->data; + if (g_ascii_strncasecmp(url, proto->name, reverse ? MIN(length, proto->length) : proto->length) == 0) { + g_type_class_unref(klass); + return proto; + } + } + + g_type_class_unref(klass); + return NULL; } static gboolean -webview_link_clicked(WebKitWebView *webview, - WebKitWebFrame *frame, - WebKitNetworkRequest *request, - WebKitWebNavigationAction *navigation_action, - WebKitWebPolicyDecision *policy_decision, - gpointer userdata) +webview_navigation_decision(WebKitWebView *webview, + WebKitWebFrame *frame, + WebKitNetworkRequest *request, + WebKitWebNavigationAction *navigation_action, + WebKitWebPolicyDecision *policy_decision, + gpointer userdata) { const gchar *uri; WebKitWebNavigationReason reason; @@ -176,9 +240,11 @@ reason = webkit_web_navigation_action_get_reason(navigation_action); if (reason == WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED) { - /* the gtk imhtml way was to create an idle cb, not sure - * why, so right now just using purple_notify_uri directly */ - purple_notify_uri(NULL, uri); + GtkWebViewProtocol *proto = webview_find_protocol(uri, FALSE); + if (proto) { + /* XXX: Do something with the return value? */ + proto->activate(GTK_WEBVIEW(webview), uri); + } webkit_web_policy_decision_ignore(policy_decision); } else if (reason == WEBKIT_WEB_NAVIGATION_REASON_OTHER) webkit_web_policy_decision_use(policy_decision); @@ -188,6 +254,133 @@ return TRUE; } +static void +do_popup_menu(WebKitWebView *webview, int button, int time, int context, + WebKitDOMHTMLAnchorElement *link, const char *uri) +{ + GtkWidget *menu; + GtkWidget *cut, *copy, *paste, *delete, *select; + + menu = gtk_menu_new(); + g_signal_connect(menu, "selection-done", + G_CALLBACK(gtk_widget_destroy), NULL); + + if ((context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK) + && !(context & WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION)) { + GtkWebViewProtocol *proto = NULL; + GList *children; + + if (uri && link) + proto = webview_find_protocol(uri, FALSE); + + if (proto && proto->context_menu) { + proto->context_menu(GTK_WEBVIEW(webview), link, menu); + } + + children = gtk_container_get_children(GTK_CONTAINER(menu)); + if (!children) { + GtkWidget *item = gtk_menu_item_new_with_label(_("No actions available")); + gtk_widget_show(item); + gtk_widget_set_sensitive(item, FALSE); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + } else { + g_list_free(children); + } + gtk_widget_show_all(menu); + + } else { + /* Using connect_swapped means we don't need any wrapper functions */ + cut = pidgin_new_item_from_stock(menu, _("Cu_t"), GTK_STOCK_CUT, + NULL, NULL, 0, 0, NULL); + g_signal_connect_swapped(G_OBJECT(cut), "activate", + G_CALLBACK(webkit_web_view_cut_clipboard), + webview); + + copy = pidgin_new_item_from_stock(menu, _("_Copy"), GTK_STOCK_COPY, + NULL, NULL, 0, 0, NULL); + g_signal_connect_swapped(G_OBJECT(copy), "activate", + G_CALLBACK(webkit_web_view_copy_clipboard), + webview); + + paste = pidgin_new_item_from_stock(menu, _("_Paste"), GTK_STOCK_PASTE, + NULL, NULL, 0, 0, NULL); + g_signal_connect_swapped(G_OBJECT(paste), "activate", + G_CALLBACK(webkit_web_view_paste_clipboard), + webview); + + delete = pidgin_new_item_from_stock(menu, _("_Delete"), GTK_STOCK_DELETE, + NULL, NULL, 0, 0, NULL); + g_signal_connect_swapped(G_OBJECT(delete), "activate", + G_CALLBACK(webkit_web_view_delete_selection), + webview); + + pidgin_separator(menu); + + select = pidgin_new_item_from_stock(menu, _("Select _All"), + GTK_STOCK_SELECT_ALL, + NULL, NULL, 0, 0, NULL); + g_signal_connect_swapped(G_OBJECT(select), "activate", + G_CALLBACK(webkit_web_view_select_all), + webview); + + gtk_widget_set_sensitive(cut, + webkit_web_view_can_cut_clipboard(webview)); + gtk_widget_set_sensitive(copy, + webkit_web_view_can_copy_clipboard(webview)); + gtk_widget_set_sensitive(paste, + webkit_web_view_can_paste_clipboard(webview)); + gtk_widget_set_sensitive(delete, + webkit_web_view_can_cut_clipboard(webview)); + } + + g_signal_emit_by_name(G_OBJECT(webview), "populate-popup", menu); + + gtk_menu_attach_to_widget(GTK_MENU(menu), GTK_WIDGET(webview), NULL); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, button, time); +} + +static gboolean +webview_popup_menu(WebKitWebView *webview) +{ + do_popup_menu(webview, 0, gtk_get_current_event_time(), + WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT, + NULL, NULL); + return TRUE; +} + +static gboolean +webview_button_pressed(WebKitWebView *webview, GdkEventButton *event) +{ + if (event->type == GDK_BUTTON_PRESS && event->button == 3) { + WebKitHitTestResult *hit; + int context; + WebKitDOMNode *node; + char *uri; + + hit = webkit_web_view_get_hit_test_result(webview, event); + g_object_get(G_OBJECT(hit), + "context", &context, + "inner-node", &node, + "link-uri", &uri, + NULL); + + if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK) { + while (node && !WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT(node)) { + node = webkit_dom_node_get_parent_node(node); + } + } + + do_popup_menu(webview, event->button, event->time, context, + WEBKIT_DOM_HTML_ANCHOR_ELEMENT(node), uri); + + g_free(uri); + + return TRUE; + } + + return FALSE; +} + /* * Smoothly scroll a WebView. * @@ -204,11 +397,7 @@ g_return_val_if_fail(priv->scroll_time != NULL, FALSE); adj = priv->vadj; -#if GTK_CHECK_VERSION(2,14,0) max_val = gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj); -#else - max_val = adj->upper - adj->page_size; -#endif scroll_val = gtk_adjustment_get_value(adj) + ((max_val - gtk_adjustment_get_value(adj)) / 3); @@ -218,7 +407,6 @@ gtk_adjustment_set_value(adj, max_val); g_timer_destroy(priv->scroll_time); priv->scroll_time = NULL; - g_source_remove(priv->scroll_src); priv->scroll_src = 0; return FALSE; } @@ -236,11 +424,7 @@ gdouble max_val; if (adj) { -#if GTK_CHECK_VERSION(2,14,0) max_val = gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj); -#else - max_val = adj->upper - adj->page_size; -#endif gtk_adjustment_set_value(adj, max_val); } @@ -383,9 +567,15 @@ GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); gpointer temp; - while ((temp = g_queue_pop_head(priv->js_queue))) + if (priv->loader) + g_source_remove(priv->loader); + + while (!g_queue_is_empty(priv->load_queue)) { + temp = g_queue_pop_head(priv->load_queue); + temp = g_queue_pop_head(priv->load_queue); g_free(temp); - g_queue_free(priv->js_queue); + } + g_queue_free(priv->load_queue); G_OBJECT_CLASS(parent_class)->finalize(G_OBJECT(webview)); } @@ -467,17 +657,22 @@ { GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); - priv->empty = TRUE; - priv->js_queue = g_queue_new(); + priv->load_queue = g_queue_new(); - g_signal_connect(webview, "navigation-policy-decision-requested", - G_CALLBACK(webview_link_clicked), NULL); + g_signal_connect(G_OBJECT(webview), "button-press-event", + G_CALLBACK(webview_button_pressed), NULL); + + g_signal_connect(G_OBJECT(webview), "popup-menu", + G_CALLBACK(webview_popup_menu), NULL); - g_signal_connect(webview, "load-started", - G_CALLBACK(webview_load_started), NULL); + g_signal_connect(G_OBJECT(webview), "navigation-policy-decision-requested", + G_CALLBACK(webview_navigation_decision), NULL); - g_signal_connect(webview, "load-finished", - G_CALLBACK(webview_load_finished), NULL); + g_signal_connect(G_OBJECT(webview), "load-started", + G_CALLBACK(webview_load_started), NULL); + + g_signal_connect(G_OBJECT(webview), "load-finished", + G_CALLBACK(webview_load_finished), NULL); g_signal_connect(G_OBJECT(webview), "resource-request-starting", G_CALLBACK(webview_resource_loading), NULL); @@ -510,13 +705,6 @@ * Public API functions *****************************************************************************/ -gboolean -gtk_webview_is_empty(GtkWebView *webview) -{ - GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); - return priv->empty; -} - char * gtk_webview_quote_js_string(const char *text) { @@ -550,14 +738,22 @@ void gtk_webview_safe_execute_script(GtkWebView *webview, const char *script) { - GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); - g_queue_push_tail(priv->js_queue, g_strdup(script)); - g_idle_add((GSourceFunc)process_js_script_queue, webview); + GtkWebViewPriv *priv; + + g_return_if_fail(webview != NULL); + + priv = GTK_WEBVIEW_GET_PRIVATE(webview); + g_queue_push_tail(priv->load_queue, GINT_TO_POINTER(LOAD_JS)); + g_queue_push_tail(priv->load_queue, g_strdup(script)); + if (!priv->is_loading && priv->loader == 0) + priv->loader = g_idle_add((GSourceFunc)process_load_queue, webview); } void gtk_webview_load_html_string(GtkWebView *webview, const char *html) { + g_return_if_fail(webview != NULL); + webkit_web_view_load_string(WEBKIT_WEB_VIEW(webview), html, NULL, NULL, "file:///"); } @@ -565,6 +761,8 @@ void gtk_webview_load_html_string_with_selection(GtkWebView *webview, const char *html) { + g_return_if_fail(webview != NULL); + gtk_webview_load_html_string(webview, html); gtk_webview_safe_execute_script(webview, "var s = window.getSelection();" @@ -582,26 +780,36 @@ void gtk_webview_append_html(GtkWebView *webview, const char *html) { - GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); - WebKitDOMDocument *doc; - WebKitDOMHTMLElement *body; - doc = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); - body = webkit_dom_document_get_body(doc); - webkit_dom_html_element_insert_adjacent_html(body, "beforeend", html, NULL); - priv->empty = FALSE; + GtkWebViewPriv *priv; + + g_return_if_fail(webview != NULL); + + priv = GTK_WEBVIEW_GET_PRIVATE(webview); + g_queue_push_tail(priv->load_queue, GINT_TO_POINTER(LOAD_HTML)); + g_queue_push_tail(priv->load_queue, g_strdup(html)); + if (!priv->is_loading && priv->loader == 0) + priv->loader = g_idle_add((GSourceFunc)process_load_queue, webview); } void gtk_webview_set_vadjustment(GtkWebView *webview, GtkAdjustment *vadj) { - GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + GtkWebViewPriv *priv; + + g_return_if_fail(webview != NULL); + + priv = GTK_WEBVIEW_GET_PRIVATE(webview); priv->vadj = vadj; } void gtk_webview_scroll_to_end(GtkWebView *webview, gboolean smooth) { - GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + GtkWebViewPriv *priv; + + g_return_if_fail(webview != NULL); + + priv = GTK_WEBVIEW_GET_PRIVATE(webview); if (priv->scroll_time) g_timer_destroy(priv->scroll_time); if (priv->scroll_src) @@ -618,17 +826,16 @@ void gtk_webview_page_up(GtkWebView *webview) { - GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); - GtkAdjustment *vadj = priv->vadj; + GtkWebViewPriv *priv; + GtkAdjustment *vadj; gdouble scroll_val; -#if GTK_CHECK_VERSION(2,14,0) + g_return_if_fail(webview != NULL); + + priv = GTK_WEBVIEW_GET_PRIVATE(webview); + vadj = priv->vadj; scroll_val = gtk_adjustment_get_value(vadj) - gtk_adjustment_get_page_size(vadj); scroll_val = MAX(scroll_val, gtk_adjustment_get_lower(vadj)); -#else - scroll_val = gtk_adjustment_get_value(vadj) - vadj->page_size; - scroll_val = MAX(scroll_val, vadj->lower); -#endif gtk_adjustment_set_value(vadj, scroll_val); } @@ -636,20 +843,18 @@ void gtk_webview_page_down(GtkWebView *webview) { - GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); - GtkAdjustment *vadj = priv->vadj; + GtkWebViewPriv *priv; + GtkAdjustment *vadj; gdouble scroll_val; gdouble page_size; -#if GTK_CHECK_VERSION(2,14,0) + g_return_if_fail(webview != NULL); + + priv = GTK_WEBVIEW_GET_PRIVATE(webview); + vadj = priv->vadj; page_size = gtk_adjustment_get_page_size(vadj); scroll_val = gtk_adjustment_get_value(vadj) + page_size; scroll_val = MIN(scroll_val, gtk_adjustment_get_upper(vadj) - page_size); -#else - page_size = vadj->page_size; - scroll_val = gtk_adjustment_get_value(vadj) + page_size; - scroll_val = MIN(scroll_val, vadj->upper - page_size); -#endif gtk_adjustment_set_value(vadj, scroll_val); } @@ -657,6 +862,10 @@ void gtk_webview_set_editable(GtkWebView *webview, gboolean editable) { + GtkWebViewPriv *priv; + g_return_if_fail(webview != NULL); + + priv = GTK_WEBVIEW_GET_PRIVATE(webview); webkit_web_view_set_editable(WEBKIT_WEB_VIEW(webview), editable); if (editable) { @@ -667,6 +876,8 @@ G_CALLBACK(editable_input_cb), NULL); } + + priv->format_functions = GTK_WEBVIEW_ALL; } void @@ -674,6 +885,8 @@ { GtkWebViewButtons buttons; + g_return_if_fail(webview != NULL); + if (flags & PURPLE_CONNECTION_HTML) { gboolean bold, italic, underline, strike; @@ -750,6 +963,8 @@ pidgin_webview_set_spellcheck(GtkWebView *webview, gboolean enable) { WebKitWebSettings *settings; + + g_return_if_fail(webview != NULL); settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webview)); g_object_set(G_OBJECT(settings), "enable-spell-checking", enable, NULL); @@ -759,20 +974,76 @@ void gtk_webview_set_whole_buffer_formatting_only(GtkWebView *webview, gboolean wbfo) { - GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + GtkWebViewPriv *priv; + + g_return_if_fail(webview != NULL); + + priv = GTK_WEBVIEW_GET_PRIVATE(webview); priv->edit.wbfo = wbfo; } void gtk_webview_set_format_functions(GtkWebView *webview, GtkWebViewButtons buttons) { - GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); - GObject *object = g_object_ref(G_OBJECT(webview)); + GtkWebViewPriv *priv; + GObject *object; + + g_return_if_fail(webview != NULL); + + priv = GTK_WEBVIEW_GET_PRIVATE(webview); + object = g_object_ref(G_OBJECT(webview)); priv->format_functions = buttons; g_signal_emit(object, signals[BUTTONS_UPDATE], 0, buttons); g_object_unref(object); } +void +gtk_webview_activate_anchor(WebKitDOMHTMLAnchorElement *link) +{ + WebKitDOMDocument *doc; + WebKitDOMEvent *event; + + doc = webkit_dom_node_get_owner_document(WEBKIT_DOM_NODE(link)); + event = webkit_dom_document_create_event(doc, "MouseEvent", NULL); + webkit_dom_event_init_event(event, "click", TRUE, TRUE); + webkit_dom_node_dispatch_event(WEBKIT_DOM_NODE(link), event, NULL); +} + +gboolean +gtk_webview_class_register_protocol(const char *name, + gboolean (*activate)(GtkWebView *webview, const char *uri), + gboolean (*context_menu)(GtkWebView *webview, WebKitDOMHTMLAnchorElement *link, GtkWidget *menu)) +{ + GtkWebViewClass *klass; + GtkWebViewProtocol *proto; + + g_return_val_if_fail(name, FALSE); + + klass = g_type_class_ref(GTK_TYPE_WEBVIEW); + g_return_val_if_fail(klass, FALSE); + + if ((proto = webview_find_protocol(name, TRUE))) { + if (activate) { + return FALSE; + } + klass->protocols = g_list_remove(klass->protocols, proto); + g_free(proto->name); + g_free(proto); + return TRUE; + } else if (!activate) { + return FALSE; + } + + proto = g_new0(GtkWebViewProtocol, 1); + proto->name = g_strdup(name); + proto->length = strlen(name); + proto->activate = activate; + proto->context_menu = context_menu; + klass->protocols = g_list_prepend(klass->protocols, proto); + + return TRUE; +} + gchar * gtk_webview_get_head_html(GtkWebView *webview) { @@ -780,6 +1051,8 @@ WebKitDOMHTMLHeadElement *head; gchar *html; + g_return_val_if_fail(webview != NULL, NULL); + doc = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); head = webkit_dom_document_get_head(doc); html = webkit_dom_html_element_get_inner_html(WEBKIT_DOM_HTML_ELEMENT(head)); @@ -794,6 +1067,8 @@ WebKitDOMHTMLElement *body; gchar *html; + g_return_val_if_fail(webview != NULL, NULL); + doc = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); body = webkit_dom_document_get_body(doc); html = webkit_dom_html_element_get_inner_html(body); @@ -808,6 +1083,8 @@ WebKitDOMHTMLElement *body; gchar *text; + g_return_val_if_fail(webview != NULL, NULL); + doc = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); body = webkit_dom_document_get_body(doc); text = webkit_dom_html_element_get_inner_text(body); @@ -823,6 +1100,8 @@ WebKitDOMDOMSelection *sel; WebKitDOMRange *range; + g_return_val_if_fail(webview != NULL, NULL); + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); win = webkit_dom_document_get_default_view(dom); sel = webkit_dom_dom_window_get_selection(win); @@ -834,7 +1113,11 @@ GtkWebViewButtons gtk_webview_get_format_functions(GtkWebView *webview) { - GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + GtkWebViewPriv *priv; + + g_return_val_if_fail(webview != NULL, 0); + + priv = GTK_WEBVIEW_GET_PRIVATE(webview); return priv->format_functions; } @@ -844,6 +1127,9 @@ gboolean *strike) { WebKitDOMDocument *dom; + + g_return_if_fail(webview != NULL); + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); if (bold) @@ -860,6 +1146,9 @@ gtk_webview_get_current_fontface(GtkWebView *webview) { WebKitDOMDocument *dom; + + g_return_val_if_fail(webview != NULL, NULL); + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); return webkit_dom_document_query_command_value(dom, "fontName"); } @@ -868,6 +1157,9 @@ gtk_webview_get_current_forecolor(GtkWebView *webview) { WebKitDOMDocument *dom; + + g_return_val_if_fail(webview != NULL, NULL); + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); return webkit_dom_document_query_command_value(dom, "foreColor"); } @@ -876,6 +1168,9 @@ gtk_webview_get_current_backcolor(GtkWebView *webview) { WebKitDOMDocument *dom; + + g_return_val_if_fail(webview != NULL, NULL); + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); return webkit_dom_document_query_command_value(dom, "backColor"); } @@ -887,6 +1182,8 @@ gchar *text; gint size; + g_return_val_if_fail(webview != NULL, 0); + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); text = webkit_dom_document_query_command_value(dom, "fontSize"); size = atoi(text); @@ -906,6 +1203,8 @@ { GObject *object; + g_return_if_fail(webview != NULL); + object = g_object_ref(G_OBJECT(webview)); g_signal_emit(object, signals[CLEAR_FORMAT], 0); g_object_unref(object); @@ -914,30 +1213,36 @@ void gtk_webview_toggle_bold(GtkWebView *webview) { + g_return_if_fail(webview != NULL); emit_format_signal(webview, GTK_WEBVIEW_BOLD); } void gtk_webview_toggle_italic(GtkWebView *webview) { + g_return_if_fail(webview != NULL); emit_format_signal(webview, GTK_WEBVIEW_ITALIC); } void gtk_webview_toggle_underline(GtkWebView *webview) { + g_return_if_fail(webview != NULL); emit_format_signal(webview, GTK_WEBVIEW_UNDERLINE); } void gtk_webview_toggle_strike(GtkWebView *webview) { + g_return_if_fail(webview != NULL); emit_format_signal(webview, GTK_WEBVIEW_STRIKE); } gboolean gtk_webview_toggle_forecolor(GtkWebView *webview, const char *color) { + g_return_val_if_fail(webview != NULL, FALSE); + do_formatting(webview, "foreColor", color); emit_format_signal(webview, GTK_WEBVIEW_FORECOLOR); @@ -947,6 +1252,8 @@ gboolean gtk_webview_toggle_backcolor(GtkWebView *webview, const char *color) { + g_return_val_if_fail(webview != NULL, FALSE); + do_formatting(webview, "backColor", color); emit_format_signal(webview, GTK_WEBVIEW_BACKCOLOR); @@ -956,6 +1263,8 @@ gboolean gtk_webview_toggle_fontface(GtkWebView *webview, const char *face) { + g_return_val_if_fail(webview != NULL, FALSE); + do_formatting(webview, "fontName", face); emit_format_signal(webview, GTK_WEBVIEW_FACE); @@ -965,7 +1274,11 @@ void gtk_webview_font_set_size(GtkWebView *webview, gint size) { - char *tmp = g_strdup_printf("%d", size); + char *tmp; + + g_return_if_fail(webview != NULL); + + tmp = g_strdup_printf("%d", size); do_formatting(webview, "fontSize", tmp); emit_format_signal(webview, GTK_WEBVIEW_SHRINK|GTK_WEBVIEW_GROW); g_free(tmp); @@ -974,21 +1287,26 @@ void gtk_webview_font_shrink(GtkWebView *webview) { + g_return_if_fail(webview != NULL); emit_format_signal(webview, GTK_WEBVIEW_SHRINK); } void gtk_webview_font_grow(GtkWebView *webview) { + g_return_if_fail(webview != NULL); emit_format_signal(webview, GTK_WEBVIEW_GROW); } void gtk_webview_insert_hr(GtkWebView *webview) { - GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + GtkWebViewPriv *priv; WebKitDOMDocument *dom; + g_return_if_fail(webview != NULL); + + priv = GTK_WEBVIEW_GET_PRIVATE(webview); dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); priv->edit.block_changed = TRUE; @@ -999,10 +1317,13 @@ void gtk_webview_insert_link(GtkWebView *webview, const char *url, const char *desc) { - GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + GtkWebViewPriv *priv; WebKitDOMDocument *dom; char *link; + g_return_if_fail(webview != NULL); + + priv = GTK_WEBVIEW_GET_PRIVATE(webview); dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); link = g_strdup_printf("<a href='%s'>%s</a>", url, desc ? desc : url); @@ -1015,10 +1336,13 @@ void gtk_webview_insert_image(GtkWebView *webview, int id) { - GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + GtkWebViewPriv *priv; WebKitDOMDocument *dom; char *img; + g_return_if_fail(webview != NULL); + + priv = GTK_WEBVIEW_GET_PRIVATE(webview); dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); img = g_strdup_printf("<img src='" PURPLE_STORED_IMAGE_PROTOCOL "%d'/>", id);
--- a/pidgin/gtkwebview.h Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkwebview.h Mon Aug 06 18:11:44 2012 +0200 @@ -70,6 +70,8 @@ { WebKitWebViewClass parent; + GList *protocols; + void (*buttons_update)(GtkWebView *, GtkWebViewButtons); void (*toggle_format)(GtkWebView *, GtkWebViewButtons); void (*clear_format)(GtkWebView *); @@ -94,17 +96,6 @@ GtkWidget *gtk_webview_new(void); /** - * TODO WEBKIT: Right now this just tests whether an append has been called - * since the last clear or since the Widget was created. So it does not - * test for load_string's called in between. - * - * @param webview The GtkWebView object - * - * @return gboolean indicating whether the webview is empty - */ -gboolean gtk_webview_is_empty(GtkWebView *webview); - -/** * A very basic routine to append html, which can be considered * equivalent to a "document.write" using JavaScript. * @@ -229,6 +220,36 @@ GtkWebViewButtons buttons); /** + * Activates a WebKitDOMHTMLAnchorElement object. This triggers the navigation + * signals, and marks the link as visited (when possible). + * + * @param link The WebKitDOMHTMLAnchorElement object + * + */ +void gtk_webview_activate_anchor(WebKitDOMHTMLAnchorElement *link); + +/** + * Register a protocol with the GtkWebView widget. Registering a protocol would + * allow certain text to be clickable. + * + * @param name The name of the protocol (e.g. http://) + * @param activate The callback to trigger when the protocol text is clicked. + * Removes any current protocol definition if @c NULL. The + * callback should return @c TRUE if the link was activated + * properly, @c FALSE otherwise. + * @param context_menu The callback to trigger when the context menu is popped + * up on the protocol text. The callback should return + * @c TRUE if the request for context menu was processed + * successfully, @c FALSE otherwise. + * + * @return @c TRUE if the protocol was successfully registered + * (or unregistered, when \a activate is @c NULL) + */ +gboolean gtk_webview_class_register_protocol(const char *name, + gboolean (*activate)(GtkWebView *webview, const char *uri), + gboolean (*context_menu)(GtkWebView *webview, WebKitDOMHTMLAnchorElement *link, GtkWidget *menu)); + +/** * Returns which formatting functions are enabled in a GtkWebView. * * @param webview The GtkWebView
--- a/pidgin/gtkwebviewtoolbar.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkwebviewtoolbar.c Mon Aug 06 18:11:44 2012 +0200 @@ -184,11 +184,15 @@ GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); GtkFontSelection *sel; - sel = GTK_FONT_SELECTION(GTK_FONT_SELECTION_DIALOG(priv->font_dialog)->fontsel); - gtk_widget_hide_all(gtk_widget_get_parent(sel->size_entry)); - gtk_widget_show_all(sel->family_list); - gtk_widget_show(gtk_widget_get_parent(sel->family_list)); - gtk_widget_show(gtk_widget_get_parent(gtk_widget_get_parent(sel->family_list))); + sel = GTK_FONT_SELECTION( + gtk_font_selection_dialog_get_font_selection(GTK_FONT_SELECTION_DIALOG(priv->font_dialog))); + gtk_widget_hide(gtk_widget_get_parent( + gtk_font_selection_get_size_entry(sel))); + gtk_widget_show_all(gtk_font_selection_get_family_list(sel)); + gtk_widget_show(gtk_widget_get_parent( + gtk_font_selection_get_family_list(sel))); + gtk_widget_show(gtk_widget_get_parent(gtk_widget_get_parent( + gtk_font_selection_get_family_list(sel)))); } static void @@ -248,10 +252,12 @@ g_signal_connect(G_OBJECT(priv->font_dialog), "delete_event", G_CALLBACK(destroy_toolbar_font), toolbar); - g_signal_connect(G_OBJECT(GTK_FONT_SELECTION_DIALOG(priv->font_dialog)->ok_button), "clicked", - G_CALLBACK(apply_font), toolbar); - g_signal_connect(G_OBJECT(GTK_FONT_SELECTION_DIALOG(priv->font_dialog)->cancel_button), "clicked", - G_CALLBACK(cancel_toolbar_font), toolbar); + g_signal_connect(G_OBJECT( + gtk_font_selection_dialog_get_ok_button(GTK_FONT_SELECTION_DIALOG(priv->font_dialog))), + "clicked", G_CALLBACK(apply_font), toolbar); + g_signal_connect(G_OBJECT( + gtk_font_selection_dialog_get_cancel_button(GTK_FONT_SELECTION_DIALOG(priv->font_dialog))), + "clicked", G_CALLBACK(cancel_toolbar_font), toolbar); g_signal_connect_after(G_OBJECT(priv->font_dialog), "realize", G_CALLBACK(realize_toolbar_font), toolbar); } @@ -300,7 +306,7 @@ char *open_tag; dialog = GTK_COLOR_SELECTION_DIALOG(priv->fgcolor_dialog); - colorsel = GTK_COLOR_SELECTION(dialog->colorsel); + colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(dialog)); open_tag = g_malloc(30); gtk_color_selection_get_current_color(colorsel, &text_color); @@ -325,18 +331,24 @@ char *color = gtk_webview_get_current_forecolor(GTK_WEBVIEW(toolbar->webview)); if (!priv->fgcolor_dialog) { + GtkWidget *ok_button; + GtkWidget *cancel_button; + priv->fgcolor_dialog = gtk_color_selection_dialog_new(_("Select Text Color")); - colorsel = GTK_COLOR_SELECTION_DIALOG(priv->fgcolor_dialog)->colorsel; + colorsel = + gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(priv->fgcolor_dialog)); if (color) { gdk_color_parse(color, &fgcolor); gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(colorsel), &fgcolor); } + g_object_get(G_OBJECT(priv->fgcolor_dialog), "ok-button", &ok_button, NULL); + g_object_get(G_OBJECT(priv->fgcolor_dialog), "cancel-button", &cancel_button, NULL); g_signal_connect(G_OBJECT(priv->fgcolor_dialog), "delete_event", G_CALLBACK(destroy_toolbar_fgcolor), toolbar); - g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(priv->fgcolor_dialog)->ok_button), "clicked", + g_signal_connect(G_OBJECT(ok_button), "clicked", G_CALLBACK(do_fgcolor), toolbar); - g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(priv->fgcolor_dialog)->cancel_button), "clicked", + g_signal_connect(G_OBJECT(cancel_button), "clicked", G_CALLBACK(cancel_toolbar_fgcolor), toolbar); } @@ -384,7 +396,7 @@ char *open_tag; dialog = GTK_COLOR_SELECTION_DIALOG(priv->bgcolor_dialog); - colorsel = GTK_COLOR_SELECTION(dialog->colorsel); + colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(dialog)); open_tag = g_malloc(30); gtk_color_selection_get_current_color(colorsel, &text_color); @@ -409,18 +421,26 @@ char *color = gtk_webview_get_current_backcolor(GTK_WEBVIEW(toolbar->webview)); if (!priv->bgcolor_dialog) { + GtkWidget *ok_button; + GtkWidget *cancel_button; + priv->bgcolor_dialog = gtk_color_selection_dialog_new(_("Select Background Color")); - colorsel = GTK_COLOR_SELECTION_DIALOG(priv->bgcolor_dialog)->colorsel; + colorsel = + gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(priv->bgcolor_dialog)); + if (color) { gdk_color_parse(color, &bgcolor); gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(colorsel), &bgcolor); } + g_object_get(G_OBJECT(priv->bgcolor_dialog), "ok-button", &ok_button, NULL); + g_object_get(G_OBJECT(priv->bgcolor_dialog), "cancel-button", + &cancel_button, NULL); g_signal_connect(G_OBJECT(priv->bgcolor_dialog), "delete_event", G_CALLBACK(destroy_toolbar_bgcolor), toolbar); - g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(priv->bgcolor_dialog)->ok_button), "clicked", + g_signal_connect(G_OBJECT(ok_button), "clicked", G_CALLBACK(do_bgcolor), toolbar); - g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(priv->bgcolor_dialog)->cancel_button), "clicked", + g_signal_connect(G_OBJECT(cancel_button), "clicked", G_CALLBACK(cancel_toolbar_bgcolor), toolbar); } @@ -775,7 +795,7 @@ smiley_dialog_input_cb(GtkWidget *dialog, GdkEvent *event, GtkWebViewToolbar *toolbar) { - if ((event->type == GDK_KEY_PRESS && event->key.keyval == GDK_Escape) || + if ((event->type == GDK_KEY_PRESS && event->key.keyval == GDK_KEY_Escape) || (event->type == GDK_BUTTON_PRESS && event->button.button == 1)) { close_smiley_dialog(toolbar); @@ -1145,19 +1165,21 @@ { GtkWidget *widget = GTK_WIDGET(data); GtkRequisition menu_req; - gint ythickness = widget->style->ythickness; + GtkAllocation allocation; + gint ythickness = gtk_widget_get_style(widget)->ythickness; int savy; + gtk_widget_get_allocation(widget, &allocation); gtk_widget_size_request(GTK_WIDGET(menu), &menu_req); - gdk_window_get_origin(widget->window, x, y); - *x += widget->allocation.x; - *y += widget->allocation.y + widget->allocation.height; + gdk_window_get_origin(gtk_widget_get_window(widget), x, y); + *x += allocation.x; + *y += allocation.y + allocation.height; savy = *y; pidgin_menu_position_func_helper(menu, x, y, push_in, data); if (savy > *y + ythickness + 1) - *y -= widget->allocation.height; + *y -= allocation.height; } static void @@ -1223,10 +1245,10 @@ { GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); if (value) { - gtk_widget_hide_all(priv->lean_view); + gtk_widget_hide(priv->lean_view); gtk_widget_show_all(priv->wide_view); } else { - gtk_widget_hide_all(priv->wide_view); + gtk_widget_hide(priv->wide_view); gtk_widget_show_all(priv->lean_view); } } @@ -1446,8 +1468,8 @@ g_signal_connect(G_OBJECT(font_button), "toggled", G_CALLBACK(pidgin_menu_clicked), font_menu); - g_signal_connect(G_OBJECT(font_menu), "deactivate", - G_CALLBACK(pidgin_menu_deactivate), font_button); + g_signal_connect_object(G_OBJECT(font_menu), "deactivate", + G_CALLBACK(pidgin_menu_deactivate), font_button, 0); gtk_container_foreach(GTK_CONTAINER(font_menu), enable_markup, NULL); @@ -1472,8 +1494,8 @@ g_signal_connect(G_OBJECT(insert_button), "toggled", G_CALLBACK(pidgin_menu_clicked), insert_menu); - g_signal_connect(G_OBJECT(insert_menu), "deactivate", - G_CALLBACK(pidgin_menu_deactivate), insert_button); + g_signal_connect_object(G_OBJECT(insert_menu), "deactivate", + G_CALLBACK(pidgin_menu_deactivate), insert_button, 0); /* Sep */ sep = gtk_separator_tool_item_new();
--- a/pidgin/gtkwhiteboard.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkwhiteboard.c Mon Aug 06 18:11:44 2012 +0200 @@ -28,6 +28,16 @@ #include "gtkwhiteboard.h" #include "gtkutils.h" +#if GTK_CHECK_VERSION(3,0,0) +#define GdkPixType GdkPixbuf +#else +#define GdkPixType GdkPixmap +#endif +struct _PidginWhiteboardPrivate { + GdkPixType *pix; + cairo_t *cr; +}; + /****************************************************************************** * Prototypes *****************************************************************************/ @@ -123,6 +133,7 @@ GtkWidget *color_button; PidginWhiteboard *gtkwb = g_new0(PidginWhiteboard, 1); + gtkwb->priv = g_new0(PidginWhiteboardPrivate, 1); gtkwb->wb = wb; purple_whiteboard_set_ui_data(wb, gtkwb); @@ -280,13 +291,11 @@ /* TODO Ask if user wants to save picture before the session is closed */ /* Clear graphical memory */ - if(gtkwb->pixmap) - { - cairo_t *cr = g_object_get_data(G_OBJECT(gtkwb->pixmap), "cairo-context"); + if (gtkwb->priv->pix) { + cairo_t *cr = gtkwb->priv->cr; if (cr) cairo_destroy(cr); - g_object_unref(gtkwb->pixmap); - gtkwb->pixmap = NULL; + g_object_unref(gtkwb->priv->pix); } colour_dialog = g_object_get_data(G_OBJECT(gtkwb->window), "colour-dialog"); @@ -300,6 +309,8 @@ gtk_widget_destroy(gtkwb->window); gtkwb->window = NULL; } + + g_free(gtkwb->priv); g_free(gtkwb); purple_whiteboard_set_ui_data(wb, NULL); } @@ -356,28 +367,43 @@ static gboolean pidgin_whiteboard_configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data) { PidginWhiteboard *gtkwb = (PidginWhiteboard*)data; - GdkPixmap *pixmap = gtkwb->pixmap; + GdkPixType *pix = gtkwb->priv->pix; cairo_t *cr; + GdkWindow *window = gtk_widget_get_window(widget); + GtkAllocation allocation; - if (pixmap) { - cr = g_object_get_data(G_OBJECT(pixmap), "cairo-context"); + if (pix) { + cr = gtkwb->priv->cr; if (cr) cairo_destroy(cr); - g_object_unref(pixmap); + g_object_unref(pix); } - pixmap = gdk_pixmap_new(widget->window, - widget->allocation.width, - widget->allocation.height, - -1); - gtkwb->pixmap = pixmap; + gtk_widget_get_allocation(widget, &allocation); - cr = gdk_cairo_create(GDK_DRAWABLE(pixmap)); - g_object_set_data(G_OBJECT(pixmap), "cairo-context", cr); - gdk_cairo_set_source_color(cr, &widget->style->white); +#if GTK_CHECK_VERSION(3,0,0) + pix = gdk_pixbuf_new(GDK_COLORSPACE_RGB, + FALSE, gdk_visual_get_depth(GDK_VISUAL(window)), + allocation.width, allocation.height); +#else + pix = gdk_pixmap_new(window, + allocation.width, + allocation.height, + -1); +#endif + + gtkwb->priv->pix = pix; + +#if GTK_CHECK_VERSION(3,0,0) + cr = gdk_cairo_create(window); +#else + cr = gdk_cairo_create(GDK_DRAWABLE(pix)); +#endif + gtkwb->priv->cr = cr; + gdk_cairo_set_source_color(cr, >k_widget_get_style(widget)->white); cairo_rectangle(cr, 0, 0, - widget->allocation.width, widget->allocation.height); + allocation.width, allocation.height); cairo_fill(cr); return TRUE; @@ -386,11 +412,16 @@ static gboolean pidgin_whiteboard_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) { PidginWhiteboard *gtkwb = (PidginWhiteboard*)(data); - GdkPixmap *pixmap = gtkwb->pixmap; + GdkPixType *pix = gtkwb->priv->pix; cairo_t *cr; +#if GTK_CHECK_VERSION(3,0,0) + cr = gdk_cairo_create(gtk_widget_get_window(widget)); + gdk_cairo_set_source_pixbuf(cr, pix, 0, 0); +#else cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); - gdk_cairo_set_source_pixmap(cr, pixmap, 0, 0); + gdk_cairo_set_source_pixmap(cr, pix, 0, 0); +#endif cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event->area.height); @@ -403,7 +434,6 @@ static gboolean pidgin_whiteboard_brush_down(GtkWidget *widget, GdkEventButton *event, gpointer data) { PidginWhiteboard *gtkwb = (PidginWhiteboard*)data; - GdkPixmap *pixmap = gtkwb->pixmap; PurpleWhiteboard *wb = gtkwb->wb; GList *draw_list = purple_whiteboard_get_draw_list(wb); @@ -418,7 +448,7 @@ BrushState = BRUSH_STATE_DOWN; - if(event->button == 1 && pixmap != NULL) + if(event->button == 1 && gtkwb->priv->pix != NULL) { /* Check if draw_list has contents; if so, clear it */ if(draw_list) @@ -456,7 +486,6 @@ GdkModifierType state; PidginWhiteboard *gtkwb = (PidginWhiteboard*)data; - GdkPixmap *pixmap = gtkwb->pixmap; PurpleWhiteboard *wb = gtkwb->wb; GList *draw_list = purple_whiteboard_get_draw_list(wb); @@ -470,7 +499,7 @@ state = event->state; } - if(state & GDK_BUTTON1_MASK && pixmap != NULL) + if(state & GDK_BUTTON1_MASK && gtkwb->priv->pix != NULL) { if((BrushState != BRUSH_STATE_DOWN) && (BrushState != BRUSH_STATE_MOTION)) { @@ -536,7 +565,6 @@ static gboolean pidgin_whiteboard_brush_up(GtkWidget *widget, GdkEventButton *event, gpointer data) { PidginWhiteboard *gtkwb = (PidginWhiteboard*)data; - GdkPixmap *pixmap = gtkwb->pixmap; PurpleWhiteboard *wb = gtkwb->wb; GList *draw_list = purple_whiteboard_get_draw_list(wb); @@ -551,7 +579,7 @@ } BrushState = BRUSH_STATE_UP; - if(event->button == 1 && pixmap != NULL) + if(event->button == 1 && gtkwb->priv->pix != NULL) { /* If the brush was never moved, express two sets of two deltas That's a * 'point,' but not for Yahoo! @@ -593,9 +621,7 @@ { PidginWhiteboard *gtkwb = purple_whiteboard_get_ui_data(wb); GtkWidget *widget = gtkwb->drawing_area; - GdkPixmap *pixmap = gtkwb->pixmap; - - cairo_t *gfx_con = g_object_get_data(G_OBJECT(pixmap), "cairo-context"); + cairo_t *gfx_con = gtkwb->priv->cr; GdkColor col; /* Interpret and convert color */ @@ -701,21 +727,23 @@ static void pidgin_whiteboard_clear(PurpleWhiteboard *wb) { PidginWhiteboard *gtkwb = purple_whiteboard_get_ui_data(wb); - GdkPixmap *pixmap = gtkwb->pixmap; GtkWidget *drawing_area = gtkwb->drawing_area; - cairo_t *cr = g_object_get_data(G_OBJECT(pixmap), "cairo-context"); + cairo_t *cr = gtkwb->priv->cr; + GtkAllocation allocation; - gdk_cairo_set_source_color(cr, &drawing_area->style->white); + gtk_widget_get_allocation(drawing_area, &allocation); + + gdk_cairo_set_source_color(cr, >k_widget_get_style(drawing_area)->white); cairo_rectangle(cr, 0, 0, - drawing_area->allocation.width, - drawing_area->allocation.height); + allocation.width, + allocation.height); cairo_fill(cr); gtk_widget_queue_draw_area(drawing_area, - 0, 0, - drawing_area->allocation.width, - drawing_area->allocation.height); + 0, 0, + allocation.width, + allocation.height); } static void pidgin_whiteboard_button_clear_press(GtkWidget *widget, gpointer data) @@ -781,12 +809,16 @@ gtk_widget_destroy(dialog); /* Makes an icon from the whiteboard's canvas 'image' */ +#if GTK_CHECK_VERSION(3,0,0) + pixbuf = gtkwb->priv->pix; +#else pixbuf = gdk_pixbuf_get_from_drawable(NULL, - (GdkDrawable*)(gtkwb->pixmap), - gdk_drawable_get_colormap(gtkwb->pixmap), - 0, 0, - 0, 0, - gtkwb->width, gtkwb->height); + (GdkDrawable*)(gtkwb->priv->pix), + gdk_drawable_get_colormap(gtkwb->priv->pix), + 0, 0, + 0, 0, + gtkwb->width, gtkwb->height); +#endif if(gdk_pixbuf_save(pixbuf, filename, "jpeg", NULL, "quality", "100", NULL)) purple_debug_info("gtkwhiteboard", "File Saved...\n"); @@ -807,12 +839,16 @@ GdkPixbuf *pixbuf; /* Makes an icon from the whiteboard's canvas 'image' */ +#if GTK_CHECK_VERSION(3,0,0) + pixbuf = gtkwb->priv->pix; +#else pixbuf = gdk_pixbuf_get_from_drawable(NULL, - (GdkDrawable*)(gtkwb->pixmap), - gdk_drawable_get_colormap(gtkwb->pixmap), - 0, 0, - 0, 0, - gtkwb->width, gtkwb->height); + (GdkDrawable*)(gtkwb->priv->pix), + gdk_drawable_get_colormap(gtkwb->priv->pix), + 0, 0, + 0, 0, + gtkwb->width, gtkwb->height); +#endif gtk_window_set_icon((GtkWindow*)(gtkwb->window), pixbuf); } @@ -853,23 +889,24 @@ { GdkColor color; GtkColorSelectionDialog *dialog; + GtkWidget *ok_button; dialog = (GtkColorSelectionDialog *)gtk_color_selection_dialog_new(_("Select color")); g_object_set_data(G_OBJECT(gtkwb->window), "colour-dialog", dialog); - g_signal_connect(G_OBJECT(dialog->colorsel), "color-changed", - G_CALLBACK(change_color_cb), gtkwb); + g_signal_connect(G_OBJECT(gtk_color_selection_dialog_get_color_selection(dialog)), + "color-changed", G_CALLBACK(change_color_cb), gtkwb); + + g_object_get(G_OBJECT(dialog), "ok-button", &ok_button, NULL); - gtk_widget_destroy(dialog->cancel_button); - gtk_widget_destroy(dialog->help_button); + g_signal_connect(G_OBJECT(ok_button), "clicked", + G_CALLBACK(color_selection_dialog_destroy), gtkwb); - g_signal_connect(G_OBJECT(dialog->ok_button), "clicked", - G_CALLBACK(color_selection_dialog_destroy), gtkwb); - - gtk_color_selection_set_has_palette(GTK_COLOR_SELECTION(dialog->colorsel), TRUE); + gtk_color_selection_set_has_palette(GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(dialog)), TRUE); pidgin_whiteboard_rgb24_to_rgb48(gtkwb->brush_color, &color); - gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(dialog->colorsel), &color); + gtk_color_selection_set_current_color( + GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(dialog)), &color); gtk_widget_show_all(GTK_WIDGET(dialog)); }
--- a/pidgin/gtkwhiteboard.h Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/gtkwhiteboard.h Mon Aug 06 18:11:44 2012 +0200 @@ -42,21 +42,26 @@ #define PALETTE_NUM_COLORS 7 /** + * A PidginWhiteboard's private data + */ +typedef struct _PidginWhiteboardPrivate PidginWhiteboardPrivate; + +/** * A PidginWhiteboard */ typedef struct _PidginWhiteboard { - PurpleWhiteboard *wb; /**< backend data for this whiteboard */ + PidginWhiteboardPrivate *priv; /**< Internal data */ - GtkWidget *window; /**< Window for the Doodle session */ - GtkWidget *drawing_area; /**< Drawing area */ + PurpleWhiteboard *wb; /**< Backend data for this whiteboard */ - GdkPixmap *pixmap; /**< Memory for drawing area */ + GtkWidget *window; /**< Window for the Doodle session */ + GtkWidget *drawing_area; /**< Drawing area */ - int width; /**< Canvas width */ - int height; /**< Canvas height */ - int brush_color; /**< Foreground color */ - int brush_size; /**< Brush size */ + int width; /**< Canvas width */ + int height; /**< Canvas height */ + int brush_color; /**< Foreground color */ + int brush_size; /**< Brush size */ } PidginWhiteboard; G_BEGIN_DECLS
--- a/pidgin/minidialog.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/minidialog.c Mon Aug 06 18:11:44 2012 +0200 @@ -184,7 +184,12 @@ guint pidgin_mini_dialog_get_num_children(PidginMiniDialog *mini_dialog) { - return g_list_length(mini_dialog->contents->children); + GList *tmp; + guint len; + tmp = gtk_container_get_children(GTK_CONTAINER(mini_dialog->contents)); + len = g_list_length(tmp); + g_list_free(tmp); + return len; } static gboolean
--- a/pidgin/pidginstock.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/pidginstock.c Mon Aug 06 18:11:44 2012 +0200 @@ -95,7 +95,7 @@ typedef struct { const char *name; - const char *dir; + const char *dir; const char *filename; gboolean microscopic; gboolean extra_small;
--- a/pidgin/pidgintooltip.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/pidgintooltip.c Mon Aug 06 18:11:44 2012 +0200 @@ -100,16 +100,37 @@ } } +#if GTK_CHECK_VERSION(3,0,0) +static gboolean +pidgin_tooltip_draw_cb(GtkWidget *widget, cairo_t *cr, gpointer data) +{ + GtkAllocation allocation; + + gtk_widget_get_allocation(widget, &allocation); + + if (pidgin_tooltip.paint_tooltip) { + gtk_paint_flat_box(gtk_widget_get_style(widget), cr, + GTK_STATE_NORMAL, GTK_SHADOW_OUT, + widget, "tooltip", + 0, 0, allocation.width, allocation.height); + pidgin_tooltip.paint_tooltip(widget, cr, data); + } + return FALSE; +} +#else static gboolean pidgin_tooltip_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) { if (pidgin_tooltip.paint_tooltip) { + cairo_t *cr = gdk_cairo_create(GDK_DRAWABLE(gtk_widget_get_window(widget))); gtk_paint_flat_box(widget->style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT, - NULL, widget, "tooltip", 0, 0, -1, -1); - pidgin_tooltip.paint_tooltip(widget, data); + NULL, widget, "tooltip", 0, 0, -1, -1); + pidgin_tooltip.paint_tooltip(widget, cr, data); + cairo_destroy(cr); } return FALSE; } +#endif static GtkWidget* setup_tooltip_window(void) @@ -189,8 +210,13 @@ gtk_window_move(GTK_WINDOW(tipwindow), x, y); gtk_widget_show(tipwindow); +#if GTK_CHECK_VERSION(3,0,0) + g_signal_connect(G_OBJECT(tipwindow), "draw", + G_CALLBACK(pidgin_tooltip_draw_cb), data); +#else g_signal_connect(G_OBJECT(tipwindow), "expose_event", G_CALLBACK(pidgin_tooltip_expose_event), data); +#endif /* Hide the tooltip when the widget is destroyed */ sig = g_signal_connect(G_OBJECT(pidgin_tooltip.widget), "destroy", G_CALLBACK(pidgin_tooltip_destroy), NULL);
--- a/pidgin/pidgintooltip.h Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/pidgintooltip.h Mon Aug 06 18:11:44 2012 +0200 @@ -53,11 +53,13 @@ /** * @param tipwindow The window for the tooltip. + * @param cr The cairo context for drawing. * @param userdata The userdata set during pidgin_tooltip_setup_for_treeview or pidgin_tooltip_show. * * @return @c TRUE if the tooltip was painted correctly, @c FALSE otherwise. */ -typedef gboolean (*PidginTooltipPaint)(GtkWidget *tipwindow, gpointer userdata); +typedef gboolean (*PidginTooltipPaint)(GtkWidget *tipwindow, cairo_t *cr, + gpointer userdata); G_BEGIN_DECLS
--- a/pidgin/plugins/contact_priority.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/plugins/contact_priority.c Mon Aug 06 18:11:44 2012 +0200 @@ -75,7 +75,7 @@ GtkWidget *ret = NULL, *hbox = NULL, *frame = NULL, *vbox = NULL; GtkWidget *label = NULL, *spin = NULL, *check = NULL; GtkWidget *optmenu = NULL; - GtkObject *adj = NULL; + GtkAdjustment *adj = NULL; GtkSizeGroup *sg = NULL; PurpleAccount *account = NULL; int i; @@ -105,8 +105,9 @@ gtk_size_group_add_widget(sg, label); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); - adj = gtk_adjustment_new(purple_prefs_get_int(pref), -500, 500, 1, 1, 1); - spin = gtk_spin_button_new((GtkAdjustment *)adj, 1, 0); + adj = GTK_ADJUSTMENT(gtk_adjustment_new(purple_prefs_get_int(pref), + -500, 500, 1, 1, 1)); + spin = gtk_spin_button_new(adj, 1, 0); g_signal_connect(G_OBJECT(spin), "value-changed", G_CALLBACK(pref_update), pref); gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 0); @@ -138,8 +139,8 @@ /* make this here so I can use it in the option menu callback, we'll * actually set it up later */ - adj = gtk_adjustment_new(0, -500, 500, 1, 1, 1); - spin = gtk_spin_button_new((GtkAdjustment *)adj, 1, 0); + adj = GTK_ADJUSTMENT(gtk_adjustment_new(0, -500, 500, 1, 1, 1)); + spin = gtk_spin_button_new(adj, 1, 0); optmenu = pidgin_account_option_menu_new(NULL, TRUE, G_CALLBACK(select_account),
--- a/pidgin/plugins/convcolors.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/plugins/convcolors.c Mon Aug 06 18:11:44 2012 +0200 @@ -302,7 +302,7 @@ } static void -disconnect_prefs_callbacks(GtkObject *object, gpointer data) +disconnect_prefs_callbacks(GtkAdjustment *object, gpointer data) { PurplePlugin *plugin = (PurplePlugin *)data; @@ -383,7 +383,7 @@ purple_prefs_connect_callback(plugin, tmp2, enable_toggled, button); } - g_signal_connect(GTK_OBJECT(ret), "destroy", G_CALLBACK(disconnect_prefs_callbacks), plugin); + g_signal_connect(G_OBJECT(ret), "destroy", G_CALLBACK(disconnect_prefs_callbacks), plugin); frame = pidgin_make_frame(ret, _("General")); pidgin_prefs_checkbox(_("Ignore incoming format"), PREF_IGNORE, frame); pidgin_prefs_checkbox(_("Apply in Chats"), PREF_CHATS, frame);
--- a/pidgin/plugins/disco/gtkdisco.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/plugins/disco/gtkdisco.c Mon Aug 06 18:11:44 2012 +0200 @@ -427,18 +427,22 @@ } static gboolean -disco_paint_tooltip(GtkWidget *tipwindow, gpointer data) +disco_paint_tooltip(GtkWidget *tipwindow, cairo_t *cr, gpointer data) { PangoLayout *layout = g_object_get_data(G_OBJECT(tipwindow), "tooltip-plugin"); -#if GTK_CHECK_VERSION(2,14,0) +#if GTK_CHECK_VERSION(3,0,0) gtk_paint_layout(gtk_widget_get_style(tipwindow), - gtk_widget_get_window(tipwindow), - GTK_STATE_NORMAL, FALSE, + cr, + GTK_STATE_NORMAL, FALSE, + tipwindow, "tooltip", + 6, 6, layout); #else - gtk_paint_layout(tipwindow->style, tipwindow->window, GTK_STATE_NORMAL, FALSE, + gtk_paint_layout(gtk_widget_get_style(tipwindow), + gtk_widget_get_window(tipwindow), + GTK_STATE_NORMAL, FALSE, + NULL, tipwindow, "tooltip", + 6, 6, layout); #endif - NULL, tipwindow, "tooltip", - 6, 6, layout); return TRUE; }
--- a/pidgin/plugins/gestures/stroke-draw.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/plugins/gestures/stroke-draw.c Mon Aug 06 18:11:44 2012 +0200 @@ -19,9 +19,7 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> -#if !GTK_CHECK_VERSION(2,14,0) -#define gtk_widget_get_window(x) x->window -#endif +#include "gtk3compat.h" static void gstroke_invisible_window_init (GtkWidget *widget); /*FIXME: Maybe these should be put in a structure, and not static...*/ @@ -339,7 +337,7 @@ unsigned int border_width; XSizeHints hints; Display *disp = GDK_WINDOW_XDISPLAY(gtk_widget_get_window(widget)); - Window wind = GDK_WINDOW_XWINDOW (gtk_widget_get_window(widget)); + Window wind = gdk_x11_window_get_xid(gtk_widget_get_window(widget)); int screen = DefaultScreen (disp); if (!gstroke_draw_strokes())
--- a/pidgin/plugins/history.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/plugins/history.c Mon Aug 06 18:11:44 2012 +0200 @@ -136,8 +136,11 @@ purple_account_get_protocol_name(((PurpleLog*)logs->data)->account)); #endif +#if 0 + /* TODO WebKit: Do this properly... */ if (!gtk_webview_is_empty(GTK_WEBVIEW(gtkconv->webview))) gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "<BR>"); +#endif escaped_alias = g_markup_escape_text(alias, -1);
--- a/pidgin/plugins/themeedit.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/plugins/themeedit.c Mon Aug 06 18:11:44 2012 +0200 @@ -306,9 +306,6 @@ } } -#if !GTK_CHECK_VERSION(2,22,0) - gtk_dialog_set_has_separator(GTK_DIALOG(dialog), TRUE); -#endif #ifdef NOT_SADRUL pidgin_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_SAVE, G_CALLBACK(save_blist_theme), dialog); #endif
--- a/pidgin/plugins/ticker/gtkticker.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/plugins/ticker/gtkticker.c Mon Aug 06 18:11:44 2012 +0200 @@ -24,38 +24,24 @@ #include "gtkticker.h" #include <gtk/gtk.h> -#if !GTK_CHECK_VERSION(2,20,0) -#define gtk_widget_get_mapped(x) GTK_WIDGET_MAPPED(x) -#define gtk_widget_set_mapped(x,y) do {\ - if (y) \ - GTK_WIDGET_SET_FLAGS(x, GTK_MAPPED); \ - else \ - GTK_WIDGET_UNSET_FLAGS(x, GTK_MAPPED); \ -} while(0) -#define gtk_widget_get_realized(x) GTK_WIDGET_REALIZED(x) -#define gtk_widget_set_realized(x,y) do {\ - if (y) \ - GTK_WIDGET_SET_FLAGS(x, GTK_REALIZED); \ - else \ - GTK_WIDGET_UNSET_FLAGS(x, GTK_REALIZED); \ -} while(0) - -#if !GTK_CHECK_VERSION(2,18,0) -#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x) - -#if !GTK_CHECK_VERSION(2,14,0) -#define gtk_widget_get_window(x) x->window -#endif -#endif -#endif +#include "gtk3compat.h" static void gtk_ticker_compute_offsets (GtkTicker *ticker); static void gtk_ticker_class_init (GtkTickerClass *klass); static void gtk_ticker_init (GtkTicker *ticker); static void gtk_ticker_map (GtkWidget *widget); static void gtk_ticker_realize (GtkWidget *widget); +#if GTK_CHECK_VERSION(3,0,0) +static void gtk_ticker_get_preferred_width (GtkWidget *widget, + gint *minimal_width, + gint *natural_width); +static void gtk_ticker_get_preferred_height (GtkWidget *widget, + gint *minimal_height, + gint *natural_height); +#else static void gtk_ticker_size_request (GtkWidget *widget, GtkRequisition *requisition); +#endif static void gtk_ticker_size_allocate (GtkWidget *widget, GtkAllocation *allocation); static void gtk_ticker_add_real (GtkContainer *container, @@ -128,7 +114,12 @@ widget_class->map = gtk_ticker_map; widget_class->realize = gtk_ticker_realize; +#if GTK_CHECK_VERSION(3,0,0) + widget_class->get_preferred_width = gtk_ticker_get_preferred_width; + widget_class->get_preferred_height = gtk_ticker_get_preferred_height; +#else widget_class->size_request = gtk_ticker_size_request; +#endif widget_class->size_allocate = gtk_ticker_size_allocate; container_class->add = gtk_ticker_add_real; @@ -144,11 +135,7 @@ static void gtk_ticker_init (GtkTicker *ticker) { -#if GTK_CHECK_VERSION(2,18,0) gtk_widget_set_has_window (GTK_WIDGET (ticker), TRUE); -#else - GTK_WIDGET_UNSET_FLAGS (ticker, GTK_NO_WINDOW); -#endif ticker->interval = (guint) 200; ticker->scootch = (guint) 2; @@ -308,9 +295,7 @@ gint attributes_mask; GdkWindow *window; GtkStyle *style; -#if GTK_CHECK_VERSION(2,18,0) GtkAllocation allocation; -#endif g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_TICKER (widget)); @@ -318,45 +303,110 @@ gtk_widget_set_realized (widget, TRUE); attributes.window_type = GDK_WINDOW_CHILD; -#if GTK_CHECK_VERSION(2,18,0) gtk_widget_get_allocation (widget, &allocation); attributes.x = allocation.x; attributes.y = allocation.y; attributes.width = allocation.width; attributes.height = allocation.height; -#else - attributes.x = widget->allocation.x; - attributes.y = widget->allocation.y; - attributes.width = widget->allocation.width; - attributes.height = widget->allocation.height; -#endif attributes.wclass = GDK_INPUT_OUTPUT; attributes.visual = gtk_widget_get_visual (widget); +#if !GTK_CHECK_VERSION(3,0,0) attributes.colormap = gtk_widget_get_colormap (widget); +#endif attributes.event_mask = gtk_widget_get_events (widget); attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK; +#if GTK_CHECK_VERSION(3,0,0) + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; +#else attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; +#endif window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); -#if GTK_CHECK_VERSION(2,18,0) gtk_widget_set_window (widget, window); -#else - widget->window = window; -#endif gdk_window_set_user_data (window, widget); -#if GTK_CHECK_VERSION(2,14,0) - style = gtk_widget_get_style (widget); - style = gtk_style_attach (style, window); + style = gtk_style_attach (gtk_widget_get_style (widget), window); gtk_widget_set_style (widget, style); -#else - style = widget->style = gtk_style_attach (widget->style, window); -#endif gtk_style_set_background (style, window, GTK_STATE_NORMAL); } +#if GTK_CHECK_VERSION(3,0,0) +static void +gtk_ticker_get_preferred_width (GtkWidget *widget, + gint *minimal_width, + gint *natural_width) +{ + GtkTicker *ticker; + GtkTickerChild *child; + GList *children; + gint child_min_width, child_nat_width; + gint width; + guint border_width; + + ticker = GTK_TICKER (widget); + *minimal_width = width = 0; + + children = ticker->children; + while (children) + { + child = children->data; + children = children->next; + + if (gtk_widget_get_visible (child->widget)) + { + gtk_widget_get_preferred_width (child->widget, &child_min_width, &child_nat_width); + + width += child_nat_width + ticker->spacing; + *minimal_width = MAX(*minimal_width, child_min_width); + } + } + if ( width > ticker->spacing ) + width -= ticker->spacing; + + border_width = gtk_container_get_border_width (GTK_CONTAINER (ticker)); + width += border_width * 2; + + *natural_width = width; +} + +static void +gtk_ticker_get_preferred_height (GtkWidget *widget, + gint *minimal_height, + gint *natural_height) +{ + GtkTicker *ticker; + GtkTickerChild *child; + GList *children; + gint child_min_height, child_nat_height; + gint height; + guint border_width; + + ticker = GTK_TICKER (widget); + height = 0; + + children = ticker->children; + while (children) + { + child = children->data; + children = children->next; + + if (gtk_widget_get_visible (child->widget)) + { + gtk_widget_get_preferred_height (child->widget, &child_min_height, &child_nat_height); + + height = MAX (height, child_nat_height); + } + } + + border_width = gtk_container_get_border_width (GTK_CONTAINER (ticker)); + height += border_width * 2; + *minimal_height = *natural_height = height; +} + +#else + static void gtk_ticker_size_request (GtkWidget *widget, GtkRequisition *requisition) { GtkTicker *ticker; @@ -395,9 +445,11 @@ requisition->height += border_width * 2; requisition->width += border_width * 2; } +#endif static void gtk_ticker_compute_offsets (GtkTicker *ticker) { + GtkAllocation allocation; GtkTickerChild *child; GtkRequisition child_requisition; GList *children; @@ -408,15 +460,8 @@ border_width = gtk_container_get_border_width (GTK_CONTAINER (ticker)); -#if GTK_CHECK_VERSION(2,18,0) - { - GtkAllocation allocation; - gtk_widget_get_allocation (GTK_WIDGET (ticker), &allocation); - ticker->width = allocation.width; - } -#else - ticker->width = GTK_WIDGET(ticker)->allocation.width; -#endif + gtk_widget_get_allocation (GTK_WIDGET (ticker), &allocation); + ticker->width = allocation.width; ticker->total = 0; children = ticker->children; while (children) { @@ -438,6 +483,7 @@ GtkAllocation *allocation) { GtkTicker *ticker; + GtkAllocation a; GtkTickerChild *child; GtkAllocation child_allocation; GtkRequisition child_requisition; @@ -450,27 +496,15 @@ ticker = GTK_TICKER (widget); -#if GTK_CHECK_VERSION(2,18,0) - { - GtkAllocation a; - gtk_widget_get_allocation (GTK_WIDGET (ticker), &a); - if ( a.width != ticker->width ) - ticker->dirty = TRUE; - } -#else - if ( GTK_WIDGET(ticker)->allocation.width != ticker->width ) + gtk_widget_get_allocation (GTK_WIDGET (ticker), &a); + if ( a.width != ticker->width ) ticker->dirty = TRUE; -#endif if ( ticker->dirty == TRUE ) { gtk_ticker_compute_offsets( ticker ); } -#if GTK_CHECK_VERSION(2,18,0) gtk_widget_set_allocation (widget, allocation); -#else - widget->allocation = *allocation; -#endif if (gtk_widget_get_realized (widget)) gdk_window_move_resize (gtk_widget_get_window (widget), allocation->x,
--- a/pidgin/plugins/timestamp.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/plugins/timestamp.c Mon Aug 06 18:11:44 2012 +0200 @@ -134,7 +134,7 @@ GtkWidget *ret; GtkWidget *frame, *label; GtkWidget *vbox, *hbox; - GtkObject *adj; + GtkAdjustment *adj; GtkWidget *spinner; ret = gtk_vbox_new(FALSE, 18);
--- a/pidgin/plugins/timestamp_format.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/plugins/timestamp_format.c Mon Aug 06 18:11:44 2012 +0200 @@ -156,7 +156,7 @@ return; dialog = gtk_dialog_new_with_buttons(PIDGIN_ALERT_TITLE, NULL, - GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); g_signal_connect_after(G_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), dialog);
--- a/pidgin/plugins/vvconfig.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/plugins/vvconfig.c Mon Aug 06 18:11:44 2012 +0200 @@ -505,14 +505,14 @@ } static void -config_destroy(GtkObject *w, gpointer nul) +config_destroy(GtkWidget *w, gpointer nul) { purple_debug_info("vvconfig", "closing vv configuration window\n"); window = NULL; } static void -config_close(GtkObject *w, gpointer nul) +config_close(GtkWidget *w, gpointer nul) { gtk_widget_destroy(GTK_WIDGET(window)); }
--- a/pidgin/plugins/xmppconsole.c Mon Aug 06 13:16:32 2012 +0200 +++ b/pidgin/plugins/xmppconsole.c Mon Aug 06 18:11:44 2012 +0200 @@ -31,6 +31,8 @@ #include <gdk/gdkkeysyms.h> +#include "gtk3compat.h" + typedef struct { PurpleConnection *gc; GtkWidget *window; @@ -314,11 +316,11 @@ gtk_size_group_add_widget(sg, label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - type_combo = gtk_combo_box_new_text(); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "get"); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "set"); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "result"); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "error"); + type_combo = gtk_combo_box_text_new(); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "get"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "set"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "result"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "error"); gtk_combo_box_set_active(GTK_COMBO_BOX(type_combo), 0); gtk_box_pack_start(GTK_BOX(hbox), type_combo, FALSE, FALSE, 0); @@ -339,7 +341,7 @@ to && *to ? to : "", to && *to ? "'" : "", g_random_int(), - gtk_combo_box_get_active_text(GTK_COMBO_BOX(type_combo))); + gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(type_combo))); gtk_webview_load_html_string_with_selection(GTK_WEBVIEW(console->entry), stanza); gtk_widget_grab_focus(console->entry); @@ -403,15 +405,15 @@ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_size_group_add_widget(sg, label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - type_combo = gtk_combo_box_new_text(); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "default"); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "unavailable"); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "subscribe"); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "unsubscribe"); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "subscribed"); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "unsubscribed"); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "probe"); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "error"); + type_combo = gtk_combo_box_text_new(); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "default"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "unavailable"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "subscribe"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "unsubscribe"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "subscribed"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "unsubscribed"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "probe"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "error"); gtk_combo_box_set_active(GTK_COMBO_BOX(type_combo), 0); gtk_box_pack_start(GTK_BOX(hbox), type_combo, FALSE, FALSE, 0); @@ -421,12 +423,12 @@ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_size_group_add_widget(sg, label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - show_combo = gtk_combo_box_new_text(); - gtk_combo_box_append_text(GTK_COMBO_BOX(show_combo), "default"); - gtk_combo_box_append_text(GTK_COMBO_BOX(show_combo), "away"); - gtk_combo_box_append_text(GTK_COMBO_BOX(show_combo), "dnd"); - gtk_combo_box_append_text(GTK_COMBO_BOX(show_combo), "xa"); - gtk_combo_box_append_text(GTK_COMBO_BOX(show_combo), "chat"); + show_combo = gtk_combo_box_text_new(); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(show_combo), "default"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(show_combo), "away"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(show_combo), "dnd"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(show_combo), "xa"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(show_combo), "chat"); gtk_combo_box_set_active(GTK_COMBO_BOX(show_combo), 0); gtk_box_pack_start(GTK_BOX(hbox), show_combo, FALSE, FALSE, 0); @@ -464,10 +466,10 @@ } to = g_markup_escape_text(gtk_entry_get_text(GTK_ENTRY(to_entry)), -1); - type = gtk_combo_box_get_active_text(GTK_COMBO_BOX(type_combo)); + type = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(type_combo)); if (!strcmp(type, "default")) type = ""; - show = gtk_combo_box_get_active_text(GTK_COMBO_BOX(show_combo)); + show = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(show_combo)); if (!strcmp(show, "default")) show = ""; status = g_markup_escape_text(gtk_entry_get_text(GTK_ENTRY(status_entry)), -1); @@ -563,12 +565,12 @@ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_size_group_add_widget(sg, label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - type_combo = gtk_combo_box_new_text(); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "chat"); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "headline"); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "groupchat"); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "normal"); - gtk_combo_box_append_text(GTK_COMBO_BOX(type_combo), "error"); + type_combo = gtk_combo_box_text_new(); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "chat"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "headline"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "groupchat"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "normal"); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(type_combo), "error"); gtk_combo_box_set_active(GTK_COMBO_BOX(type_combo), 0); gtk_box_pack_start(GTK_BOX(hbox), type_combo, FALSE, FALSE, 0); @@ -630,7 +632,8 @@ *to ? to : "", *to ? "'" : "", g_random_int(), - gtk_combo_box_get_active_text(GTK_COMBO_BOX(type_combo)), + gtk_combo_box_text_get_active_text( + GTK_COMBO_BOX_TEXT(type_combo)), *body ? "<body>" : "", *body ? body : "", @@ -668,7 +671,8 @@ if (strcmp(purple_account_get_protocol_id(account), "prpl-jabber")) return; - gtk_combo_box_append_text(GTK_COMBO_BOX(console->dropdown), purple_account_get_username(account)); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(console->dropdown), + purple_account_get_username(account)); console->accounts = g_list_append(console->accounts, gc); console->count++; @@ -701,7 +705,7 @@ if (l == NULL) return; - gtk_combo_box_remove_text(GTK_COMBO_BOX(console->dropdown), i); + gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(console->dropdown), i); console->accounts = g_list_remove(console->accounts, gc); console->count--; @@ -745,7 +749,7 @@ } static void -console_destroy(GtkObject *window, gpointer nul) +console_destroy(GtkWidget *window, gpointer nul) { g_list_free(console->accounts); g_free(console); @@ -788,13 +792,13 @@ label = gtk_label_new(_("Account: ")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_box_pack_start(GTK_BOX(console->hbox), label, FALSE, FALSE, 0); - console->dropdown = gtk_combo_box_new_text(); + console->dropdown = gtk_combo_box_text_new(); for (connections = purple_connections_get_all(); connections; connections = connections->next) { PurpleConnection *gc = connections->data; if (!strcmp(purple_account_get_protocol_id(purple_connection_get_account(gc)), "prpl-jabber")) { console->count++; console->accounts = g_list_append(console->accounts, gc); - gtk_combo_box_append_text(GTK_COMBO_BOX(console->dropdown), + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(console->dropdown), purple_account_get_username(purple_connection_get_account(gc))); if (!console->gc) console->gc = gc;
--- a/po/de.po Mon Aug 06 13:16:32 2012 +0200 +++ b/po/de.po Mon Aug 06 18:11:44 2012 +0200 @@ -11,8 +11,8 @@ msgstr "" "Project-Id-Version: de\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-06-11 19:37+0200\n" -"PO-Revision-Date: 2012-06-11 19:36+0200\n" +"POT-Creation-Date: 2012-07-12 17:36+0200\n" +"PO-Revision-Date: 2012-07-12 17:36+0200\n" "Last-Translator: Jochen Kemnade <jochenkemnade@web.de>\n" "Language-Team: German <de@li.org>\n" "Language: de\n" @@ -11574,6 +11574,13 @@ msgid "New Event" msgstr "Neue Ereignisse" +msgid "" +"The account has disconnected and you are no longer in this chat. You will " +"automatically rejoin the chat when the account reconnects." +msgstr "" +"Das Konto wurde getrennt und Sie sind nicht mehr in diesem Chat. Sie werden " +"den Chat automatisch wieder betreten, wenn das Konto wieder verbunden ist." + msgid "clear: Clears all conversation scrollbacks." msgstr "clear: Leert alle Gesprächsfenster." @@ -11865,6 +11872,9 @@ msgid "Malay" msgstr "Malaiisch" +msgid "Burmese" +msgstr "Birmanisch" + msgid "Bokmål Norwegian" msgstr "Bokmål Norwegisch"