From 0d6cfa678313e25fd4e9773c7d99ff475bd9044b Mon Sep 17 00:00:00 2001 From: Eric Wertz Date: Fri, 3 Mar 2017 09:28:05 -0500 Subject: [PATCH] Added ability to show battery icon when supported, set dock window struts --- Makefile | 6 +- battery.c | 57 ++++++++++++++ battery.h | 3 + clock.c | 11 ++- clock.h | 4 +- main.c | 20 ++++- xutils.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ xutils.h | 51 +++++++++++++ 8 files changed, 359 insertions(+), 11 deletions(-) create mode 100644 battery.c create mode 100644 battery.h create mode 100644 xutils.c create mode 100644 xutils.h diff --git a/Makefile b/Makefile index 77ec352..887684f 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ CC = gcc -CFLAGS = -g -Wall -lm -lX11 `pkg-config --cflags gtk+-3.0 libwnck-3.0` +CFLAGS = -Wunused-result -g -Wall -lm -lX11 -lXext `pkg-config --cflags gtk+-3.0 libwnck-3.0` LDFLAGS = `pkg-config --libs gtk+-3.0 libwnck-3.0` -DEPS = dock_icon.h ericdock.h clock.h drawing.h eric_window.h pager_item.h tooltip_window.h -OBJ = dock_icon.o tooltip_window.o eric_window.o clock.o main.o pager_item.o drawing.o +DEPS = dock_icon.h ericdock.h clock.h drawing.h eric_window.h pager_item.h tooltip_window.h battery.h xutils.h +OBJ = dock_icon.o tooltip_window.o eric_window.o clock.o main.o pager_item.o drawing.o battery.o xutils.o %.o: %.c $(DEPS) $(CC) $(CFLAGS) -c -o $@ $< diff --git a/battery.c b/battery.c new file mode 100644 index 0000000..fe09940 --- /dev/null +++ b/battery.c @@ -0,0 +1,57 @@ +#include + +#include "ericdock.h" +#include "battery.h" + +//Battery stuff +typedef struct { + double charge_percent; + int status; +} Battery; + +void getbatteryinfo( Battery* bat ) +{ + FILE* fp_charge_full; + FILE* fp_charge_now; + FILE* fp_status; + int charge_full, charge_now; + char buffer[256]; + + fp_charge_full = fopen( "/sys/class/power_supply/BAT0/charge_full", "r" ); + fp_charge_now = fopen( "/sys/class/power_supply/BAT0/charge_now", "r" ); + fp_status = fopen( "/sys/class/power_supply/BAT0/status", "r" ); + + fgets( buffer, 255, fp_charge_full ); + charge_full = atoi( buffer ); + fgets( buffer, 255, fp_charge_now ); + charge_now = atoi( buffer ); + fgets( buffer, 255, fp_status ); + + bat->charge_percent = (double)charge_now / (double)charge_full; + if( strcmp( "Charging\n", buffer ) == 0 ) bat->status = 1; + if( strcmp( "Discharging\n", buffer ) == 0 ) bat->status = 0; + + fclose( fp_charge_full ); + fclose( fp_charge_now ); + fclose( fp_status ); +} + +void draw_battery_icon( cairo_t* cr, double x, double y, double height ) +{ + Battery bat; + getbatteryinfo( &bat ); + //bat.charge_percent * 100.0 + //bat.status == 1 means charging + + cairo_set_line_width( cr, 2.0 ); + cairo_rectangle( cr, x+height*0.375, y+height*0.125, height*0.25, height*0.125 ); + cairo_rectangle( cr, x+height*0.25, y+height*0.25, height*0.5, height*0.75 ); + cairo_stroke( cr ); + + if( bat.charge_percent <= 0.15 ) + cairo_set_source_rgb( cr, 0.9, 0.0, 0.0 ); + + cairo_rectangle( cr, x+height*0.25+2.0, y+height*0.25+(height*0.75*(1.0-bat.charge_percent))+2.0, height*0.5-4.0, height*0.75*bat.charge_percent-4.0 ); + cairo_fill( cr ); +} + diff --git a/battery.h b/battery.h new file mode 100644 index 0000000..5be4640 --- /dev/null +++ b/battery.h @@ -0,0 +1,3 @@ +#pragma once + +void draw_battery_icon( cairo_t* cr, double x, double y, double height ); diff --git a/clock.c b/clock.c index 94fae5f..57f841c 100644 --- a/clock.c +++ b/clock.c @@ -61,7 +61,7 @@ void clock_init( gpointer window ) g_timeout_add_seconds(1,clock_refresh, window); } -void clock_draw_timestring(cairo_t* cr, double x, double y, int blurpass) +double clock_draw_timestring(cairo_t* cr, double x, double y, int blurpass) { time_t rawtime; struct tm * timeinfo; @@ -87,6 +87,7 @@ void clock_draw_timestring(cairo_t* cr, double x, double y, int blurpass) if(blurpass==1) cairo_translate(cr,-2.0,0); cairo_text_extents_t extents; + double text_width = 0; double text_x = x; char timestring[64]; cairo_set_font_face(cr,cairo_toy_font_face_create("Source Sans Pro",CAIRO_FONT_SLANT_NORMAL,CAIRO_FONT_WEIGHT_NORMAL)); @@ -95,6 +96,7 @@ void clock_draw_timestring(cairo_t* cr, double x, double y, int blurpass) sprintf(timestring,"%i:%02i%s",hour, minute, ampm); cairo_text_extents(cr,timestring,&extents); text_x-=extents.x_advance; + text_width = text_x; cairo_move_to(cr,text_x, y - SCALE_VALUE( 4.0 ) ); cairo_text_path(cr,timestring); @@ -102,6 +104,7 @@ void clock_draw_timestring(cairo_t* cr, double x, double y, int blurpass) timeinfo->tm_mon+1, timeinfo->tm_mday, timeinfo->tm_year + 1900 ); cairo_text_extents(cr,timestring,&extents); text_x = x - extents.x_advance; + text_width = text_width < text_x? text_x: text_width; cairo_move_to(cr,text_x, y - extents.y_bearing + SCALE_VALUE( 4.0 ) ); cairo_text_path(cr,timestring); @@ -128,9 +131,11 @@ void clock_draw_timestring(cairo_t* cr, double x, double y, int blurpass) cairo_stroke_preserve(cr); } cairo_fill(cr); + + return text_width; } -void clock_draw( cairo_t* cr, double x, double y, eric_window* w ) +double clock_draw( cairo_t* cr, double x, double y, eric_window* w ) { //cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, clock_alpha); //if(clock_alpha!=0) draw_clock(cr,2.0); @@ -147,5 +152,5 @@ void clock_draw( cairo_t* cr, double x, double y, eric_window* w ) w->text_color.blue = 1.0 - w->text_color.blue; w->text_color.alpha = clock_alpha; gdk_cairo_set_source_rgba( cr, &w->text_color ); - clock_draw_timestring( cr, x, y, 0 ); + return clock_draw_timestring( cr, x, y, 0 ); } diff --git a/clock.h b/clock.h index 221c327..c36d94c 100644 --- a/clock.h +++ b/clock.h @@ -8,5 +8,5 @@ gboolean clock_refresh(gpointer data); void clock_init( gpointer window ); -void clock_draw_timestring(cairo_t* cr, double x, double y, int blurpass); -void clock_draw( cairo_t* cr, double x, double y, eric_window* w ); +double clock_draw_timestring(cairo_t* cr, double x, double y, int blurpass); +double clock_draw( cairo_t* cr, double x, double y, eric_window* w ); diff --git a/main.c b/main.c index 6c47a44..884bef2 100644 --- a/main.c +++ b/main.c @@ -10,18 +10,21 @@ GList* dock_icons = NULL; eric_window* dock_window = NULL; -#include "ericdock.h" #include "clock.h" +#include "xutils.h" //Structure to hold actual pager items #include "pager_item.h" +#include "battery.h" +#include "ericdock.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" +int show_battery_icon; + int screen_width; int screen_height; @@ -187,7 +190,9 @@ static gboolean draw_dock_window( GtkWidget* widget, cairo_t* cr, eric_window* w x += SCALE_VALUE( 47.0 ); } - clock_draw( cr, (double)screen_width-SCALE_VALUE(10), ( BAR_HEIGHT * UI_SCALE ) / 2.0, w ); + double clock_width = clock_draw( cr, (double)screen_width-SCALE_VALUE(10), ( BAR_HEIGHT * UI_SCALE ) / 2.0, w ); + if( show_battery_icon ) + draw_battery_icon( cr, clock_width-SCALE_VALUE( 48.0 ), (( BAR_HEIGHT * UI_SCALE ) / 2.0)-SCALE_VALUE( 12 ), SCALE_VALUE( 24 ) ); return FALSE; } @@ -289,6 +294,15 @@ void setup_dock_window() //Init clock drawing clock_init( dock_window->window ); + + //Check if there's a battery + FILE* f = fopen( "/sys/class/power_supply/BAT0/charge_full", "r" ); + show_battery_icon = f != NULL; + if( f ) + fclose(f); + + //Set window struts + xutils_set_strut( gtk_widget_get_window( dock_window->window ), GTK_POS_BOTTOM, SCALE_VALUE( BAR_HEIGHT ), 0, screen_width ); } static void wnck_window_opened( WnckScreen* screen, WnckWindow* window, gpointer data ) diff --git a/xutils.c b/xutils.c new file mode 100644 index 0000000..c24e576 --- /dev/null +++ b/xutils.c @@ -0,0 +1,218 @@ +/* Xlib utils */ + +/* + * Copyright (C) 2001 Havoc Pennington + * 2009 Michal Hruby + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "xutils.h" + +enum { + STRUT_LEFT = 0, + STRUT_RIGHT = 1, + STRUT_TOP = 2, + STRUT_BOTTOM = 3, + STRUT_LEFT_START = 4, + STRUT_LEFT_END = 5, + STRUT_RIGHT_START = 6, + STRUT_RIGHT_END = 7, + STRUT_TOP_START = 8, + STRUT_TOP_END = 9, + STRUT_BOTTOM_START = 10, + STRUT_BOTTOM_END = 11 +}; + +//pulled out of xutils.c +static Atom net_wm_strut = 0; +static Atom net_wm_strut_partial = 0; + +/* xutils_set_strut: + * @gdk_window: window to set struts on + * @position: position of the window, top=0, right=1, bottom=2, left=3 + * @strut: the height of the strut + * @strut_start: the start position of the strut + * @strut_end: the end position of the strut + * + * Sets struts for a given @gdk_window on the specified @position. + * To let a maximised window not cover the given struts + * + * - partially pulled out of xutils.c - + */ +void +xutils_set_strut(GdkWindow* gdk_window, + GtkPositionType position, + guint32 strut, + guint32 strut_start, + guint32 strut_end) +{ + Display* display; + Window window; + gulong struts [12] = { 0, }; + + g_return_if_fail(GDK_IS_WINDOW(gdk_window)); + + display = GDK_WINDOW_XDISPLAY(gdk_window); + window = GDK_WINDOW_XID(gdk_window); + + if (net_wm_strut == None) { + net_wm_strut = XInternAtom(display, "_NET_WM_STRUT", False); + } + if (net_wm_strut_partial == None) { + net_wm_strut_partial = XInternAtom(display, "_NET_WM_STRUT_PARTIAL", False); + } + + switch (position) { + case GTK_POS_TOP: + struts [STRUT_TOP] = strut; + struts [STRUT_TOP_START] = strut_start; + struts [STRUT_TOP_END] = strut_end; + break; + case GTK_POS_RIGHT: + struts [STRUT_RIGHT] = strut; + struts [STRUT_RIGHT_START] = strut_start; + struts [STRUT_RIGHT_END] = strut_end; + break; + case GTK_POS_BOTTOM: + struts [STRUT_BOTTOM] = strut; + struts [STRUT_BOTTOM_START] = strut_start; + struts [STRUT_BOTTOM_END] = strut_end; + break; + case GTK_POS_LEFT: + struts [STRUT_LEFT] = strut; + struts [STRUT_LEFT_START] = strut_start; + struts [STRUT_LEFT_END] = strut_end; + break; + } + + gdk_error_trap_push(); + XChangeProperty(display, window, net_wm_strut, + XA_CARDINAL, 32, PropModeReplace, + (guchar*) &struts, 4); + XChangeProperty(display, window, net_wm_strut_partial, + XA_CARDINAL, 32, PropModeReplace, + (guchar*) &struts, 12); + gdk_error_trap_pop(); +} + +cairo_region_t* +xutils_get_input_shape(GdkWindow* window) +{ + cairo_region_t* region = cairo_region_create(); + + cairo_rectangle_int_t rect; + XRectangle* rects; + int count = 0; + int ordering = 0; + gint err; + + gdk_error_trap_push(); + rects = XShapeGetRectangles(GDK_WINDOW_XDISPLAY(window), + GDK_WINDOW_XID(window), + ShapeInput, &count, &ordering); + + for (int i = 0; i < count; ++i) { + rect.x = rects[i].x; + rect.y = rects[i].y; + rect.width = rects[i].width; + rect.height = rects[i].height; + + cairo_region_union_rectangle(region, &rect); + } + if (rects) { + free(rects); + } + + return region; +} + +GdkWindow* +xutils_get_window_at_pointer(GdkDisplay* display) +{ + GdkWindow* result = NULL; + Window root; + Window child; + int root_x; + int root_y; + int win_x; + int win_y; + unsigned int flags; + + Bool res = XQueryPointer(GDK_DISPLAY_XDISPLAY(display), + GDK_ROOT_WINDOW(), &root, &child, + &root_x, &root_y, &win_x, &win_y, &flags); + if (!res) { + return NULL; + } + + result = gdk_x11_window_lookup_for_display(display, child); + if (!result && child != None) { + result = gdk_x11_window_foreign_new_for_display(display,child); + } + + return result; +} + +gboolean +xutils_is_window_minimized(GdkWindow* window) +{ + gboolean result = FALSE; + + g_return_val_if_fail(GDK_IS_WINDOW(window), FALSE); + + Atom type; + int format; + gulong nitems; + gulong bytes_after; + gulong* num; + Atom wm_state = gdk_x11_atom_to_xatom( + gdk_atom_intern_static_string("WM_STATE")); + + gdk_error_trap_push(); + type = None; + XGetWindowProperty(GDK_WINDOW_XDISPLAY(window), + GDK_WINDOW_XID(window), + wm_state, + 0, G_MAXLONG, + False, wm_state, &type, &format, &nitems, + &bytes_after, (void*)&num); + + if (gdk_error_trap_pop()) { + return FALSE; + } + + if (type != wm_state) { + XFree(num); + return FALSE; + } + + result = *num == IconicState; + + XFree(num); + + return result; +} diff --git a/xutils.h b/xutils.h new file mode 100644 index 0000000..6a45031 --- /dev/null +++ b/xutils.h @@ -0,0 +1,51 @@ +/* Xlib utilities */ + +/* + * Copyright (C) 2001 Havoc Pennington + * 2009 Michal Hruby + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef WNCK_XUTILS_H +#define WNCK_XUTILS_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void xutils_set_strut(GdkWindow* gdk_window, + GtkPositionType position, + guint32 strut, + guint32 strut_start, + guint32 strut_end); + +cairo_region_t* xutils_get_input_shape(GdkWindow* window); + +GdkWindow* xutils_get_window_at_pointer(GdkDisplay* gdk_display); + +gboolean xutils_is_window_minimized(GdkWindow* window); + +#ifdef __cplusplus +} // extern "C" +#endif + + +#endif /* WNCK_XUTILS_H */ -- 2.47.0