LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-06-2021, 10:14 AM   #1
teckk
Senior Member
 
Registered: Oct 2004
Distribution: FreeBSD Arch
Posts: 3,619
Blog Entries: 2

Rep: Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163
C Practice, Linux analogue clock


You'll need gtk3 and cairo for this.
https://www.cairographics.org/manual/cairo-cairo-t.html
https://docs.gtk.org/gtk3/
https://docs.huihoo.com/api/gtk/2.6/gobject/

clock.c
Code:
//Gtk3 Analogue-Digital Linux clock

#include <math.h>
#include <cairo.h>
#include <gtk/gtk.h>
#include <time.h>

//Clock size
#define WINDOW_WIDTH  800
#define WINDOW_HEIGHT 800

//Colors
#define WHITE   255, 255, 255
#define RED     255, 0, 0
#define CYAN    0, 255, 255
#define BLUE   0, 0, 135
#define WIDTH   3

static char buffer[256];
static time_t curtime; //Epoch
static struct tm *loctime;
static int seconds;
static int minutes;
static int hours;
static int radius;
static int width;

//Distributions for clock face
static char dist[] = "Powered by Arch Linux"; 
//static char dist[] = "Powered by Slackware Linux";
//static char dist[] = "Powered by Debian Linux";
//static char dist[] = "Powered by Ubuntu Linux";

//Quit
static void quit_application(gpointer app)
{
    g_application_quit (G_APPLICATION (app));
}

//Window Frame
static void show_hide_frame(GtkWindow *window)
{
    gtk_window_set_decorated(window, !gtk_window_get_decorated(window));
}

//Right click menu
int show_popup(GtkWidget *widget, GdkEvent *event) 
{
    const int RIGHT_CLICK = 3;
    if (event->type == GDK_BUTTON_PRESS) 
    {
        GdkEventButton *bevent = (GdkEventButton *) event;

        if (bevent->button == RIGHT_CLICK) 
        {      
            gtk_menu_popup_at_pointer(GTK_MENU(widget), NULL);
        }
        return TRUE;
    }
    return FALSE;
}

//Hour ticks
void HourTick (GtkWidget *widget, cairo_t *cr, int hourSeg, int cx, int cy)
{
    double htRadians = hourSeg * 3.14 / 6.0;
    //Draw line from .9 * rad to 1.0 * rad for hours
    int x1 = cx+(int) ((0.9 * radius * sin (htRadians)));
    int y1 = cy-(int) ((0.9 * radius * cos (htRadians)));
    int x2 = cx+(int) ((1.0 * radius * sin (htRadians)));
    int y2 = cy-(int) ((1.0 * radius * cos (htRadians)));
    cairo_set_source_rgb(cr, CYAN); //Color
    cairo_set_line_width(cr, WIDTH); //Width
    cairo_move_to(cr, x1, y1); //Place and length
    cairo_line_to(cr, x2, y2); //Add line
    cairo_stroke(cr);
}

//Minute ticks
void MinTick (GtkWidget *widget, cairo_t *cr, int hourSeg, int cx, int cy)
{   
    double mtRadians = hourSeg * 3.14 / 30.0;
    //Draw line from .96 * rad to 1.0 * rad for mins
    int a1 = cx+(int) ((0.96 * radius * sin (mtRadians)));
    int b1 = cy-(int) ((0.96 * radius * cos (mtRadians)));
    int a2 = cx+(int) ((1.0 * radius * sin (mtRadians)));
    int b2 = cy-(int) ((1.0 * radius * cos (mtRadians)));
    cairo_set_source_rgb(cr, CYAN);
    cairo_set_line_width(cr, WIDTH);
    cairo_move_to(cr, a1, b1);
    cairo_line_to(cr, a2, b2);
    cairo_stroke(cr);
}   

//Second hand
void DrawSeconds (GtkWidget *widget, cairo_t *cr, int cx, int cy)
{
    //Get radians from seconds
    float sRadians = seconds * 3.14 / 30.0;
    //Draw second hand
    cairo_set_source_rgb(cr, RED); //Color
    cairo_set_line_width(cr, WIDTH); //Width
    cairo_move_to(cr, cx, cy); //Place and length
    cairo_line_to(cr, cx + (0.9 * radius * sin (sRadians)),
                    cy - (0.9 * radius * cos (sRadians)));
    cairo_stroke(cr);
}

//Minute hand
void DrawMinutes (GtkWidget *widget, cairo_t *cr, int cx, int cy)
{
    //Get radians
    float mRadians = (minutes * 3.14 / 30.0) + (seconds * 3.14 / 1800.0);
    //Draw minute hand
    cairo_set_source_rgb(cr, CYAN);
    cairo_set_line_width(cr, WIDTH * 2);
    cairo_move_to(cr, cx, cy);
    cairo_line_to(cr, cx + (0.8 * radius * sin (mRadians)),
                   cy - (0.8 * radius * cos (mRadians)));
    cairo_stroke(cr);
}

