Changeset 6872


Ignore:
Timestamp:
Oct 8, 2008, 8:29:53 PM (13 years ago)
Author:
charles
Message:

(gtk) #1064: sexy-icon-entry.c uses deprecated gtk+ 2.13.x api

Location:
trunk/gtk
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/Makefile.am

    r6871 r6872  
    44GTK_EXTRA_CPPFLAGS="-DG_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DPANGO_DISABLE_DEPRECATED"
    55endif
     6
     7sexy-marshal.h: marshal.list
     8        glib-genmarshal --prefix=sexy_marshal ./marshal.list --header > sexy-marshal.h
     9
     10sexy-marshal.c: marshal.list
     11        glib-genmarshal --prefix=sexy_marshal ./marshal.list --body > sexy-marshal.c
     12
     13
    614
    715AM_CPPFLAGS = \
     
    3745    stats.h \
    3846    sexy-icon-entry.h \
     47    sexy-marshal.h \
    3948    torrent-cell-renderer.h \
    4049    tracker-list.h \
     
    6675    notify.c \
    6776    sexy-icon-entry.c \
     77    sexy-marshal.c \
    6878    stats.c \
    6979    torrent-cell-renderer.c \
     
    118128
    119129if WIN32
     130
    120131transmission.res: transmission.rc
    121132        $(WINDRES) -J rc -i transmission.rc -O coff -o transmission.res
    122133
    123134BUILT_SOURCES = \
    124         transmission.res
     135        sexy-marshal.h \
     136        sexy-marshal.c \
     137        setransmission.res
    125138
    126139CLEANFILES += \
     
    132145transmission_LDFLAGS = \
    133146        -mwindows
     147
     148else
     149
     150BUILT_SOURCES = \
     151        sexy-marshal.h \
     152        sexy-marshal.c
     153
    134154endif
    135 
  • trunk/gtk/sexy-icon-entry.c

    r6795 r6872  
    2121#include <string.h>
    2222#include <gtk/gtk.h>
     23
    2324#include "sexy-icon-entry.h"
     25#include "sexy-marshal.h"
    2426
    2527#define ICON_MARGIN 2
    2628#define MAX_ICONS 2
    2729
    28 #define IS_VALID_ICON_ENTRY_POSITION( pos ) \
    29     ( ( pos ) == SEXY_ICON_ENTRY_PRIMARY    \
    30     || ( pos ) == SEXY_ICON_ENTRY_SECONDARY )
     30#define IS_VALID_ICON_ENTRY_POSITION(pos) \
     31        ((pos) == SEXY_ICON_ENTRY_PRIMARY || \
     32         (pos) == SEXY_ICON_ENTRY_SECONDARY)
    3133
    3234typedef struct
    3335{
    34     GtkImage *   icon;
    35     gboolean     highlight;
    36     gboolean     hovered;
    37     GdkWindow *  window;
     36        GtkImage *icon;
     37        gboolean highlight;
     38        gboolean hovered;
     39        GdkWindow *window;
     40
    3841} SexyIconInfo;
    3942
    4043struct _SexyIconEntryPriv
    4144{
    42     SexyIconInfo    icons[MAX_ICONS];
    43 
    44     gulong          icon_released_id;
     45        SexyIconInfo icons[MAX_ICONS];
     46
     47        gulong icon_released_id;
    4548};
    4649
    4750enum
    4851{
    49     ICON_PRESSED,
    50     ICON_RELEASED,
    51     LAST_SIGNAL
     52        ICON_PRESSED,
     53        ICON_RELEASED,
     54        LAST_SIGNAL
    5255};
    5356
    54 static void           sexy_icon_entry_class_init( SexyIconEntryClass *klass );
    55 
    56 static void           sexy_icon_entry_editable_init(
    57     GtkEditableClass *iface );
    58 
    59 static void           sexy_icon_entry_init( SexyIconEntry *entry );
    60 
    61 static void           sexy_icon_entry_finalize( GObject *obj );
    62 
    63 static void           sexy_icon_entry_destroy( GtkObject *obj );
    64 
    65 static void           sexy_icon_entry_map( GtkWidget *widget );
    66 
    67 static void           sexy_icon_entry_unmap( GtkWidget *widget );
    68 
    69 static void           sexy_icon_entry_realize( GtkWidget *widget );
    70 
    71 static void           sexy_icon_entry_unrealize( GtkWidget *widget );
    72 
    73 static void           sexy_icon_entry_size_request(
    74     GtkWidget *widget,
    75     GtkRequisition *
    76                requisition );
    77 
    78 static void           sexy_icon_entry_size_allocate(
    79     GtkWidget *widget,
    80     GtkAllocation *
    81                allocation );
    82 
    83 static gint           sexy_icon_entry_expose( GtkWidget *     widget,
    84                                               GdkEventExpose *event );
    85 
    86 static gint           sexy_icon_entry_enter_notify(
    87     GtkWidget *       widget,
    88     GdkEventCrossing *event );
    89 
    90 static gint           sexy_icon_entry_leave_notify(
    91     GtkWidget *       widget,
    92     GdkEventCrossing *event );
    93 
    94 static gint           sexy_icon_entry_button_press( GtkWidget *     widget,
    95                                                     GdkEventButton *event );
    96 
    97 static gint           sexy_icon_entry_button_release(
    98     GtkWidget *     widget,
    99     GdkEventButton *event );
     57static void sexy_icon_entry_class_init(SexyIconEntryClass *klass);
     58static void sexy_icon_entry_editable_init(GtkEditableClass *iface);
     59static void sexy_icon_entry_init(SexyIconEntry *entry);
     60static void sexy_icon_entry_finalize(GObject *obj);
     61static void sexy_icon_entry_destroy(GtkObject *obj);
     62static void sexy_icon_entry_map(GtkWidget *widget);
     63static void sexy_icon_entry_unmap(GtkWidget *widget);
     64static void sexy_icon_entry_realize(GtkWidget *widget);
     65static void sexy_icon_entry_unrealize(GtkWidget *widget);
     66static void sexy_icon_entry_size_request(GtkWidget *widget,
     67                                                                                  GtkRequisition *requisition);
     68static void sexy_icon_entry_size_allocate(GtkWidget *widget,
     69                                                                                   GtkAllocation *allocation);
     70static gint sexy_icon_entry_expose(GtkWidget *widget, GdkEventExpose *event);
     71static gint sexy_icon_entry_enter_notify(GtkWidget *widget,
     72                                                                                           GdkEventCrossing *event);
     73static gint sexy_icon_entry_leave_notify(GtkWidget *widget,
     74                                                                                           GdkEventCrossing *event);
     75static gint sexy_icon_entry_button_press(GtkWidget *widget,
     76                                                                                           GdkEventButton *event);
     77static gint sexy_icon_entry_button_release(GtkWidget *widget,
     78                                                                                                 GdkEventButton *event);
    10079
    10180static GtkEntryClass *parent_class = NULL;
    102 static guint          signals[LAST_SIGNAL] = {0};
    103 
    104 G_DEFINE_TYPE_EXTENDED( SexyIconEntry, sexy_icon_entry, GTK_TYPE_ENTRY,
    105                        0,
    106                        G_IMPLEMENT_INTERFACE( GTK_TYPE_EDITABLE,
    107                                               sexy_icon_entry_editable_init ) );
    108 
    109 static void
    110 sexy_icon_entry_class_init( SexyIconEntryClass *klass )
    111 {
    112     GObjectClass *  gobject_class;
    113     GtkObjectClass *object_class;
    114     GtkWidgetClass *widget_class;
    115 
    116     parent_class = g_type_class_peek_parent( klass );
    117 
    118     gobject_class = G_OBJECT_CLASS( klass );
    119     object_class  = GTK_OBJECT_CLASS( klass );
    120     widget_class  = GTK_WIDGET_CLASS( klass );
    121 
    122     gobject_class->finalize = sexy_icon_entry_finalize;
    123 
    124     object_class->destroy = sexy_icon_entry_destroy;
    125 
    126     widget_class->map = sexy_icon_entry_map;
    127     widget_class->unmap = sexy_icon_entry_unmap;
    128     widget_class->realize = sexy_icon_entry_realize;
    129     widget_class->unrealize = sexy_icon_entry_unrealize;
    130     widget_class->size_request = sexy_icon_entry_size_request;
    131     widget_class->size_allocate = sexy_icon_entry_size_allocate;
    132     widget_class->expose_event = sexy_icon_entry_expose;
    133     widget_class->enter_notify_event = sexy_icon_entry_enter_notify;
    134     widget_class->leave_notify_event = sexy_icon_entry_leave_notify;
    135     widget_class->button_press_event = sexy_icon_entry_button_press;
    136     widget_class->button_release_event = sexy_icon_entry_button_release;
    137 
    138     /**
    139      * SexyIconEntry::icon-pressed:
    140      * @entry: The entry on which the signal is emitted.
    141      * @icon_pos: The position of the clicked icon.
    142      * @button: The mouse button clicked.
    143      *
    144      * The ::icon-pressed signal is emitted when an icon is clicked.
    145      */
    146     signals[ICON_PRESSED] =
    147         g_signal_new( "icon_pressed",
    148                       G_TYPE_FROM_CLASS( gobject_class ),
    149                       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
    150                       G_STRUCT_OFFSET( SexyIconEntryClass, icon_pressed ),
    151                       NULL, NULL,
    152                       gtk_marshal_VOID__INT_INT,
    153                       G_TYPE_NONE, 2,
    154                       G_TYPE_INT,
    155                       G_TYPE_INT );
    156 
    157     /**
    158      * SexyIconEntry::icon-released:
    159      * @entry: The entry on which the signal is emitted.
    160      * @icon_pos: The position of the clicked icon.
    161      * @button: The mouse button clicked.
    162      *
    163      * The ::icon-released signal is emitted on the button release from a
    164      * mouse click.
    165      */
    166     signals[ICON_RELEASED] =
    167         g_signal_new( "icon_released",
    168                       G_TYPE_FROM_CLASS( gobject_class ),
    169                       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
    170                       G_STRUCT_OFFSET( SexyIconEntryClass, icon_released ),
    171                       NULL, NULL,
    172                       gtk_marshal_VOID__INT_INT,
    173                       G_TYPE_NONE, 2,
    174                       G_TYPE_INT,
    175                       G_TYPE_INT );
    176 }
    177 
    178 static void
    179 sexy_icon_entry_editable_init( GtkEditableClass *iface G_GNUC_UNUSED )
    180 {}
    181 
    182 static void
    183 sexy_icon_entry_init( SexyIconEntry *entry )
    184 {
    185     entry->priv = g_new0( SexyIconEntryPriv, 1 );
    186 }
    187 
    188 static void
    189 sexy_icon_entry_finalize( GObject *obj )
    190 {
    191     SexyIconEntry *entry;
    192 
    193     g_return_if_fail( obj != NULL );
    194     g_return_if_fail( SEXY_IS_ICON_ENTRY( obj ) );
    195 
    196     entry = SEXY_ICON_ENTRY( obj );
    197 
    198     g_free( entry->priv );
    199 
    200     if( G_OBJECT_CLASS( parent_class )->finalize )
    201         G_OBJECT_CLASS( parent_class )->finalize( obj );
    202 }
    203 
    204 static void
    205 sexy_icon_entry_destroy( GtkObject *obj )
    206 {
    207     SexyIconEntry *entry;
    208 
    209     entry = SEXY_ICON_ENTRY( obj );
    210 
    211     sexy_icon_entry_set_icon( entry, SEXY_ICON_ENTRY_PRIMARY, NULL );
    212     sexy_icon_entry_set_icon( entry, SEXY_ICON_ENTRY_SECONDARY, NULL );
    213 
    214     if( GTK_OBJECT_CLASS( parent_class )->destroy )
    215         GTK_OBJECT_CLASS( parent_class )->destroy( obj );
    216 }
    217 
    218 static void
    219 sexy_icon_entry_map( GtkWidget *widget )
    220 {
    221     if( GTK_WIDGET_REALIZED( widget ) && !GTK_WIDGET_MAPPED( widget ) )
    222     {
    223         SexyIconEntry *entry = SEXY_ICON_ENTRY( widget );
    224         int            i;
    225 
    226         GTK_WIDGET_CLASS( parent_class )->map( widget );
    227 
    228         for( i = 0; i < MAX_ICONS; i++ )
    229         {
    230             if( entry->priv->icons[i].icon != NULL )
    231                 gdk_window_show( entry->priv->icons[i].window );
    232         }
    233     }
    234 }
    235 
    236 static void
    237 sexy_icon_entry_unmap( GtkWidget *widget )
    238 {
    239     if( GTK_WIDGET_MAPPED( widget ) )
    240     {
    241         SexyIconEntry *entry = SEXY_ICON_ENTRY( widget );
    242         int            i;
    243 
    244         for( i = 0; i < MAX_ICONS; i++ )
    245         {
    246             if( entry->priv->icons[i].icon != NULL )
    247                 gdk_window_hide( entry->priv->icons[i].window );
    248         }
    249 
    250         GTK_WIDGET_CLASS( parent_class )->unmap( widget );
    251     }
     81static guint signals[LAST_SIGNAL] = {0};
     82
     83G_DEFINE_TYPE_EXTENDED(SexyIconEntry, sexy_icon_entry, GTK_TYPE_ENTRY,
     84                                           0,
     85                                           G_IMPLEMENT_INTERFACE(GTK_TYPE_EDITABLE,
     86                                                                                         sexy_icon_entry_editable_init));
     87
     88static void
     89sexy_icon_entry_class_init(SexyIconEntryClass *klass)
     90{
     91        GObjectClass *gobject_class;
     92        GtkObjectClass *object_class;
     93        GtkWidgetClass *widget_class;
     94        GtkEntryClass *entry_class;
     95
     96        parent_class = g_type_class_peek_parent(klass);
     97
     98        gobject_class = G_OBJECT_CLASS(klass);
     99        object_class  = GTK_OBJECT_CLASS(klass);
     100        widget_class  = GTK_WIDGET_CLASS(klass);
     101        entry_class   = GTK_ENTRY_CLASS(klass);
     102
     103        gobject_class->finalize = sexy_icon_entry_finalize;
     104
     105        object_class->destroy = sexy_icon_entry_destroy;
     106
     107        widget_class->map = sexy_icon_entry_map;
     108        widget_class->unmap = sexy_icon_entry_unmap;
     109        widget_class->realize = sexy_icon_entry_realize;
     110        widget_class->unrealize = sexy_icon_entry_unrealize;
     111        widget_class->size_request = sexy_icon_entry_size_request;
     112        widget_class->size_allocate = sexy_icon_entry_size_allocate;
     113        widget_class->expose_event = sexy_icon_entry_expose;
     114        widget_class->enter_notify_event = sexy_icon_entry_enter_notify;
     115        widget_class->leave_notify_event = sexy_icon_entry_leave_notify;
     116        widget_class->button_press_event = sexy_icon_entry_button_press;
     117        widget_class->button_release_event = sexy_icon_entry_button_release;
     118
     119        /**
     120         * SexyIconEntry::icon-pressed:
     121         * @entry: The entry on which the signal is emitted.
     122         * @icon_pos: The position of the clicked icon.
     123         * @button: The mouse button clicked.
     124         *
     125         * The ::icon-pressed signal is emitted when an icon is clicked.
     126         */
     127        signals[ICON_PRESSED] =
     128                g_signal_new("icon_pressed",
     129                                         G_TYPE_FROM_CLASS(gobject_class),
     130                                         G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
     131                                         G_STRUCT_OFFSET(SexyIconEntryClass, icon_pressed),
     132                                         NULL, NULL,
     133                                         sexy_marshal_VOID__INT_INT,
     134                                         G_TYPE_NONE, 2,
     135                                         G_TYPE_INT,
     136                                         G_TYPE_INT);
     137
     138        /**
     139         * SexyIconEntry::icon-released:
     140         * @entry: The entry on which the signal is emitted.
     141         * @icon_pos: The position of the clicked icon.
     142         * @button: The mouse button clicked.
     143         *
     144         * The ::icon-released signal is emitted on the button release from a
     145         * mouse click.
     146         */
     147        signals[ICON_RELEASED] =
     148                g_signal_new("icon_released",
     149                                         G_TYPE_FROM_CLASS(gobject_class),
     150                                         G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
     151                                         G_STRUCT_OFFSET(SexyIconEntryClass, icon_released),
     152                                         NULL, NULL,
     153                                         gtk_marshal_VOID__INT_INT,
     154                                         G_TYPE_NONE, 2,
     155                                         G_TYPE_INT,
     156                                         G_TYPE_INT);
     157}
     158
     159static void
     160sexy_icon_entry_editable_init(GtkEditableClass *iface G_GNUC_UNUSED)
     161{
     162};
     163
     164static void
     165sexy_icon_entry_init(SexyIconEntry *entry)
     166{
     167        entry->priv = g_new0(SexyIconEntryPriv, 1);
     168}
     169
     170static void
     171sexy_icon_entry_finalize(GObject *obj)
     172{
     173        SexyIconEntry *entry;
     174
     175        g_return_if_fail(obj != NULL);
     176        g_return_if_fail(SEXY_IS_ICON_ENTRY(obj));
     177
     178        entry = SEXY_ICON_ENTRY(obj);
     179
     180        g_free(entry->priv);
     181
     182        if (G_OBJECT_CLASS(parent_class)->finalize)
     183                G_OBJECT_CLASS(parent_class)->finalize(obj);
     184}
     185
     186static void
     187sexy_icon_entry_destroy(GtkObject *obj)
     188{
     189        SexyIconEntry *entry;
     190
     191        entry = SEXY_ICON_ENTRY(obj);
     192
     193        sexy_icon_entry_set_icon(entry, SEXY_ICON_ENTRY_PRIMARY, NULL);
     194        sexy_icon_entry_set_icon(entry, SEXY_ICON_ENTRY_SECONDARY, NULL);
     195
     196        if (GTK_OBJECT_CLASS(parent_class)->destroy)
     197                GTK_OBJECT_CLASS(parent_class)->destroy(obj);
     198}
     199
     200static void
     201sexy_icon_entry_map(GtkWidget *widget)
     202{
     203        if (GTK_WIDGET_REALIZED(widget) && !GTK_WIDGET_MAPPED(widget))
     204        {
     205                SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
     206                int i;
     207
     208                GTK_WIDGET_CLASS(parent_class)->map(widget);
     209
     210                for (i = 0; i < MAX_ICONS; i++)
     211                {
     212                        if (entry->priv->icons[i].icon != NULL)
     213                                gdk_window_show(entry->priv->icons[i].window);
     214                }
     215        }
     216}
     217
     218static void
     219sexy_icon_entry_unmap(GtkWidget *widget)
     220{
     221        if (GTK_WIDGET_MAPPED(widget))
     222        {
     223                SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
     224                int i;
     225
     226                for (i = 0; i < MAX_ICONS; i++)
     227                {
     228                        if (entry->priv->icons[i].icon != NULL)
     229                                gdk_window_hide(entry->priv->icons[i].window);
     230                }
     231
     232                GTK_WIDGET_CLASS(parent_class)->unmap(widget);
     233        }
    252234}
    253235
    254236static gint
    255 get_icon_width( SexyIconEntry *       entry,
    256                 SexyIconEntryPosition icon_pos )
    257 {
    258     GtkRequisition requisition;
    259     gint           menu_icon_width;
    260     gint           width;
    261     SexyIconInfo * icon_info = &entry->priv->icons[icon_pos];
    262 
    263     if( icon_info->icon == NULL )
    264         return 0;
    265 
    266     gtk_widget_size_request( GTK_WIDGET( icon_info->icon ), &requisition );
    267     gtk_icon_size_lookup( GTK_ICON_SIZE_MENU, &menu_icon_width, NULL );
    268 
    269     width = MAX( requisition.width, menu_icon_width );
    270 
    271     return width;
    272 }
    273 
    274 static void
    275 get_borders( SexyIconEntry *entry,
    276              gint *         xborder,
    277              gint *         yborder )
    278 {
    279     GtkWidget *widget = GTK_WIDGET( entry );
    280     gint       focus_width;
    281     gboolean   interior_focus;
    282 
    283     gtk_widget_style_get( widget,
    284                           "interior-focus", &interior_focus,
    285                           "focus-line-width", &focus_width,
    286                           NULL );
    287 
    288     if( gtk_entry_get_has_frame( GTK_ENTRY( entry ) ) )
    289     {
    290         *xborder = widget->style->xthickness;
    291         *yborder = widget->style->ythickness;
    292     }
    293     else
    294     {
    295         *xborder = 0;
    296         *yborder = 0;
    297     }
    298 
    299     if( !interior_focus )
    300     {
    301         *xborder += focus_width;
    302         *yborder += focus_width;
    303     }
    304 }
    305 
    306 static void
    307 get_text_area_size( SexyIconEntry *entry,
    308                     GtkAllocation *alloc )
    309 {
    310     GtkWidget *    widget = GTK_WIDGET( entry );
    311     GtkRequisition requisition;
    312     gint           xborder, yborder;
    313 
    314     gtk_widget_get_child_requisition( widget, &requisition );
    315     get_borders( entry, &xborder, &yborder );
    316 
    317     alloc->x      = xborder;
    318     alloc->y      = yborder;
    319     alloc->width  = widget->allocation.width - xborder * 2;
    320     alloc->height = requisition.height       - yborder * 2;
    321 }
    322 
    323 static void
    324 get_icon_allocation( SexyIconEntry *             icon_entry,
    325                      gboolean                    left,
    326                      GtkAllocation *widget_alloc G_GNUC_UNUSED,
    327                      GtkAllocation *             text_area_alloc,
    328                      GtkAllocation *             allocation,
    329                      SexyIconEntryPosition *     icon_pos )
    330 {
    331     gboolean rtl;
    332 
    333     rtl = ( gtk_widget_get_direction( GTK_WIDGET( icon_entry ) ) ==
    334             GTK_TEXT_DIR_RTL );
    335 
    336     if( left )
    337         *icon_pos =
    338             ( rtl ? SEXY_ICON_ENTRY_SECONDARY : SEXY_ICON_ENTRY_PRIMARY );
    339     else
    340         *icon_pos =
    341             ( rtl ? SEXY_ICON_ENTRY_PRIMARY : SEXY_ICON_ENTRY_SECONDARY );
    342 
    343     allocation->y = text_area_alloc->y;
    344     allocation->width = get_icon_width( icon_entry, *icon_pos );
    345     allocation->height = text_area_alloc->height;
    346 
    347     if( left )
    348         allocation->x = text_area_alloc->x + ICON_MARGIN;
    349     else
    350     {
    351         allocation->x = text_area_alloc->x + text_area_alloc->width -
    352                         allocation->width - ICON_MARGIN;
    353     }
    354 }
    355 
    356 static void
    357 sexy_icon_entry_realize( GtkWidget *widget )
    358 {
    359     SexyIconEntry *entry = SEXY_ICON_ENTRY( widget );
    360     GdkWindowAttr  attributes;
    361     gint           attributes_mask;
    362     int            i;
    363 
    364     GTK_WIDGET_CLASS( parent_class )->realize( widget );
    365 
    366     attributes.x = 0;
    367     attributes.y = 0;
    368     attributes.width = 1;
    369     attributes.height = 1;
    370     attributes.window_type = GDK_WINDOW_CHILD;
    371     attributes.wclass = GDK_INPUT_OUTPUT;
    372     attributes.visual = gtk_widget_get_visual( widget );
    373     attributes.colormap = gtk_widget_get_colormap( widget );
    374     attributes.event_mask = gtk_widget_get_events( widget );
    375     attributes.event_mask |=
    376         ( GDK_EXPOSURE_MASK
    377           | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
    378           | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK );
    379 
    380     attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
    381 
    382     for( i = 0; i < MAX_ICONS; i++ )
    383     {
    384         SexyIconInfo *icon_info;
    385 
    386         icon_info = &entry->priv->icons[i];
    387         icon_info->window = gdk_window_new( widget->window, &attributes,
    388                                             attributes_mask );
    389         gdk_window_set_user_data( icon_info->window, widget );
    390 
    391         gdk_window_set_background( icon_info->window,
    392                                    &widget->style->base[GTK_WIDGET_STATE(
    393                                                             widget )] );
    394     }
    395 
    396     gtk_widget_queue_resize( widget );
    397 }
    398 
    399 static void
    400 sexy_icon_entry_unrealize( GtkWidget *widget )
    401 {
    402     SexyIconEntry *entry = SEXY_ICON_ENTRY( widget );
    403     int            i;
    404 
    405     GTK_WIDGET_CLASS( parent_class )->unrealize( widget );
    406 
    407     for( i = 0; i < MAX_ICONS; i++ )
    408     {
    409         SexyIconInfo *icon_info = &entry->priv->icons[i];
    410 
    411         gdk_window_destroy( icon_info->window );
    412         icon_info->window = NULL;
    413     }
    414 }
    415 
    416 static void
    417 sexy_icon_entry_size_request( GtkWidget *     widget,
    418                               GtkRequisition *requisition )
    419 {
    420     SexyIconEntry *entry;
    421     gint           icon_widths = 0;
    422     int            i;
    423 
    424     entry    = SEXY_ICON_ENTRY( widget );
    425 
    426     for( i = 0; i < MAX_ICONS; i++ )
    427     {
    428         int icon_width = get_icon_width( entry, i );
    429 
    430         if( icon_width > 0 )
    431             icon_widths += icon_width + ICON_MARGIN;
    432     }
    433 
    434     GTK_WIDGET_CLASS( parent_class )->size_request( widget, requisition );
    435 
    436     if( icon_widths > requisition->width )
    437         requisition->width += icon_widths;
    438 }
    439 
    440 static void
    441 place_windows( SexyIconEntry *icon_entry,
    442                GtkAllocation *widget_alloc )
    443 {
    444     SexyIconEntryPosition left_icon_pos;
    445     SexyIconEntryPosition right_icon_pos;
    446     GtkAllocation         left_icon_alloc;
    447     GtkAllocation         right_icon_alloc;
    448     GtkAllocation         text_area_alloc;
    449 
    450     get_text_area_size( icon_entry, &text_area_alloc );
    451     get_icon_allocation( icon_entry, TRUE, widget_alloc, &text_area_alloc,
    452                          &left_icon_alloc, &left_icon_pos );
    453     get_icon_allocation( icon_entry, FALSE, widget_alloc, &text_area_alloc,
    454                          &right_icon_alloc, &right_icon_pos );
    455 
    456     if( left_icon_alloc.width > 0 )
    457     {
    458         text_area_alloc.x = left_icon_alloc.x + left_icon_alloc.width +
    459                             ICON_MARGIN;
    460     }
    461 
    462     if( right_icon_alloc.width > 0 )
    463         text_area_alloc.width -= right_icon_alloc.width + ICON_MARGIN;
    464 
    465     text_area_alloc.width -= text_area_alloc.x;
    466 
    467     gdk_window_move_resize( icon_entry->priv->icons[left_icon_pos].window,
    468                             left_icon_alloc.x, left_icon_alloc.y,
    469                             left_icon_alloc.width, left_icon_alloc.height );
    470 
    471     gdk_window_move_resize( icon_entry->priv->icons[right_icon_pos].window,
    472                             right_icon_alloc.x, right_icon_alloc.y,
    473                             right_icon_alloc.width, right_icon_alloc.height );
    474 
    475     gdk_window_move_resize( GTK_ENTRY( icon_entry )->text_area,
    476                             text_area_alloc.x, text_area_alloc.y,
    477                             text_area_alloc.width, text_area_alloc.height );
    478 }
    479 
    480 static void
    481 sexy_icon_entry_size_allocate( GtkWidget *    widget,
    482                                GtkAllocation *allocation )
    483 {
    484     g_return_if_fail( SEXY_IS_ICON_ENTRY( widget ) );
    485     g_return_if_fail( allocation != NULL );
    486 
    487     widget->allocation = *allocation;
    488 
    489     GTK_WIDGET_CLASS( parent_class )->size_allocate( widget, allocation );
    490 
    491     if( GTK_WIDGET_REALIZED( widget ) )
    492         place_windows( SEXY_ICON_ENTRY( widget ), allocation );
     237get_icon_width(SexyIconEntry *entry, SexyIconEntryPosition icon_pos)
     238{
     239        GtkRequisition requisition;
     240        gint menu_icon_width;
     241        gint width;
     242        SexyIconInfo *icon_info = &entry->priv->icons[icon_pos];
     243
     244        if (icon_info->icon == NULL)
     245                return 0;
     246
     247        gtk_widget_size_request(GTK_WIDGET(icon_info->icon), &requisition);
     248        gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &menu_icon_width, NULL);
     249
     250        width = MAX(requisition.width, menu_icon_width);
     251
     252        return width;
     253}
     254
     255static void
     256get_borders(SexyIconEntry *entry, gint *xborder, gint *yborder)
     257{
     258        GtkWidget *widget = GTK_WIDGET(entry);
     259        gint focus_width;
     260        gboolean interior_focus;
     261
     262        gtk_widget_style_get(widget,
     263                                                 "interior-focus", &interior_focus,
     264                                                 "focus-line-width", &focus_width,
     265                                                 NULL);
     266
     267        if (gtk_entry_get_has_frame(GTK_ENTRY(entry)))
     268        {
     269                *xborder = widget->style->xthickness;
     270                *yborder = widget->style->ythickness;
     271        }
     272        else
     273        {
     274                *xborder = 0;
     275                *yborder = 0;
     276        }
     277
     278        if (!interior_focus)
     279        {
     280                *xborder += focus_width;
     281                *yborder += focus_width;
     282        }
     283}
     284
     285static void
     286get_text_area_size(SexyIconEntry *entry, GtkAllocation *alloc)
     287{
     288        GtkWidget *widget = GTK_WIDGET(entry);
     289        GtkRequisition requisition;
     290        gint xborder, yborder;
     291
     292        gtk_widget_get_child_requisition(widget, &requisition);
     293        get_borders(entry, &xborder, &yborder);
     294
     295        alloc->x      = xborder;
     296        alloc->y      = yborder;
     297        alloc->width  = widget->allocation.width - xborder * 2;
     298        alloc->height = requisition.height       - yborder * 2;
     299}
     300
     301static void
     302get_icon_allocation(SexyIconEntry *icon_entry,
     303                                        gboolean left,
     304                                        GtkAllocation *widget_alloc G_GNUC_UNUSED,
     305                                        GtkAllocation *text_area_alloc,
     306                                        GtkAllocation *allocation,
     307                                        SexyIconEntryPosition *icon_pos)
     308{
     309        gboolean rtl;
     310
     311        rtl = (gtk_widget_get_direction(GTK_WIDGET(icon_entry)) ==
     312                   GTK_TEXT_DIR_RTL);
     313
     314        if (left)
     315                *icon_pos = (rtl ? SEXY_ICON_ENTRY_SECONDARY : SEXY_ICON_ENTRY_PRIMARY);
     316        else
     317                *icon_pos = (rtl ? SEXY_ICON_ENTRY_PRIMARY : SEXY_ICON_ENTRY_SECONDARY);
     318
     319        allocation->y = text_area_alloc->y;
     320        allocation->width = get_icon_width(icon_entry, *icon_pos);
     321        allocation->height = text_area_alloc->height;
     322
     323        if (left)
     324                allocation->x = text_area_alloc->x + ICON_MARGIN;
     325        else
     326        {
     327                allocation->x = text_area_alloc->x + text_area_alloc->width -
     328                                allocation->width - ICON_MARGIN;
     329        }
     330}
     331
     332static void
     333sexy_icon_entry_realize(GtkWidget *widget)
     334{
     335        SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
     336        GdkWindowAttr attributes;
     337        gint attributes_mask;
     338        int i;
     339
     340        GTK_WIDGET_CLASS(parent_class)->realize(widget);
     341
     342        attributes.x = 0;
     343        attributes.y = 0;
     344        attributes.width = 1;
     345        attributes.height = 1;
     346        attributes.window_type = GDK_WINDOW_CHILD;
     347        attributes.wclass = GDK_INPUT_OUTPUT;
     348        attributes.visual = gtk_widget_get_visual(widget);
     349        attributes.colormap = gtk_widget_get_colormap(widget);
     350        attributes.event_mask = gtk_widget_get_events(widget);
     351        attributes.event_mask |=
     352                (GDK_EXPOSURE_MASK
     353                 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
     354                 | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
     355
     356        attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
     357
     358        for (i = 0; i < MAX_ICONS; i++)
     359        {
     360                SexyIconInfo *icon_info;
     361
     362                icon_info = &entry->priv->icons[i];
     363                icon_info->window = gdk_window_new(widget->window, &attributes,
     364                                                                                   attributes_mask);
     365                gdk_window_set_user_data(icon_info->window, widget);
     366
     367                gdk_window_set_background(icon_info->window,
     368                        &widget->style->base[GTK_WIDGET_STATE(widget)]);
     369        }
     370
     371        gtk_widget_queue_resize(widget);
     372}
     373
     374static void
     375sexy_icon_entry_unrealize(GtkWidget *widget)
     376{
     377        SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
     378        int i;
     379
     380        GTK_WIDGET_CLASS(parent_class)->unrealize(widget);
     381
     382        for (i = 0; i < MAX_ICONS; i++)
     383        {
     384                SexyIconInfo *icon_info = &entry->priv->icons[i];
     385
     386                gdk_window_destroy(icon_info->window);
     387                icon_info->window = NULL;
     388        }
     389}
     390
     391static void
     392sexy_icon_entry_size_request(GtkWidget *widget, GtkRequisition *requisition)
     393{
     394        GtkEntry *gtkentry;
     395        SexyIconEntry *entry;
     396        gint icon_widths = 0;
     397        int i;
     398
     399        gtkentry = GTK_ENTRY(widget);
     400        entry    = SEXY_ICON_ENTRY(widget);
     401
     402        for (i = 0; i < MAX_ICONS; i++)
     403        {
     404                int icon_width = get_icon_width(entry, i);
     405
     406                if (icon_width > 0)
     407                        icon_widths += icon_width + ICON_MARGIN;
     408        }
     409
     410        GTK_WIDGET_CLASS(parent_class)->size_request(widget, requisition);
     411
     412        if (icon_widths > requisition->width)
     413                requisition->width += icon_widths;
     414}
     415
     416static void
     417place_windows(SexyIconEntry *icon_entry, GtkAllocation *widget_alloc)
     418{
     419        SexyIconEntryPosition left_icon_pos;
     420        SexyIconEntryPosition right_icon_pos;
     421        GtkAllocation left_icon_alloc;
     422        GtkAllocation right_icon_alloc;
     423        GtkAllocation text_area_alloc;
     424
     425        get_text_area_size(icon_entry, &text_area_alloc);
     426        get_icon_allocation(icon_entry, TRUE, widget_alloc, &text_area_alloc,
     427                                                &left_icon_alloc, &left_icon_pos);
     428        get_icon_allocation(icon_entry, FALSE, widget_alloc, &text_area_alloc,
     429                                                &right_icon_alloc, &right_icon_pos);
     430
     431        if (left_icon_alloc.width > 0)
     432        {
     433                text_area_alloc.x = left_icon_alloc.x + left_icon_alloc.width +
     434                                    ICON_MARGIN;
     435        }
     436
     437        if (right_icon_alloc.width > 0)
     438                text_area_alloc.width -= right_icon_alloc.width + ICON_MARGIN;
     439
     440        text_area_alloc.width -= text_area_alloc.x;
     441
     442        gdk_window_move_resize(icon_entry->priv->icons[left_icon_pos].window,
     443                                                   left_icon_alloc.x, left_icon_alloc.y,
     444                                                   left_icon_alloc.width, left_icon_alloc.height);
     445
     446        gdk_window_move_resize(icon_entry->priv->icons[right_icon_pos].window,
     447                                                   right_icon_alloc.x, right_icon_alloc.y,
     448                                                   right_icon_alloc.width, right_icon_alloc.height);
     449
     450        gdk_window_move_resize(GTK_ENTRY(icon_entry)->text_area,
     451                                                   text_area_alloc.x, text_area_alloc.y,
     452                                                   text_area_alloc.width, text_area_alloc.height);
     453}
     454
     455static void
     456sexy_icon_entry_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
     457{
     458        g_return_if_fail(SEXY_IS_ICON_ENTRY(widget));
     459        g_return_if_fail(allocation != NULL);
     460
     461        widget->allocation = *allocation;
     462
     463        GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation);
     464
     465        if (GTK_WIDGET_REALIZED(widget))
     466                place_windows(SEXY_ICON_ENTRY(widget), allocation);
    493467}
    494468
    495469static GdkPixbuf *
    496 get_pixbuf_from_icon( SexyIconEntry *       entry,
    497                       SexyIconEntryPosition icon_pos )
    498 {
    499     GdkPixbuf *   pixbuf = NULL;
    500     gchar *       stock_id;
    501     SexyIconInfo *icon_info = &entry->priv->icons[icon_pos];
    502     GtkIconSize   size;
    503 
    504     switch( gtk_image_get_storage_type( GTK_IMAGE( icon_info->icon ) ) )
    505     {
    506         case GTK_IMAGE_PIXBUF:
    507             pixbuf = gtk_image_get_pixbuf( GTK_IMAGE( icon_info->icon ) );
    508             g_object_ref( pixbuf );
    509             break;
    510 
    511         case GTK_IMAGE_STOCK:
    512             gtk_image_get_stock( GTK_IMAGE(
    513                                      icon_info->icon ), &stock_id, &size );
    514             pixbuf = gtk_widget_render_icon( GTK_WIDGET( entry ),
    515                                              stock_id, size, NULL );
    516             break;
    517 
    518         default:
    519             return NULL;
    520     }
    521 
    522     return pixbuf;
     470get_pixbuf_from_icon(SexyIconEntry *entry, SexyIconEntryPosition icon_pos)
     471{
     472        GdkPixbuf *pixbuf = NULL;
     473        const gchar *stock_id;
     474        SexyIconInfo *icon_info = &entry->priv->icons[icon_pos];
     475        GtkIconSize size;
     476        int w, h;
     477
     478        switch (gtk_image_get_storage_type(GTK_IMAGE(icon_info->icon)))
     479        {
     480                case GTK_IMAGE_PIXBUF:
     481                        pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(icon_info->icon));
     482                        g_object_ref(pixbuf);
     483                        break;
     484
     485                case GTK_IMAGE_STOCK:
     486                        gtk_image_get_stock(GTK_IMAGE(icon_info->icon), (char**)&stock_id, &size);
     487                        pixbuf = gtk_widget_render_icon(GTK_WIDGET(entry),
     488                                                                                        stock_id, size, NULL);
     489                        break;
     490
     491                case GTK_IMAGE_ICON_NAME:
     492                        gtk_image_get_icon_name (GTK_IMAGE(icon_info->icon), &stock_id, &size);
     493                        gtk_icon_size_lookup (size, &w, &h);
     494                        pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), stock_id, size, 0, NULL);
     495                        break;
     496         
     497                default:
     498                        return NULL;
     499        }
     500
     501        return pixbuf;
    523502}
    524503
    525504/* Kudos to the gnome-panel guys. */
    526505static void
    527 colorshift_pixbuf( GdkPixbuf *dest,
    528                    GdkPixbuf *src,
    529                    int        shift )
    530 {
    531     gint    i, j;
    532     gint    width, height, has_alpha, src_rowstride, dest_rowstride;
    533     guchar *target_pixels;
    534     guchar *original_pixels;
    535     guchar *pix_src;
    536     guchar *pix_dest;
    537     int     val;
    538     guchar  r, g, b;
    539 
    540     has_alpha       = gdk_pixbuf_get_has_alpha( src );
    541     width           = gdk_pixbuf_get_width( src );
    542     height          = gdk_pixbuf_get_height( src );
    543     src_rowstride   = gdk_pixbuf_get_rowstride( src );
    544     dest_rowstride  = gdk_pixbuf_get_rowstride( dest );
    545     original_pixels = gdk_pixbuf_get_pixels( src );
    546     target_pixels   = gdk_pixbuf_get_pixels( dest );
    547 
    548     for( i = 0; i < height; i++ )
    549     {
    550         pix_dest = target_pixels   + i * dest_rowstride;
    551         pix_src  = original_pixels + i * src_rowstride;
    552 
    553         for( j = 0; j < width; j++ )
    554         {
    555             r = *( pix_src++ );
    556             g = *( pix_src++ );
    557             b = *( pix_src++ );
    558 
    559             val = r + shift;
    560             *( pix_dest++ ) = CLAMP( val, 0, 255 );
    561 
    562             val = g + shift;
    563             *( pix_dest++ ) = CLAMP( val, 0, 255 );
    564 
    565             val = b + shift;
    566             *( pix_dest++ ) = CLAMP( val, 0, 255 );
    567 
    568             if( has_alpha )
    569                 *( pix_dest++ ) = *( pix_src++ );
    570         }
    571     }
    572 }
    573 
    574 static void
    575 draw_icon( GtkWidget *           widget,
    576            SexyIconEntryPosition icon_pos )
    577 {
    578     SexyIconEntry *entry = SEXY_ICON_ENTRY( widget );
    579     SexyIconInfo * icon_info = &entry->priv->icons[icon_pos];
    580     GdkPixbuf *    pixbuf;
    581     gint           x, y, width, height;
    582 
    583     if( icon_info->icon == NULL || !GTK_WIDGET_REALIZED( widget ) )
    584         return;
    585 
    586     if( ( pixbuf = get_pixbuf_from_icon( entry, icon_pos ) ) == NULL )
    587         return;
    588 
    589     gdk_drawable_get_size( icon_info->window, &width, &height );
    590 
    591     if( width == 1 || height == 1 )
    592     {
    593         /*
    594          * size_allocate hasn't been called yet. These are the default values.
    595          */
    596         return;
    597     }
    598 
    599     if( gdk_pixbuf_get_height( pixbuf ) > height )
    600     {
    601         GdkPixbuf *temp_pixbuf;
    602         int        scale;
    603 
    604         scale = height - ( 2 * ICON_MARGIN );
    605 
    606         temp_pixbuf = gdk_pixbuf_scale_simple( pixbuf, scale, scale,
    607                                                GDK_INTERP_BILINEAR );
    608 
    609         g_object_unref( pixbuf );
    610 
    611         pixbuf = temp_pixbuf;
    612     }
    613 
    614     x = ( width  - gdk_pixbuf_get_width( pixbuf ) ) / 2;
    615     y = ( height - gdk_pixbuf_get_height( pixbuf ) ) / 2;
    616 
    617     if( icon_info->hovered )
    618     {
    619         GdkPixbuf *temp_pixbuf;
    620 
    621         temp_pixbuf = gdk_pixbuf_copy( pixbuf );
    622 
    623         colorshift_pixbuf( temp_pixbuf, pixbuf, 30 );
    624 
    625         g_object_unref( pixbuf );
    626 
    627         pixbuf = temp_pixbuf;
    628     }
    629 
    630     gdk_draw_pixbuf( icon_info->window, widget->style->black_gc, pixbuf,
    631                      0, 0, x, y, -1, -1,
    632                      GDK_RGB_DITHER_NORMAL, 0, 0 );
    633 
    634     g_object_unref( pixbuf );
     506colorshift_pixbuf(GdkPixbuf *dest, GdkPixbuf *src, int shift)
     507{
     508        gint i, j;
     509        gint width, height, has_alpha, src_rowstride, dest_rowstride;
     510        guchar *target_pixels;
     511        guchar *original_pixels;
     512        guchar *pix_src;
     513        guchar *pix_dest;
     514        int val;
     515        guchar r, g, b;
     516
     517        has_alpha       = gdk_pixbuf_get_has_alpha(src);
     518        width           = gdk_pixbuf_get_width(src);
     519        height          = gdk_pixbuf_get_height(src);
     520        src_rowstride   = gdk_pixbuf_get_rowstride(src);
     521        dest_rowstride  = gdk_pixbuf_get_rowstride(dest);
     522        original_pixels = gdk_pixbuf_get_pixels(src);
     523        target_pixels   = gdk_pixbuf_get_pixels(dest);
     524
     525        for (i = 0; i < height; i++)
     526        {
     527                pix_dest = target_pixels   + i * dest_rowstride;
     528                pix_src  = original_pixels + i * src_rowstride;
     529
     530                for (j = 0; j < width; j++)
     531                {
     532                        r = *(pix_src++);
     533                        g = *(pix_src++);
     534                        b = *(pix_src++);
     535
     536                        val = r + shift;
     537                        *(pix_dest++) = CLAMP(val, 0, 255);
     538
     539                        val = g + shift;
     540                        *(pix_dest++) = CLAMP(val, 0, 255);
     541
     542                        val = b + shift;
     543                        *(pix_dest++) = CLAMP(val, 0, 255);
     544
     545                        if (has_alpha)
     546                                *(pix_dest++) = *(pix_src++);
     547                }
     548        }
     549}
     550
     551static void
     552draw_icon(GtkWidget *widget, SexyIconEntryPosition icon_pos)
     553{
     554        SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
     555        SexyIconInfo *icon_info = &entry->priv->icons[icon_pos];
     556        GdkPixbuf *pixbuf;
     557        gint x, y, width, height;
     558
     559        if (icon_info->icon == NULL || !GTK_WIDGET_REALIZED(widget))
     560                return;
     561
     562        if ((pixbuf = get_pixbuf_from_icon(entry, icon_pos)) == NULL)
     563                return;
     564
     565        gdk_drawable_get_size(icon_info->window, &width, &height);
     566
     567        if (width == 1 || height == 1)
     568        {
     569                /*
     570                 * size_allocate hasn't been called yet. These are the default values.
     571                 */
     572                return;
     573        }
     574
     575        if (gdk_pixbuf_get_height(pixbuf) > height)
     576        {
     577                GdkPixbuf *temp_pixbuf;
     578                int scale;
     579
     580                scale = height - (2 * ICON_MARGIN);
     581
     582                temp_pixbuf = gdk_pixbuf_scale_simple(pixbuf, scale, scale,
     583                                                                                          GDK_INTERP_BILINEAR);
     584
     585                g_object_unref(pixbuf);
     586
     587                pixbuf = temp_pixbuf;
     588        }
     589
     590        x = (width  - gdk_pixbuf_get_width(pixbuf)) / 2;
     591        y = (height - gdk_pixbuf_get_height(pixbuf)) / 2;
     592
     593        if (icon_info->hovered)
     594        {
     595                GdkPixbuf *temp_pixbuf;
     596
     597                temp_pixbuf = gdk_pixbuf_copy(pixbuf);
     598
     599                colorshift_pixbuf(temp_pixbuf, pixbuf, 30);
     600
     601                g_object_unref(pixbuf);
     602
     603                pixbuf = temp_pixbuf;
     604        }
     605
     606        gdk_draw_pixbuf(icon_info->window, widget->style->black_gc, pixbuf,
     607                                        0, 0, x, y, -1, -1,
     608                                        GDK_RGB_DITHER_NORMAL, 0, 0);
     609
     610        g_object_unref(pixbuf);
    635611}
    636612
    637613static gint
    638 sexy_icon_entry_expose( GtkWidget *     widget,
    639                         GdkEventExpose *event )
    640 {
    641     SexyIconEntry *entry;
    642 
    643     g_return_val_if_fail( SEXY_IS_ICON_ENTRY( widget ), FALSE );
    644     g_return_val_if_fail( event != NULL, FALSE );
    645 
    646     entry = SEXY_ICON_ENTRY( widget );
    647 
    648     if( GTK_WIDGET_DRAWABLE( widget ) )
    649     {
    650         gboolean found = FALSE;
    651         int      i;
    652 
    653         for( i = 0; i < MAX_ICONS && !found; i++ )
    654         {
    655             SexyIconInfo *icon_info = &entry->priv->icons[i];
    656 
    657             if( event->window == icon_info->window )
    658             {
    659                 gint          width;
    660                 GtkAllocation text_area_alloc;
    661 
    662                 get_text_area_size( entry, &text_area_alloc );
    663                 gdk_drawable_get_size( icon_info->window, &width, NULL );
    664 
    665                 gtk_paint_flat_box( widget->style, icon_info->window,
    666                                     GTK_WIDGET_STATE(
    667                                         widget ), GTK_SHADOW_NONE,
    668                                     NULL, widget, "entry_bg",
    669                                     0, 0, width, text_area_alloc.height );
    670 
    671                 draw_icon( widget, i );
    672 
    673                 found = TRUE;
    674             }
    675         }
    676 
    677         if( !found )
    678             GTK_WIDGET_CLASS( parent_class )->expose_event( widget, event );
    679     }
    680 
    681     return FALSE;
    682 }
    683 
    684 static void
    685 update_icon( GObject *obj   G_GNUC_UNUSED,
    686              GParamSpec *   param,
    687              SexyIconEntry *entry )
    688 {
    689     if( param != NULL )
    690     {
    691         const char *name = g_param_spec_get_name( param );
    692 
    693         if( strcmp( name, "pixbuf" )   && strcmp( name, "stock" )
    694           && strcmp( name, "image" )    && strcmp( name, "pixmap" )
    695           && strcmp( name, "icon_set" ) && strcmp( name, "pixbuf_animation" ) )
    696         {
    697             return;
    698         }
    699     }
    700 
    701     gtk_widget_queue_resize( GTK_WIDGET( entry ) );
     614sexy_icon_entry_expose(GtkWidget *widget, GdkEventExpose *event)
     615{
     616        SexyIconEntry *entry;
     617
     618        g_return_val_if_fail(SEXY_IS_ICON_ENTRY(widget), FALSE);
     619        g_return_val_if_fail(event != NULL, FALSE);
     620
     621        entry = SEXY_ICON_ENTRY(widget);
     622
     623        if (GTK_WIDGET_DRAWABLE(widget))
     624        {
     625                gboolean found = FALSE;
     626                int i;
     627
     628                for (i = 0; i < MAX_ICONS && !found; i++)
     629                {
     630                        SexyIconInfo *icon_info = &entry->priv->icons[i];
     631
     632                        if (event->window == icon_info->window)
     633                        {
     634                                gint width;
     635                                GtkAllocation text_area_alloc;
     636
     637                                get_text_area_size(entry, &text_area_alloc);
     638                                gdk_drawable_get_size(icon_info->window, &width, NULL);
     639
     640                                gtk_paint_flat_box(widget->style, icon_info->window,
     641                                                                   GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE,
     642                                                                   NULL, widget, "entry_bg",
     643                                                                   0, 0, width, text_area_alloc.height);
     644
     645                                draw_icon(widget, i);
     646
     647                                found = TRUE;
     648                        }
     649                }
     650
     651                if (!found)
     652                        GTK_WIDGET_CLASS(parent_class)->expose_event(widget, event);
     653        }
     654
     655        return FALSE;
     656}
     657
     658static void
     659update_icon(GObject *obj G_GNUC_UNUSED, GParamSpec *param, SexyIconEntry *entry)
     660{
     661        if (param != NULL)
     662        {
     663                const char *name = g_param_spec_get_name(param);
     664
     665                if (strcmp(name, "pixbuf")   && strcmp(name, "stock")  &&
     666                        strcmp(name, "image")    && strcmp(name, "pixmap") &&
     667                        strcmp(name, "icon-set") && strcmp(name, "pixbuf-animation") &&
     668                        strcmp(name, "icon-name"))
     669                {
     670                        return;
     671                }
     672        }
     673
     674        gtk_widget_queue_resize(GTK_WIDGET(entry));
    702675}
    703676
    704677static gint
    705 sexy_icon_entry_enter_notify( GtkWidget *       widget,
    706                               GdkEventCrossing *event )
    707 {
    708     SexyIconEntry *entry = SEXY_ICON_ENTRY( widget );
    709     int            i;
    710 
    711     for( i = 0; i < MAX_ICONS; i++ )
    712     {
    713         if( event->window == entry->priv->icons[i].window )
    714         {
    715             if( sexy_icon_entry_get_icon_highlight( entry, i ) )
    716             {
    717                 entry->priv->icons[i].hovered = TRUE;
    718 
    719                 update_icon( NULL, NULL, entry );
    720 
    721                 break;
    722             }
    723         }
    724     }
    725 
    726     return FALSE;
     678sexy_icon_entry_enter_notify(GtkWidget *widget, GdkEventCrossing *event)
     679{
     680        SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
     681        int i;
     682
     683        for (i = 0; i < MAX_ICONS; i++)
     684        {
     685                if (event->window == entry->priv->icons[i].window)
     686                {
     687                        if (sexy_icon_entry_get_icon_highlight(entry, i))
     688                        {
     689                                entry->priv->icons[i].hovered = TRUE;
     690
     691                                update_icon(NULL, NULL, entry);
     692
     693                                break;
     694                        }
     695                }
     696        }
     697
     698        return FALSE;
    727699}
    728700
    729701static gint
    730 sexy_icon_entry_leave_notify( GtkWidget *       widget,
    731                               GdkEventCrossing *event )
    732 {
    733     SexyIconEntry *entry = SEXY_ICON_ENTRY( widget );
    734     int            i;
    735 
    736     for( i = 0; i < MAX_ICONS; i++ )
    737     {
    738         if( event->window == entry->priv->icons[i].window )
    739         {
    740             if( sexy_icon_entry_get_icon_highlight( entry, i ) )
    741             {
    742                 entry->priv->icons[i].hovered = FALSE;
    743 
    744                 update_icon( NULL, NULL, entry );
    745 
    746                 break;
    747             }
    748         }
    749     }
    750 
    751     return FALSE;
     702sexy_icon_entry_leave_notify(GtkWidget *widget, GdkEventCrossing *event)
     703{
     704        SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
     705        int i;
     706
     707        for (i = 0; i < MAX_ICONS; i++)
     708        {
     709                if (event->window == entry->priv->icons[i].window)
     710                {
     711                        if (sexy_icon_entry_get_icon_highlight(entry, i))
     712                        {
     713                                entry->priv->icons[i].hovered = FALSE;
     714
     715                                update_icon(NULL, NULL, entry);
     716
     717                                break;
     718                        }
     719                }
     720        }
     721
     722        return FALSE;
    752723}
    753724
    754725static gint
    755 sexy_icon_entry_button_press( GtkWidget *     widget,
    756                               GdkEventButton *event )
    757 {
    758     SexyIconEntry *entry = SEXY_ICON_ENTRY( widget );
    759     int            i;
    760 
    761     for( i = 0; i < MAX_ICONS; i++ )
    762     {
    763         if( event->window == entry->priv->icons[i].window )
    764         {
    765             if( event->button == 1
    766               && sexy_icon_entry_get_icon_highlight( entry, i ) )
    767             {
    768                 entry->priv->icons[i].hovered = FALSE;
    769 
    770                 update_icon( NULL, NULL, entry );
    771             }
    772 
    773             g_signal_emit( entry, signals[ICON_PRESSED], 0, i,
    774                            event->button );
    775 
    776             return TRUE;
    777         }
    778     }
    779 
    780     if( GTK_WIDGET_CLASS( parent_class )->button_press_event )
    781         return GTK_WIDGET_CLASS( parent_class )->button_press_event( widget,
    782                                                                      event );
    783 
    784     return FALSE;
     726sexy_icon_entry_button_press(GtkWidget *widget, GdkEventButton *event)
     727{
     728        SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
     729        int i;
     730
     731        for (i = 0; i < MAX_ICONS; i++)
     732        {
     733                if (event->window == entry->priv->icons[i].window)
     734                {
     735                        if (event->button == 1 &&
     736                                sexy_icon_entry_get_icon_highlight(entry, i))
     737                        {
     738                                entry->priv->icons[i].hovered = FALSE;
     739
     740                                update_icon(NULL, NULL, entry);
     741                        }
     742
     743                        g_signal_emit(entry, signals[ICON_PRESSED], 0, i, event->button);
     744
     745                        return TRUE;
     746                }
     747        }
     748
     749        if (GTK_WIDGET_CLASS(parent_class)->button_press_event)
     750                return GTK_WIDGET_CLASS(parent_class)->button_press_event(widget,
     751                                                                                                                                  event);
     752
     753        return FALSE;
    785754}
    786755
    787756static gint
    788 sexy_icon_entry_button_release( GtkWidget *     widget,
    789                                 GdkEventButton *event )
    790 {
    791     SexyIconEntry *entry = SEXY_ICON_ENTRY( widget );
    792     int            i;
    793 
    794     for( i = 0; i < MAX_ICONS; i++ )
    795     {
    796         GdkWindow *icon_window = entry->priv->icons[i].window;
    797 
    798         if( event->window == icon_window )
    799         {
    800             int width, height;
    801             gdk_drawable_get_size( icon_window, &width, &height );
    802 
    803             if( event->button == 1
    804               && sexy_icon_entry_get_icon_highlight( entry, i )
    805               && event->x >= 0     && event->y >= 0
    806               && event->x <= width && event->y <= height )
    807             {
    808                 entry->priv->icons[i].hovered = TRUE;
    809 
    810                 update_icon( NULL, NULL, entry );
    811             }
    812 
    813             g_signal_emit( entry, signals[ICON_RELEASED], 0, i,
    814                            event->button );
    815 
    816             return TRUE;
    817         }
    818     }
    819 
    820     if( GTK_WIDGET_CLASS( parent_class )->button_release_event )
    821         return GTK_WIDGET_CLASS( parent_class )->button_release_event(
    822                    widget,
    823                    event );
    824 
    825     return FALSE;
     757sexy_icon_entry_button_release(GtkWidget *widget, GdkEventButton *event)
     758{
     759        SexyIconEntry *entry = SEXY_ICON_ENTRY(widget);
     760        int i;
     761
     762        for (i = 0; i < MAX_ICONS; i++)
     763        {
     764                GdkWindow *icon_window = entry->priv->icons[i].window;
     765
     766                if (event->window == icon_window)
     767                {
     768                        int width, height;
     769                        gdk_drawable_get_size(icon_window, &width, &height);
     770
     771                        if (event->button == 1 &&
     772                                sexy_icon_entry_get_icon_highlight(entry, i) &&
     773                                event->x >= 0     && event->y >= 0 &&
     774                                event->x <= width && event->y <= height)
     775                        {
     776                                entry->priv->icons[i].hovered = TRUE;
     777
     778                                update_icon(NULL, NULL, entry);
     779                        }
     780
     781                        g_signal_emit(entry, signals[ICON_RELEASED], 0, i, event->button);
     782
     783                        return TRUE;
     784                }
     785        }
     786
     787        if (GTK_WIDGET_CLASS(parent_class)->button_release_event)
     788                return GTK_WIDGET_CLASS(parent_class)->button_release_event(widget,
     789                                                                                                                                        event);
     790
     791        return FALSE;
    826792}
    827793
     
    834800 */
    835801GtkWidget *
    836 sexy_icon_entry_new( void )
    837 {
    838     return GTK_WIDGET( g_object_new( SEXY_TYPE_ICON_ENTRY, NULL ) );
     802sexy_icon_entry_new(void)
     803{
     804        return GTK_WIDGET(g_object_new(SEXY_TYPE_ICON_ENTRY, NULL));
    839805}
    840806
     
    848814 */
    849815void
    850 sexy_icon_entry_set_icon( SexyIconEntry *       entry,
    851                           SexyIconEntryPosition icon_pos,
    852                           GtkImage *            icon )
    853 {
    854     SexyIconInfo *icon_info;
    855 
    856     g_return_if_fail( entry != NULL );
    857     g_return_if_fail( SEXY_IS_ICON_ENTRY( entry ) );
    858     g_return_if_fail( IS_VALID_ICON_ENTRY_POSITION( icon_pos ) );
    859     g_return_if_fail( icon == NULL || GTK_IS_IMAGE( icon ) );
    860 
    861     icon_info = &entry->priv->icons[icon_pos];
    862 
    863     if( icon == icon_info->icon )
    864         return;
    865 
    866     if( icon_pos == SEXY_ICON_ENTRY_SECONDARY
    867       && entry->priv->icon_released_id != 0 )
    868     {
    869         g_signal_handler_disconnect( entry, entry->priv->icon_released_id );
    870         entry->priv->icon_released_id = 0;
    871     }
    872 
    873     if( icon == NULL )
    874     {
    875         if( icon_info->icon != NULL )
    876         {
    877             gtk_widget_destroy( GTK_WIDGET( icon_info->icon ) );
    878             icon_info->icon = NULL;
    879 
    880             /*
    881              * Explicitly check, as the pointer may become invalidated
    882              * during destruction.
    883              */
    884             if( icon_info->window != NULL
    885               && GDK_IS_WINDOW( icon_info->window ) )
    886                 gdk_window_hide( icon_info->window );
    887         }
    888     }
    889     else
    890     {
    891         if( icon_info->window != NULL && icon_info->icon == NULL )
    892             gdk_window_show( icon_info->window );
    893 
    894         g_signal_connect( G_OBJECT( icon ), "notify",
    895                           G_CALLBACK( update_icon ), entry );
    896 
    897         icon_info->icon = icon;
    898         g_object_ref( icon );
    899     }
    900 
    901     update_icon( NULL, NULL, entry );
     816sexy_icon_entry_set_icon(SexyIconEntry *entry, SexyIconEntryPosition icon_pos,
     817                                                 GtkImage *icon)
     818{
     819        SexyIconInfo *icon_info;
     820
     821        g_return_if_fail(entry != NULL);
     822        g_return_if_fail(SEXY_IS_ICON_ENTRY(entry));
     823        g_return_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos));
     824        g_return_if_fail(icon == NULL || GTK_IS_IMAGE(icon));
     825
     826        icon_info = &entry->priv->icons[icon_pos];
     827
     828        if (icon == icon_info->icon)
     829                return;
     830
     831        if (icon_pos == SEXY_ICON_ENTRY_SECONDARY &&
     832                entry->priv->icon_released_id != 0)
     833        {
     834                g_signal_handler_disconnect(entry, entry->priv->icon_released_id);
     835                entry->priv->icon_released_id = 0;
     836        }
     837
     838        if (icon == NULL)
     839        {
     840                if (icon_info->icon != NULL)
     841                {
     842                        gtk_widget_destroy(GTK_WIDGET(icon_info->icon));
     843                        icon_info->icon = NULL;
     844
     845                        /*
     846                         * Explicitly check, as the pointer may become invalidated
     847                         * during destruction.
     848                         */
     849                        if (icon_info->window != NULL && GDK_IS_WINDOW(icon_info->window))
     850                                gdk_window_hide(icon_info->window);
     851                }
     852        }
     853        else
     854        {
     855                if (icon_info->window != NULL && icon_info->icon == NULL)
     856                        gdk_window_show(icon_info->window);
     857
     858                g_signal_connect(G_OBJECT(icon), "notify",
     859                                                 G_CALLBACK(update_icon), entry);
     860
     861                icon_info->icon = icon;
     862                g_object_ref(icon);
     863        }
     864
     865        update_icon(NULL, NULL, entry);
    902866}
    903867
     
    911875 */
    912876void
    913 sexy_icon_entry_set_icon_highlight( SexyIconEntry *       entry,
    914                                     SexyIconEntryPosition icon_pos,
    915                                     gboolean              highlight )
    916 {
    917     SexyIconInfo *icon_info;
    918 
    919     g_return_if_fail( entry != NULL );
    920     g_return_if_fail( SEXY_IS_ICON_ENTRY( entry ) );
    921     g_return_if_fail( IS_VALID_ICON_ENTRY_POSITION( icon_pos ) );
    922 
    923     icon_info = &entry->priv->icons[icon_pos];
    924 
    925     if( icon_info->highlight == highlight )
    926         return;
    927 
    928     icon_info->highlight = highlight;
     877sexy_icon_entry_set_icon_highlight(SexyIconEntry *entry,
     878                                                                   SexyIconEntryPosition icon_pos,
     879                                                                   gboolean highlight)
     880{
     881        SexyIconInfo *icon_info;
     882
     883        g_return_if_fail(entry != NULL);
     884        g_return_if_fail(SEXY_IS_ICON_ENTRY(entry));
     885        g_return_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos));
     886
     887        icon_info = &entry->priv->icons[icon_pos];
     888
     889        if (icon_info->highlight == highlight)
     890                return;
     891
     892        icon_info->highlight = highlight;
    929893}
    930894
     
    939903 */
    940904GtkImage *
    941 sexy_icon_entry_get_icon( const SexyIconEntry * entry,
    942                           SexyIconEntryPosition icon_pos )
    943 {
    944     g_return_val_if_fail( entry != NULL, NULL );
    945     g_return_val_if_fail( SEXY_IS_ICON_ENTRY( entry ), NULL );
    946     g_return_val_if_fail( IS_VALID_ICON_ENTRY_POSITION( icon_pos ), NULL );
    947 
    948     return entry->priv->icons[icon_pos].icon;
     905sexy_icon_entry_get_icon(const SexyIconEntry *entry,
     906                                                 SexyIconEntryPosition icon_pos)
     907{
     908        g_return_val_if_fail(entry != NULL, NULL);
     909        g_return_val_if_fail(SEXY_IS_ICON_ENTRY(entry), NULL);
     910        g_return_val_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos), NULL);
     911
     912        return entry->priv->icons[icon_pos].icon;
    949913}
    950914
     
    959923 */
    960924gboolean
    961 sexy_icon_entry_get_icon_highlight( const SexyIconEntry * entry,
    962                                     SexyIconEntryPosition icon_pos )
    963 {
    964     g_return_val_if_fail( entry != NULL, FALSE );
    965     g_return_val_if_fail( SEXY_IS_ICON_ENTRY( entry ), FALSE );
    966     g_return_val_if_fail( IS_VALID_ICON_ENTRY_POSITION( icon_pos ), FALSE );
    967 
    968     return entry->priv->icons[icon_pos].highlight;
    969 }
    970 
    971 static void
    972 clear_button_clicked_cb( SexyIconEntry *       icon_entry,
    973                          SexyIconEntryPosition icon_pos,
    974                          int                   button )
    975 {
    976     if( icon_pos != SEXY_ICON_ENTRY_SECONDARY || button != 1 )
    977         return;
    978 
    979     gtk_entry_set_text( GTK_ENTRY( icon_entry ), "" );
     925sexy_icon_entry_get_icon_highlight(const SexyIconEntry *entry,
     926                                                                   SexyIconEntryPosition icon_pos)
     927{
     928        g_return_val_if_fail(entry != NULL, FALSE);
     929        g_return_val_if_fail(SEXY_IS_ICON_ENTRY(entry), FALSE);
     930        g_return_val_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos), FALSE);
     931
     932        return entry->priv->icons[icon_pos].highlight;
     933}
     934
     935static void
     936clear_button_clicked_cb(SexyIconEntry *icon_entry,
     937                                                SexyIconEntryPosition icon_pos,
     938                                                int button)
     939{
     940        if (icon_pos != SEXY_ICON_ENTRY_SECONDARY || button != 1)
     941                return;
     942
     943        gtk_entry_set_text(GTK_ENTRY(icon_entry), "");
    980944}
    981945
     
    988952 */
    989953void
    990 sexy_icon_entry_add_clear_button( SexyIconEntry *icon_entry )
    991 {
    992     GtkWidget *icon;
    993 
    994     g_return_if_fail( icon_entry != NULL );
    995     g_return_if_fail( SEXY_IS_ICON_ENTRY( icon_entry ) );
    996 
    997     icon = gtk_image_new_from_stock( GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU );
    998     gtk_widget_show( icon );
    999     sexy_icon_entry_set_icon( SEXY_ICON_ENTRY( icon_entry ),
    1000                              SEXY_ICON_ENTRY_SECONDARY,
    1001                              GTK_IMAGE( icon ) );
    1002     sexy_icon_entry_set_icon_highlight( SEXY_ICON_ENTRY( icon_entry ),
    1003                                         SEXY_ICON_ENTRY_SECONDARY, TRUE );
    1004 
    1005     if( icon_entry->priv->icon_released_id != 0 )
    1006     {
    1007         g_signal_handler_disconnect( icon_entry,
    1008                                      icon_entry->priv->icon_released_id );
    1009     }
    1010 
    1011     icon_entry->priv->icon_released_id =
    1012         g_signal_connect( G_OBJECT( icon_entry ), "icon_released",
    1013                           G_CALLBACK( clear_button_clicked_cb ), NULL );
    1014 }
    1015 
     954sexy_icon_entry_add_clear_button(SexyIconEntry *icon_entry)
     955{
     956        GtkWidget *icon;
     957
     958        g_return_if_fail(icon_entry != NULL);
     959        g_return_if_fail(SEXY_IS_ICON_ENTRY(icon_entry));
     960
     961        icon = gtk_image_new_from_stock(GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU);
     962        gtk_widget_show(icon);
     963        sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(icon_entry),
     964                                                         SEXY_ICON_ENTRY_SECONDARY,
     965                                                         GTK_IMAGE(icon));
     966        sexy_icon_entry_set_icon_highlight(SEXY_ICON_ENTRY(icon_entry),
     967                                                                           SEXY_ICON_ENTRY_SECONDARY, TRUE);
     968
     969        if (icon_entry->priv->icon_released_id != 0)
     970        {
     971                g_signal_handler_disconnect(icon_entry,
     972                                                                        icon_entry->priv->icon_released_id);
     973        }
     974
     975        icon_entry->priv->icon_released_id =
     976                g_signal_connect(G_OBJECT(icon_entry), "icon_released",
     977                                                 G_CALLBACK(clear_button_clicked_cb), NULL);
     978}
Note: See TracChangeset for help on using the changeset viewer.