Posts

Showing posts from 2021

Offscreen rendering in GTK

Image
  GTK provides a simple OffscreenWindow API to render content offscreen and then paint a widget with that content on demand. This is important if you want to avoid flickering or don't want to show user the content till it's fully ready. The "draw" event handler of gtk_drawing_area_new widget widget draws webview widget on the cairo surface passed to the handler using gtk_widget_draw (GTK_WIDGET (webView), cr) . Keyboard, mouse and scroll events are copied and forwarded to the webview widget. We can listen to WebKitWebView 's "load-changed" event for blocklist managment. ./browser "http://www.google.com" browser.c #include <gtk/gtkx.h> #include <webkit2/webkit2.h> static gboolean refresh_widget (GtkWidget *widget, GdkEvent *event,                         gpointer xv_widget) {   if (GTK_IS_WIDGET (xv_widget))     gtk_widget_queue_draw (GTK_WIDGET (xv_widget));   return FALSE; } static gboolean xwidget_osr_draw_cb (GtkWidget *wid

Browser in GNU Emacs

Image
There are two ways to browse rich web on GNU Emacs - both of them involves xwidget. Notice the different symbols ( widget and socket ) passed to (xwidget-insert) command. Apart from the technical difference, widget is keyboard oriented and socket is mouse oriented from usability perspective. Inbuilt webkitgtk2 widget Since it's inbuilt (runs in same process as Emacs), it is better integrated with Emacs compared to the other option. There are keyboard commands to manage the browsing. Though this flickers a lot to suit my taste. Also, input handling is a bit cumbersome.   (setq w (xwidget-insert (point) ' webkit "test" 400 600)) External Surf browser Surf browser also uses webkitgtk2. It's the only browser which supports XEmbed protocol. This means you can use mouse and keyboard normally as you'd do while browsing web.   With my patch , you should be able to invoke surf as below:   (setq w (xwidget-insert (point) ' socket "test" 400 600 '(

Build your own browser

Image
Build your own browser using GTK and webkit2. ./browser "http://www.google.com" To add content blocking, connect to the "decide-policy" signal and use webkit_policy_decision_ignore() . browser.c #include <gtk/gtkx.h> #include <webkit2/webkit2.h> int main(int argc, char* argv[]) {   // Initialize GTK+   gtk_init(&argc, &argv);   // Create an 800x600 window that will contain the browser instance   GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);   g_signal_connect(window, "delete-event", gtk_main_quit, NULL);   gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);        // Create a browser instance   WebKitWebView *webView = WEBKIT_WEB_VIEW(webkit_web_view_new());   gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(webView));   // Load a web page into the browser instance   webkit_web_view_load_uri(webView, argv[1]);   // Make sure the main window and all its contents are visible   gtk_widget_show_all(window);   // Run t

gVim in GNU Emacs

Image
  You can also embed gVim in GNU Emacs (GTK build with X11 backend). There are two things to take care of in this case - moving focus to the embedded widget and redirecting keyboard input to the widget. A GTK widget can only have focus if it's set that way (remember there are multiple widgets in a window): // Allow to receive keyboard input gtk_widget_set_can_focus (widget, TRUE); // Receive keyboard input gtk_widget_grab_focus (widget);   Emacs filters keyboard events (KeyPress) before passing it to GTK. That's how C-g always works in Emacs. When Emacs receives XEMBED_REQUEST_FOCUS (event->type == ClientMessage && event->xclient.message_type == dpyinfo->Xatom_XEMBED && event->xclient.data.l[1] == XEMBED_REQUEST_FOCUS) , we need to set input focus to the widget using XSetInputFocus() using the handle event->xclient.window . Additionally, we set a flag that a widget is active. Whenever this flag is active, we stop filtering keyboard events. Th

Embedding GTK applications via XEmbed - 2

Image
In previous post , we learnt the basics of embedding a GTK application in another application. This works fine when the embedded application supports client server architecture like gVim. Note that in this case the client mode invocations are short lived processes while server process runs throughout the lifetime of the application. In contrast, an application like VLC provides a remote control interface to run  multiple operations in the same process. In this case, we need to obtain an input channel of the process and write our commands to the same. Here's an updated version of the code. Remember to update the two bold paths with appropriate video locations. The application starts with one video and then switches to the next one when the button is clicked. embed.c #include <gtk/gtkx.h> gchar *string; GMutex mutex; void send_hello(GtkButton *btn) {   /* Note the \n at the end */   string = g_strdup_printf("add /home/anand/Downloads/test.mp4 \n"); } static void cb

Debian: No graphical display after hibernate

After a recent upgrade on debian bullseye (Debian 5.10.84-1 (2021-12-08)), I was unable to get a graphical display after resuming from hibernate. Though terminal login worked just fine. Seems like it's a problem with NetworkManager changing hostname. It will change it if the hostname variable is not set in configuration file. Following advice at https://bbs.archlinux.org/viewtopic.php?pid=684936#p684936 , I added following two lines in /etc/NetworkManager/NetworkManager.conf   [keyfile] hostname = <your hostname>        

Embedding SDL widget in GTK application

  Here's an updated version of Embedding SDL widget in GTK application using SDL2 and GTK 3.0. embed.c #include <stdio.h> #include <gtk/gtkx.h> #include <SDL.h> #include <stdbool.h> static SDL_Window *sdl_window; static SDL_Renderer *sdl_renderer; static GtkWindow *gtk_window; static GtkWidget *gtk_da; static void *gdk_window; static void *window_id; static gboolean idle(void *ud) {     if(!sdl_window) {         printf("creating SDL window for window id %p\n", window_id);         sdl_window = SDL_CreateWindowFrom(window_id);         printf("sdl_window=%p\n", sdl_window);         if(!sdl_window) {             printf("%s\n", SDL_GetError());         }         sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);         printf("sdl_renderer=%p\n", sdl_renderer);         if(!sdl_renderer) {             printf("%s\n", SDL_GetError());         }     } else {         SDL_SetRenderDrawColor(sdl_renderer, 255, 0, 0

Embedding GTK applications via XEmbed

Image
Together with GtkPlug , GtkSocket provides the ability to embed widgets from one process into another process in a fashion that is transparent to the user. One process creates a GtkSocket widget and passes that widget’s window ID to the other process, which then creates a GtkPlug with that window ID . Any widgets contained in the GtkPlug then will appear inside the first application’s window. Here's an updated version of Embedding applications via XEmbed using GTK 3.0. Reference Here are commands for running some GTK applications in embedded mode: gvim --servername %d --socketid %d #GVim server gvim --servername %d --remote-send 'GoHello, World!<Esc><C-O>' #GVim client cvlc --drawable-xid %d out.mp4     #VLC xterm -into %lu    # Terminal emulator mpv --wid=%lu url     # mpv video player surf -e %lu   # Surf web browser from Suckless based on webkitgtk2 embed.c #include <gtk/gtkx.h> #define EXPR "'GoHello, World!<Esc><C-O>'&

Formula Editor in GNU Emacs

Image
    Here's a simple formula editor using SVG for quick note taking in GNU Emacs. Presently, it's a single line editor. You can use arrow keys to move around, Shift+arrow keys for selection and backspace for deleting characters. Use Ctrl + x prefix for special actions like grouping (g), fractions (f) and exponents (e). (require 'formula)   M-x formula-mode Code: https://gitlab.com/atamariya/emacs/-/blob/dev/lisp/svg.el https://gitlab.com/atamariya/emacs/-/blob/dev/lisp/formula.el   How it works? In the video, an event loop is started in the scratch buffer. All the edit operations update text and text property in a temporary buffer, say a.txt. Based on this information, in-memory SVG DOM is updated. Ultimately, the display engine updates the view with this SVG image.

SVG Hack for Emacs Display Engine

Image
    Here's throwing an idea into the wild. How about using SVG for rendering in the Emacs display engine? The attached image shows the rendering as a proof of concept for feasibility. The top window shows the SVG rendering of the buffer shown in the bottom window. One obvious advantage is precise positioning of content including inline popups for auto-completion. This also precludes any major changes to the display engine data structures. Other use cases include feature filled tooltips, inline completion popup, multi-column layouts, watermarks etc In this hack, the elisp code navigates from (window-start) to (window-end) reading a line of text from associated buffer and displaying the same in SVG. I've used (read-event) and (lookup-key) to allow for key translations for navigation commands. Hopefully with a tighter integration, all of this will not be required. Positioning of point is one open area. We would need the bounding box of text for accurate positioning. We have thr

PCB Design in GNU Emacs

Image
Gerber For fun, here's a Gerber file generated from SVG footprints drawn in GNU Emacs . Note: gerbv displays polygon pad incorrectly as circle in fast mode . You should use use normal mode for this. Or else use gerbview . 3D Model If you have properly modeled footprints (1:1 scale, XY plane of the 3D model on the PCB and origin at the center of the bounding box), then you can easily generate 3D view of the assembly. In this screenshot, you can see the generated model being rendered by view3dscene. The code expects eda:url attribute to point to the 3D model (.wrl file for VRML 2.0). The shape with eda:type="board" is used as the PCB. (require 'gerber) (setq canvas-plugin-map pcb-canvas-map) Fancy fonts on Silkscreen Do you want fancy fonts on your PCB silkscreen? You can use a Hershey font or stroke font in SVG format to achieve the desired result. A small collection of these fonts are available at https://gitlab.com/oskay/svg-fonts . Code: https://gitlab.com/at

SPICE simulation in GNU Emacs (From schematics)

Image
Now you can design and run SPICE simulation for simple circuits in GNU Emacs. Since the circuit and graphs are in SVG format, you can easily annotate and share it on the web or embed it in a document.   Video tutorial for configuring the circuit diagram, running the simulation and plotting the results is below:  Video tutorial for drawing the circuit diagram using widgets is below:   Code:   https://gitlab.com/atamariya/emacs/-/blob/dev/lisp/svg.el https://gitlab.com/atamariya/emacs/-/blob/dev/lisp/spice-mode.el   Setup: Setup is covered in following blog posts. https://lifeofpenguin.blogspot.com/2021/10/svg-widget-in-gnu-emacs.html https://lifeofpenguin.blogspot.com/2021/10/spice-simulation-in-gnu-emacs.html Additionally, we need to make special spice plugin (defined in spice-mode.el) available to canvas-mode. This makes plugin keybindings available via C-x in canvas-mode. To do this, add following to .emacs (setq canvas-plugin-map spice-canvas-map)   How does it work? SVG is an

SVG widget in GNU Emacs

Image
  (Top) SVG sprite sheet (Bottom) widgets from sprite sheet (Left) SVG widget in Emacs buffer Now you can use SVG widget in GNU Emacs. That is, use an SVG image or fragment as background for push-button widget in Emacs buffer. You can also specify the width and height of the widget for finer control. Generally speaking, you can use any type of image for this purpose. But SVG suits best because you can draw widget of any size without any distortion.   The ability to use SVG fragment means you can define multiple symbols in an SVG and use the same as a sprite sheet or a symbol library for your UI requirements. Thus the number of files to be managed is reduced. An SVG symbol library is a simple SVG file with each symbol as a direct descendant of the root node. Video above shows an example of such usage. Another use case would be better looking customize form. Or at the very least, rounded "Save" and "Cancel" buttons. In other words, a more visually appealing UI in grap

SPICE simulation in GNU Emacs

Image
Now you can manage and run SPICE simulation within GNU Emacs using ngspice. To visualize the output, the code uses ngspice control card to run gnuplot.   .emacs ;; Check the location of spice-mode.el (load "~/spice-mode.el") (setq spice-simulator "Ngspice"       spice-waveform-viewer "ngplot") ;; ngplot is a new custom viewer defined in elisp which uses gnuplot   Install ngspice and gnuplot # apt install ngspice gnuplot Download https://gitlab.com/atamariya/emacs/-/blob/dev/lisp/spice-mode.el . Load the file (load "~/spice-mode.el") Open a new buffer and activate mode using M-x spice-mode . Select simulator Ngspice and waveform viewer ngplot via menu or by setting variables (same as in .emacs above). Enter circuit definition. Run the simulation using C-c C-r (spice-compile). Go to error, if any, using 'next-error' ( M-x next-error or M-g n ). Plot the results using C-c C-v (spice-plot). Enter the fields (e.g. int out) to be plotted. S

GNU Emacs as a lightweight PHP IDE

Image
  Auto-complete for PHP Auto-complete using company   This is a simple Proof-of-Concept for PHP auto-complete based on CEDET semantic. Given a semantic setup, addition of the following two files (Makefile.in changes too if grammar file should be compiled during build) should allow auto-complete as in above picture. PHP Grammar file: https://gitlab.com/atamariya/emacs/-/blob/php/admin/grammars/php.wy PHP mode definition: https://gitlab.com/atamariya/emacs/-/blob/php/lisp/cedet/semantic/php.el

Draw and Scribble Notes in GNU Emacs

Image
        SVG seems to be quite handy for quick note-taking. You can easily draw simple shapes, use symbols from an SVG library and augment it with some freehand drawing. Combined with excellent keyboard editing of Emacs, you'll not miss anything while taking notes. Code: https://gitlab.com/atamariya/emacs/-/blob/dev/lisp/svg.el   Installation When you are drawing programmatically, you need to be able to track nodes by unique ids. e.g. if you call (svg-circle) followed by (svg-rect) using the same id, you should end up with an SVG rectange node. With out of the box svg.el, you'll end up with SVG circle node with attributes from (svg-rect). Hence canvas mode will not work with out of the box svg.el as is.   Till my patch which addresses this issue is merged in Emacs core (see https://lists.gnu.org/archive/html/emacs-devel/2021-09/msg00798.html ), you'll need to add following commands in your init file (~/.emacs) to use it.   ;; Assuming you have downloaded svg.el to ~/ (load

Sheet music in GNU Emacs

Image
Use "Bravura Text" font for music symbols. Use C-x 8 RET to enter music symbols. G clef is U+1D11E .  Staff is U+E01A . Notes are U+1D15F and U+E1D6 . Use display text properties to raise the symbols.  (put-text-property (region-beginning) (region-end) 'display '(raise 0.1)) Save the file in enriched-mode to preserve the formatting. To display raise text property, add the following in .emacs . (setq enriched-allow-eval-in-display-props t) Code: https://gitlab.com/atamariya/emacs/tree/dev Music Symbol reference: http://www.smufl.org/files/smufl-0.9.pdf

Basic WYSIWYG printing in GNU Emacs

Image
Unicode text (top) converted to PS file (bottom) Document printed using HP3545 printer Unicode RTL text (top) converted to PS file (bottom) ASCII text in Braille font (top) converted to PS file (bottom) Unicode CJK text (top) converted to PS file (bottom) Sheet music using Bravura Text (top) converted to PS file (bottom) Sudoko grid (top) converted to PS file (bottom) Text with fancy fonts (top) converted to PS file (bottom) Text file (left) converted to PS file (right) Welcome screen (left) with SVG image and font variations converted to PS file (right)   Full resolution JPG in image-mode (left) converted to fit in an A4 page (right)   Format a text file in text-mode. Please note that you need to use proportional font (aka variable pitch font) in the frame to have text with varying sizes.  DejaVuSans font is used in the screenshot. Also, be aware that font-lock-mode might interfere with the formatting. If you're unable to change formatting, try turning off font-lock-mode. Install