//Hour hand
void DrawHours (GtkWidget *widget, cairo_t *cr, int cx, int cy)
{
   //Get radians
   float hRadians = ((hours % 12) * 3.14 / 6.0) + (minutes * 3.14 / 360.0);
   //Draw hour hand
   cairo_set_source_rgb(cr, CYAN);
   cairo_set_line_width(cr, WIDTH * 3);
   cairo_move_to(cr, cx, cy);
   cairo_line_to(cr, cx + (0.6 * radius * sin (hRadians)),
                   cy - (0.6 * radius * cos (hRadians)));
   cairo_stroke(cr);
}

//Draw
static gboolean draw_cb(GtkWidget *widget, cairo_t *cr, gpointer data)
{
    int midx = gtk_widget_get_allocated_width(widget)/2; //Center
    int midy = gtk_widget_get_allocated_height(widget)/2;
    int hourSeg;
    
    //Draw Tickmarks at each hour/minute
    for (hourSeg = 1; hourSeg <= 60; hourSeg++)
    {
        MinTick(widget, cr, hourSeg, midx, midy);
        if(hourSeg <= 12)
        {
            HourTick(widget, cr, hourSeg, midx, midy);
        }
    }
    
    //Digital Clock
    cairo_set_source_rgb(cr, WHITE); //Font Color
    cairo_set_font_size (cr, 50); //Font size
    cairo_move_to(cr, midx/1.4, midy/2); //Position
    cairo_show_text(cr, buffer);
    
    //Powered by distribution
    cairo_set_source_rgb(cr, BLUE); //Distro color
    cairo_set_font_size (cr, 50); //Distro Size
    width = strlen(dist) * 28 / 2; //Approx center
    cairo_move_to(cr, midx - width, midy/1.1);
    cairo_show_text(cr, dist);
    
    radius = MIN (midx, midy) -2 ; //Clock radius in window
    cairo_move_to(cr, midx , 0);
    //Clock Hands
    DrawHours (widget, cr, midx, midy);
    DrawMinutes (widget, cr, midx, midy);
    DrawSeconds (widget, cr, midx, midy);
    return FALSE;
}

//Get Time
static gint time_handler (GtkWidget *widget)
{
    curtime = time(NULL);
    loctime = localtime(&curtime);
    seconds = loctime->tm_sec;
    minutes = loctime->tm_min;
    hours   = loctime->tm_hour;
    strftime(buffer, 256, "%H:%M:%S", loctime);
    gtk_widget_queue_draw(widget);
    return TRUE;
}

static void activate (GtkApplication* app, gpointer user_data)
{
    GtkWidget *window;
    GtkWidget *drawing_area;
    GtkWidget *ebox;
    GtkWidget *pmenu;
    GtkWidget *frameMenuItem;
    GtkWidget *hideMenuItem;
    GtkWidget *quitMenuItem;

    window = gtk_application_window_new (app);
    gtk_window_set_title (GTK_WINDOW (window), "Gtk3 Clock"); //Title
    gtk_window_set_default_size (GTK_WINDOW (window), //App size
                                    WINDOW_WIDTH, WINDOW_HEIGHT);
    gtk_window_set_decorated (GTK_WINDOW (window), FALSE); //Window decorations
    gtk_container_set_border_width (GTK_CONTAINER (window), 0);
    gtk_widget_set_app_paintable(window, TRUE); //Window color

    GdkScreen *screen = gtk_widget_get_screen(window);
    GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
    gtk_widget_set_visual(window, visual);

    ebox = gtk_event_box_new();
    gtk_container_add(GTK_CONTAINER(window), ebox);

    drawing_area = gtk_drawing_area_new();
    gtk_widget_set_size_request (drawing_area, WINDOW_WIDTH - 2 , 
                                    WINDOW_HEIGHT - 2);
    
    gtk_container_add(GTK_CONTAINER (ebox), drawing_area);

    g_signal_connect(drawing_area, "draw", 
                        G_CALLBACK (draw_cb), NULL);
    g_signal_connect(drawing_area, "delete-event", 
                        G_CALLBACK (gtk_main_quit), NULL);

    pmenu = gtk_menu_new();
    //Right click menu items
    frameMenuItem = gtk_menu_item_new_with_label("Show-Hide Frame");
    gtk_widget_show(frameMenuItem);
    gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), frameMenuItem);

    hideMenuItem = gtk_menu_item_new_with_label("Minimize");
    gtk_widget_show(hideMenuItem);
    gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), hideMenuItem);

    quitMenuItem = gtk_menu_item_new_with_label("Quit");
    gtk_widget_show(quitMenuItem);
    gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), quitMenuItem);  
    //Connect to signals
    g_signal_connect_swapped(G_OBJECT(frameMenuItem), "activate", 
        G_CALLBACK(show_hide_frame), GTK_WINDOW(window));    

    g_signal_connect_swapped(G_OBJECT(hideMenuItem), "activate", 
        G_CALLBACK(gtk_window_iconify), GTK_WINDOW(window));    

    g_signal_connect_swapped(G_OBJECT(quitMenuItem), "activate", 
        G_CALLBACK(quit_application), app);  

    g_signal_connect_swapped(G_OBJECT(window), "destroy",
        G_CALLBACK(quit_application), app);
        
    g_signal_connect_swapped(G_OBJECT(ebox), "button-press-event", 
        G_CALLBACK(show_popup), pmenu);  

    g_timeout_add (1000, (GSourceFunc) time_handler, drawing_area);
    
    gtk_widget_show_all(window);
}

int main (int argc, char **argv)
{
    GtkApplication *app;
    int status;

    app = gtk_application_new("my.clock", G_APPLICATION_FLAGS_NONE);
    g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);

    status = g_application_run(G_APPLICATION (app), argc, argv);
    g_object_unref (app); //Mem Freed

    return status;
}
You can compile that with:
Code:
gcc -lm clock.c -o clock $(pkg-config --cflags --libs gtk+-3.0)
Or with:
Code:
gcc -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 \
-I/usr/include/harfbuzz -I/usr/include/glib-2.0 \
-I/usr/lib/glib-2.0/include -I/usr/include/cairo \
-I/usr/include/gdk-pixbuf-2.0 -I/usr/include/atk-1.0 \
-pthread -lgtk-3 -lgdk-3 -lz -lpangocairo-1.0 -lpango-1.0 \
-lharfbuzz -latk-1.0 -lcairo-gobject -lcairo -lm \
-lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 \
clock.c -o clock
Or create a Makefile and run make.

Makefile
Code:
CFLAGS += -Wall -Wextra -Wno-unused-parameter -O3
__NAME__ = clock
__NAME_UPPERCASE__ = CLOCK

INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
INSTALL_DATA = $(INSTALL) -m 644

prefix = /usr/local
exec_prefix = $(prefix)
bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
datarootdir = $(prefix)/share
mandir = $(datarootdir)/man
man1dir = $(mandir)/man1
datadir = $(prefix)/share

.PHONY: all clean install installdirs

all: $(__NAME__)

$(__NAME__): clock.c
	$(CC) $(CFLAGS) $(LDFLAGS) \
		-D__NAME__=\"$(__NAME__)\" \
		-D__NAME_UPPERCASE__=\"$(__NAME_UPPERCASE__)\" \
		-o $@ $< \
		-lm `pkg-config --cflags --libs gtk+-3.0`

install: all installdirs
	$(INSTALL_PROGRAM) $(__NAME__) $(DESTDIR)$(bindir)/$(__NAME__)
	$(INSTALL_DATA) man1/$(__NAME__).1 $(DESTDIR)$(man1dir)/$(__NAME__).1
	$(INSTALL_DATA) man1/$(__NAME__).usage.1 \
		$(DESTDIR)$(man1dir)/$(__NAME__).usage.1

installdirs:
	mkdir -p $(DESTDIR)$(bindir) $(DESTDIR)$(man1dir) \
		$(DESTDIR)$(libdir)/$(__NAME__)/web_extensions \
		$(DESTDIR)$(datadir)/$(__NAME__)/user-scripts

clean:
	#Nothing to clean

Last edited by teckk; 09-06-2021 at 10:15 AM.
 
Old 09-06-2021, 10:26 AM   #2
teckk
Senior Member
 
Registered: Oct 2004
Distribution: FreeBSD Arch
Posts: 3,619

Original Poster
Blog Entries: 2

Rep: Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163
More C Practice.

You'll need gcc gtk3 and webkit2gtk installed.

gtkbrowser.c
Code:
//Basic webkit2gtk web browser in c

#include <gtk/gtk.h>
#include <webkit2/webkit2.h>

//Home page
const gchar *HomePage = "https://www.linuxquestions.org/questions/";

//User agent
const gchar* agent = "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_1 "
        "like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) "
        "Version/10.0 Mobile/14A403 Safari/602.1";

static void destroyWindow(GtkWidget* widget, GtkWidget* window)
{
    gtk_main_quit();
}

static gboolean closeWebView(WebKitWebView* webView, GtkWidget* window)
{
    gtk_widget_destroy(window);
    return TRUE;
}

int main(int argc, char* argv[])
{
    gtk_init(&argc, &argv);
    g_set_application_name("My Browser"); //Browser name

    GtkWidget *main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    
    //Window size
    gtk_window_set_default_size(GTK_WINDOW(main_window), 1400, 1000);

    WebKitWebView *webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
    
    //Zoom level
    webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(webView), 1.5);
    
    //Browser settings
    WebKitSettings *settings = webkit_settings_new();
    g_object_set(G_OBJECT (settings), "enable-javascript", FALSE, NULL);
    g_object_set(G_OBJECT (settings), "auto-load-images", FALSE, NULL);
    g_object_set(G_OBJECT (settings), "minimum-font-size", 18, NULL);
    g_object_set(G_OBJECT (settings), "enable-developer-extras", TRUE, NULL);
    g_object_set(G_OBJECT (settings), "print-backgrounds", FALSE, NULL);
    g_object_set(G_OBJECT (settings), "user-agent", agent, NULL);

    webkit_web_view_set_settings(WEBKIT_WEB_VIEW(webView), settings);

    gtk_container_add(GTK_CONTAINER(main_window), GTK_WIDGET(webView));
    
    g_signal_connect(main_window, "destroy", G_CALLBACK(destroyWindow), NULL);
    g_signal_connect(webView, "close", G_CALLBACK(closeWebView), main_window);
    
    const gchar* url;
    
    //Get args
    if(argc > 2)
    {
        //fprintf(stderr, "Too may args!\nUsage: "__NAME__" [URI]\n");
        fprintf(stderr, "Too may args!\nUsage: gtkbrowser [URI]\n");
        return 0;
    }
    else if(argc == 2)
    {
        url = argv[1];
    }
    else
    {
       url = HomePage;
    }
    
    webkit_web_view_load_uri(webView, url);
    gtk_widget_grab_focus(GTK_WIDGET(webView));
    gtk_widget_show_all(main_window);

    gtk_main();

    return 0;
}
Compile with
Code:
gcc gtkbrowser.c -o gtkbrowser $(pkg-config --cflags --libs gtk+-3.0 glib-2.0 webkit2gtk-4.0)
Or use a Makefile with make

Makefile
Code:
CFLAGS += -Wall -Wextra -Wno-unused-parameter -O3
__NAME__ = gtkbrowser
__NAME_UPPERCASE__ = GTKBROWSER

INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
INSTALL_DATA = $(INSTALL) -m 644

prefix = /usr/local
exec_prefix = $(prefix)
bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
datarootdir = $(prefix)/share
mandir = $(datarootdir)/man
man1dir = $(mandir)/man1
datadir = $(prefix)/share

.PHONY: all clean install installdirs

all: $(__NAME__)

$(__NAME__): gtkbrowser.c
	$(CC) $(CFLAGS) $(LDFLAGS) \
		-D__NAME__=\"$(__NAME__)\" \
		-D__NAME_UPPERCASE__=\"$(__NAME_UPPERCASE__)\" \
		-o $@ $< \
		`pkg-config --cflags --libs gtk+-3.0 glib-2.0 webkit2gtk-4.0`

install: all installdirs
	$(INSTALL_PROGRAM) $(__NAME__) $(DESTDIR)$(bindir)/$(__NAME__)
	$(INSTALL_DATA) man1/$(__NAME__).1 $(DESTDIR)$(man1dir)/$(__NAME__).1
	$(INSTALL_DATA) man1/$(__NAME__).usage.1 \
		$(DESTDIR)$(man1dir)/$(__NAME__).usage.1

installdirs:
	mkdir -p $(DESTDIR)$(bindir) $(DESTDIR)$(man1dir) \
		$(DESTDIR)$(libdir)/$(__NAME__)/web_extensions \
		$(DESTDIR)$(datadir)/$(__NAME__)/user-scripts

clean:
    #Nothing to clean
Code:
make
Edit: I can not get that c code to post right between tags, and I can't see why? Moderator, can you?

Last edited by teckk; 09-06-2021 at 10:59 AM.
 
Old 09-06-2021, 10:39 AM   #3
teckk
Senior Member
 
Registered: Oct 2004
Distribution: FreeBSD Arch
Posts: 3,619

Original Poster
Blog Entries: 2

Rep: Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163
Trying to figure out what symbols the forums code tags aren't liking.

Duh, been coding for days, half blinb I guess, missed a / on [/code]

Last edited by teckk; 09-06-2021 at 11:00 AM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Analogue clock for Gnome Pannel DavidMcCann Linux - Software 3 04-25-2007 05:52 AM
An analogue for Device Manager in Linux royeo Linux - Hardware 3 07-07-2006 09:54 AM
Best analogue video capture card for use with linux slothpuck Linux - Hardware 5 09-04-2005 03:55 PM
Analogue of acme on KDE chem1 Linux - Software 0 02-28-2004 03:56 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:31 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration