]> Eric's Git Repo - ericdock.git/commitdiff
Breaking out icons/pager items/tooltip window... fixed winkey+number
authorEricDWertz <EricDWertz@gmail.com>
Mon, 19 Sep 2016 14:12:21 +0000 (10:12 -0400)
committerEricDWertz <EricDWertz@gmail.com>
Mon, 19 Sep 2016 14:12:21 +0000 (10:12 -0400)
shortcuts and tooltip window rendering

dock_icon.h [new file with mode: 0644]
drawing.h [new file with mode: 0644]
pager_item.h [new file with mode: 0644]
tooltip_window.h [new file with mode: 0644]

diff --git a/dock_icon.h b/dock_icon.h
new file mode 100644 (file)
index 0000000..b1bf3ed
--- /dev/null
@@ -0,0 +1,126 @@
+#pragma once
+/*
+ * dock_icon - Represents an icon on the dock
+ * holds pager_items
+ *
+ * renders/handles events based on how many pager_items it contains
+ */
+#include <gtk/gtk.h>
+
+#define WNCK_I_KNOW_THIS_IS_UNSTABLE
+#include <libwnck/libwnck.h>
+
+typedef struct
+{
+    WnckClassGroup* class_group;
+    GdkPixbuf* icon_pixbuf;
+    GList* pager_items;
+    double x, y;
+    double width, height;
+    int icon_state;
+    int is_active;
+    int selected_index;
+} dock_icon;
+
+#include "tooltip_window.h"
+
+extern dock_icon* tooltip_window_icon;
+
+dock_icon* dock_icon_create( WnckClassGroup* class_group )
+{
+    dock_icon* icon = malloc( sizeof( dock_icon ) );
+    icon->class_group = class_group;
+    icon->icon_pixbuf = wnck_class_group_get_icon( class_group );
+    icon->pager_items = NULL;
+    icon->icon_state = ICON_STATE_NORMAL;
+
+    icon->width = SCALE_VALUE( 42 );
+    icon->height = SCALE_VALUE( 48 );
+
+    icon->selected_index = 0;
+
+    return icon;
+}
+
+//Goes to the next pager item, looping back to the start if necessary
+pager_item* dock_icon_get_next_pager_item( dock_icon* icon )
+{
+    pager_item* item;
+
+    icon->selected_index++;
+    if( icon->selected_index >= g_list_length( icon->pager_items ) )
+    {
+        icon->selected_index = 0;
+    }
+
+    item = g_list_nth_data( icon->pager_items, icon->selected_index );
+
+    return item;
+}
+
+void dock_icon_clear_pager_item_state( dock_icon* icon )
+{
+    GList* pager_list;
+    pager_item* item;
+
+    for( pager_list = icon->pager_items; pager_list != NULL; pager_list = pager_list->next )
+    {
+        item = pager_list->data;
+        item->icon_state = ICON_STATE_NORMAL;
+    }
+}
+
+/* Event whenever a dock icon is clicked or selected via keyboard
+ * Will switch to app, or if more than one pager_items, show menu
+ */
+void dock_icon_activate( dock_icon* icon, Time time, int from_click )
+{
+    if( !icon->pager_items )
+        return;
+
+    if( g_list_length( icon->pager_items ) > 1 )
+    {
+        pager_item* item;
+
+        dock_icon_clear_pager_item_state( icon );
+
+        if( tooltip_window_icon != icon )
+        {
+            tooltip_window_icon = icon;
+            tooltip_window_show();
+            icon->selected_index = 0;
+            item = (pager_item*)icon->pager_items->data;
+        }
+        else
+        {
+            item = dock_icon_get_next_pager_item( icon );
+        }
+
+        if( !from_click )
+        {
+            item->icon_state = ICON_STATE_HOVER;
+            wnck_window_activate( item->window, time );
+            gtk_widget_queue_draw( tooltip_window->window );
+        }
+    }
+    else
+    {
+        //Activiate the only one we have
+        pager_item* item = (pager_item*)icon->pager_items->data;
+        wnck_window_activate( item->window, time );
+        tooltip_window_hide();
+    }
+}
+
+void dock_icon_mouse_down( dock_icon* icon, double mx, double my, Time time )
+{
+    double it, ib, il, ir;
+
+    il = icon->x; ir = icon->x + icon->width;
+    it = icon->y; ib = icon->y + icon->height; 
+
+    if( il < mx && mx < ir && it < my && my < ib )
+    {
+        dock_icon_activate( icon, time, TRUE );
+    }
+}
diff --git a/drawing.h b/drawing.h
new file mode 100644 (file)
index 0000000..9d9394c
--- /dev/null
+++ b/drawing.h
@@ -0,0 +1,20 @@
+#pragma once
+/*
+ * Drawing functions!
+ */
+#include <gtk/gtk.h>
+
+void draw_rounded_rect(cairo_t* cr,double x,double y,double w,double h,double r)
+{
+       cairo_move_to(cr,x+r,y);
+       cairo_line_to(cr,x+w-r*2,y);
+       cairo_arc(cr,x+w-r,y+r,r,-M_PI/2.0,0);
+       cairo_line_to(cr,x+w,y+h-r*2);
+       cairo_arc(cr,x+w-r,y+h-r,r,0,M_PI/2.0);
+       cairo_line_to(cr, x+r,y+h);
+       cairo_arc(cr,x+r,y+h-r,r,M_PI/2.0,M_PI);
+       cairo_line_to(cr, x, y+r);
+       cairo_arc(cr,x+r,y+r,r,M_PI,-M_PI/2.0);
+       cairo_close_path(cr);
+}
+
diff --git a/pager_item.h b/pager_item.h
new file mode 100644 (file)
index 0000000..7121ba4
--- /dev/null
@@ -0,0 +1,96 @@
+#pragma once
+/*
+ * pager_item - held by the dock_icon object
+ */
+
+#include <gtk/gtk.h>
+
+#define WNCK_I_KNOW_THIS_IS_UNSTABLE
+#include <libwnck/libwnck.h>
+
+#include "drawing.h"
+
+//Structure to hold actual pager items
+typedef struct
+{
+    WnckWindow* window;
+    char name[256];
+    GdkPixbuf* icon_pixbuf;
+    double x, y;
+    double width, height;
+    double text_height;
+    int icon_state;
+} pager_item;
+
+void pager_item_name_changed( WnckWindow* window, pager_item* item )
+{
+    strcpy( item->name, wnck_window_get_name( window ) );
+}
+
+void pager_item_icon_changed( WnckWindow* window, pager_item* item )
+{
+    item->icon_pixbuf = wnck_window_get_mini_icon( window );
+}
+
+pager_item* pager_item_create( WnckWindow* window )
+{
+    pager_item* item = malloc( sizeof( pager_item ) );
+    item->window = window;
+    strcpy( item->name, wnck_window_get_name( item->window ) );
+    item->icon_pixbuf = wnck_window_get_mini_icon( item->window );
+    item->icon_state = ICON_STATE_NORMAL;
+
+    g_signal_connect( G_OBJECT( window ), "name-changed", G_CALLBACK( pager_item_name_changed ), (gpointer)item );
+    g_signal_connect( G_OBJECT( window ), "icon-changed", G_CALLBACK( pager_item_name_changed ), (gpointer)item );
+
+    item->width = SCALE_VALUE( 320 );
+    item->height = SCALE_VALUE( 24.0 );
+    item->text_height = SCALE_VALUE( 16.0 );
+
+    return item;
+}
+
+/* Returns bool if state has changed */
+int pager_item_mouse_move( pager_item* item, double mx, double my )
+{
+    double it, ib, il, ir;
+    int old_state, state_changed;
+
+    old_state = item->icon_state;
+
+    il = item->x; ir = item->x + item->width;
+    it = item->y; ib = item->y + item->height; 
+
+    if( il < mx && mx < ir && it < my && my < ib )
+    {
+        item->icon_state = ICON_STATE_HOVER;
+    }
+    else
+    {
+        item->icon_state = ICON_STATE_NORMAL;
+    }
+
+    return old_state != item->icon_state;
+}
+
+void pager_item_draw( pager_item* item, cairo_t* cr, eric_window* w, cairo_pattern_t* pattern )
+{
+    if( item->icon_state == ICON_STATE_HOVER )
+    {
+        w->text_color.alpha = 0.25;
+        gdk_cairo_set_source_rgba( cr, &w->text_color );
+        draw_rounded_rect( cr, item->x, item->y, 
+                item->width, item->height, SCALE_VALUE( 2.0 ) );
+        cairo_fill( cr );
+    }
+
+    gdk_cairo_set_source_pixbuf( cr, item->icon_pixbuf, item->x, item->y + SCALE_VALUE( 6.0 ) );
+    cairo_paint( cr );
+
+    cairo_set_source( cr, pattern );
+    cairo_move_to( cr, item->x + SCALE_VALUE( 20.0 ), item->y + item->text_height  );
+    cairo_text_path( cr, item->name );
+
+    cairo_fill( cr );
+
+}
diff --git a/tooltip_window.h b/tooltip_window.h
new file mode 100644 (file)
index 0000000..ca0c618
--- /dev/null
@@ -0,0 +1,151 @@
+#pragma once
+
+#define WNCK_I_KNOW_THIS_IS_UNSTABLE
+#include <libwnck/libwnck.h>
+
+#include "eric_window.h"
+#include "dock_icon.h"
+#include "drawing.h"
+
+eric_window* tooltip_window = NULL;
+dock_icon* tooltip_window_icon = NULL;
+
+void tooltip_window_hide()
+{
+    tooltip_window_icon = NULL;
+    gtk_widget_hide( tooltip_window->window );
+}
+
+gboolean tooltip_window_lose_focus( GtkWidget* widget, GdkEvent* event, gpointer user )
+{
+    tooltip_window_hide();
+    return TRUE;
+}
+
+void tooltip_window_mouse_down( GtkWidget* widget, GdkEvent* event, gpointer user )
+{
+    GdkEventButton* e = (GdkEventButton*)event;
+    if( e->button != 1 )
+        return;
+
+    double mx, my;
+    double it, ib, il, ir;
+    dock_icon* icon;
+    pager_item* item;
+    GList* pager_list;
+
+    mx = e->x; my = e->y;
+    for( pager_list = tooltip_window_icon->pager_items; pager_list != NULL; pager_list = pager_list->next )
+    {
+        item = pager_list->data;
+        if( my > item->y && my < item->y + SCALE_VALUE( 24.0 ) )
+        {
+            wnck_window_activate( item->window, e->time );
+            tooltip_window_hide();
+        }
+    }
+}
+
+gboolean tooltip_window_mouse_move( GtkWidget* widget, GdkEvent* event, gpointer user )
+{
+    double mx, my;
+    double it, ib, il, ir;
+    int old_state, new_state, state_changed;
+    dock_icon* icon;
+    pager_item* item;
+    GList *icon_list, *item_list;
+    GdkEventMotion* e = (GdkEventMotion*)event;
+
+    mx = e->x;
+    my = e->y;
+
+    for( item_list = tooltip_window_icon->pager_items; item_list != NULL; item_list = item_list->next )
+    {
+        item = item_list->data;
+
+
+        if( pager_item_mouse_move( item, mx, my ) )
+            state_changed = TRUE;
+    }
+
+    if( state_changed )
+        gtk_widget_queue_draw( tooltip_window->window );
+
+    return FALSE;
+}
+
+static gboolean tooltip_window_draw( GtkWidget* widget, cairo_t* cr, eric_window* w )
+{
+    double x, y;
+    GList* pager_list;
+    pager_item* item;
+    cairo_pattern_t* pattern;
+
+    cairo_set_operator( cr, CAIRO_OPERATOR_OVER );
+    w->text_color.alpha = 1.0;
+    cairo_set_font_face( cr, cairo_toy_font_face_create( ERIC_DOCK_FONT, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL ) );
+    cairo_set_font_size( cr, SCALE_VALUE( 12.0 ) );
+
+    x = SCALE_VALUE( 5.0 ); //margin-left
+    y = SCALE_VALUE( 2.0 ); //margin-top
+    pattern = cairo_pattern_create_linear( SCALE_VALUE( ERIC_DOCK_TOOLTIP_WIDTH - 21.0 ), 0, SCALE_VALUE( ERIC_DOCK_TOOLTIP_WIDTH - 5.0 ), 0 );
+    cairo_pattern_add_color_stop_rgba( pattern, 0.0, w->text_color.red, w->text_color.green, w->text_color.blue, 1.0 );
+    cairo_pattern_add_color_stop_rgba( pattern, 1.0, w->text_color.red, w->text_color.green, w->text_color.blue, 0.0 );
+    for( pager_list = tooltip_window_icon->pager_items; pager_list != NULL; pager_list = pager_list->next )
+    {
+        item = (pager_item*)pager_list->data;
+
+        item->x = x;
+        item->y = y;
+        pager_item_draw( item, cr, w, pattern );
+
+        y += SCALE_VALUE( 24.0 );
+    }
+
+    cairo_pattern_destroy( pattern );
+}
+
+
+
+void tooltip_window_create( GtkWidget* dock_window )
+{
+    eric_window* w = eric_window_create( 10, 10, "" );
+    gtk_window_move( GTK_WINDOW( w->window ), 0, 1040 );
+    gtk_window_set_type_hint( GTK_WINDOW( w->window ), GDK_WINDOW_TYPE_HINT_DIALOG );
+    gtk_window_set_decorated( GTK_WINDOW( w->window ), FALSE );
+    gtk_window_set_skip_pager_hint( GTK_WINDOW( w->window ), TRUE );
+    gtk_window_set_transient_for( GTK_WINDOW( w->window ), GTK_WINDOW( dock_window ) );
+    gtk_window_set_keep_above( GTK_WINDOW( w->window ), TRUE );
+    
+    gtk_widget_add_events( w->window, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK );
+    g_signal_connect( G_OBJECT( w->window ), "focus-out-event", G_CALLBACK(tooltip_window_lose_focus), NULL );
+    g_signal_connect( G_OBJECT( w->window ), "motion-notify-event", G_CALLBACK(tooltip_window_mouse_move), NULL );
+    g_signal_connect( G_OBJECT( w->window ), "button-press-event", G_CALLBACK(tooltip_window_mouse_down), NULL );
+    w->draw_callback = tooltip_window_draw;
+
+    tooltip_window = w;
+}
+
+
+void tooltip_window_update_geometry()
+{
+    int pager_count;
+    int wx, wy;
+
+    pager_count = g_list_length( tooltip_window_icon->pager_items ); 
+
+    gtk_window_get_position( GTK_WINDOW( dock_window->window ), &wx, &wy );
+    gtk_window_resize( GTK_WINDOW( tooltip_window->window ), SCALE_VALUE(ERIC_DOCK_TOOLTIP_WIDTH), SCALE_VALUE( pager_count * 24 ) );
+    gtk_window_move( GTK_WINDOW( tooltip_window->window ), wx + (int)tooltip_window_icon->x, wy - (int)SCALE_VALUE( pager_count * 24 ) );
+}
+
+void tooltip_window_show()
+{
+    int wx, wy;
+    int w, h;
+
+    tooltip_window_update_geometry();
+    gtk_widget_show_all( tooltip_window->window );
+    gtk_widget_queue_draw( tooltip_window->window );
+}
+