Repository: kivy/kivy

Issue:
SDL2 - exit_on_escape and on_request_close do not work
``` python
import os
os.environ['KIVY_WINDOW'] = 'sdl2'

from kivy.config import Config
Config.set('kivy', 'exit_on_escape', 'False')

from kivy.app import App
from kivy.uix.button import Button


class MyApp(App):

    def on_start(self):
        self.root_window.bind(on_request_close=lambda *args: True)

    def on_pause(self):
        return True

    def build(self):
        return Button()

if __name__ == '__main__':
    MyApp().run()

```



Discussion:
I'm not manually specifying a KIVY_WINDOW platform in my code.
It used to work in my app, now does not, and I'm sorry but I have no idea what exactly broke it :(

If you want to see my app code, it's the Tetrimus repo on my GitHub.

I solved my own issue by changing import order. But for the sdl2-specific thing, I really have no clue, as my current import order (more or less) matches the one above!

@Cheaterman yes, config options should be set before importing the rest of kivy. While checking out your issue, i have found these bugs in the sdl2 provider.


Resolving patch:
diff --git a/kivy/core/window/__init__.py b/kivy/core/window/__init__.py
--- a/kivy/core/window/__init__.py
+++ b/kivy/core/window/__init__.py
@@ -1096,7 +1096,7 @@ def on_dropfile(self, filename):
 
         .. warning::
 
-            This event is currently works sdl2 window provider and on pygame
+            This event currently works with sdl2 window provider, on pygame
             window provider and MacOSX with a patched version of pygame.
             This event is left in place for further evolution
             (ios, android etc.)
diff --git a/kivy/core/window/window_sdl2.py b/kivy/core/window/window_sdl2.py
--- a/kivy/core/window/window_sdl2.py
+++ b/kivy/core/window/window_sdl2.py
@@ -39,8 +39,13 @@
 KMOD_LALT = 256
 KMOD_LMETA = 1024
 KMOD_RMETA = 2048
+
 SDLK_SHIFTL = 1073742049
 SDLK_SHIFTR = 1073742053
+SDLK_LCTRL = 1073742048
+SDLK_RCTRL = 1073742052
+SDLK_LALT = 1073742050
+SDLK_RALT = 1073742054
 SDLK_LEFT = 1073741904
 SDLK_RIGHT = 1073741903
 SDLK_UP = 1073741906
@@ -98,6 +103,20 @@ def __init__(self, **kwargs):
         self._meta_keys = (KMOD_LCTRL, KMOD_RCTRL, KMOD_RSHIFT,
             KMOD_LSHIFT, KMOD_RALT, KMOD_LALT, KMOD_LMETA,
             KMOD_RMETA)
+        self.command_keys = {
+                    27: 'escape',
+                    8: 'backspace',
+                    13: 'enter',
+                    127: 'del',
+                    271: 'enter',
+                    273: 'up',
+                    274: 'down',
+                    275: 'right',
+                    276: 'left',
+                    278: 'home',
+                    279: 'end',
+                    280: 'pgup',
+                    281: 'pgdown'}
 
     def create_window(self, *largs):
 
@@ -215,17 +234,6 @@ def screenshot(self, *largs, **kwargs):
         width, height = self.size
         data = glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE)
         self._win.save_bytes_in_png(filename, data, width, height)
-        return
-        # TODO
-        filename = super(WindowPygame, self).screenshot(*largs, **kwargs)
-        if filename is None:
-            return None
-        from kivy.core.gl import glReadPixels, GL_RGB, GL_UNSIGNED_BYTE
-        width, height = self.size
-        data = glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE)
-        data = str(buffer(data))
-        surface = pygame.image.fromstring(data, self.size, 'RGB', True)
-        pygame.image.save(surface, filename)
         Logger.debug('Window: Screenshot saved at <%s>' % filename)
         return filename
 
@@ -332,7 +340,7 @@ def _mainloop(self):
             elif action == 'joybuttonup':
                 stickid, buttonid = args
                 self.dispatch('on_joy_button_up', stickid, buttonid)
-                
+
             elif action in ('keydown', 'keyup'):
                 mod, key, scancode, kstr = args
                 if mod in self._meta_keys:
@@ -341,9 +349,7 @@ def _mainloop(self):
                     except ValueError:
                         pass
 
-                # XXX ios keyboard suck, when backspace is hit, the delete
-                # keycode is sent. fix it.
-                key_swap = {127: 8,  # back
+                key_swap = {
                             SDLK_LEFT: 276,
                             SDLK_RIGHT: 275,
                             SDLK_UP: 273,
@@ -353,13 +359,27 @@ def _mainloop(self):
                             SDLK_PAGEDOWN: 281,
                             SDLK_PAGEUP: 280,
                             SDLK_SHIFTL: 303,
-                            SDLK_SHIFTR: 304}
+                            SDLK_SHIFTR: 304,
+                            SDLK_LCTRL: KMOD_LCTRL,
+                            SDLK_RCTRL: KMOD_RCTRL,
+                            SDLK_LALT: KMOD_LALT,
+                            SDLK_RALT: KMOD_RALT}
+
+                if platform == 'ios':
+                    # XXX ios keyboard suck, when backspace is hit, the delete
+                    # keycode is sent. fix it.
+                    key_swap[127] = 8  # back
+
                 try:
                     key = key_swap[key]
                 except KeyError:
                     pass
 
                 self._update_modifiers(mod)
+                if 'shift' in self._modifiers and key\
+                        not in self.command_keys.keys():
+                    return
+
                 if action == 'keyup':
                     self.dispatch('on_key_up', key, scancode)
                     continue
@@ -484,16 +504,6 @@ def _update_modifiers(self, mods=None):
             self._modifiers.append('meta')
         return
 
-    def on_keyboard(self, key, scancode=None, str=None, modifier=None):
-        # Quit if user presses ESC or the typical OSX shortcuts CMD+q or CMD+w
-        # TODO If just CMD+w is pressed, only the window should be closed.
-        is_osx = sys.platform == 'darwin'
-        if key == 27 or (is_osx and key in (113, 119) and modifier == 1024):
-            stopTouchApp()
-            self.close()  # not sure what to do here
-            return True
-        super(WindowSDL, self).on_keyboard(key, scancode, str, modifier)
-
     def request_keyboard(self, callback, target, input_type='text'):
         self._sdl_keyboard = super(WindowSDL, self).\
             request_keyboard(callback, target, input_type)


Test patch: