initial focus behavior.

This adds an initial FocusBehavior. It's not complete, and is missing docs. I want to first see if this is in the right direction.

The main thing that needs to be explained is the reason for allowing the user to supply a keyboard using the keyboard property. The reason is imagine having multiple keyboards in the systemandmulti mode. Then as the user tabs through widgets, at each tab, a keyboard is requested and released. This is fairly slow. If the user supplies the keyboard, we don't have to request and release, we just bind and unbind which is very fast. This doesn't seem to be an issue when the keyboard mode is single keyboard.

You can see the large speed difference by running the example code below with and without commenting out Clock.schedule_once(self.late_start, 5). By leaving it in, and clicking on a button and then holding down tab you'll see it's a lot faster than if its commented out.


    from kivy.config import Config
    Config.set('kivy', 'keyboard_mode', 'systemandmulti')
    
    from kivy.app import App
    from kivy.uix.gridlayout import GridLayout
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.button import Button
    from kivy.uix.behaviors import FocusBehavior
    from kivy.core.window import Window
    from kivy.clock import Clock
    
    
    class FocusButton(FocusBehavior, Button):
    
        def on_focused(self, instance, value, *largs):
            self.background_color = [1, 0, 0, 1] if value else [1, 1, 1, 1]
    
        def keyboard_on_key_down(self, window, keycode, text, modifiers):
            if super(FocusButton, self).keyboard_on_key_down(window, keycode,
                                                             text, modifiers):
                return True
            self.text = keycode[1]
            return True
    
    class FocusApp(App):
    
        def build(self):
            root = BoxLayout()
            self.grid1 = grid1 = GridLayout(cols=4)
            self.grid2 = grid2 = GridLayout(cols=4)
            root.add_widget(grid1)
            root.add_widget(grid2)
            for i in range(40):
                grid1.add_widget(FocusButton(text=str(i)))
            for i in range(40):
                grid2.add_widget(FocusButton(text=str(i)))
            FocusBehavior.autopopulate_focus(grid1)
            FocusBehavior.autopopulate_focus(grid2)
            Clock.schedule_once(self.late_start, 5)
            return root
    
        def late_start(self, *l):
            keyboard1 = Window.request_keyboard(None, self.grid1.children[-1])
            keyboard2 = Window.request_keyboard(None, self.grid2.children[-1])
            for c in self.grid1.children:
                c.keyboard = keyboard1
            for c in self.grid2.children:
                c.keyboard = keyboard2
    
    
    if __name__ == '__main__':
        FocusApp().run()