Repository: kivy/kivy

Issue:
Screen already managed by another ScreenManager (kivy users)
as reported on kivy-users, the showcase demo crashes when using any of the ShaderTransitions.
## <bountysource-plugin>

Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/9558285-screen-already-managed-by-another-screenmanager-kivy-users?utm_campaign=plugin&utm_content=tracker%2F42681&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F42681&utm_medium=issues&utm_source=github).
</bountysource-plugin>



Discussion:
see PR #3144

@denys-duchier I don't see the crash. Could you post a log?

@akshayaurora the exception happens once you have moved to the next screen and try to get back to the previous screen.

Below are the modifs you need to exercise this bug; then run the showcase demo, click on the right-facing caret to go to the next screen, then click on the left-facing caret to go back to the previous screen, and that's when you get an exception:

``` diff
diff --git a/examples/demo/showcase/showcase.kv b/examples/demo/showcase/showcase.kv
index a81d062..76dacde 100644
--- a/examples/demo/showcase/showcase.kv
+++ b/examples/demo/showcase/showcase.kv
@@ -35,6 +35,7 @@
                 height: self.height if root.fullscreen else self.minimum_height


+#:import SM kivy.uix.screenmanager
 BoxLayout:
     orientation: 'vertical'

@@ -95,6 +96,7 @@ BoxLayout:

     ScreenManager:
         id: sm
+        transition: SM.FadeTransition()
         on_current_screen:
             spnr.text = args[1].name
             idx = app.screen_names.index(args[1].name)
```

To understand the problem, I instrumented, in class `ScreenManager`, the methods `add_widget`, `real_add_widget`, `remove_widget`, and `real_remove_widget`, and for each one I printed the argument widget and the stack trace.

On the **good** case (i.e. with `SlideTransition`), the following happens when you click on a caret::

```
on_release > go_next_screen > switch_to >
    add_widget
    real_add_widget

The animation runs,  then

stop > on_complete >
    remove_widget
    remove_screen > real_remove_widget
```

On the **bad** case (i.e. with `FadeTransition`), the following happens::

```
on_release > go_next_screen > switch_to >
    add_widget
    real_remove_widget

The animation runs, then

stop > on_complete >
    remove_screen > real_add_widget
```

Notice that the previous screen has not gone through `remove_widget`, therefore when you attempt to move back to it, the code goes into `add_widget` with a screen that was **not** removed; and that's the reason for the exception.

My patch modifies the bahaviour of `ShaderTransition` so that it conforms again to the logic used in `TransitionBase`.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@denys-duchier you are trying to use switch_to to a screen already loaded on screen, Notice the `Note` on the doc https://kivy.org/doc/stable/api-kivy.uix.screenmanager.html?highlight=screen#advanced-usage

I think the confusion comes from the following message in the doc for `switch_to`, `Add a new screen to the ScreenManager and switch to it. The previous screen will be removed from the children. `

The Screen get's removed from children but is still managed by the ScreenManager.

I'll fix the doc to explain this and update the Showcase to avoid this issue.
Ah didn't notice this was a issue with FadeTransition not with SlideTransition...

Resolving patch:
diff --git a/kivy/uix/screenmanager.py b/kivy/uix/screenmanager.py
--- a/kivy/uix/screenmanager.py
+++ b/kivy/uix/screenmanager.py
@@ -497,7 +497,6 @@ def _remove_out_canvas(self, *args):
     def add_screen(self, screen):
         self.screen_in.pos = self.screen_out.pos
         self.screen_in.size = self.screen_out.size
-        self.manager.remove_widget(self.screen_out)
         self.manager.real_remove_widget(self.screen_out)
         self.manager.canvas.add(self.screen_out.canvas)
 


Test patch: