Mercurial > pidgin
view src/applet.c @ 2903:7630fb86df77
[gaim-migrate @ 2916]
thanks doug porter
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Thu, 20 Dec 2001 19:58:43 +0000 |
parents | 87d11d2a7d59 |
children | 32c78c57b351 |
line wrap: on
line source
/************************************************************** ** ** GaimGnomeAppletMgr ** Author - Quinticent (John Palmieri: johnp@martianrock.com) ** ** Purpose - Takes over the task of managing the GNOME applet ** code and provides a centralized codebase for ** GNOME integration for Gaim. ** ** ** gaim ** ** Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> ** ** 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #ifdef USE_APPLET #include <string.h> #include <gdk-pixbuf/gdk-pixbuf.h> #include <libart_lgpl/art_affine.h> #include <libart_lgpl/art_rgb_affine.h> #include <libart_lgpl/art_rgb_rgba_affine.h> #include "gaim.h" #include "applet.h" #include "pixmaps/aimicon.xpm" static int connecting = 0; gboolean applet_buddy_show = FALSE; GtkWidget *applet; static GtkWidget *icon; static GtkAllocation *get_applet_pos(gboolean); static gint sizehint = 48; static PanelBackType backtype = PANEL_BACK_NONE; static GdkColor *backcolor = NULL; static char *backfile = NULL; static void make_background(guchar *dest) { guchar *p; int r,g,b,i; if (backcolor && (backtype == PANEL_BACK_COLOR)) { guchar *p; int r,g,b,i; r = backcolor->red>>8; g = backcolor->green>>8; b = backcolor->blue>>8; p = dest; for (i = 0; i < sizehint * sizehint; i++) { *p++ = r; *p++ = g; *p++ = b; } return; } else if (backfile && (backtype == PANEL_BACK_PIXMAP)) { GdkPixbuf *pb = gdk_pixbuf_new_from_file(backfile); if (pb) { int dw = sizehint; int dh = sizehint; int offx = applet->allocation.x; int offy = applet->allocation.y; int drs = dw * 3; guchar *tile = gdk_pixbuf_get_pixels(pb); int w = gdk_pixbuf_get_width(pb); int h = gdk_pixbuf_get_height(pb); int rowstride = gdk_pixbuf_get_rowstride(pb); int has_alpha = gdk_pixbuf_get_has_alpha(pb); guchar *p; int i,j,x,y,a; guchar *imgrow; int off; p = dest; y = offy % h; off = drs - (dw*3); /*the space after width ends until next row*/ for(j=0;j<dh;j++) { x = offx % w; imgrow = tile + y * rowstride + (has_alpha?/*x*4*/x<<2:x*3); for(i=0;i<dw;i++) { *(p++) = *(imgrow++); *(p++) = *(imgrow++); *(p++) = *(imgrow++); if(has_alpha) { a = *(imgrow++); if(a!=255) { guchar *pp = p-3; pp[0] = (pp[0]*a)>>8; pp[1] = (pp[1]*a)>>8; pp[2] = (pp[2]*a)>>8; } } x++; if(x>=w) { x = 0; imgrow = tile + y * rowstride; } } p += off; y++; if(y>=h) y = 0; } gdk_pixbuf_unref(pb); return; } } r = applet->style->bg[GTK_WIDGET_STATE(applet)].red>>8; g = applet->style->bg[GTK_WIDGET_STATE(applet)].green>>8; b = applet->style->bg[GTK_WIDGET_STATE(applet)].blue>>8; p = dest; for (i = 0; i < sizehint * sizehint; i++) { *p++ = r; *p++ = g; *p++ = b; } } static GdkPixmap *get_applet_icon(const char *name) { GdkPixmap *cache; GdkGC *gc; char *path; GdkPixbuf *pb, *scale = NULL; guchar *dst; double affine[6]; if (!applet) return NULL; cache = gdk_pixmap_new(applet->window, sizehint, sizehint, gtk_widget_get_visual(applet)->depth); gc = gdk_gc_new(cache); gdk_gc_copy(gc, applet->style->bg_gc[GTK_WIDGET_STATE(applet)]); path = gnome_pixmap_file(name); if (path) scale = gdk_pixbuf_new_from_file(path); g_free(path); if (!scale) return NULL; pb = gdk_pixbuf_scale_simple(scale, sizehint, sizehint, GDK_INTERP_HYPER); gdk_pixbuf_unref(scale); dst = g_new0(guchar, sizehint*sizehint*3); make_background(dst); art_affine_identity(affine); if (gdk_pixbuf_get_has_alpha(pb)) art_rgb_rgba_affine(dst, 0, 0, sizehint, sizehint, sizehint * 3, gdk_pixbuf_get_pixels(pb), gdk_pixbuf_get_width(pb), gdk_pixbuf_get_height(pb), gdk_pixbuf_get_rowstride(pb), affine, ART_FILTER_NEAREST, NULL); else art_rgb_affine(dst, 0, 0, sizehint, sizehint, sizehint * 3, gdk_pixbuf_get_pixels(pb), gdk_pixbuf_get_width(pb), gdk_pixbuf_get_height(pb), gdk_pixbuf_get_rowstride(pb), affine, ART_FILTER_NEAREST, NULL); gdk_pixbuf_unref(pb); gdk_draw_rgb_image(cache, gc, 0, 0, sizehint, sizehint, GDK_RGB_DITHER_NORMAL, dst, sizehint * 3); g_free(dst); gdk_gc_unref(gc); return cache; } static gboolean update_applet() { char buf[BUF_LONG]; GSList *c = connections; GdkPixmap *newpix; if (connecting) { newpix = get_applet_icon(GAIM_GNOME_CONNECT_ICON); applet_set_tooltips(_("Attempting to sign on....")); } else if (!connections) { newpix = get_applet_icon(GAIM_GNOME_OFFLINE_ICON); applet_set_tooltips(_("Offline. Click to bring up login box.")); } else if (awaymessage) { int dsr = 0; if ((away_options & OPT_AWAY_QUEUE) && message_queue) { GSList *m = message_queue; while (m) { struct queued_message *qm = m->data; if (qm->flags & WFLAG_RECV) dsr++; m = m->next; } } if (dsr) { newpix = get_applet_icon(GAIM_GNOME_MSG_PENDING_ICON); g_snprintf(buf, sizeof(buf), _("Away: %d pending."), dsr); } else { newpix = get_applet_icon(GAIM_GNOME_AWAY_ICON); g_snprintf(buf, sizeof(buf), _("Away.")); } applet_set_tooltips(buf); } else { newpix = get_applet_icon(GAIM_GNOME_ONLINE_ICON); g_snprintf(buf, sizeof buf, "Online: "); while (c) { strcat(buf, ((struct gaim_connection *)c->data)->username); c = g_slist_next(c); if (c) strcat(buf, ", "); } applet_set_tooltips(buf); } if (newpix) { gtk_pixmap_set(GTK_PIXMAP(icon), newpix, NULL); gdk_pixmap_unref(newpix); } return TRUE; } static void back_changed(AppletWidget *applet, PanelBackType type, char *file, GdkColor *clr) { backtype = type; if (backfile) g_free(backfile); if (file) backfile = g_strdup(file); else backfile = NULL; if (backcolor) gdk_color_free(backcolor); if (clr) backcolor = gdk_color_copy(clr); else backcolor = NULL; update_applet(); } #ifdef HAVE_PANEL_PIXEL_SIZE static void applet_change_pixel_size(GtkWidget *w, int size, gpointer data) { sizehint = size; gtk_widget_set_usize(icon, sizehint, sizehint); update_applet(); } #endif extern GtkWidget *mainwindow; void applet_show_login(AppletWidget *widget, gpointer data) { show_login(); if (blist_options & OPT_BLIST_NEAR_APPLET) { GtkAllocation *a = get_applet_pos(FALSE); gtk_widget_set_uposition(mainwindow, a->x, a->y); } } void applet_do_signon(AppletWidget *widget, gpointer data) { applet_show_login(NULL, 0); } void insert_applet_away() { GSList *awy = away_messages; struct away_message *a; char *awayname; applet_widget_register_callback_dir(APPLET_WIDGET(applet), "away/", _("Away")); applet_widget_register_callback(APPLET_WIDGET(applet), "away/new", _("New Away Message"), (AppletCallbackFunc)create_away_mess, NULL); while (awy) { a = (struct away_message *)awy->data; awayname = g_malloc(sizeof *awayname * (6 + strlen(a->name))); awayname[0] = '\0'; strcat(awayname, "away/"); strcat(awayname, a->name); applet_widget_register_callback(APPLET_WIDGET(applet), awayname, a->name, (AppletCallbackFunc)do_away_message, a); awy = awy->next; g_free(awayname); } } void remove_applet_away() { GSList *awy = away_messages; struct away_message *a; char *awayname; if (!applet) return; applet_widget_unregister_callback(APPLET_WIDGET(applet), "away/new"); while (awy) { a = (struct away_message *)awy->data; awayname = g_malloc(sizeof *awayname * (6 + strlen(a->name))); awayname[0] = '\0'; strcat(awayname, "away/"); strcat(awayname, a->name); applet_widget_unregister_callback(APPLET_WIDGET(applet), awayname); awy = g_slist_next(awy); g_free(awayname); } applet_widget_unregister_callback_dir(APPLET_WIDGET(applet), "away/"); applet_widget_unregister_callback(APPLET_WIDGET(applet), "away"); } static GtkAllocation *get_applet_pos(gboolean for_blist) { gint x, y, pad; GtkRequisition buddy_req, applet_req; GtkAllocation *result = g_new0(GtkAllocation, 1); GNOME_Panel_OrientType orient = applet_widget_get_panel_orient(APPLET_WIDGET(applet)); pad = 5; gdk_window_get_position(gtk_widget_get_parent_window(icon), &x, &y); if (for_blist) { if (blist_options & OPT_BLIST_SAVED_WINDOWS) { buddy_req.width = blist_pos.width; buddy_req.height = blist_pos.height; } else { buddy_req = blist->requisition; } } else { buddy_req = mainwindow->requisition; } applet_req = icon->requisition; switch (orient) { case ORIENT_UP: result->x = x; result->y = y - (buddy_req.height + pad); break; case ORIENT_DOWN: result->x = x; result->y = y + applet_req.height + pad; break; case ORIENT_LEFT: result->x = x - (buddy_req.width + pad); result->y = y; break; case ORIENT_RIGHT: result->x = x + applet_req.width + pad; result->y = y; break; } if (result->x < 0) result->x = 0; if (result->y < 0) result->y = 0; if (result->x > gdk_screen_width() - buddy_req.width) result->x = gdk_screen_width() - buddy_req.width; if (result->y > gdk_screen_height() - buddy_req.height) result->y = gdk_screen_height() - buddy_req.height; return result; } void createOnlinePopup() { GtkAllocation *al; if (blist) gtk_widget_show(blist); al = get_applet_pos(TRUE); if (blist_options & OPT_BLIST_NEAR_APPLET) gtk_widget_set_uposition(blist, al->x, al->y); else if (blist_options & OPT_BLIST_SAVED_WINDOWS) gtk_widget_set_uposition(blist, blist_pos.x - blist_pos.xoff, blist_pos.y - blist_pos.yoff); g_free(al); } void AppletClicked(GtkWidget *sender, GdkEventButton *ev, gpointer data) { if (!ev || ev->button != 1 || ev->type != GDK_BUTTON_PRESS) return; if (applet_buddy_show) { applet_buddy_show = FALSE; if (!connections && mainwindow) gtk_widget_hide(mainwindow); else gtk_widget_hide(blist); } else { applet_buddy_show = TRUE; if (!connections) applet_show_login(APPLET_WIDGET(applet), NULL); else createOnlinePopup(); } } /*************************************************************** ** ** Initialize GNOME stuff ** ****************************************************************/ gint init_applet_mgr(int argc, char *argv[]) { GdkPixmap *pm; applet_widget_init("Gaim", VERSION, argc, argv, NULL, 0, NULL); applet = applet_widget_new("gaim_applet"); if (!applet) g_error(_("Can't create Gaim applet!")); gtk_signal_connect(GTK_OBJECT(applet), "back_change", GTK_SIGNAL_FUNC(back_changed), NULL); gtk_widget_set_events(applet, gtk_widget_get_events(applet) | GDK_BUTTON_PRESS_MASK); gtk_widget_realize(applet); pm = get_applet_icon(GAIM_GNOME_OFFLINE_ICON); if (!pm) pm = gdk_pixmap_create_from_xpm_d(applet->window, NULL, &applet->style->bg[GTK_WIDGET_STATE(applet)], aimicon_xpm); icon = gtk_pixmap_new(pm, NULL); #ifdef HAVE_PANEL_PIXEL_SIZE gtk_widget_set_usize(icon, 5, 5); #else gtk_widget_set_usize(icon, 48, 48); #endif gdk_pixmap_unref(pm); applet_widget_add(APPLET_WIDGET(applet), icon); applet_widget_register_stock_callback(APPLET_WIDGET(applet), "about", GNOME_STOCK_MENU_ABOUT, _("About..."), (AppletCallbackFunc)show_about, NULL); gtk_signal_connect(GTK_OBJECT(applet), "button_press_event", GTK_SIGNAL_FUNC(AppletClicked), NULL); gtk_signal_connect(GTK_OBJECT(applet), "destroy", GTK_SIGNAL_FUNC(do_quit), NULL); #ifdef HAVE_PANEL_PIXEL_SIZE gtk_signal_connect(GTK_OBJECT(applet), "change_pixel_size", GTK_SIGNAL_FUNC(applet_change_pixel_size), NULL); #endif gtk_widget_show(icon); gtk_widget_show(applet); return 0; } void set_user_state(enum gaim_user_states state) { if (state == signing_on) connecting++; else if ((state == away || state == online) && connecting > 0) connecting--; update_applet(); } void applet_set_tooltips(char *msg) { if (!applet) return; applet_widget_set_tooltip(APPLET_WIDGET(applet), msg); } #endif /*USE_APPLET */