diff --git a/TODO.mkdn b/TODO.mkdn
index b0a7c58..2c74cd5 100644
--- a/TODO.mkdn
+++ b/TODO.mkdn
@@ -59,8 +59,6 @@
     * Save commonly-used times on a per-handle basis!
 * Make the memo list highlight/recolor the names of channels you're in
     (including secret ones)
-* Make right-clicking on a tab open up the right-click menu one would get on
-    right-clicking the title (frame??)
 * Add an option to Cycle (for log separation)
 
 * Add a separate 'Tweaks' section in Options
@@ -80,15 +78,10 @@
     * Enable/Disable toggle (Firefox style option sheet-esque? Seems okay.)
     * Ctrl+W closes tab
     * Ctrl+Shift+PGUP/PGDN moves tab
-    * Make Ctrl+J/K usable for tab changing
     * Option to disable Ctrl+Tab's jump to newest
     * Ctrl+Shift+V "Mass Paste" option (parse lines in sequence)?
 * Make system messages use timestamps like everything else
 * Offer option for timestamps in memos
-* Make certain dialogues start on the safer of the two options
-    * Make the Reconnect dialog start on reconnect
-    * Make the Rejoin dialog start on rejoin
-    * Make the Invite dialog start on decline
 * Make a status window/popup to contain logs of information like invites
 
 ### "Security"
@@ -98,7 +91,7 @@ design.**
 
 If you want Pesterchum to be more secure, either get ghostDunk to make changes
 to the server and its administration policies, or get everyone to switch to this
-version of the client. There aren't really any other choices.
+version of the client. There aren't really any other options.
 
 * Flood protection (don't send because of the same target too many times in a
     row)
@@ -144,13 +137,23 @@ version of the client. There aren't really any other choices.
 ## Todo/Done
 **Everything in this section has already been completed.**
 
+### GUI
+* Toggle individual tab flash / alert sounds (from the same right-click memo
+    that lets us toggle OOC)
+* Make CTRL+PGUP/PGDN switch memo/pester tabs
+* Make Ctrl+J/K usable for tab changing
+* Make right-clicking on a tab open up the right-click menu one would get on
+    right-clicking the title (frame??)
+* Right-click in userlist offers option to Pester
+* Make certain dialogues start on the safer of the two options
+    * Make the Reconnect dialog start on Reconnect
+    * Make the Rejoin dialog start on Rejoin
+    * Make the Invite dialog start on Decline
+
 ### Usability
 * Fix parser text-loss bug that plagues everyone (especially Chumdroid users)
 * Make /me messages that cut continue into more /me messages
 * Make sound work on Windows through QSound (disables volume control)
