Repository: mitmproxy/mitmproxy

Issue:
Mitmproxy lets us interact with other tab, when focusing on the other one.
##### Steps to reproduce the problem:

1. Open mitmproxy.
2. Press `-` to open two pane layout.
3. Start intercepting something.
4. Choose any flow to see **Flow details**.
5. Change focus on other tab by pressing `Shift+Tab`.
6. Click on "Request" or "Response" by pressing left button of mouse.

![2017-12-31 19-52-30](https://user-images.githubusercontent.com/20267977/34463805-5bb3ebd0-ee70-11e7-883b-c6dc720e4127.png)

I am getting:
```
Traceback (most recent call last):
  File "mitmproxy/tools/console/master.py", line 216, in run
  File "site-packages/urwid/main_loop.py", line 278, in run
  File "site-packages/urwid/main_loop.py", line 376, in _run
  File "site-packages/urwid/main_loop.py", line 682, in run
  File "site-packages/urwid/main_loop.py", line 719, in _loop
  File "site-packages/urwid/raw_display.py", line 393, in <lambda>
  File "site-packages/urwid/raw_display.py", line 493, in parse_input
  File "site-packages/urwid/main_loop.py", line 403, in _update
  File "site-packages/urwid/main_loop.py", line 500, in process_input
  File "mitmproxy/tools/console/window.py", line 277, in mouse_event
  File "site-packages/urwid/container.py", line 1169, in mouse_event
  File "site-packages/urwid/container.py", line 1687, in mouse_event
  File "site-packages/urwid/container.py", line 1169, in mouse_event
  File "site-packages/urwid/container.py", line 1169, in mouse_event
  File "site-packages/urwid/container.py", line 1148, in mouse_event
  File "site-packages/urwid/container.py", line 2201, in mouse_event
  File "mitmproxy/tools/console/tabs.py", line 19, in mouse_event
  File "mitmproxy/tools/console/tabs.py", line 34, in change_tab
  File "mitmproxy/tools/console/tabs.py", line 73, in show
  File "mitmproxy/tools/console/flowview.py", line 86, in view_response
  File "mitmproxy/tools/console/flowview.py", line 160, in conn_text
  File "mitmproxy/command.py", line 221, in call
  File "mitmproxy/command.py", line 212, in call_args
  File "mitmproxy/command.py", line 101, in call
  File "mitmproxy/command.py", line 251, in wrapper
  File "mitmproxy/tools/console/consoleaddons.py", line 514, in flowview_mode
mitmproxy.exceptions.CommandError: Not viewing a flow.
```

##### Any other comments? What have you tried so far?
I think the problem is mitmproxy lets us to interact with other tab, when focusing on other.
So, we can click on different stuff in not focused tab by pressing left button of mouse.

It is possible due to https://github.com/mitmproxy/mitmproxy/blob/master/mitmproxy/tools/console/tabs.py
(in particular https://github.com/mitmproxy/mitmproxy/blob/master/mitmproxy/tools/console/tabs.py#L17).

`tabs.Tabs` is the superclass for `HelpView` and `FlowDetails` classes, so the problem is relevant to "Flow details" and "Help" tabs. Continue to work on it.


##### System information

Mitmproxy: 3.0.0.dev1101 (commit d9d4d15) binary
Python:    3.5.2
OpenSSL:   OpenSSL 1.1.0g  2 Nov 2017
Platform:  Linux-4.4.0-104-generic-x86_64-with-debian-stretch-sid

  
Mitmproxy lets us interact with other tab, when focusing on the other one.
##### Steps to reproduce the problem:

1. Open mitmproxy.
2. Press `-` to open two pane layout.
3. Start intercepting something.
4. Choose any flow to see **Flow details**.
5. Change focus on other tab by pressing `Shift+Tab`.
6. Click on "Request" or "Response" by pressing left button of mouse.

![2017-12-31 19-52-30](https://user-images.githubusercontent.com/20267977/34463805-5bb3ebd0-ee70-11e7-883b-c6dc720e4127.png)

I am getting:
```
Traceback (most recent call last):
  File "mitmproxy/tools/console/master.py", line 216, in run
  File "site-packages/urwid/main_loop.py", line 278, in run
  File "site-packages/urwid/main_loop.py", line 376, in _run
  File "site-packages/urwid/main_loop.py", line 682, in run
  File "site-packages/urwid/main_loop.py", line 719, in _loop
  File "site-packages/urwid/raw_display.py", line 393, in <lambda>
  File "site-packages/urwid/raw_display.py", line 493, in parse_input
  File "site-packages/urwid/main_loop.py", line 403, in _update
  File "site-packages/urwid/main_loop.py", line 500, in process_input
  File "mitmproxy/tools/console/window.py", line 277, in mouse_event
  File "site-packages/urwid/container.py", line 1169, in mouse_event
  File "site-packages/urwid/container.py", line 1687, in mouse_event
  File "site-packages/urwid/container.py", line 1169, in mouse_event
  File "site-packages/urwid/container.py", line 1169, in mouse_event
  File "site-packages/urwid/container.py", line 1148, in mouse_event
  File "site-packages/urwid/container.py", line 2201, in mouse_event
  File "mitmproxy/tools/console/tabs.py", line 19, in mouse_event
  File "mitmproxy/tools/console/tabs.py", line 34, in change_tab
  File "mitmproxy/tools/console/tabs.py", line 73, in show
  File "mitmproxy/tools/console/flowview.py", line 86, in view_response
  File "mitmproxy/tools/console/flowview.py", line 160, in conn_text
  File "mitmproxy/command.py", line 221, in call
  File "mitmproxy/command.py", line 212, in call_args
  File "mitmproxy/command.py", line 101, in call
  File "mitmproxy/command.py", line 251, in wrapper
  File "mitmproxy/tools/console/consoleaddons.py", line 514, in flowview_mode
mitmproxy.exceptions.CommandError: Not viewing a flow.
```

##### Any other comments? What have you tried so far?
I think the problem is mitmproxy lets us to interact with other tab, when focusing on other.
So, we can click on different stuff in not focused tab by pressing left button of mouse.

It is possible due to https://github.com/mitmproxy/mitmproxy/blob/master/mitmproxy/tools/console/tabs.py
(in particular https://github.com/mitmproxy/mitmproxy/blob/master/mitmproxy/tools/console/tabs.py#L17).

`tabs.Tabs` is the superclass for `HelpView` and `FlowDetails` classes, so the problem is relevant to "Flow details" and "Help" tabs. Continue to work on it.


##### System information

Mitmproxy: 3.0.0.dev1101 (commit d9d4d15) binary
Python:    3.5.2
OpenSSL:   OpenSSL 1.1.0g  2 Nov 2017
Platform:  Linux-4.4.0-104-generic-x86_64-with-debian-stretch-sid

  


Discussion:

Resolving patch:
diff --git a/mitmproxy/tools/console/window.py b/mitmproxy/tools/console/window.py
--- a/mitmproxy/tools/console/window.py
+++ b/mitmproxy/tools/console/window.py
@@ -234,28 +234,34 @@ def pop(self, *args, **kwargs):
             self.view_changed()
             self.focus_changed()
 
-    def current(self, keyctx):
+    def stacks_sorted_by_focus(self):
         """
-            Returns the active widget, but only the current focus or overlay has
-            a matching key context.
+        Returns:
+            self.stacks, with the focused stack first.
         """
-        t = self.focus_stack().top_widget()
-        if t.keyctx == keyctx:
-            return t
+        stacks = self.stacks.copy()
+        stacks.insert(0, stacks.pop(self.pane))
+        return stacks
 
-    def current_window(self, keyctx):
+    def current(self, keyctx):
         """
-            Returns the active window, ignoring overlays.
+        Returns the active widget with a matching key context, including overlays.
+        If multiple stacks have an active widget with a matching key context,
+        the currently focused stack is preferred.
         """
-        t = self.focus_stack().top_window()
-        if t.keyctx == keyctx:
-            return t
+        for s in self.stacks_sorted_by_focus():
+            t = s.top_widget()
+            if t.keyctx == keyctx:
+                return t
 
-    def any(self, keyctx):
+    def current_window(self, keyctx):
         """
-            Returns the top window of either stack if they match the context.
+        Returns the active window with a matching key context, ignoring overlays.
+        If multiple stacks have an active widget with a matching key context,
+        the currently focused stack is preferred.
         """
-        for t in [x.top_window() for x in self.stacks]:
+        for s in self.stacks_sorted_by_focus():
+            t = s.top_window()
             if t.keyctx == keyctx:
                 return t
 


Test patch: