GTK and scrolling without scrollbars

There's still some work to do on the full screen plugin for Rhythmbox, but the current version is very usable indeed. The latest addition is scrolling by hovering the track list.

I changed the display from a normal fixed table with 3 tracks to a gtk.Layout with a gtk.VBox containing n tracks. In a Layout widget it's possible to freely place and move child widgets, so by detecting motion events on the edges of the Layout you can emulate scrolling by moving a child widget accordingly with Layout.move(widget, x, y). Unfortunately I get a rather nasty blinking effect when scrolling too fast, and I don't have an explanation for this, so I'd be glad to hear from anyone who can help.

def track_layout_scroll(self, widget, event):  
    time_step = 10 #msecs  
    ycoord = event.y  
    accel_factor = 10 #how many pixels to scroll at the edge  
    edge_distance = 100.0 #pixels  
    layout_size = widget.get_size()  
    top_dist = edge_distance - ycoord  
    bot_dist = edge_distance - layout_size[1] + ycoord

    if top_dist > 0:  
        accel = -1 - (top_dist / edge_distance) * accel_factor  
    elif bot_dist > 0:  
        accel =  1 + (bot_dist / edge_distance) * accel_factor  
    else:  
        accel = 0.0





    if self.scroll_event_id:  
        gobject.source_remove(self.scroll_event_id)

    if not accel == 0.0:  
        self.scroll_event_id = gobject.timeout_add(time_step, self.do_scrolling, accel, widget)





 def do_scrolling(self, accel, layout_widget):  
    step = int(1*accel)  
    if step == 0:  
        return  
    vbox_size = self.vbox.size_request()  
    layout_size = layout_widget.get_size()  
    scroll_height = vbox_size[1]-layout_size[1]  
    if self.scroll_y + step < 0:  
        self.scroll_y = 0  
    elif self.scroll_y + step > scroll_height:  
        self.scroll_y = scroll_height  
    else:  
        self.scroll_y += step

    self.track_layout.move(self.vbox, 0, -self.scroll_y)  
    return self.scroll_y > 0 and self.scroll_y < scroll_height

The code is related to my Rhythmbox plugin, but I'm sure you get the idea. Also please note, that track_layout_scroll has to receive notify_motion_event from the Layout widget, and that you have to set a size for the Layout widget with set_size().

Update: By playing around with time_step (lowering it to be more exact) and slowing down the acceleration, I managed to almost make the white flashes disappear.