Click to close notifications in Ubuntu

 •  Filed under ubuntu, desktop, click to close, notifications

Do you love the way your notifications in the upper right corner of your screen look, but do you hate that there' s no way to close these notifications? Then look no further and read along as this article guides you through the process of 'patching' the notify-osd source code to make notifications clickable.

So, here's a preparation list for this little project:

  • You need a development (virtual) environment, I have chosen for a 16.04 virtual machine
  • You need to run the following commands to get the needed development packages installed on your system:
    • sudo apt install build-essential
    • sudo apt install devscripts
  • You need to uncomment the lines starting with deb-src inside /etc/apt/sources.list to allow source package fetching
  • Update your package cache! (sudo apt update)
  • Create a working directory to work in (I used /home/bart/Documents/notify-osd)
  • Install the build dependencies for sudo with sudo apt build-dep notify-osd

The first thing to do is getting the sources cloned into the working directory with this command

  • apt source notify-osd

Great! Now you can cd into the notify-osd source folder, for example

  • cd notify-osd-0.9.35+16.04.20160415

Now it's time to patch the source code of the bubble.c file inside the src directory.
Replace this block of code

// set an 1x1 input-region to allow click-through 
region = cairo_region_create_rectangle (&rect);  
if (cairo_region_status (region) == CAIRO_STATUS_SUCCESS)  
{
        gtk_widget_input_shape_combine_region (window, NULL);
        gtk_widget_input_shape_combine_region (window, region);
}
cairo_region_destroy (region);  

with this

// set an 1x1 input-region to allow click-through 
region = cairo_region_create_rectangle (&rect);  
if (cairo_region_status (region) == CAIRO_STATUS_SUCCESS)  
{
        gtk_widget_input_shape_combine_region (window, NULL);
        gtk_widget_input_shape_combine_region (window, region);
        GdkWindow *window_ = gtk_widget_get_window (window);
        gdk_window_set_events (window_, gdk_window_get_events (window_) | GDK_BUTTON_PRESS);
}
cairo_region_destroy (region);  



Replace this block

// hook up window-event handlers to window
g_signal_connect (window,  
                  "draw",
                  G_CALLBACK (bubble_draw),
                  this);

with this

// hook up window-event handlers to window
g_signal_connect (window,  
                  "draw",
                  G_CALLBACK (bubble_draw),
                  this);

g_signal_connect (window,  
                  "button-press-event",
                  G_CALLBACK (button_press_event_handler),
                  this);



Put this function block

static gboolean  
button_press_event_handler (GtkWidget* window G_GNUC_UNUSED,  
        GdkEventButton* event,
        Bubble* bubble)
{
        BubblePrivate* priv;
        priv = bubble->priv;

        if (priv->mouse_over && event->button == 1)
        {
                bubble_hide (bubble);
                dbus_send_close_signal (bubble_get_sender (bubble),
                        bubble_get_id (bubble),
                        1);

                g_signal_emit (bubble, g_bubble_signals[TIMED_OUT], 0);

                return TRUE;
        }

        return FALSE;
}

above this function block

static gboolean  
redraw_handler (Bubble* bubble)  
{
        ...
        ...
        ...
}

Save the file, and build a Debian package with debuild -uc -us

This should work! At least it did for me ;)