diff options
author | Daniel Kamil Kozar <dkk089@gmail.com> | 2017-11-29 20:40:36 +0100 |
---|---|---|
committer | Daniel Kamil Kozar <dkk089@gmail.com> | 2017-11-29 20:40:36 +0100 |
commit | b1538a9d1369dcd3155f8560c671d56112a2ccc3 (patch) | |
tree | 1e033d30c188360613b1c36372e94a097ce7300b | |
parent | 3b89b04945adfb72d82e59ba5695588fa65b8cb7 (diff) | |
parent | 5c3cf26f08de066f7631025d5113824ff2ce217a (diff) | |
download | pidgin-b1538a9d1369dcd3155f8560c671d56112a2ccc3.tar.gz |
merge
29 files changed, 443 insertions, 298 deletions
@@ -15,7 +15,7 @@ If concerns are raised as to the copyright holder of a particular 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-2013 by the following: +Copyright (C) 1998-2017 by the following: Mark Saleem Abdulrasool @@ -310,9 +310,11 @@ Ho-seok Lee Jean-Yves Lefort Moses Lei Ambrose C. Li +Tom Li Nicolas Lichtmaier Wesley Lin Shaun Lindsay +Shivaram Lingamneni Artem Litvinovich Josh Littlefield Daniel Ljungborg @@ -351,6 +353,7 @@ James McLaughlin Torrey McMahon Greg McNew Robert McQueen +Christof Meerwald Mihály Mészáros Robert Mibus David Michael @@ -619,6 +622,7 @@ The Written Word, Inc. Kevin Wu Won Pui Lam Wong Justin Wood +David Woodhouse Ximian Ma Xuan Yonas Yanfa @@ -1,17 +1,40 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul -version 2.12.1 (??/??/????): +version 2.13.0 (??/??/????): libpurple: * Unified string comparison. (PR #186) (Arkadiy Illarionov) + * Properlly shell escape URI's when opening them. (PR #271 Daniel Kamil Kozar) + + libgnt: + * Fixed build against curses 6.0 with opaque structs set. (#16764 dimstar) + (PR #268 Daniel Kamil Kozar) + * Fixed a crash when resizing the window. (#16680 marcus) (PR #269 Daniel Kamil Kozar) + + General: + * Fixed bashism in autotools. (#16836 lameventanas) (PR #267 Daniel Kamil Kozar) XMPP: * Show XEP-0066 OOB URLs in any message, not just headlines + * Fix a user after free (#17200 debarshiray) (PR #266 Ethan Blanton) + * Removed pipelining from BOSH connections (#17025 PR #295 Tom Li) IRC: * Fix "Registration timeout" on SASL auth with InspIRCd servers (and possibly others not based on charybdis/ratbox/ircd-seven) * Fix issues with plugins that modify outgoing messages (such as the custom PART/QUIT feature of the IRC More plugin) + * Fix IRC buffer handling. (#12562 PR #272 Shivaram Lingamneni) + + Pidgin: + * Better support for dark themes. (#12572 Alyssa Rosenzweig and Gary Kramlich) + * Fixed IPv6 links by not escaping []'s. (#16391 cyisfor) (PR #270 Daniel Kamil Kozar) + * Only write buddy icons to the cache if they're not already cached. (PR #276 David Woodhouse) + * Rejoin persistent chats after reconnect. (#15687 PR #285 Christof Meerwald) + * Made the WIN32 Transparency plugin work on all platforms. (#3124 PR #287 Daniel Kamil Kozar) + * Ensure search results buttons are labeled (Backport from de2d88e575ee) + + Finch: + * Fix handling of search results (#17238 David Woodhouse) version 2.12.0 (03/09/2017): libpurple: diff --git a/ChangeLog.API b/ChangeLog.API index 44d18bc452..223d529424 100644 --- a/ChangeLog.API +++ b/ChangeLog.API @@ -1,5 +1,10 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +version 2.13.0: + libpurple: + Added: + * purple_uri_escape_for_open + version 2.12.0: libpurple: Added: diff --git a/configure.ac b/configure.ac index e81eda9572..71b9f7b6ae 100644 --- a/configure.ac +++ b/configure.ac @@ -43,10 +43,10 @@ AC_PREREQ([2.50]) # # Make sure to update finch/libgnt/configure.ac with libgnt version changes. # -m4_define([purple_lt_current], [12]) +m4_define([purple_lt_current], [13]) m4_define([purple_major_version], [2]) -m4_define([purple_minor_version], [12]) -m4_define([purple_micro_version], [1]) +m4_define([purple_minor_version], [13]) +m4_define([purple_micro_version], [0]) m4_define([purple_version_suffix], [devel]) m4_define([purple_version], [purple_major_version.purple_minor_version.purple_micro_version]) @@ -748,7 +748,7 @@ AC_ARG_WITH(gstreamer, [AS_HELP_STRING([--with-gstreamer=<version>], [compile with GStreamer 0.10 or 1.0 interface (default: auto)])], with_gstreamer="$withval", with_gstreamer="auto") if test "x$enable_gst" != "xno"; then - if test "x$with_gstreamer" == "xauto"; then + if test "x$with_gstreamer" = "xauto"; then PKG_CHECK_MODULES(GSTREAMER, [gstreamer-1.0], [ AC_DEFINE(USE_GSTREAMER, 1, [Use GStreamer for playing sounds]) with_gstreamer="1.0" @@ -772,7 +772,7 @@ Use --disable-gstreamer if you do not need GStreamer (sound) support. fi ]) ]) - elif test "x$with_gstreamer" == "x1.0"; then + elif test "x$with_gstreamer" = "x1.0"; then PKG_CHECK_MODULES(GSTREAMER, [gstreamer-1.0], [ AC_DEFINE(USE_GSTREAMER, 1, [Use GStreamer 1.0 for playing sounds]) AC_SUBST(GSTREAMER_CFLAGS) @@ -787,7 +787,7 @@ Use --disable-gstreamer if you do not need GStreamer (sound) support. ]) fi ]) - elif test "x$with_gstreamer" == "x0.10"; then + elif test "x$with_gstreamer" = "x0.10"; then PKG_CHECK_MODULES(GSTREAMER, [gstreamer-0.10], [ AC_DEFINE(USE_GSTREAMER, 1, [Use GStreamer 0.10 for playing sounds]) AC_SUBST(GSTREAMER_CFLAGS) @@ -807,14 +807,14 @@ Use --disable-gstreamer if you do not need GStreamer (sound) support. fi fi -if test "x$with_gtk" == "x3" -a "x$with_gstreamer" == "x0.10"; then +if test "x$with_gtk" = "x3" -a "x$with_gstreamer" = "x0.10"; then AC_MSG_ERROR([WebKitGTK+ 3.0 cannot be mixed with GStreamer 0.10. Please switch to WebKitGTK+ 2.0 or GStreamer 1.0.]) -elif test "x$with_gtk" == "x2" -a "x$with_gstreamer" == "x1.0"; then +elif test "x$with_gtk" = "x2" -a "x$with_gstreamer" = "x1.0"; then AC_MSG_ERROR([WebKitGTK+ 2.0 cannot be mixed with GStreamer 1.0. Please switch to WebKitGTK+ 3.0 or GStreamer 0.10.]) fi -if test "x$with_gstreamer" == "x0.10" -o "x$with_gstreamer" == "x1.0"; then +if test "x$with_gstreamer" = "x0.10" -o "x$with_gstreamer" = "x1.0"; then AC_SUBST(GSTREAMER_VER, [$with_gstreamer]) else AC_SUBST(GSTREAMER_VER, "") @@ -823,7 +823,7 @@ fi dnl ####################################################################### dnl # Check for GStreamer Video dnl ####################################################################### -if test "x$enable_gst" != "xno" -a "x$with_gstreamer" == "x1.0"; then +if test "x$enable_gst" != "xno" -a "x$with_gstreamer" = "x1.0"; then AC_ARG_ENABLE(gstreamer-video, [AS_HELP_STRING([--disable-gstreamer-video], [compile without GStreamer 1.0 Video Overlay support])], enable_gstvideo="$enableval", enable_gstvideo="yes") @@ -843,7 +843,7 @@ fi dnl ####################################################################### dnl # Check for GStreamer Interfaces dnl ####################################################################### -if test "x$enable_gst" != "xno" -a "x$with_gstreamer" == "x0.10"; then +if test "x$enable_gst" != "xno" -a "x$with_gstreamer" = "x0.10"; then AC_ARG_ENABLE(gstreamer-interfaces, [AS_HELP_STRING([--disable-gstreamer-interfaces], [compile without GStreamer 0.10 interface support])], enable_gstinterfaces="$enableval", enable_gstinterfaces="yes") @@ -867,7 +867,7 @@ AC_ARG_ENABLE(farstream, [AS_HELP_STRING([--disable-farstream], [compile without farstream support])], enable_farstream="$enableval", enable_farstream="yes") if test "x$enable_farstream" != "xno"; then - if test "x$with_gstreamer" == "x1.0"; then + if test "x$with_gstreamer" = "x1.0"; then PKG_CHECK_MODULES(FARSTREAM, [farstream-0.2 >= 0.2.7], [ AC_SUBST(FARSTREAM_CFLAGS) AC_SUBST(FARSTREAM_LIBS) @@ -898,9 +898,9 @@ AC_ARG_ENABLE(vv, [AS_HELP_STRING([--disable-vv], [compile without voice and video support])], enable_vv="$enableval", enable_vv="yes") if test "x$enable_vv" != "xno"; then - if test "x$enable_gst" != "xno" -a "x$with_gstreamer" == "x1.0" -a "x$enable_gstvideo" != "xno" -a "x$enable_farstream" != "xno"; then + if test "x$enable_gst" != "xno" -a "x$with_gstreamer" = "x1.0" -a "x$enable_gstvideo" != "xno" -a "x$enable_farstream" != "xno"; then AC_DEFINE(USE_VV, 1, [Use voice and video]) - elif test "x$enable_gst" != "xno" -a "x$with_gstreamer" == "x0.10" -a "x$enable_gstinterfaces" != "xno" -a "x$enable_farstream" != "xno"; then + elif test "x$enable_gst" != "xno" -a "x$with_gstreamer" = "x0.10" -a "x$enable_gstinterfaces" != "xno" -a "x$enable_farstream" != "xno"; then AC_DEFINE(USE_VV, 1, [Use voice and video]) else enable_vv="no" @@ -918,7 +918,7 @@ AM_CONDITIONAL(USE_VV, test "x$enable_vv" != "xno") dnl ####################################################################### dnl # Check for Raw data streams support in Farstream dnl ####################################################################### -if test "x$enable_vv" != "xno" -a "x$with_gstreamer" == "x1.0"; then +if test "x$enable_vv" != "xno" -a "x$with_gstreamer" = "x1.0"; then AC_MSG_CHECKING(for raw data support in Farstream) PKG_CHECK_MODULES(GSTAPP, [gstreamer-app-1.0], [ AC_DEFINE(USE_GSTAPP, 1, [Use GStreamer Video Overlay support]) diff --git a/finch/gntnotify.c b/finch/gntnotify.c index f32650d2b5..1ee752ee16 100644 --- a/finch/gntnotify.c +++ b/finch/gntnotify.c @@ -388,10 +388,11 @@ static void finch_notify_sr_new_rows(PurpleConnection *gc, PurpleNotifySearchResults *results, void *data) { - GntTree *tree = GNT_TREE(data); + GntWindow *window = GNT_WINDOW(data); + GntTree *tree = GNT_TREE(g_object_get_data(G_OBJECT(window), "tree-widget")); GList *o; - /* XXX: Do I need to empty the tree here? */ + gnt_tree_remove_all(GNT_TREE(tree)); for (o = results->rows; o; o = o->next) { @@ -483,12 +484,16 @@ finch_notify_searchresults(PurpleConnection *gc, const char *title, gnt_box_add_widget(GNT_BOX(window), box); - finch_notify_sr_new_rows(gc, results, tree); + g_object_set_data(G_OBJECT(window), "tree-widget", tree); + finch_notify_sr_new_rows(gc, results, window); + + g_signal_connect(G_OBJECT(window), "destroy", + G_CALLBACK(notify_msg_window_destroy_cb), GINT_TO_POINTER(PURPLE_NOTIFY_SEARCHRESULTS)); gnt_widget_show(window); g_object_set_data(G_OBJECT(window), "notify-results", results); - return tree; + return window; } static void * diff --git a/finch/libgnt/gntmain.c b/finch/libgnt/gntmain.c index 71548df9b5..bccf021c02 100644 --- a/finch/libgnt/gntmain.c +++ b/finch/libgnt/gntmain.c @@ -407,10 +407,11 @@ raise: #ifdef SIGWINCH static void (*org_winch_handler)(int); +static void (*org_winch_handler_sa)(int, siginfo_t *, void *); #endif static void -sighandler(int sig) +sighandler(int sig, siginfo_t *info, void *data) { switch (sig) { #ifdef SIGWINCH @@ -419,16 +420,15 @@ sighandler(int sig) g_idle_add((GSourceFunc)refresh_screen, NULL); if (org_winch_handler) org_winch_handler(sig); - signal(SIGWINCH, sighandler); + if (org_winch_handler_sa) + org_winch_handler_sa(sig, info, data); break; #endif case SIGCHLD: clean_pid(); - signal(SIGCHLD, sighandler); break; case SIGINT: ask_before_exit(); - signal(SIGINT, sighandler); break; } } @@ -456,6 +456,10 @@ void gnt_init() { char *filename; const char *locale; + struct sigaction act; +#ifdef SIGWINCH + struct sigaction oact; +#endif if (channel) return; @@ -501,11 +505,25 @@ void gnt_init() werase(stdscr); wrefresh(stdscr); + act.sa_sigaction = sighandler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_SIGINFO; + #ifdef SIGWINCH - org_winch_handler = signal(SIGWINCH, sighandler); + org_winch_handler = NULL; + org_winch_handler_sa = NULL; + sigaction(SIGWINCH, &act, &oact); + if (oact.sa_flags & SA_SIGINFO) + { + org_winch_handler_sa = oact.sa_sigaction; + } + else if (oact.sa_handler != SIG_DFL && oact.sa_handler != SIG_IGN) + { + org_winch_handler = oact.sa_handler; + } #endif - signal(SIGCHLD, sighandler); - signal(SIGINT, sighandler); + sigaction(SIGCHLD, &act, NULL); + sigaction(SIGINT, &act, NULL); signal(SIGPIPE, SIG_IGN); #if !GLIB_CHECK_VERSION(2, 36, 0) diff --git a/finch/libgnt/gntwm.c b/finch/libgnt/gntwm.c index 310d6c621c..705a487539 100644 --- a/finch/libgnt/gntwm.c +++ b/finch/libgnt/gntwm.c @@ -174,37 +174,37 @@ work_around_for_ncurses_bug(void) cchar_t ch; PANEL *below = panel; - sx = panel->win->_begx; - ex = panel->win->_maxx + sx; - sy = panel->win->_begy; - ey = panel->win->_maxy + sy; + sx = getbegx(panel->win); + ex = getmaxx(panel->win) + sx; + sy = getbegy(panel->win); + ey = getmaxy(panel->win) + sy; while ((below = panel_below(below)) != NULL) { - if (sy > below->win->_begy + below->win->_maxy || - ey < below->win->_begy) + if (sy > getbegy(below->win) + getmaxy(below->win) || + ey < getbegy(below->win)) continue; - if (sx > below->win->_begx + below->win->_maxx || - ex < below->win->_begx) + if (sx > getbegx(below->win) + getmaxx(below->win) || + ex < getbegx(below->win)) continue; - for (y = MAX(sy, below->win->_begy); y <= MIN(ey, below->win->_begy + below->win->_maxy); y++) { - if (mvwin_wch(below->win, y - below->win->_begy, sx - 1 - below->win->_begx, &ch) != OK) + for (y = MAX(sy, getbegy(below->win)); y <= MIN(ey, getbegy(below->win) + getmaxy(below->win)); y++) { + if (mvwin_wch(below->win, y - getbegy(below->win), sx - 1 - getbegx(below->win), &ch) != OK) goto right; w = widestringwidth(ch.chars); if (w > 1 && (ch.attr & 1)) { ch.chars[0] = ' '; ch.attr &= ~ A_CHARTEXT; - mvwadd_wch(below->win, y - below->win->_begy, sx - 1 - below->win->_begx, &ch); - touchline(below->win, y - below->win->_begy, 1); + mvwadd_wch(below->win, y - getbegy(below->win), sx - 1 - getbegx(below->win), &ch); + touchline(below->win, y - getbegy(below->win), 1); } right: - if (mvwin_wch(below->win, y - below->win->_begy, ex + 1 - below->win->_begx, &ch) != OK) + if (mvwin_wch(below->win, y - getbegy(below->win), ex + 1 - getbegx(below->win), &ch) != OK) continue; w = widestringwidth(ch.chars); if (w > 1 && !(ch.attr & 1)) { ch.chars[0] = ' '; ch.attr &= ~ A_CHARTEXT; - mvwadd_wch(below->win, y - below->win->_begy, ex + 1 - below->win->_begx, &ch); - touchline(below->win, y - below->win->_begy, 1); + mvwadd_wch(below->win, y - getbegy(below->win), ex + 1 - getbegx(below->win), &ch); + touchline(below->win, y - getbegy(below->win), 1); } } } diff --git a/libpurple/buddyicon.c b/libpurple/buddyicon.c index 7f5a290539..14e03c09b9 100644 --- a/libpurple/buddyicon.c +++ b/libpurple/buddyicon.c @@ -174,8 +174,12 @@ purple_buddy_icon_data_cache(PurpleStoredImage *img) } } - purple_util_write_data_to_file_absolute(path, purple_imgstore_get_data(img), - purple_imgstore_get_size(img)); + if (!g_file_test(path, G_FILE_TEST_IS_REGULAR)) + { + purple_util_write_data_to_file_absolute(path, purple_imgstore_get_data(img), + purple_imgstore_get_size(img)); + } + g_free(path); } diff --git a/libpurple/media/backend-fs2.c b/libpurple/media/backend-fs2.c index fd658ce0c1..036efb1918 100644 --- a/libpurple/media/backend-fs2.c +++ b/libpurple/media/backend-fs2.c @@ -1151,7 +1151,7 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, FsParticipant *participant; PurpleMediaBackendFs2Session *session; PurpleMediaBackendFs2Stream *media_stream; - gchar *name; + const gchar *name; value = gst_structure_get_value(structure, "stream"); stream = g_value_get_object(value); @@ -1165,8 +1165,7 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, local_candidate->foundation); g_object_get(stream, "participant", &participant, NULL); - g_object_get(participant, "cname", &name, NULL); - g_object_unref(participant); + name = g_object_get_data(G_OBJECT(participant), "purple-name"); media_stream = get_stream(self, session->id, name); media_stream->local_candidates = g_list_append( @@ -1177,6 +1176,7 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, g_signal_emit_by_name(self, "new-candidate", session->id, name, candidate); g_object_unref(candidate); + g_object_unref(participant); } else if (gst_structure_has_name(structure, #ifdef HAVE_FARSIGHT "farsight-local-candidates-prepared")) { @@ -1187,18 +1187,18 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, FsStream *stream; FsParticipant *participant; PurpleMediaBackendFs2Session *session; - gchar *name; value = gst_structure_get_value(structure, "stream"); stream = g_value_get_object(value); session = get_session_from_fs_stream(self, stream); g_object_get(stream, "participant", &participant, NULL); - g_object_get(participant, "cname", &name, NULL); - g_object_unref(participant); g_signal_emit_by_name(self, "candidates-prepared", - session->id, name); + session->id, + g_object_get_data(G_OBJECT(participant), "purple-name")); + + g_object_unref(participant); } else if (gst_structure_has_name(structure, #ifdef HAVE_FARSIGHT "farsight-new-active-candidate-pair")) { @@ -1212,7 +1212,6 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, FsParticipant *participant; PurpleMediaBackendFs2Session *session; PurpleMediaCandidate *lcandidate, *rcandidate; - gchar *name; value = gst_structure_get_value(structure, "stream"); stream = g_value_get_object(value); @@ -1222,8 +1221,6 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, remote_candidate = g_value_get_boxed(value); g_object_get(stream, "participant", &participant, NULL); - g_object_get(participant, "cname", &name, NULL); - g_object_unref(participant); session = get_session_from_fs_stream(self, stream); @@ -1231,8 +1228,11 @@ gst_handle_message_element(GstBus *bus, GstMessage *msg, rcandidate = candidate_from_fs(remote_candidate); g_signal_emit_by_name(self, "active-candidate-pair", - session->id, name, lcandidate, rcandidate); + session->id, + g_object_get_data(G_OBJECT(participant), "purple-name"), + lcandidate, rcandidate); + g_object_unref(participant); g_object_unref(lcandidate); g_object_unref(rcandidate); } else if (gst_structure_has_name(structure, @@ -1959,6 +1959,9 @@ create_participant(PurpleMediaBackendFs2 *self, const gchar *name) return FALSE; } + g_object_set_data_full(G_OBJECT(participant), "purple-name", + g_strdup(name), g_free); + #ifndef HAVE_FARSIGHT if (g_object_class_find_property(G_OBJECT_GET_CLASS(participant), "cname")) { diff --git a/libpurple/protocols/irc/irc.c b/libpurple/protocols/irc/irc.c index 2078985d90..133c4d1aa0 100644 --- a/libpurple/protocols/irc/irc.c +++ b/libpurple/protocols/irc/irc.c @@ -685,31 +685,38 @@ static void irc_input_cb_ssl(gpointer data, PurpleSslConnection *gsc, return; } - if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) { - irc->inbuflen += IRC_INITIAL_BUFSIZE; - irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); - } + do { + // resize buffer upwards so we have at least IRC_BUFSIZE_INCREMENT + // bytes free in inbuf + if (irc->inbuflen < irc->inbufused + IRC_BUFSIZE_INCREMENT) { + if (irc->inbuflen + IRC_BUFSIZE_INCREMENT <= IRC_MAX_BUFSIZE) { + irc->inbuflen += IRC_BUFSIZE_INCREMENT; + irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); + } else { + // discard unparseable data from the buffer + irc->inbufused = 0; + } + } - len = purple_ssl_read(gsc, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1); + len = purple_ssl_read(gsc, irc->inbuf + irc->inbufused, irc->inbuflen - irc->inbufused - 1); + if (len > 0) { + read_input(irc, len); + } + } while (len > 0); - if (len < 0 && errno == EAGAIN) { - /* Try again later */ - return; - } else if (len < 0) { + if (len < 0 && errno != EAGAIN) { gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); purple_connection_error_reason (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); - return; } else if (len == 0) { purple_connection_error_reason (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Server closed the connection")); - return; } - read_input(irc, len); + /* else: len < 0 && errno == EAGAIN; this is fine, try again later */ } static void irc_input_cb(gpointer data, gint source, PurpleInputCondition cond) @@ -718,12 +725,18 @@ static void irc_input_cb(gpointer data, gint source, PurpleInputCondition cond) struct irc_conn *irc = gc->proto_data; int len; - if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) { - irc->inbuflen += IRC_INITIAL_BUFSIZE; - irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); + /* see irc_input_cb_ssl */ + if (irc->inbuflen < irc->inbufused + IRC_BUFSIZE_INCREMENT) { + if (irc->inbuflen + IRC_BUFSIZE_INCREMENT <= IRC_MAX_BUFSIZE) { + irc->inbuflen += IRC_BUFSIZE_INCREMENT; + irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); + } else { + irc->inbufused = 0; + } } - len = read(irc->fd, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1); + len = read(irc->fd, irc->inbuf + irc->inbufused, irc->inbuflen - irc->inbufused - 1); + if (len < 0 && errno == EAGAIN) { return; } else if (len < 0) { diff --git a/libpurple/protocols/irc/irc.h b/libpurple/protocols/irc/irc.h index fde35c42c7..f587790d60 100644 --- a/libpurple/protocols/irc/irc.h +++ b/libpurple/protocols/irc/irc.h @@ -44,7 +44,8 @@ #define IRC_DEFAULT_QUIT "Leaving." -#define IRC_INITIAL_BUFSIZE 1024 +#define IRC_BUFSIZE_INCREMENT 1024 +#define IRC_MAX_BUFSIZE 16384 #define IRC_MAX_MSG_SIZE 512 diff --git a/libpurple/protocols/jabber/bosh.c b/libpurple/protocols/jabber/bosh.c index af178c64bc..d80ecd6ac1 100644 --- a/libpurple/protocols/jabber/bosh.c +++ b/libpurple/protocols/jabber/bosh.c @@ -68,7 +68,6 @@ struct _PurpleBOSHConnection { char *path; guint16 port; - gboolean pipelining; gboolean ssl; enum { @@ -212,7 +211,6 @@ jabber_bosh_connection_init(JabberStream *js, const char *url) conn->port = port; conn->path = g_strdup_printf("/%s", path); g_free(path); - conn->pipelining = TRUE; if (purple_ip_address_is_valid(host)) js->serverFQDN = g_strdup(js->user->domain); @@ -285,12 +283,6 @@ find_available_http_connection(PurpleBOSHConnection *conn) if (purple_debug_is_verbose()) debug_dump_http_connections(conn); - /* Easy solution: Does everyone involved support pipelining? Hooray! Just use - * one TCP connection! */ - if (conn->pipelining) - return conn->connections[0]->state == HTTP_CONN_CONNECTED ? - conn->connections[0] : NULL; - /* First loop, look for a connection that's ready */ for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) { if (conn->connections[i] && @@ -465,27 +457,6 @@ jabber_bosh_connection_send_keepalive(PurpleBOSHConnection *bosh) send_timer_cb(bosh); } -static void -jabber_bosh_disable_pipelining(PurpleBOSHConnection *bosh) -{ - /* Do nothing if it's already disabled */ - if (!bosh->pipelining) - return; - - purple_debug_info("jabber", "BOSH: Disabling pipelining on conn %p\n", - bosh); - bosh->pipelining = FALSE; - if (bosh->connections[1] == NULL) { - bosh->connections[1] = jabber_bosh_http_connection_init(bosh); - http_connection_connect(bosh->connections[1]); - } else { - /* Shouldn't happen; this should be the only place pipelining - * is turned off. - */ - g_warn_if_reached(); - } -} - static void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode *node) { xmlnode *child; JabberStream *js = conn->js; @@ -726,11 +697,6 @@ static void http_connection_disconnected(PurpleHTTPConnection *conn) conn->requests = 0; } - if (conn->bosh->pipelining) { - /* Hmmmm, fall back to multiple connections */ - jabber_bosh_disable_pipelining(conn->bosh); - } - if (!had_requests) /* If the server disconnected us without any requests, let's * just wait until we have something to send before we reconnect @@ -807,7 +773,6 @@ jabber_bosh_http_connection_process(PurpleHTTPConnection *conn) if (!g_ascii_strncasecmp(tmp, "close", strlen("close"))) { conn->close = TRUE; - jabber_bosh_disable_pipelining(conn->bosh); } } diff --git a/libpurple/protocols/jabber/jingle/rtp.c b/libpurple/protocols/jabber/jingle/rtp.c index 876b80fb36..05cb2cb1bb 100644 --- a/libpurple/protocols/jabber/jingle/rtp.c +++ b/libpurple/protocols/jabber/jingle/rtp.c @@ -950,6 +950,7 @@ jingle_rtp_initiate_media(JabberStream *js, const gchar *who, JingleTransport *transport; JabberBuddy *jb; JabberBuddyResource *jbr; + gboolean ret = FALSE; const gchar *transport_type; gchar *resource = NULL, *me = NULL, *sid = NULL; @@ -958,16 +959,15 @@ jingle_rtp_initiate_media(JabberStream *js, const gchar *who, jb = jabber_buddy_find(js, who, FALSE); if (!jb) { purple_debug_error("jingle-rtp", "Could not find Jabber buddy\n"); - return FALSE; + goto out; } resource = jabber_get_resource(who); jbr = jabber_buddy_find_resource(jb, resource); - g_free(resource); if (!jbr) { purple_debug_error("jingle-rtp", "Could not find buddy's resource - %s\n", resource); - return FALSE; + goto out; } if (jabber_resource_has_capability(jbr, JINGLE_TRANSPORT_ICEUDP)) { @@ -977,7 +977,7 @@ jingle_rtp_initiate_media(JabberStream *js, const gchar *who, } else { purple_debug_error("jingle-rtp", "Resource doesn't support " "the same transport types\n"); - return FALSE; + goto out; } /* set ourselves as initiator */ @@ -985,7 +985,6 @@ jingle_rtp_initiate_media(JabberStream *js, const gchar *who, sid = jabber_get_next_id(js); session = jingle_session_create(js, sid, me, who, TRUE); - g_free(sid); if (type & PURPLE_MEDIA_AUDIO) { @@ -1005,13 +1004,17 @@ jingle_rtp_initiate_media(JabberStream *js, const gchar *who, jingle_rtp_init_media(content); } - g_free(me); - if (jingle_rtp_get_media(session) == NULL) { - return FALSE; + goto out; } - return TRUE; + ret = TRUE; + +out: + g_free(me); + g_free(resource); + g_free(sid); + return ret; } void diff --git a/libpurple/tests/test_util.c b/libpurple/tests/test_util.c index 303a056117..4239d9312c 100644 --- a/libpurple/tests/test_util.c +++ b/libpurple/tests/test_util.c @@ -232,6 +232,24 @@ START_TEST(test_strdup_withhtml) } END_TEST +START_TEST(test_uri_escape_for_open) +{ + /* make sure shell stuff is escaped... */ + gchar *result = purple_uri_escape_for_open("https://$(xterm)"); + assert_string_equal_free("https://%24%28xterm%29", result); + + result = purple_uri_escape_for_open("https://`xterm`"); + assert_string_equal_free("https://%60xterm%60", result); + + result = purple_uri_escape_for_open("https://$((25 + 13))"); + assert_string_equal_free("https://%24%28%2825%20+%2013%29%29", result); + + /* ...but keep brackets so that ipv6 links can be opened. */ + result = purple_uri_escape_for_open("https://[123:4567:89a::::]"); + assert_string_equal_free("https://[123:4567:89a::::]", result); +} +END_TEST + Suite * util_suite(void) { @@ -284,5 +302,9 @@ util_suite(void) tcase_add_test(tc, test_strdup_withhtml); suite_add_tcase(s, tc); + tc = tcase_create("escape_uri_for_open"); + tcase_add_test(tc, test_uri_escape_for_open); + suite_add_tcase(s, tc); + return s; } diff --git a/libpurple/util.c b/libpurple/util.c index 044a7acff0..ba7ad4b152 100644 --- a/libpurple/util.c +++ b/libpurple/util.c @@ -4583,6 +4583,17 @@ purple_uri_list_extract_filenames(const gchar *uri_list) return result; } +char * +purple_uri_escape_for_open(const char *unescaped) +{ + /* Replace some special characters like $ with their percent-encoded value. + * This shouldn't be necessary because we shell-escape the entire arg before + * exec'ing the browser, however, we had a report that a URL containing + * $(xterm) was causing xterm to start on his system. This is obviously a + * bug on his system, but it's pretty easy for us to protect against it. */ + return g_uri_escape_string(unescaped, "[]:;/%#,+?=&@", FALSE); +} + /************************************************************************** * UTF8 String Functions **************************************************************************/ diff --git a/libpurple/util.h b/libpurple/util.h index ede673e19e..d7ae1957ca 100644 --- a/libpurple/util.h +++ b/libpurple/util.h @@ -1330,6 +1330,17 @@ GList *purple_uri_list_extract_uris(const gchar *uri_list); */ GList *purple_uri_list_extract_filenames(const gchar *uri_list); +/** + * This function escapes any characters that might be interpreted by the shell + * when executing a program to open a URI on some systems. + * + * @param unescaped The unescaped URI. + * + * @return A newly allocated string with any shell metacharacters replaced with + * their escaped equivalents. + */ +char *purple_uri_escape_for_open(const char *unescaped); + /*@}*/ /************************************************************************** diff --git a/libpurple/win32/libc_interface.c b/libpurple/win32/libc_interface.c index 96bea53568..ee772e8de5 100644 --- a/libpurple/win32/libc_interface.c +++ b/libpurple/win32/libc_interface.c @@ -31,6 +31,7 @@ #include "config.h" #include "debug.h" #include "libc_internal.h" +#include "util.h" #include <glib/gstdio.h> /** This is redefined here because we can't include internal.h */ diff --git a/pidgin/Makefile.am b/pidgin/Makefile.am index 84d927ba59..09fa65ca39 100644 --- a/pidgin/Makefile.am +++ b/pidgin/Makefile.am @@ -81,6 +81,7 @@ pidgin_SOURCES = \ gtksourceview-marshal.c \ gtkstatus-icon-theme.c \ gtkstatusbox.c \ + gtkstyle.c \ gtkthemes.c \ gtkutils.c \ gtkwhiteboard.c \ @@ -131,6 +132,7 @@ pidgin_headers = \ gtksourceview-marshal.h \ gtkstatus-icon-theme.h \ gtkstatusbox.h \ + gtkstyle.h \ pidginstock.h \ gtkthemes.h \ gtkutils.h \ diff --git a/pidgin/Makefile.mingw b/pidgin/Makefile.mingw index aa77ddabf2..664edd2176 100644 --- a/pidgin/Makefile.mingw +++ b/pidgin/Makefile.mingw @@ -89,6 +89,7 @@ PIDGIN_C_SRC = \ gtksourceundomanager.c \ gtkstatus-icon-theme.c \ gtkstatusbox.c \ + gtkstyle.c \ gtkthemes.c \ gtkutils.c \ gtkwhiteboard.c \ diff --git a/pidgin/gtkblist.c b/pidgin/gtkblist.c index 125788e920..746da67efb 100644 --- a/pidgin/gtkblist.c +++ b/pidgin/gtkblist.c @@ -60,6 +60,7 @@ #include "gtkstatusbox.h" #include "gtkscrollbook.h" #include "gtksmiley.h" +#include "gtkstyle.h" #include "gtkblist-theme.h" #include "gtkblist-theme-loader.h" #include "gtkutils.h" @@ -4178,7 +4179,7 @@ theme_font_get_face_default(PidginThemeFont *font, const char *def) gchar * pidgin_blist_get_name_markup(PurpleBuddy *b, gboolean selected, gboolean aliased) { - const char *name, *name_color, *name_font, *status_color, *status_font; + const char *name, *name_color, *name_font, *status_color, *status_font, *dim_grey; char *text = NULL; PurplePlugin *prpl; PurplePluginProtocolInfo *prpl_info = NULL; @@ -4281,13 +4282,15 @@ pidgin_blist_get_name_markup(PurpleBuddy *b, gboolean selected, gboolean aliased theme = pidgin_blist_get_theme(); name_color = NULL; + dim_grey = pidgin_style_is_dark(NULL) ? "light slate grey" : "dim grey"; + if (theme) { if (purple_presence_is_idle(presence)) { namefont = statusfont = pidgin_blist_theme_get_idle_text_info(theme); - name_color = "dim grey"; + name_color = dim_grey; } else if (!purple_presence_is_online(presence)) { namefont = pidgin_blist_theme_get_offline_text_info(theme); - name_color = "dim grey"; + name_color = dim_grey; statusfont = pidgin_blist_theme_get_status_text_info(theme); } else if (purple_presence_is_available(presence)) { namefont = pidgin_blist_theme_get_online_text_info(theme); @@ -4301,14 +4304,14 @@ pidgin_blist_get_name_markup(PurpleBuddy *b, gboolean selected, gboolean aliased && (purple_presence_is_idle(presence) || !purple_presence_is_online(presence))) { - name_color = "dim grey"; + name_color = dim_grey; } } name_color = theme_font_get_color_default(namefont, name_color); name_font = theme_font_get_face_default(namefont, ""); - status_color = theme_font_get_color_default(statusfont, "dim grey"); + status_color = theme_font_get_color_default(statusfont, dim_grey); status_font = theme_font_get_face_default(statusfont, ""); if (aliased && selected) { @@ -4726,6 +4729,15 @@ conversation_created_cb(PurpleConversation *conv, PidginBuddyList *gtkblist) } } break; + default: + break; + } +} + +static void +chat_joined_cb(PurpleConversation *conv, PidginBuddyList *gtkblist) +{ + switch (conv->type) { case PURPLE_CONV_TYPE_CHAT: { PurpleChat *chat = purple_blist_find_chat(conv->account, conv->name); @@ -6092,6 +6104,9 @@ static void pidgin_blist_show(PurpleBuddyList *list) purple_signal_connect(handle, "conversation-created", gtkblist, PURPLE_CALLBACK(conversation_created_cb), gtkblist); + purple_signal_connect(handle, "chat-joined", gtkblist, + PURPLE_CALLBACK(chat_joined_cb), + gtkblist); gtk_widget_hide(gtkblist->headline_hbox); @@ -6535,7 +6550,7 @@ static void buddy_node(PurpleBuddy *buddy, GtkTreeIter *iter, PurpleBlistNode *n textcolor = pidgin_theme_font_get_color_describe(pair); else /* If no theme them default to making idle buddy names grey */ - textcolor = "dim grey"; + textcolor = pidgin_style_is_dark(NULL) ? "light slate grey" : "dim grey"; if (textcolor) { idle = g_strdup_printf("<span color='%s' font_desc='%s'>%d:%02d</span>", diff --git a/pidgin/gtkconv.c b/pidgin/gtkconv.c index b98c6375ef..d04997e682 100644 --- a/pidgin/gtkconv.c +++ b/pidgin/gtkconv.c @@ -63,6 +63,7 @@ #include "gtkpounce.h" #include "gtkprefs.h" #include "gtkprivacy.h" +#include "gtkstyle.h" #include "gtkthemes.h" #include "gtkutils.h" #include "pidginstock.h" @@ -8176,41 +8177,57 @@ pidgin_conversations_init(void) purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", handle, PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL); - { - /* Set default tab colors */ - GString *str = g_string_new(NULL); - GtkSettings *settings = gtk_settings_get_default(); - GtkStyle *parent = gtk_rc_get_style_by_paths(settings, "tab-container.tab-label*", NULL, G_TYPE_NONE), *now; - struct { - const char *stylename; - const char *labelname; - const char *color; - } styles[] = { - {"pidgin_tab_label_typing_default", "tab-label-typing", "#4e9a06"}, - {"pidgin_tab_label_typed_default", "tab-label-typed", "#c4a000"}, - {"pidgin_tab_label_attention_default", "tab-label-attention", "#006aff"}, - {"pidgin_tab_label_unreadchat_default", "tab-label-unreadchat", "#cc0000"}, - {"pidgin_tab_label_event_default", "tab-label-event", "#888a85"}, - {NULL, NULL, NULL} - }; - int iter; - for (iter = 0; styles[iter].stylename; iter++) { - now = gtk_rc_get_style_by_paths(settings, styles[iter].labelname, NULL, G_TYPE_NONE); - if (parent == now || - (parent && now && parent->rc_style == now->rc_style)) { - g_string_append_printf(str, "style \"%s\" {\n" - "fg[ACTIVE] = \"%s\"\n" - "}\n" - "widget \"*%s\" style \"%s\"\n", - styles[iter].stylename, - styles[iter].color, - styles[iter].labelname, styles[iter].stylename); - } +} + +/* Invalidate the first tab color set */ +static gboolean tab_color_fuse = TRUE; + +static void +pidgin_conversations_set_tab_colors(void) +{ + /* Set default tab colors */ + GString *str = g_string_new(NULL); + GtkSettings *settings = gtk_settings_get_default(); + GtkStyle *parent = gtk_rc_get_style_by_paths(settings, "tab-container.tab-label*", NULL, G_TYPE_NONE), *now; + struct { + const char *stylename; + const char *labelname; + const char *color; + } styles[] = { + {"pidgin_tab_label_typing_default", "tab-label-typing", "#4e9a06"}, + {"pidgin_tab_label_typed_default", "tab-label-typed", "#c4a000"}, + {"pidgin_tab_label_attention_default", "tab-label-attention", "#006aff"}, + {"pidgin_tab_label_unreadchat_default", "tab-label-unreadchat", "#cc0000"}, + {"pidgin_tab_label_event_default", "tab-label-event", "#888a85"}, + {NULL, NULL, NULL} + }; + int iter; + + if(tab_color_fuse) { + tab_color_fuse = FALSE; + return; + } + + for (iter = 0; styles[iter].stylename; iter++) { + now = gtk_rc_get_style_by_paths(settings, styles[iter].labelname, NULL, G_TYPE_NONE); + if (parent == now || + (parent && now && parent->rc_style == now->rc_style)) { + GdkColor color; + gdk_color_parse(styles[iter].color, &color); + pidgin_style_adjust_contrast(gtk_widget_get_default_style(), &color); + + g_string_append_printf(str, "style \"%s\" {\n" + "fg[ACTIVE] = \"%s\"\n" + "}\n" + "widget \"*%s\" style \"%s\"\n", + styles[iter].stylename, + gdk_color_to_string(&color), + styles[iter].labelname, styles[iter].stylename); } - gtk_rc_parse_string(str->str); - g_string_free(str, TRUE); - gtk_rc_reset_styles(settings); } + gtk_rc_parse_string(str->str); + g_string_free(str, TRUE); + gtk_rc_reset_styles(settings); } void @@ -9385,6 +9402,9 @@ pidgin_conv_window_new() gtk_window_iconify(GTK_WINDOW(win->window)); #endif + /* Fix colours */ + pidgin_conversations_set_tab_colors(); + return win; } @@ -10252,6 +10272,9 @@ generate_nick_colors(guint *color_count, GdkColor background) gdk_color_parse(DEFAULT_HIGHLIGHT_COLOR, &nick_highlight); gdk_color_parse(DEFAULT_SEND_COLOR, &send_color); + pidgin_style_adjust_contrast(NULL, &nick_highlight); + pidgin_style_adjust_contrast(NULL, &send_color); + srand(background.red + background.green + background.blue + 1); breakout_time = time(NULL) + 3; diff --git a/pidgin/gtkimhtml.c b/pidgin/gtkimhtml.c index 777db0bef4..283900c314 100644 --- a/pidgin/gtkimhtml.c +++ b/pidgin/gtkimhtml.c @@ -44,6 +44,7 @@ #include "gtksourceiter.h" #include "gtksourceundomanager.h" #include "gtksourceview-marshal.h" +#include "gtkstyle.h" #include <gtk/gtk.h> #include <glib.h> #include <gdk/gdkkeysyms.h> @@ -469,6 +470,7 @@ gtk_imhtml_style_set(GtkWidget *widget, GtkStyle *prev_style) } else { GdkColor defcolor; gdk_color_parse(styles[i].def, &defcolor); + pidgin_style_adjust_contrast(gtk_widget_get_style(widget), &defcolor); g_object_set(tag, "foreground-gdk", &defcolor, NULL); } } diff --git a/pidgin/gtknotify.c b/pidgin/gtknotify.c index f1e1bae736..60d7dd8e1f 100644 --- a/pidgin/gtknotify.c +++ b/pidgin/gtknotify.c @@ -1044,7 +1044,7 @@ pidgin_notify_searchresults(PurpleConnection *gc, const char *title, switch (b->type) { case PURPLE_NOTIFY_BUTTON_LABELED: if(b->label) { - button = gtk_button_new_with_label(b->label); + button = gtk_dialog_add_button(GTK_DIALOG(window), b->label, GTK_RESPONSE_NONE); } else { purple_debug_warning("gtknotify", "Missing button label\n"); } @@ -1284,13 +1284,7 @@ pidgin_notify_uri(const char *uri) GSList *argv = NULL, *argv_remote = NULL; gchar **usercmd_argv = NULL; - /* Replace some special characters like $ with their percent-encoded - value. This shouldn't be necessary because we shell-escape the entire - arg before exec'ing the browser, however, we had a report that a URL - containing $(xterm) was causing xterm to start on his system. This is - obviously a bug on his system, but it's pretty easy for us to protect - against it. */ - uri_escaped = g_uri_escape_string(uri, ":;/%#,+?=&@", FALSE); + uri_escaped = purple_uri_escape_for_open(uri); web_browser = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/browsers/browser"); diff --git a/pidgin/gtkstyle.c b/pidgin/gtkstyle.c new file mode 100644 index 0000000000..a1985fe700 --- /dev/null +++ b/pidgin/gtkstyle.c @@ -0,0 +1,70 @@ +/* + * @file gtkstyle.c GTK+ Style utility functions + * @ingroup pidgin + */ + +/* 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 + * 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 + * + */ +#include "gtkstyle.h" + +/* Assume light mode */ +static gboolean dark_mode_cache = FALSE; + +gboolean +pidgin_style_is_dark(GtkStyle *style) { + GdkColor bg; + + if (!style) { + return dark_mode_cache; + } + + bg = style->base[GTK_STATE_NORMAL]; + + if (bg.red != 0xFFFF || bg.green != 0xFFFF || bg.blue != 0xFFFF) { + dark_mode_cache = ((int) bg.red + (int) bg.green + (int) bg.blue) < (65536 * 3 / 2); + } + + return dark_mode_cache; +} + +void +pidgin_style_adjust_contrast(GtkStyle *style, GdkColor *color) { + if (pidgin_style_is_dark(style)) { + gdouble r, g, b, h, s, v; + + r = ((gdouble) color->red) / 65535.0; + g = ((gdouble) color->green) / 65535.0; + b = ((gdouble) color->blue) / 65535.0; + + gtk_rgb_to_hsv(r, g, b, &h, &s, &v); + + v += 0.3; + v = v > 1.0 ? 1.0 : v; + s = 0.7; + + gtk_hsv_to_rgb(h, s, v, &r, &g, &b); + + color->red = (guint16) (r * 65535.0); + color->green = (guint16) (g * 65535.0); + color->blue = (guint16) (b * 65535.0); + } +} diff --git a/pidgin/gtkstyle.h b/pidgin/gtkstyle.h new file mode 100644 index 0000000000..0b65a226f6 --- /dev/null +++ b/pidgin/gtkstyle.h @@ -0,0 +1,59 @@ +/** + * @file gtkstyle.h GTK+ Style utility functions + * @ingroup pidgin + */ + +/* 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 _PIDGINSTYLE_H_ +#define _PIDGINSTYLE_H_ + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +/*@{*/ + +/** + * Returns TRUE if dark mode is enabled and foreground colours should be invertred + * + * @param style The GtkStyle in use, or NULL to use a cached version. + * + * @return @c TRUE if dark mode, @c FALSE otherwise + */ + +gboolean pidgin_style_is_dark(GtkStyle *style); + +/** + * Lighten a color if dark mode is enabled. + * + * @param style The GtkStyle in use. + * + * @param color Color to be lightened. Transformed color will be written here. + */ + +void pidgin_style_adjust_contrast(GtkStyle *style, GdkColor *color); + +/*@}*/ + +G_END_DECLS + +#endif /* _PIDGINSTYLE_H_ */ diff --git a/pidgin/plugins/Makefile.am b/pidgin/plugins/Makefile.am index 3bb8c22402..bdf7a337d0 100644 --- a/pidgin/plugins/Makefile.am +++ b/pidgin/plugins/Makefile.am @@ -47,6 +47,7 @@ spellchk_la_LDFLAGS = -module -avoid-version themeedit_la_LDFLAGS = -module -avoid-version timestamp_la_LDFLAGS = -module -avoid-version timestamp_format_la_LDFLAGS = -module -avoid-version +transparency_la_LDFLAGS = -module -avoid-version unity_la_LDFLAGS = -module -avoid-version vvconfig_la_LDFLAGS = -module -avoid-version xmppconsole_la_LDFLAGS = -module -avoid-version @@ -68,6 +69,7 @@ plugin_LTLIBRARIES = \ themeedit.la \ timestamp.la \ timestamp_format.la \ + transparency.la \ xmppconsole.la if USE_VV @@ -98,6 +100,7 @@ spellchk_la_SOURCES = spellchk.c themeedit_la_SOURCES = themeedit.c themeedit-icon.c themeedit-icon.h timestamp_la_SOURCES = timestamp.c timestamp_format_la_SOURCES = timestamp_format.c +transparency_la_SOURCES = transparency.c unity_la_SOURCES = unity.c vvconfig_la_SOURCES = vvconfig.c xmppconsole_la_SOURCES = xmppconsole.c @@ -118,6 +121,7 @@ spellchk_la_LIBADD = $(GTK_LIBS) themeedit_la_LIBADD = $(GTK_LIBS) timestamp_la_LIBADD = $(GTK_LIBS) timestamp_format_la_LIBADD = $(GTK_LIBS) +transparency_la_LIBADD = $(GTK_LIBS) unity_la_LIBADD = $(GTK_LIBS) $(UNITY_LIBS) vvconfig_la_LIBADD = $(GTK_LIBS) $(GSTREAMER_LIBS) xmppconsole_la_LIBADD = $(GTK_LIBS) diff --git a/pidgin/plugins/Makefile.mingw b/pidgin/plugins/Makefile.mingw index f16f9f506d..22984d31f5 100644 --- a/pidgin/plugins/Makefile.mingw +++ b/pidgin/plugins/Makefile.mingw @@ -10,7 +10,6 @@ include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak DISCO_PLUGIN := ./disco GTKPERL_PLUGIN := ./perl TICKER_PLUGIN := ./ticker -TRANSPARENCY_PLUGIN := ./win32/transparency WINPREFS_PLUGIN := ./win32/winprefs .SUFFIXES: @@ -63,14 +62,12 @@ all: plugins $(MAKE) -C $(DISCO_PLUGIN) -f $(MINGW_MAKEFILE) $(MAKE) -C $(GTKPERL_PLUGIN) -f $(MINGW_MAKEFILE) $(MAKE) -C $(TICKER_PLUGIN) -f $(MINGW_MAKEFILE) - $(MAKE) -C $(TRANSPARENCY_PLUGIN) -f $(MINGW_MAKEFILE) $(MAKE) -C $(WINPREFS_PLUGIN) -f $(MINGW_MAKEFILE) install: all $(PIDGIN_INSTALL_PLUGINS_DIR) $(MAKE) -C $(DISCO_PLUGIN) -f $(MINGW_MAKEFILE) install $(MAKE) -C $(GTKPERL_PLUGIN) -f $(MINGW_MAKEFILE) install $(MAKE) -C $(TICKER_PLUGIN) -f $(MINGW_MAKEFILE) install - $(MAKE) -C $(TRANSPARENCY_PLUGIN) -f $(MINGW_MAKEFILE) install $(MAKE) -C $(WINPREFS_PLUGIN) -f $(MINGW_MAKEFILE) install cp *.dll $(PIDGIN_INSTALL_PLUGINS_DIR) @@ -102,6 +99,7 @@ plugins: \ themeedit.dll \ timestamp_format.dll \ timestamp.dll \ + transparency.dll \ xmppconsole.dll ## @@ -112,7 +110,6 @@ clean: $(MAKE) -C $(DISCO_PLUGIN) -f $(MINGW_MAKEFILE) clean $(MAKE) -C $(GTKPERL_PLUGIN) -f $(MINGW_MAKEFILE) clean $(MAKE) -C $(TICKER_PLUGIN) -f $(MINGW_MAKEFILE) clean - $(MAKE) -C $(TRANSPARENCY_PLUGIN) -f $(MINGW_MAKEFILE) clean $(MAKE) -C $(WINPREFS_PLUGIN) -f $(MINGW_MAKEFILE) clean include $(PIDGIN_COMMON_TARGETS) diff --git a/pidgin/plugins/win32/transparency/win2ktrans.c b/pidgin/plugins/transparency.c index 3fc80e7064..4ee7b9b57d 100644 --- a/pidgin/plugins/win32/transparency/win2ktrans.c +++ b/pidgin/plugins/transparency.c @@ -21,7 +21,6 @@ * 02111-1301, USA. * */ -#include <gdk/gdkwin32.h> #include "internal.h" #include "core.h" @@ -39,6 +38,8 @@ /* * MACROS & DEFINES */ +/* The plugin name is left unchanged from its WinAPI days in order to keep it + * loading for users who were using it. */ #define WINTRANS_PLUGIN_ID "gtk-win-trans" #define blist (purple_get_blist() \ @@ -58,15 +59,15 @@ typedef struct { /* * LOCALS */ -static const char *OPT_WINTRANS_IM_ENABLED= "/plugins/gtk/win32/wintrans/im_enabled"; -static const char *OPT_WINTRANS_IM_ALPHA = "/plugins/gtk/win32/wintrans/im_alpha"; -static const char *OPT_WINTRANS_IM_SLIDER = "/plugins/gtk/win32/wintrans/im_slider"; -static const char *OPT_WINTRANS_IM_ONFOCUS= "/plugins/gtk/win32/wintrans/im_solid_onfocus"; -static const char *OPT_WINTRANS_IM_ONTOP = "/plugins/gtk/win32/wintrans/im_always_on_top"; -static const char *OPT_WINTRANS_BL_ENABLED= "/plugins/gtk/win32/wintrans/bl_enabled"; -static const char *OPT_WINTRANS_BL_ALPHA = "/plugins/gtk/win32/wintrans/bl_alpha"; -static const char *OPT_WINTRANS_BL_ONFOCUS= "/plugins/gtk/win32/wintrans/bl_solid_onfocus"; -static const char *OPT_WINTRANS_BL_ONTOP = "/plugins/gtk/win32/wintrans/bl_always_on_top"; +static const char *OPT_WINTRANS_IM_ENABLED= "/plugins/gtk/transparency/im_enabled"; +static const char *OPT_WINTRANS_IM_ALPHA = "/plugins/gtk/transparency/im_alpha"; +static const char *OPT_WINTRANS_IM_SLIDER = "/plugins/gtk/transparency/im_slider"; +static const char *OPT_WINTRANS_IM_ONFOCUS= "/plugins/gtk/transparency/im_solid_onfocus"; +static const char *OPT_WINTRANS_IM_ONTOP = "/plugins/gtk/transparency/im_always_on_top"; +static const char *OPT_WINTRANS_BL_ENABLED= "/plugins/gtk/transparency/bl_enabled"; +static const char *OPT_WINTRANS_BL_ALPHA = "/plugins/gtk/transparency/bl_alpha"; +static const char *OPT_WINTRANS_BL_ONFOCUS= "/plugins/gtk/transparency/bl_solid_onfocus"; +static const char *OPT_WINTRANS_BL_ONTOP = "/plugins/gtk/transparency/bl_always_on_top"; static GSList *window_list = NULL; /* @@ -76,31 +77,13 @@ static GSList *window_list = NULL; /* Set window transparency level */ static void set_wintrans(GtkWidget *window, int alpha, gboolean enabled, gboolean always_on_top) { - - HWND hWnd = GDK_WINDOW_HWND(window->window); - LONG style = GetWindowLong(hWnd, GWL_EXSTYLE); - if (enabled) { - style |= WS_EX_LAYERED; - } else { - style &= ~WS_EX_LAYERED; - } - SetWindowLong(hWnd, GWL_EXSTYLE, style); - - if (enabled) { - SetWindowPos(hWnd, - always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, - 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - SetLayeredWindowAttributes(hWnd, 0, alpha, LWA_ALPHA); + gdk_window_set_opacity(window->window, alpha / 255.0); + gdk_window_set_keep_above(window->window, always_on_top); } else { - /* Ask the window and its children to repaint */ - SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - - RedrawWindow(hWnd, NULL, NULL, - RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN); + gdk_window_set_opacity(window->window, 1); + gdk_window_set_keep_above(window->window, 0); } - } /* When a conv window is focused, if we're only transparent when unfocused, @@ -270,11 +253,6 @@ static void add_slider(GtkWidget *win) { gtk_window_get_size(GTK_WINDOW(win), &width, &height); gtk_box_pack_start(GTK_BOX(vbox), slider_box, FALSE, FALSE, 0); -#if 0 /*Now that we save window sizes, don't resize it or else it causes windows to grow*/ - /* Make window taller so we don't slowly collapse its message area */ - gtk_window_resize(GTK_WINDOW(win), width, - (height + slidereq.height)); -#endif /* Add window to list, to track that it has a slider */ slidwin = g_new0(slider_win, 1); slidwin->win = win; @@ -290,22 +268,7 @@ static void remove_sliders() { slider_win *slidwin = (slider_win*) tmp->data; if (slidwin != NULL && GTK_IS_WINDOW(slidwin->win)) { -#if 0 - GtkRequisition slidereq; - gint width, height; - /* Figure out how tall the slider was */ - gtk_widget_size_request( - slidwin->slider, &slidereq); - gtk_window_get_size( - GTK_WINDOW(slidwin->win), - &width, &height); -#endif gtk_widget_destroy(slidwin->slider); -#if 0 - gtk_window_resize( - GTK_WINDOW(slidwin->win), - width, (height - slidereq.height)); -#endif } g_free(slidwin); tmp = tmp->next; @@ -518,7 +481,7 @@ static gboolean plugin_load(PurplePlugin *plugin) { } static gboolean plugin_unload(PurplePlugin *plugin) { - purple_debug_info(WINTRANS_PLUGIN_ID, "Unloading win2ktrans plugin\n"); + purple_debug_info(WINTRANS_PLUGIN_ID, "Unloading transparency plugin\n"); remove_convs_wintrans(TRUE); @@ -703,8 +666,8 @@ static PurplePluginInfo info = static void init_plugin(PurplePlugin *plugin) { - purple_prefs_add_none("/plugins/gtk/win32"); - purple_prefs_add_none("/plugins/gtk/win32/wintrans"); + purple_prefs_add_none("/plugins/gtk"); + purple_prefs_add_none("/plugins/gtk/transparency"); purple_prefs_add_bool(OPT_WINTRANS_IM_ENABLED, FALSE); purple_prefs_add_int(OPT_WINTRANS_IM_ALPHA, 255); purple_prefs_add_bool(OPT_WINTRANS_IM_SLIDER, FALSE); @@ -714,6 +677,7 @@ init_plugin(PurplePlugin *plugin) purple_prefs_add_int(OPT_WINTRANS_BL_ALPHA, 255); purple_prefs_add_bool(OPT_WINTRANS_BL_ONFOCUS, FALSE); purple_prefs_add_bool(OPT_WINTRANS_BL_ONTOP, FALSE); + purple_prefs_rename("/plugins/gtk/win32/wintrans", "/plugins/gtk/transparency"); } PURPLE_INIT_PLUGIN(wintrans, init_plugin, info) diff --git a/pidgin/plugins/win32/transparency/Makefile.mingw b/pidgin/plugins/win32/transparency/Makefile.mingw deleted file mode 100644 index f04d81ae4f..0000000000 --- a/pidgin/plugins/win32/transparency/Makefile.mingw +++ /dev/null @@ -1,75 +0,0 @@ -# -# Makefile.mingw -# -# Description: Makefile for win32trans plugin. -# - -PIDGIN_TREE_TOP := ../../../.. -include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak - -TARGET = win2ktrans - -## -## INCLUDE PATHS -## -INCLUDE_PATHS += -I. \ - -I$(GTK_TOP)/include \ - -I$(GTK_TOP)/include/gtk-2.0 \ - -I$(GTK_TOP)/include/glib-2.0 \ - -I$(GTK_TOP)/include/pango-1.0 \ - -I$(GTK_TOP)/include/atk-1.0 \ - -I$(GTK_TOP)/include/cairo \ - -I$(GTK_TOP)/lib/glib-2.0/include \ - -I$(GTK_TOP)/lib/gtk-2.0/include \ - -I$(PURPLE_TOP) \ - -I$(PURPLE_TOP)/win32 \ - -I$(PIDGIN_TOP) \ - -I$(PIDGIN_TOP)/win32 \ - -I$(PIDGIN_TREE_TOP) - -LIB_PATHS += -L$(GTK_TOP)/lib \ - -L$(PURPLE_TOP) \ - -L$(PIDGIN_TOP) - -## -## SOURCES, OBJECTS -## -C_SRC = win2ktrans.c - -OBJECTS = $(C_SRC:%.c=%.o) - -## -## LIBRARIES -## -LIBS = -lgtk-win32-2.0 \ - -lglib-2.0 \ - -lgdk-win32-2.0 \ - -lgmodule-2.0 \ - -lgobject-2.0 \ - -lintl \ - -lpidgin \ - -lpurple - -include $(PIDGIN_COMMON_RULES) - -## -## TARGET DEFINITIONS -## -.PHONY: all install clean - -all: $(TARGET).dll - -install: all $(PIDGIN_INSTALL_PLUGINS_DIR) - cp $(TARGET).dll $(PIDGIN_INSTALL_PLUGINS_DIR) - -$(TARGET).dll: $(PURPLE_DLL).a $(PIDGIN_DLL).a $(OBJECTS) - $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll - -## -## CLEAN RULES -## -clean: - rm -rf $(OBJECTS) - rm -rf $(TARGET).dll - -include $(PIDGIN_COMMON_TARGETS) |