From 39c3e54df37fea1c8bb3c368f9a6190a1441009b Mon Sep 17 00:00:00 2001 From: EricDWertz Date: Mon, 19 Sep 2016 10:18:51 -0400 Subject: [PATCH] main and eric_window.h changes --- eric_window.h | 36 ++++- main.c | 357 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 374 insertions(+), 19 deletions(-) diff --git a/eric_window.h b/eric_window.h index 16e5b26..155b76e 100644 --- a/eric_window.h +++ b/eric_window.h @@ -1,10 +1,9 @@ +#pragma once /* * eric_window.h * creates a transluscent window using the current theme color */ -#pragma once - #include #include #include @@ -16,14 +15,26 @@ * TODO: add text color */ -typedef struct +typedef struct eric_window eric_window; +struct eric_window { GtkWidget* window; GdkRGBA background_color; GdkRGBA background_color_old; GdkRGBA background_color_new; + GdkRGBA text_color; + GdkRGBA text_color_old; + GdkRGBA text_color_new; double background_change_percentage; -} eric_window; + gboolean (*draw_callback)( GtkWidget* widget, cairo_t* cr, eric_window* w ); +}; + +double gdk_rgba_get_luminance( GdkRGBA *color ) +{ + return ( color->red ) * 0.2126 + + ( color->green ) * 0.7152 + + ( color->blue ) * 0.0722; +} static void gdk_color_lerp( GdkRGBA* c1, GdkRGBA* c2, double s, GdkRGBA* out ) { @@ -38,6 +49,8 @@ static gboolean eric_window_animation_timer( eric_window* w ) w->background_change_percentage += 0.05; gdk_color_lerp( &w->background_color_old, &w->background_color_new, w->background_change_percentage, &w->background_color); + gdk_color_lerp( &w->text_color_old, &w->text_color_new, + w->background_change_percentage, &w->text_color); gtk_widget_queue_draw( w->window ); if( w->background_change_percentage >= 1.0 ) return FALSE; @@ -52,7 +65,10 @@ static gboolean eric_window_draw( GtkWidget* widget, cairo_t* cr, eric_window* w gdk_cairo_set_source_rgba( cr, &w->background_color ); cairo_paint( cr ); - return FALSE; + if( w->draw_callback == NULL ) + return FALSE; + else + return w->draw_callback( widget, cr, w ); } @@ -75,6 +91,11 @@ void eric_window_gsettings_value_changed( GSettings *settings, const gchar *key, { w->background_color_old = w->background_color; gdk_rgba_parse( &w->background_color_new, g_settings_get_string( settings, "primary-color" ) ); + w->text_color_old = w->text_color; + if( gdk_rgba_get_luminance( &w->background_color_new ) > 0.5 ) + gdk_rgba_parse( &w->text_color_new, "#000000" ); + else + gdk_rgba_parse( &w->text_color_new, "#FFFFFF" ); w->background_change_percentage = 0.0; g_timeout_add( 32, (gpointer)eric_window_animation_timer, w ); @@ -84,6 +105,7 @@ void eric_window_gsettings_value_changed( GSettings *settings, const gchar *key, eric_window* eric_window_create( int width, int height, char* title ) { eric_window* w = malloc( sizeof( eric_window ) ); + w->draw_callback = NULL; if( title == NULL ) title = "eric window"; @@ -117,6 +139,10 @@ eric_window* eric_window_create( int width, int height, char* title ) g_signal_connect_data( gsettings, "changed", G_CALLBACK( eric_window_gsettings_value_changed ), (gpointer)w, 0, 0 ); gdk_rgba_parse( &w->background_color, g_settings_get_string( gsettings, "primary-color" ) ); + if( gdk_rgba_get_luminance( &w->background_color ) > 0.5 ) + gdk_rgba_parse( &w->text_color, "#000000" ); + else + gdk_rgba_parse( &w->text_color, "#FFFFFF" ); return w; } diff --git a/main.c b/main.c index 3dab451..6dba789 100644 --- a/main.c +++ b/main.c @@ -1,34 +1,193 @@ #include #include +#include #define WNCK_I_KNOW_THIS_IS_UNSTABLE #include #include "eric_window.h" +#define ERIC_DOCK_FONT "Source Sans Pro Regular" +#define ERIC_DOCK_TOOLTIP_SHADOW_RADIUS 16.0 +#define ERIC_DOCK_TOOLTIP_WIDTH ERIC_DOCK_TOOLTIP_SHADOW_RADIUS + 320.0 +#define ERIC_DOCK_TOOLTIP_ITEM_HEIGHT 24.0 +#define UI_SCALE 1.0 +#define SCALE_VALUE(x) (x)*UI_SCALE + +#define ICON_STATE_NORMAL 0 +#define ICON_STATE_HOVER 1 +#define ICON_STATE_ACTIVE 2 + +GList* dock_icons = NULL; +eric_window* dock_window = NULL; + +//Structure to hold actual pager items +#include "pager_item.h" + +//Stucture to hold class groups... which are icons on the dock +//Will need to have support for launchers and stuff in the future +#include "dock_icon.h" + +#include "tooltip_window.h" + +//Logic to add a window to the pager items. +//If a matching class group already exists it will be added to that, otherwise create +//a new class group and add the window to that. +void add_window_to_pager( WnckWindow* window ) +{ + GList* icon_list; + int found_class_group = 0; + dock_icon *icon, *new_dock_icon; + + WnckClassGroup* class = wnck_window_get_class_group( window ); + for( icon_list = dock_icons; icon_list != NULL; icon_list = icon_list->next ) + { + icon = (dock_icon*)icon_list->data; + if( icon->class_group == class ) + { + icon->pager_items = g_list_append( icon->pager_items, pager_item_create( window ) ); + found_class_group = 1; + break; + } + } + + if( !found_class_group ) + { + //Add a new dock item + new_dock_icon = dock_icon_create( class ); + new_dock_icon->pager_items = g_list_append( + new_dock_icon->pager_items, + pager_item_create( window ) + ); + + dock_icons = g_list_append( dock_icons, new_dock_icon ); + } +} + +dock_icon* get_dock_icon_at_position( int pos ) +{ + GList* icon_list; + int i = 0; + + for( icon_list = dock_icons; icon_list != NULL; icon_list = icon_list->next ) + { + if( i == pos ) + return (dock_icon*)icon_list->data; + i++; + } + return NULL; +} + GdkFilterReturn handle_x11_event( GdkXEvent *xevent, GdkEvent *event, gpointer data ) { XEvent* xev = (XEvent*)xevent; + dock_icon* icon; + pager_item* item; + + Display* dpy = GDK_DISPLAY_XDISPLAY( gdk_display_get_default() ); + if( xev->type == KeyPress ) { - printf( "Got a key press event!\n" ); + if( xev->xkey.keycode == 133 || xev->xkey.keycode == 134 ) + { + printf( "Got a super key press event!\n" ); + } + else + { + printf( "Got a number key press event!\n" ); + + icon = get_dock_icon_at_position( xev->xkey.keycode - 10 ); + if( icon ) + { + dock_icon_activate( icon, xev->xkey.time, FALSE ); + } + } + } + if( xev->type == KeyRelease ) + { + if( xev->xkey.keycode >= 10 && xev->xkey.keycode <= 20 ) + { + printf( "Got a number key release event!\n" ); + } + else + { + if( xev->xkey.keycode == 133 || xev->xkey.keycode == 134 ) + { + printf( "Got a super key release event!\n" ); + tooltip_window_hide(); + } + else + { + printf( "Flusing events\n" ); + XAllowEvents( dpy, ReplayKeyboard, xev->xkey.time ); + XFlush( dpy ); + } + } } return GDK_FILTER_CONTINUE; } -int main( int argc, char* argv[] ) +static gboolean draw_dock_window( GtkWidget* widget, cairo_t* cr, eric_window* w ) { - int i; + GList* icon_list = dock_icons; + dock_icon* icon; + double x, y; + double rx, ry, width; + int i, pager_count, icon_count; + + icon_count = g_list_length( dock_icons ); + x = floor( 960.0 - SCALE_VALUE( 47.0 * (double)icon_count / 2.0 ) ); + y = SCALE_VALUE( 5.0 ); + cairo_set_operator( cr, CAIRO_OPERATOR_OVER ); + for( icon_list = dock_icons; icon_list != NULL; icon_list = icon_list->next ) + { + icon = (dock_icon*)icon_list->data; - gtk_init( &argc, &argv ); + w->text_color.alpha = 0.25; + gdk_cairo_set_source_rgba( cr, &w->text_color ); + if( icon->icon_state == ICON_STATE_HOVER ) + { + draw_rounded_rect( cr, x, y-SCALE_VALUE( 2.0 ), SCALE_VALUE( 42.0 ), SCALE_VALUE( 42.0 ), SCALE_VALUE( 2.0 ) ); + cairo_fill( cr ); + } + if( icon->is_active ) + { + draw_rounded_rect( cr, x, y-SCALE_VALUE( 2.0 ), SCALE_VALUE( 42.0 ), SCALE_VALUE( 42.0 ), SCALE_VALUE( 2.0 ) ); + cairo_fill( cr ); + } + if( !GDK_IS_PIXBUF( icon->icon_pixbuf ) ) + icon->icon_pixbuf = wnck_class_group_get_icon( icon->class_group ); + gdk_cairo_set_source_pixbuf( cr, icon->icon_pixbuf, x+SCALE_VALUE( 4.0 ), y ); + cairo_paint( cr ); - eric_window* w = eric_window_create( 1920, 40, "" ); - gtk_window_move( GTK_WINDOW( w->window ), 0, 1040 ); - gtk_window_set_type_hint( GTK_WINDOW( w->window ), GDK_WINDOW_TYPE_HINT_DOCK ); + pager_count = g_list_length( icon->pager_items ); + if( pager_count > 0 ) + { + //Draw rectangles + width = (SCALE_VALUE(32.0) / pager_count ); + rx = x + SCALE_VALUE(4.0); + ry = y + SCALE_VALUE(34.0); + w->text_color.alpha = 0.5; + gdk_cairo_set_source_rgba( cr, &w->text_color ); + for( i = 0; i < pager_count; i++ ) + { + cairo_rectangle( cr, rx+SCALE_VALUE( 1.0 ), ry, width-SCALE_VALUE( 2.0 ), SCALE_VALUE( 4.0 ) ); + rx += width; + } + cairo_fill( cr ); + } + icon->x = x; + icon->y = y; - gtk_widget_show_all( w->window ); + x += SCALE_VALUE( 47.0 ); + } + return FALSE; +} +void grab_keys() +{ + int i; Display* dpy = GDK_DISPLAY_XDISPLAY( gdk_display_get_default() ); Window xwin = RootWindow( dpy, DefaultScreen( dpy ) ); @@ -38,19 +197,189 @@ int main( int argc, char* argv[] ) XGrabKey( dpy, i, Mod4Mask | Mod2Mask, xwin, True, GrabModeAsync, GrabModeAsync ); XGrabKey( dpy, i, Mod4Mask, xwin, True, GrabModeAsync, GrabModeAsync ); } + XGrabKey( dpy, 133, AnyModifier, xwin, True, GrabModeAsync, GrabModeAsync ); + XGrabKey( dpy, 134, AnyModifier, xwin, True, GrabModeAsync, GrabModeAsync ); gdk_window_add_filter( NULL, handle_x11_event, NULL ); +} + +gboolean window_mouse_move( GtkWidget* widget, GdkEvent* event, gpointer user ) +{ + double mx, my; + double it, ib, il, ir; + int old_state, state_changed; + dock_icon* icon; + pager_item* item; + GList *icon_list, *item_list; + GdkEventMotion* e = (GdkEventMotion*)event; + + mx = e->x; + my = e->y; + if( widget == dock_window->window ) + { + for( icon_list = dock_icons; icon_list != NULL; icon_list = icon_list->next ) + { + icon = (dock_icon*)icon_list->data; + old_state = icon->icon_state; + it = 0; ib = SCALE_VALUE( 48 ); + il = icon->x; ir = icon->x + SCALE_VALUE( 42 ); + if( il < mx && mx < ir && it < my && my < ib ) + { + icon->icon_state = ICON_STATE_HOVER; + } + else + { + icon->icon_state = ICON_STATE_NORMAL; + } + if( old_state != icon->icon_state ) + state_changed = 1; + + if( state_changed ) + gtk_widget_queue_draw( dock_window->window ); + } + } + return FALSE; +} + +void dock_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* icon_list; + int pager_count; + + mx = e->x; my = e->y; + for( icon_list = dock_icons; icon_list != NULL; icon_list = icon_list->next ) + { + icon = (dock_icon*)icon_list->data; + dock_icon_mouse_down( icon, mx, my, e->time ); + } +} + +void setup_dock_window() +{ + GdkScreen* screen = gdk_screen_get_default(); + int mon = gdk_screen_get_primary_monitor( screen ); + GdkRectangle mon_geom; + gdk_screen_get_monitor_geometry( screen, mon, &mon_geom ); + int sw, sh; + sw = mon_geom.width; + sh = mon_geom.height; + + dock_window = eric_window_create( sw, 48 * UI_SCALE, "" ); + gtk_window_move( GTK_WINDOW( dock_window->window ), 0, sh - 48 * UI_SCALE ); + gtk_window_set_type_hint( GTK_WINDOW( dock_window->window ), GDK_WINDOW_TYPE_HINT_DOCK ); + + dock_window->draw_callback = draw_dock_window; + + gtk_widget_add_events( dock_window->window, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK ); + g_signal_connect( G_OBJECT( dock_window->window ), "motion-notify-event", G_CALLBACK(window_mouse_move), NULL ); + g_signal_connect( G_OBJECT( dock_window->window ), "button-press-event", G_CALLBACK(dock_window_mouse_down), NULL ); + + gtk_widget_show_now( dock_window->window ); +} + +static void wnck_window_opened( WnckScreen* screen, WnckWindow* window, gpointer data ) +{ + if( !wnck_window_is_skip_pager( window ) && !wnck_window_is_skip_tasklist( window ) ) + { + add_window_to_pager( window ); + gtk_widget_queue_draw( dock_window->window ); + } +} + +static void wnck_window_closed( WnckScreen* screen, WnckWindow* window, gpointer data ) +{ + GList *icon_list, *pager_list; + dock_icon* icon; + pager_item* item; + + for( icon_list = dock_icons; icon_list != NULL; icon_list = icon_list->next ) + { + icon = (dock_icon*)icon_list->data; + for( pager_list = icon->pager_items; pager_list != NULL; pager_list = pager_list->next ) + { + item = (pager_item*)pager_list->data; + if( item->window == window ) + { + icon->pager_items = g_list_remove( icon->pager_items, item ); + free( item ); + printf( "Removed pager item\n" ); + break; + } + } + if( icon->pager_items == NULL ) + { + dock_icons = g_list_remove( dock_icons, icon ); + free( icon ); + printf( "Removed dock icon\n" ); + break; + } + } + gtk_widget_queue_draw( dock_window->window ); +} + +static void wnck_active_window_changed( WnckScreen* screen, WnckWindow* prev_window, gpointer user ) +{ + GList *icon_list, *pager_list; + dock_icon* icon; + pager_item* item; + WnckWindow* active = wnck_screen_get_active_window( screen ); + int old_state, state_changed; + int has_active; + + state_changed = 0; + for( icon_list = dock_icons; icon_list != NULL; icon_list = icon_list->next ) + { + icon = (dock_icon*)icon_list->data; + old_state = icon->is_active; + has_active = 0; + for( pager_list = icon->pager_items; pager_list != NULL; pager_list = pager_list->next ) + { + item = (pager_item*)pager_list->data; + if( item->window == active ) + { + has_active = 1; + break; + } + } + if( has_active ) + icon->is_active = 1; + else + icon->is_active = 0; + + if( icon->is_active != old_state ) + state_changed = 1; + } + if( state_changed ) + gtk_widget_queue_draw( dock_window->window ); +} + +void init_wnck() +{ WnckScreen* screen; GList* window_list; screen = wnck_screen_get_default(); - wnck_screen_force_update( screen ); + g_signal_connect( screen, "window-opened", G_CALLBACK( wnck_window_opened ), NULL ); + g_signal_connect( screen, "window-closed", G_CALLBACK( wnck_window_closed ), NULL ); + g_signal_connect( screen, "active-window-changed", G_CALLBACK( wnck_active_window_changed ), NULL ); +} - for( window_list = wnck_screen_get_windows( screen ); window_list != NULL; window_list = window_list->next ) - { - WnckWindow* window = WNCK_WINDOW( window_list->data ); - printf( "%s%s\n", wnck_window_get_name( window ), wnck_class_group_get_name( wnck_window_get_class_group( window ) ) ); - } +int main( int argc, char* argv[] ) +{ + gtk_init( &argc, &argv ); + + setup_dock_window(); + tooltip_window_create( dock_window->window ); + grab_keys(); + init_wnck(); gtk_main(); return 0; -- 2.47.0