-* Toggle individual tab flash / alert sounds (from the same right-click memo
-    that lets us toggle OOC)
-* Make CTRL+PGUP/PGDN switch memo/pester tabs
 * Color tags are now posted as their shorter hexadecimal forms, if applicable
     (255,255,255 -> #FFFFFF, for example)
 * Separate auto-idle and checkbox idle so they don't share a state (and make
diff --git a/console.py b/console.py
index 7594cc0..77b21f2 100644
--- a/console.py
+++ b/console.py
@@ -9,6 +9,7 @@ import dataobjs, generic, memos, parsetools, ostools
 from version import _pcVersion
 
 from pnc.dep.attrdict import AttrDict
+#~from styling import styler
 
 _datadir = ostools.getDataDir()
 
@@ -19,6 +20,7 @@ logging.basicConfig(level=logging.WARNING)
 
 
 class ConsoleWindow(QtGui.QDialog):
+#~class ConsoleWindow(styler.PesterBaseWindow):
     # A simple console class, cobbled together from the corpse of another.
 
     # This is a holder for our text inputs.
@@ -110,6 +112,10 @@ class ConsoleWindow(QtGui.QDialog):
         parent.console.is_open = False
         parent.console.window = None
 
+    def hideEvent(self, event):
+        parent = self.parent()
+        parent.console.is_open = False
+
     # Actual console stuff.
     def execInConsole(self, scriptstr, env=None):
         # Since that's what imports *us*, this should be okay
diff --git a/convo.py b/convo.py
index b9baede..350efaa 100644
--- a/convo.py
+++ b/convo.py
@@ -15,10 +15,11 @@ from parsetools import convertTags, lexMessage, splitMessage, mecmd, colorBegin,
 import parsetools
 
 import pnc.lexercon as lexercon
+from pnc.dep.attrdict import AttrDict
 
 class PesterTabWindow(QtGui.QFrame):
     def __init__(self, mainwindow, parent=None, convo="convo"):
-        QtGui.QFrame.__init__(self, parent)
+        super(PesterTabWindow, self).__init__(parent)
         self.setAttribute(QtCore.Qt.WA_QuitOnClose, False)
         self.setFocusPolicy(QtCore.Qt.ClickFocus)
         self.mainwindow = mainwindow
@@ -33,6 +34,30 @@ class PesterTabWindow(QtGui.QFrame):
         self.connect(self.tabs, QtCore.SIGNAL('tabMoved(int, int)'),
                      self, QtCore.SLOT('tabMoved(int, int)'))
 
+        self.shortcuts = AttrDict()
+        self.shortcuts.tabNext = QtGui.QShortcut(
+                QtGui.QKeySequence('Ctrl+j'), self,
+                context=QtCore.Qt.WidgetWithChildrenShortcut)
+        self.shortcuts.tabLast = QtGui.QShortcut(
+                QtGui.QKeySequence('Ctrl+k'), self,
+                context=QtCore.Qt.WidgetWithChildrenShortcut)
+        # Note that we use reversed keys here.
+        self.shortcuts.tabUp = QtGui.QShortcut(
+                QtGui.QKeySequence('Ctrl+PgDown'), self,
+                context=QtCore.Qt.WidgetWithChildrenShortcut)
+        self.shortcuts.tabDn = QtGui.QShortcut(
+                QtGui.QKeySequence('Ctrl+PgUp'), self,
+                context=QtCore.Qt.WidgetWithChildrenShortcut)
+
+        self.connect(self.shortcuts.tabNext, QtCore.SIGNAL('activated()'),
+                self, QtCore.SLOT('nudgeTabNext()'))
+        self.connect(self.shortcuts.tabUp, QtCore.SIGNAL('activated()'),
+                self, QtCore.SLOT('nudgeTabNext()'))
+        self.connect(self.shortcuts.tabLast, QtCore.SIGNAL('activated()'),
+                self, QtCore.SLOT('nudgeTabLast()'))
+        self.connect(self.shortcuts.tabDn, QtCore.SIGNAL('activated()'),
+                self, QtCore.SLOT('nudgeTabLast()'))
+
         self.initTheme(self.mainwindow.theme)
         self.layout = QtGui.QVBoxLayout()
         self.layout.setContentsMargins(0,0,0,0)
@@ -96,38 +121,39 @@ class PesterTabWindow(QtGui.QFrame):
                 nexti = (self.tabIndices[self.currentConvo.title()] + 1) % self.tabs.count()
             self.tabs.setCurrentIndex(nexti)
 
-        elif (mods == QtCore.Qt.ControlModifier and
-                keypress in (QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown)):
-            # Inverted controls. Might add an option for this if people want
-            # it.
-            if keypress == QtCore.Qt.Key_PageDown:
-                direction = 1
-            elif keypress == QtCore.Qt.Key_PageUp:
-                direction = -1
-            # ...Processing...
-            tabs = self.tabs
-            # Pick our new index by sliding up or down the tab range.
-            # NOTE: This feels like it could error. In fact, it /will/ if
-            # there are no tabs, but...that shouldn't happen, should it?
-            # There are probably other scenarios, too, so we'll have to
-            # check on this later.
-            #
-            # Calculate the new index.
-            ct = tabs.count()
-            cind = tabs.currentIndex()
-            nind = cind + direction
-            if nind > (ct - 1):
-                # The new index would be higher than the maximum; loop.
-                nind = nind % ct
-            # Otherwise, negative syntax should get it for us.
-            nind = range(ct)[nind]
-            # Change to the selected tab.
-            # Note that this will send out the usual callbacks that handle
-            # focusing and such.
-            tabs.setCurrentIndex(nind)
-            # Ensure this doesn't fall through normally.
-            # (Not an issue here, but this used to be on a TextArea.)
-            return
+    @QtCore.pyqtSlot()
+    def nudgeTabNext(self): return self.nudgeTabIndex(+1)
+    @QtCore.pyqtSlot()
+    def nudgeTabLast(self): return self.nudgeTabIndex(-1)
+
+    def nudgeTabIndex(self, direction):
+        # Inverted controls. Might add an option for this if people want
+        # it.
+        #~if keypress == QtCore.Qt.Key_PageDown:
+        #~    direction = 1
+        #~elif keypress == QtCore.Qt.Key_PageUp:
+        #~    direction = -1
+        # ...Processing...
+        tabs = self.tabs
+        # Pick our new index by sliding up or down the tab range.
+        # NOTE: This feels like it could error. In fact, it /will/ if
+        # there are no tabs, but...that shouldn't happen, should it?
+        # There are probably other scenarios, too, so we'll have to
+        # check on this later.
+        #
+        # Calculate the new index.
+        ct = tabs.count()
+        cind = tabs.currentIndex()
+        nind = cind + direction
+        if nind > (ct - 1):
+            # The new index would be higher than the maximum; loop.
+            nind = nind % ct
+        # Otherwise, negative syntax should get it for us.
+        nind = range(ct)[nind]
+        # Change to the selected tab.
+        # Note that this will send out the usual callbacks that handle
+        # focusing and such.
+        tabs.setCurrentIndex(nind)
 
     def contextMenuEvent(self, event):
         #~if event.reason() == QtGui.QContextMenuEvent.Mouse:
@@ -450,8 +476,7 @@ class PesterText(QtGui.QTextEdit):
     def keyPressEvent(self, event):
         # First parent is the PesterConvo containing this.
         # Second parent is the PesterTabWindow containing *it*.
-        pass_to_super = (QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown,
-                QtCore.Qt.Key_Up, QtCore.Qt.Key_Down)
+        pass_to_super = (QtCore.Qt.Key_Up, QtCore.Qt.Key_Down)
         parent = self.parent()
         key = event.key()
         keymods = event.modifiers()
@@ -554,8 +579,6 @@ class PesterInput(QtGui.QLineEdit):
             prev = self.parent().history.prev()
             if prev is not None:
                 self.setText(prev)
-        elif event.key() in [QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown]:
-            self.parent().textArea.keyPressEvent(event)
         self.parent().mainwindow.idler.time = 0
         super(PesterInput, self).keyPressEvent(event)
 
diff --git a/memos.py b/memos.py
index a1230f2..ac20036 100644
--- a/memos.py
+++ b/memos.py
@@ -375,6 +375,9 @@ class PesterMemo(PesterConvo):
         self.userlist = RightClickList(self)
         self.userlist.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Expanding))
         self.userlist.optionsMenu = QtGui.QMenu(self)
+        self.pesterChumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/pester"], self)
+        self.connect(self.pesterChumAction, QtCore.SIGNAL('triggered()'),
+                     self, QtCore.SLOT('newPesterSlot()'))
         self.addchumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self)
         self.connect(self.addchumAction, QtCore.SIGNAL('triggered()'),
                      self, QtCore.SLOT('addChumSlot()'))
@@ -390,6 +393,7 @@ class PesterMemo(PesterConvo):
         self.quirkDisableAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirkkill"], self)
         self.connect(self.quirkDisableAction, QtCore.SIGNAL('triggered()'),
                      self, QtCore.SLOT('killQuirkUser()'))
+        self.userlist.optionsMenu.addAction(self.pesterChumAction)
         self.userlist.optionsMenu.addAction(self.addchumAction)
         # ban & op list added if we are op
 
@@ -1024,6 +1028,12 @@ class PesterMemo(PesterConvo):
                 msgbox.setText(self.mainwindow.theme["convo/text/kickedmemo"])
                 msgbox.setInformativeText("press 0k to rec0nnect or cancel to absc0nd")
                 msgbox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
+                # Find the OK button and make it default
+                for b in msgbox.buttons():
+                    if msgbox.buttonRole(b) == QtGui.QMessageBox.AcceptRole:
+                        # We found the 'OK' button, set it as the default
+                        b.setAutoDefault(True)
+                        break
                 ret = msgbox.exec_()
                 if ret == QtGui.QMessageBox.Ok:
                     self.userlist.clear()
@@ -1160,6 +1170,15 @@ class PesterMemo(PesterConvo):
         elif c.lower() == self.channel.lower() and h == "" and update[0] in ["+","-"]:
             self.updateChanModes(update, op)
 
