summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: cb12003)
raw | patch | inline | side by side (parent: cb12003)
author | EricDWertz <EricDWertz@gmail.com> | |
Mon, 19 Sep 2016 14:12:21 +0000 (10:12 -0400) | ||
committer | EricDWertz <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] | patch | blob |
drawing.h | [new file with mode: 0644] | patch | blob |
pager_item.h | [new file with mode: 0644] | patch | blob |
tooltip_window.h | [new file with mode: 0644] | patch | blob |
diff --git a/dock_icon.h b/dock_icon.h
--- /dev/null
+++ b/dock_icon.h
@@ -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
--- /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
--- /dev/null
+++ b/pager_item.h
@@ -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
--- /dev/null
+++ b/tooltip_window.h
@@ -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 );
+}
+