Blob Blame History Raw
From 0d21c65472d93dbfafcd0aed8566bad49f41caab Mon Sep 17 00:00:00 2001
From: Michael Webster <miketwebster@gmail.com>
Date: Thu, 14 Jun 2018 23:05:00 -0400
Subject: [PATCH] nemo-terminal: Fix terminal location changes, respect follow
 setting (nemo-follows-terminal doesn't work, but we can have the terminal
 follow or not.  Fix popup menu display.

---
 nemo-terminal/src/nemo_terminal.py                 | 74 ++++++++--------------
 .../org.nemo.extensions.nemo-terminal.gschema.xml  |  2 +-
 2 files changed, 29 insertions(+), 47 deletions(-)

diff --git a/nemo-terminal/src/nemo_terminal.py b/nemo-terminal/src/nemo_terminal.py
index 8beaad0..5aa861d 100755
--- a/nemo-terminal/src/nemo_terminal.py
+++ b/nemo-terminal/src/nemo_terminal.py
@@ -50,12 +50,7 @@
 _ = gettext.gettext
 
 import gi
-try:
-    gi.require_version('Vte', '2.90')
-    VTE_2_90_API = True
-except:
-    gi.require_version('Vte', '2.91')
-    VTE_2_90_API = False
+gi.require_version('Vte', '2.91')
 gi.require_version('Nemo', '3.0')
 from gi.repository import GObject, Nemo, Gtk, Gdk, Vte, GLib, Gio
 
@@ -92,17 +87,15 @@ def __init__(self, uri, window):
         self.shell_pid = -1
         self.term = Vte.Terminal()
 
-        if VTE_2_90_API:
-            self.shell_pid = self.term.fork_command_full(Vte.PtyFlags.DEFAULT, self._path, [terminal_or_default()], None, GLib.SpawnFlags.SEARCH_PATH, None, None)[1]
-        else:
-            self.shell_pid = self.term.spawn_sync(Vte.PtyFlags.DEFAULT, self._path, [terminal_or_default()], None, GLib.SpawnFlags.SEARCH_PATH, None, None, None)[1]
+        self.shell_pid = self.term.spawn_sync(Vte.PtyFlags.DEFAULT, self._path, [terminal_or_default()], None, GLib.SpawnFlags.SEARCH_PATH, None, None, None)[1]
+
         # Make vte.sh active
         #vte_current_dir_script = ". /etc/profile.d/vte.sh ; clear"
         #self.term.feed_child(vte_current_dir_script, len(vte_current_dir_script))
 
         self.term.connect_after("child-exited", self._on_term_child_exited)
         self.term.connect_after("popup-menu", self._on_term_popup_menu)
-        self.term.connect("button-release-event", self._on_term_popup_menu)
+        self.term.connect("button-press-event", self._on_term_popup_menu)
 
         #Accelerators
         accel_group = Gtk.AccelGroup()
@@ -131,10 +124,7 @@ def __init__(self, uri, window):
         self.term.connect("drag_data_received", self._on_drag_data_received)
 
         # Container
-        if VTE_2_90_API:
-            self.vscrollbar = Gtk.VScrollbar.new(self.term.adjustment)
-        else:
-            self.vscrollbar = Gtk.VScrollbar.new(self.term.get_vadjustment())
+        self.vscrollbar = Gtk.VScrollbar.new(self.term.get_vadjustment())
 
         self.hbox = Gtk.HBox()
         self.hbox.pack_start(self.term, True, True, 0)
@@ -184,12 +174,11 @@ def __init__(self, uri, window):
         menu_item.connect_after("activate",
                                 lambda w: self.show_about_dialog())
         self.menu.add(menu_item)
-        #
         self.menu.show_all()
-        #Conf
-        self._set_term_height( \
-            settings.get_value("default-terminal-height").get_byte())
+
+        self._set_term_height(settings.get_int("default-terminal-height"))
         self._visible = True
+
         #Lock
         self._respawn_lock = False
         #Register the callback for show/hide
@@ -240,7 +229,12 @@ def change_directory(self, uri):
         Args:
             uri -- The URI of the destination directory.
         """
+
+        if settings.get_enum("default-follow-mode") in (0, 2):
+            return 
+
         self._path = self._uri_to_path(uri)
+
         if not self._shell_is_busy():
             # Clear any input
             eraselinekeys = settings.get_string("terminal-erase-line").decode('string_escape')
@@ -338,26 +332,16 @@ def destroy(self):
     def _shell_is_busy(self):
         """Check if the shell is waiting for a command or not."""
         wchan_path = "/proc/%i/wchan" % self.shell_pid
+
         wchan = open(wchan_path, "r").read()
-        if wchan == "n_tty_read":
-            return False
-        elif wchan == "schedule":
-            shell_stack_path = "/proc/%i/stack" % self.shell_pid
-            try:
-                for line in open(shell_stack_path, "r"):
-                    if line.split(" ")[-1].startswith("n_tty_read"):
-                        return False
-                return True
-            except IOError:
-                #We can't know...
-                return False
-        elif wchan == "wait_woken":
+
+        if wchan == "poll_schedule_timeout":
             return False
-        elif wchan == "do_wait":
-            return True
-        else:
+        elif wchan in ("do_wait", "wait_woken"):
             return True
 
+        return False
+
     def _uri_to_path(self, uri):
         """Returns the path corresponding of the given URI.
 
@@ -377,17 +361,17 @@ def _set_term_height(self, height):
 
     def _on_term_popup_menu(self, widget, event=None):
         """Displays the contextual menu on right-click and menu-key."""
-        if event: #button-release-event
-            if event.type == Gdk.EventType.BUTTON_RELEASE \
-                    and event.button != 3:
-                return
+        if event and event.button != 3:
+            return Gdk.EVENT_PROPAGATE
         # Should the Paste Filenames option be displayed?
         gtkClipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
         if gtkClipboard.wait_is_uris_available():
             self.menu_item_pastefilenames.show()
         else:
             self.menu_item_pastefilenames.hide()
-        self.menu.popup(None, None, None, None, 3, 0)
+        self.menu.popup_at_pointer(event)
+
+        return Gdk.EVENT_STOP
 
     def _on_term_child_exited(self, term):
         """Called when the shell is terminated.
@@ -396,10 +380,7 @@ def _on_term_child_exited(self, term):
             term -- The VTE terminal (self.term).
         """
         if not self._respawn_lock:
-            if VTE_2_90_API:
-                self.shell_pid = self.term.fork_command_full(Vte.PtyFlags.DEFAULT, self._path, [terminal_or_default()], None, GLib.SpawnFlags.SEARCH_PATH, None, None)[1]
-            else:
-                self.shell_pid = self.term.spawn_sync(Vte.PtyFlags.DEFAULT, self._path, [terminal_or_default()], None, GLib.SpawnFlags.SEARCH_PATH, None, None, None)[1]
+            self.shell_pid = self.term.spawn_sync(Vte.PtyFlags.DEFAULT, self._path, [terminal_or_default()], None, GLib.SpawnFlags.SEARCH_PATH, None, None, None)[1]
 
     def _on_drag_data_received(self, widget, drag_context, x, y, data, info, time):
         """Handles drag & drop."""
@@ -518,7 +499,6 @@ def _on_crowbar_pp_parent_set(self, widget, old_parent):
                       % __app_disp_name__)
             hbox.nt.destroy()
 
-
 class NemoTerminalProvider(GObject.GObject, Nemo.LocationWidgetProvider, Nemo.NameAndDescProvider):
     """Provides Nemo Terminal in Nemo."""
 
@@ -562,7 +542,9 @@ def _toggle_visible(self, window, event):
             settings.set_boolean("default-visible",  window.term_visible)
             for callback in window.toggle_hide_cb:
                 callback(window.term_visible)
-            return True #Stop the event propagation
+            return Gdk.EVENT_STOP #Stop the event propagation
+
+        return Gdk.EVENT_PROPAGATE
 
     def get_name_and_desc(self):
         return [("Nemo Terminal:::Embedded terminal for Nemo")]
diff --git a/nemo-terminal/src/org.nemo.extensions.nemo-terminal.gschema.xml b/nemo-terminal/src/org.nemo.extensions.nemo-terminal.gschema.xml
index 1bc9d65..f4769aa 100644
--- a/nemo-terminal/src/org.nemo.extensions.nemo-terminal.gschema.xml
+++ b/nemo-terminal/src/org.nemo.extensions.nemo-terminal.gschema.xml
@@ -15,7 +15,7 @@
 	<schema path="/org/nemo/extensions/nemo-terminal/" 
 	    id="org.nemo.extensions.nemo-terminal" 
 	    gettext-domain="nemo-terminal">
-	    <key name="default-terminal-height" type="y">    
+	    <key name="default-terminal-height" type="i">    
 	        <default>5</default>
 	        <summary>Set the default number of lines for the terminal.</summary>
 	        <description>Set the default number of lines for the terminal when it is first opened.</description>
From 80fbb7598719b8d7da8b4ad5c89297d4cfa5a78f Mon Sep 17 00:00:00 2001
From: Michael Webster <miketwebster@gmail.com>
Date: Sun, 17 Jun 2018 13:07:54 -0400
Subject: [PATCH] nemo_terminal.py: Change how we check for a busy terminal to
 checking for a child process.

This is a much more stable method to use that covers nearly all cases.
Checking wchan was prone to breaking every so often as kernel changes
would alter how wchan behaves.  Simply checking to see if our pseudo-
term process has a child is the same method gnome-terminal uses to
make sure a window isn't busy before closing it, and, it turns out,
is the same way nautilus-terminal does this check as well (though in
a slightly different manner.)

The only thing this would fail to catch is something like a 'read'
in a script, which isn't a program, but a built-in command, but I
think the likelyhood of this being a problem in the context of a
nemo extension is pretty low.

