Meltdown – The Computer Lab Prank

I remember that little prank from the days I was a student. You work on an X terminal, and out of the blue, all the display contents gradually disappear’ Pixel after pixel turns black. But don’t worry – you’ll regain control over your display shortly. shortly.
Everyone can access other X terminal display, and mess with it.

How Does It Work?

This program is a simple one using the GDK library, Gnome’s window management package. Including ‘gdk.h’ will also include:

The Program’s Flow

The main function of the program performs the following steps:
1. Initialize GDK.
2. Create a window whose dimensions are the same as those of the root window.
3. Make the window’s background transparent.
4. Make the window a full-screen window.
5. Add an event handler. to handle Expose events.
The event handler will perform the following steps:
1. Create a list of columns and lengths (number of blackened pixels).
2. Create the Graphics Context for the window.
3. Blacken pixels until all pixels are black.
4. Quit the main loop.

Includes And Structures:

#include <stdio.h>
#include <stdlib.h>  
#include <gdk/gdk.h>

GMainLoop *mainloop;
GList *list;

typedef struct col_and_length_t{
  short col;  // Column number
  short len;  // Number of blackened pixels.
} col_and_length;`

The main function:

int main(int argc, char *argv[]){
  gdk_init(NULL, NULL);
  GdkDisplay *disp=gdk_display_get_default();
  GdkScreen *scr = gdk_display_get_default_screen (disp);
  GdkWindow *root = gdk_screen_get_root_window(scr);
  int rootWidth = gdk_window_get_width(root);
  int rootHeight = gdk_window_get_height(root);
  GdkWindowAttr attr;
  attr.window_type = GDK_WINDOW_TOPLEVEL;

  GdkWindow *newWin=gdk_window_new(root,&attr, GDK_WA_X | GDK_WA_Y);
  gdk_event_handler_set (eventFunc, newWin, NULL);
  GdkRGBA color;

  gdk_window_set_background_rgba(newWin, &color);
  gdk_event_handler_set (eventFunc, newWin, NULL);
  mainloop = g_main_new (TRUE);
  g_main_loop_run (mainloop);

return 0;

The event handler

void start_meltdown(GdkWindow *newWin, int height){
  cairo_t *gc=gdk_cairo_create(newWin);
  cairo_set_source_rgb (gc, 0, 0, 0);
  int cell_no,size;
  GList *link;
  col_and_length *link_data;

    cell_no=random() % size;
    link = g_list_nth(list,cell_no);
    link_data = (col_and_length *)link->data;
    cairo_move_to(gc, link_data->col, link_data->len);
    cairo_rel_line_to(gc, 0, 1);
    if (link_data->len >= height){
      list=g_list_remove_link(list, link);

void eventFunc(GdkEvent *evt, gpointer data){
  GdkWindow *newWin = (GdkWindow *)data;
  if (gdk_event_get_event_type(evt) == GDK_EXPOSE && gdk_event_get_window (evt) == newWin){
    int width=gdk_window_get_width(newWin);
    int height=gdk_window_get_height(newWin);
    int i;
    for (i=0; i<width;i++){
      col_and_length *cell=(col_and_length *)calloc(sizeof(col_and_length), 1);
      list = g_list_append(list, cell);



In linux, compiling a program is easy thanks to the pkg-config command.
Run the following from the command line:

gcc meltdown.c `pkg-config --cflags --libs gdk-3.0` -o meltdown

Now, to run the program type:


Written with StackEdit.


Creating Custom Cursors With GDK-Pixbuf-2 And Cairo

Wait! Why use GDK-2 when there ate later stable versions you can download for free? Sometimes you use a tool – such as OpenCV – that integrates with GTK-2, and GDK-2.

Your operating system may allow you to create custom cursor, or mouse pointers, of your own with colors and an alpha channel (opacity). GDK allows you to create a cursor from a pixel buffer (pixbuf), using the function ‘gdk_cursor_new_from_pixbuf‘.  OK, but first let’s make a pixel buffer. In the documentation of GDK 3, I found 2 functions to create a pixbuf: gdk_pixbuf_get_from_window and gdk_pixbuf_get_from_surface. The latter does not exist in GDK-2. However, there is one method, I haven’t found documented` It’s called gdk_pixbuf_new_from_data.  You can get the data from Cairo after you’ve drawn your image using Cairo.

Using Cairo might be a bit confusing because::

  • Cairo uses two data types for color channels: double-precision floating-point numbers and unsigned 8-bit integers.
  • The color of the cursor is not as intended when calling ‘cairo_set_source_rgba’.

The following function in C will demonstrate what I mean:

Here, when the cursor is created its color is yellow, but if you save your created image to a file it will be cyan.

Yellow cursor over the red square.
Yellow cursor over the red square.

The image when saved to a PNG file

The image when saved to a PNG file

void createCursor(){
    double arcEnd=2*M_PI;
    GdkPixbuf *pixbuf;
    int stride=cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, 10); // Will be used later, when we'll create the pixbuf.
    cairo_surface_t *surf=cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 10, 10); // A canvas of width 10 and height 10.
    cairo_t *cairo_ctx = cairo_create(surf);
    cairo_set_source_rgba(cairo_ctx, 0., 1., 1., 1.); // Double precision values for Red, Green, Blue and Alpha channels between 0 and 1.

    cairo_arc(cairo_ctx,5,5,4,0,arcEnd); // Draw a circle or an arc of a circle whose center is at (5,5) and whose radius is 4
                                         // The arc begins at angle 0 and ends in angle 2Π
    cairo_fill(cairo_ctx); // Fill the circle with cyan, though we've intended to create a yellow one.

    // Create an example image for the blog
    cairo_surface_write_to_png(surf, "/tmp/fortheblog.png");

    guchar *data = cairo_image_surface_get_data(surf); // The data is in BGR, reverse order of RGB !!!

    pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, true, 8, 10, 10, stride, NULL, NULL); // Stride is the difference in bytes between two
                                                                                                      // consecutive rows.
    cursor=gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf, 5, 5);


“cursor” in this function is a global variable of type “GdkCursor *”.Now, to add the cursor to a window, use gdk_window_set_cursor.

The “gtk_pixbuf_new_from_data” Function.

This function uses the data returned from the function “cairo_image_surface_get_data”. The data is a pointer to a character. The function receiving the data doesn’t know how many characters are referred to, and how to split it into rows and columns. Following is its prototype:

GdkPixbuf *gdk_pixbuf_new_from_data (const guchar *data,
                     GdkColorspace colorspace,
                     gboolean has_alpha,
                     int bits_per_sample,
                     int width, int height,
                     int rowstride,
                     GdkPixbufDestroyNotify destroy_fn,
                     gpointer destroy_fn_data);

How To Develop a Firefox Extension – Intro

Firefox users can add functionality to their browser by installing an add-on.  To install an add-n click on Tools->Add-ons.

Add On

You can then search for your requested add-on: add-on to download movies from a site, to share a page in Facebook, to add a Delicious bookmark, etc. Another useful add-on is DOM Inspector, which allows you to locate and modify document elements. Firefox add-ons are written in Javascript and access document elements, just like Javascript scripts within HTML documents, except that the document an add-on accesses is named Chrome Document.

Accessing the Chrome Document

The Chrome document contains more than just the “window” element, accessed from a web page using Javascript. Chrome also contains menus, toolbars and other widgets. Let’s make changing one of the Chrome document’s elements your first step in add-on development. If you don’t have DOM Inspector installed in your browser, you can get it here. Now, you can use it to play around a little bit. For example, let’s change the ‘Tools’ menu’s name to ‘Fools’.

To do so, perform the following steps:

  1. Tools->Web Developer->DOM Inspector:
  2. In the DOM Inspector menu bar, choose: File->Inspect Chrome Document->(tab name)
  3. In the DOM Inspector Window, click the magnifying-glass icon.
  4. In the browser’s window click ‘Tools’ menu
    IMPORTANT! This will NOT work if the “Global Menu BAR Integration” add-on is enabled!!!
  5. Open the DOM Inspector window.
    The ‘tools-menu’ node will appear on the right-hand part of the window.
    Now, you can see that the value of the node’s “label” attribute is “Tools”
  6. Right click the “Label” attribute, then left-click “Edit”.
  7. In the “Edit Attributes” window opened change the Node Value and click “OK”.
  8. Nice work!!!

Congratulations! Now you know how to access chrome elements and modify them. This will help you later when you learn how to do it in Javascript.

Learn more about add-on development here.