summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: c55d8d0)
raw | patch | inline | side by side (parent: c55d8d0)
author | EricDWertz <EricDWertz@gmail.com> | |
Mon, 19 Sep 2016 14:18:51 +0000 (10:18 -0400) | ||
committer | EricDWertz <EricDWertz@gmail.com> | |
Mon, 19 Sep 2016 14:18:51 +0000 (10:18 -0400) |
eric_window.h | patch | blob | history | |
main.c | patch | blob | history |
diff --git a/eric_window.h b/eric_window.h
index 16e5b263663bea7eed437d87f229a2ed40147a06..155b76eff692155420981c25dc5b768a794bc8d1 100644 (file)
--- a/eric_window.h
+++ b/eric_window.h
+#pragma once
/*
* eric_window.h
* creates a transluscent window using the current theme color
*/
-#pragma once
-
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gio/gio.h>
* 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 )
{
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;
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 );
}
{
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 );
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";
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;
}
index 3dab4513c360cfd7aac5f1212139752ad2d01167..6dba789988df3dc81adf3bb1864ef56d15809443 100644 (file)
--- a/main.c
+++ b/main.c
#include <gdk/gdkx.h>
#include <X11/Xlib.h>
+#include <math.h>
#define WNCK_I_KNOW_THIS_IS_UNSTABLE
#include <libwnck/libwnck.h>
#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 ) );
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;