Fixes #134
---
 nemo-terminal/src/nemo_terminal.py | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/nemo-terminal/src/nemo_terminal.py b/nemo-terminal/src/nemo_terminal.py
index 5aa861d..62fd7d8 100755
--- a/nemo-terminal/src/nemo_terminal.py
+++ b/nemo-terminal/src/nemo_terminal.py
@@ -331,16 +331,16 @@ def destroy(self):
 
     def _shell_is_busy(self):
         """Check if the shell is waiting for a command or not."""
-        wchan_path = "/proc/%i/wchan" % self.shell_pid
 
-        wchan = open(wchan_path, "r").read()
+        pty = self.term.get_pty()
+        fd = pty.get_fd()
 
-        if wchan == "poll_schedule_timeout":
+        fgpid = os.tcgetpgrp(fd)
+
+        if fgpid == -1 or fgpid == self.shell_pid:
             return False
-        elif wchan in ("do_wait", "wait_woken"):
-            return True
 
-        return False
+        return True
 
     def _uri_to_path(self, uri):
         """Returns the path corresponding of the given URI.
From 3d83425665040d6aa4e2d4f5a760b172d9206f41 Mon Sep 17 00:00:00 2001
From: Michael Webster <miketwebster@gmail.com>
Date: Mon, 18 Jun 2018 20:52:30 -0400
Subject: [PATCH] nemo_terminal.py: allow for python-gi differences when
 calling Vte.Terminal.feed_child().

---
 nemo-terminal/src/nemo_terminal.py | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/nemo-terminal/src/nemo_terminal.py b/nemo-terminal/src/nemo_terminal.py
index 62fd7d8..2f71734 100755
--- a/nemo-terminal/src/nemo_terminal.py
+++ b/nemo-terminal/src/nemo_terminal.py
@@ -218,9 +218,9 @@ def _paste_filenames_clipboard(self):
             for idx, uri in enumerate(uris):
                 path = Gio.file_parse_name(uri).get_path()
                 quoted = GLib.shell_quote(path)
-                self.term.feed_child(quoted, len(quoted))
+                self.feed_child(quoted)
                 if idx != (len(uris)-1):
-                    self.term.feed_child(' ', 1)
+                    self.feed_child(' ')
         return
 
     def change_directory(self, uri):
@@ -238,17 +238,17 @@ def change_directory(self, uri):
         if not self._shell_is_busy():
             # Clear any input
             eraselinekeys = settings.get_string("terminal-erase-line").decode('string_escape')
-            self.term.feed_child(eraselinekeys, len(eraselinekeys))
+            self.feed_child(eraselinekeys)
 
             # Change directory
             cdcmd_nonewline = settings.get_string("terminal-change-directory-command") \
                 % GLib.shell_quote(self._path)
             cdcmd = "%s\n" % cdcmd_nonewline
-            self.term.feed_child(cdcmd, len(cdcmd))
+            self.feed_child(cdcmd)
 
             # Restore user input
             restorelinekeys = settings.get_string("terminal-restore-line").decode('string_escape')
-            self.term.feed_child(restorelinekeys, len(restorelinekeys))
+            self.feed_child(restorelinekeys)
 
     def get_widget(self):
         """Return the top-level widget of Nemo Terminal."""
@@ -386,8 +386,17 @@ def _on_drag_data_received(self, widget, drag_context, x, y, data, info, time):
         """Handles drag & drop."""
         for uri in data.get_uris():
             path = "'%s' " % self._uri_to_path(uri).replace("'", r"'\''")
-            self.term.feed_child(path, len(path))
+            self.feed_child(path)
 
+    def feed_child(self, text):
+        """
+        gobject-introspection/python-gi differences force us to try with and
+        without the text length. One of them will work.
+        """
+        try:
+            self.term.feed_child(text)
+        except TypeError:
+            self.term.feed_child(text, len(text))
 
 class Crowbar(object):
     """Modify the Nemo' widget tree when the crowbar is inserted in it.
From ce9d9631d50286e814d3619c2be3f06a810682a2 Mon Sep 17 00:00:00 2001
From: Michael Webster <miketwebster@gmail.com>
Date: Mon, 18 Jun 2018 22:25:44 -0400
Subject: [PATCH] nemo_terminal.py: fix callback arguments for child-exited
 signal.

---
 nemo-terminal/src/nemo_terminal.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/nemo-terminal/src/nemo_terminal.py b/nemo-terminal/src/nemo_terminal.py
index 2f71734..13da1a9 100755
--- a/nemo-terminal/src/nemo_terminal.py
+++ b/nemo-terminal/src/nemo_terminal.py
@@ -373,7 +373,7 @@ def _on_term_popup_menu(self, widget, event=None):
 
         return Gdk.EVENT_STOP
 
-    def _on_term_child_exited(self, term):
+    def _on_term_child_exited(self, term, status):
         """Called when the shell is terminated.
 
         Args: