]> Eric's Git Repo - ericdock.git/commitdiff
Added ability to show battery icon when supported, set dock window struts
authorEric Wertz <ericdwertz@gmail.com>
Fri, 3 Mar 2017 14:28:05 +0000 (09:28 -0500)
committerEric Wertz <ericdwertz@gmail.com>
Fri, 3 Mar 2017 14:28:05 +0000 (09:28 -0500)
Makefile
battery.c [new file with mode: 0644]
battery.h [new file with mode: 0644]
clock.c
clock.h
main.c
xutils.c [new file with mode: 0644]
xutils.h [new file with mode: 0644]

index 77ec352ffe833b9b3207e14b695312ddcca80241..887684f0e8decc70509bf78f2d694d0f9414aabb 100644 (file)
--- 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 (file)
index 0000000..fe09940
--- /dev/null
+++ b/battery.c
@@ -0,0 +1,57 @@
+#include <stdlib.h>
+
+#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 (file)
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 94fae5f662e9ea7c622c9e942b027aaac619f2f8..57f841c989223b53325dfdb9c5a2e76f199f0361 100644 (file)
--- 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 221c327afef0dcdbad9ba487c8df0d0ab1ac06da..c36d94c7a55d00818c3be99f6d6f0addbfdd28f0 100644 (file)
--- 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 6c47a44175d572dc45631a681e384515f0ee814b..884bef2e8a852bcacaeea5bf4c23ee8e82b6a007 100644 (file)
--- a/main.c
+++ b/main.c
 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 (file)
index 0000000..c24e576
--- /dev/null
+++ b/xutils.c
@@ -0,0 +1,218 @@
+/* Xlib utils */
+
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ *               2009 Michal Hruby <michal.mhr@gmail.com>
+ *
+ * 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 <string.h>
+#include <stdio.h>
+#include <malloc.h>
+
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/shape.h>
+
+#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 (file)
index 0000000..6a45031
--- /dev/null
+++ b/xutils.h
@@ -0,0 +1,51 @@
+/* Xlib utilities */
+
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ *               2009 Michal Hruby <michal.mhr@gmail.com>
+ *
+ * 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 <glib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#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 */