+    @QtCore.pyqtSlot()
+    def newPesterSlot(self):
+        # We're opening a pester with someone in our user list.
+        user = self.userlist.currentItem()
+        if not user:
+            return
+        user = unicode(user.text())
+        self.mainwindow.newConversation(user)
+
     @QtCore.pyqtSlot()
     def addChumSlot(self):
         if not self.userlist.currentItem():
diff --git a/menus.py b/menus.py
index e10534b..72da1e5 100644
--- a/menus.py
+++ b/menus.py
@@ -1730,6 +1730,9 @@ class LoadingScreen(QtGui.QDialog):
         self.loadinglabel = QtGui.QLabel("CONN3CT1NG", self)
         self.cancel = QtGui.QPushButton("QU1T >:?", self)
         self.ok = QtGui.QPushButton("R3CONN3CT >:]", self)
+        # Help reduce the number of accidental Pesterchum closures... :|
+        self.cancel.setAutoDefault(False)
+        self.ok.setAutoDefault(True)
         self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
                      self, QtCore.SLOT('reject()'))
         self.connect(self.ok, QtCore.SIGNAL('clicked()'),
diff --git a/pesterchum.py b/pesterchum.py
index f55d91b..5fbbee6 100644
--- a/pesterchum.py
+++ b/pesterchum.py
@@ -1085,6 +1085,7 @@ class PesterWindow(MovingWindow):
         self.memos = CaseInsensitiveDict()
         self.tabconvo = None
         self.tabmemo = None
+        self.shortcuts = AttrDict()
         if "advanced" in options:
               self.advanced = options["advanced"]
         else: self.advanced = False
@@ -1179,6 +1180,16 @@ class PesterWindow(MovingWindow):
         self.console.action = QtGui.QAction("Console", self)
         self.connect(self.console.action, QtCore.SIGNAL('triggered()'),
                     self, QtCore.SLOT('showConsole()'))
+        self.console.shortcut = QtGui.QShortcut(
+                QtGui.QKeySequence("Ctrl+`"), self)
+        # Make sure the shortcut works anywhere.
+        # karxi: There's something wrong with the inheritance scheme here.
+        self.console.shortcut.setContext(QtCore.Qt.ApplicationShortcut)
+        self.connect(self.console.shortcut, QtCore.SIGNAL('activated()'),
+                self, QtCore.SLOT('showConsole()'))
+        #~# Use new-style connections
+        #~self.console.shortcut.activated.connect(self.showConsole)
+        # Apparently those can crash sometimes...c'est la vie. Can't use 'em.
         self.console.is_open = False
 
         filemenu = self.menu.addMenu(self.theme["main/menus/client/_name"])
@@ -2002,6 +2013,12 @@ class PesterWindow(MovingWindow):
         msgbox.setText("You're invited!")
         msgbox.setInformativeText("%s has invited you to the memo: %s\nWould you like to join them?" % (handle, channel))
         msgbox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
+        # Find the Cancel button and make it default
+        for b in msgbox.buttons():
+            if msgbox.buttonRole(b) == QtGui.QMessageBox.RejectRole:
+                # We found the 'Cancel' button, set it as the default
+                b.setAutoDefault(True)
+                break
         ret = msgbox.exec_()
         if ret == QtGui.QMessageBox.Ok:
             self.newMemo(unicode(channel), "+0:00")
@@ -2299,6 +2316,11 @@ class PesterWindow(MovingWindow):
         secret = self.memochooser.secretChannel.isChecked()
         invite = self.memochooser.inviteChannel.isChecked()
 
+        # Join the ones on the list first
+        for SelectedMemo in self.memochooser.SelectedMemos():
+            channel = "#"+unicode(SelectedMemo.target)
+            self.newMemo(channel, time)
+
         if self.memochooser.newmemoname():
             newmemo = self.memochooser.newmemoname()
             channel = unicode(newmemo).replace(" ", "_")
@@ -2313,10 +2335,6 @@ class PesterWindow(MovingWindow):
                 # the server has confirmed that we've joined....
                 self.newMemo(c, time, secret=secret, invite=invite)
 
-        for SelectedMemo in self.memochooser.SelectedMemos():
-            channel = "#"+unicode(SelectedMemo.target)
-            self.newMemo(channel, time)
-
         self.memochooser = None
     @QtCore.pyqtSlot()
     def memoChooserClose(self):