diff --git a/src/chat_control.py b/src/chat_control.py index f17ebe255..295574271 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -868,7 +868,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): keyID=keyID, type_=type_, chatstate=chatstate, msg_id=msg_id, composing_xep=composing_xep, resource=resource, user_nick=self.user_nick, xhtml=xhtml, label=label, - callback=callback, callback_args= callback_args)) + callback=callback, callback_args=callback_args, control=self)) # Record the history of sent messages self.save_message(message, 'sent') @@ -2631,13 +2631,15 @@ class ChatControl(ChatControlBase): if contact.our_chatstate == 'inactive' and state == 'composing': # go active before gajim.nec.push_outgoing_event(MessageOutgoingEvent(None, - account=self.account, jid=self.contact.jid, chatstate='active')) + account=self.account, jid=self.contact.jid, chatstate='active', + control=self)) contact.our_chatstate = 'active' self.reset_kbd_mouse_timeout_vars() gajim.nec.push_outgoing_event(MessageOutgoingEvent(None, account=self.account, jid=self.contact.jid, chatstate=state, - msg_id=contact.msg_id, composing_xep=contact.composing_xep)) + msg_id=contact.msg_id, composing_xep=contact.composing_xep, + control=self)) contact.our_chatstate = state if contact.our_chatstate == 'active': diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index 0cca49b10..d44be1e30 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -926,23 +926,6 @@ class ConnectionHandlersBase: continue if sess.control: sess.control.no_autonegotiation = False - if sess.enable_encryption: - sess.terminate_e2e() - self.delete_session(jid, sess.thread_id) - - if obj.ptype == 'unavailable': - for jid in (obj.jid, obj.fjid): - if jid not in self.sessions: - continue - # automatically terminate sessions that they haven't sent a - # thread ID in, only if other part support thread ID - for sess in self.sessions[jid].values(): - if not sess.received_thread_id: - contact = gajim.contacts.get_contact(self.name, jid) - if contact and (contact.supports(xmpp.NS_SSN) or \ - contact.supports(xmpp.NS_ESESSION)): - sess.terminate() - del self.sessions[jid][sess.thread_id] if gajim.config.get('log_contact_status_changes') and \ gajim.config.should_log(self.name, obj.jid): diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py index 38b4fd84b..035651d9b 100644 --- a/src/common/connection_handlers_events.py +++ b/src/common/connection_handlers_events.py @@ -2187,6 +2187,7 @@ class MessageOutgoingEvent(nec.NetworkIncomingEvent): self.callback_args = [] self.now = False self.is_loggable = True + self.control = None def generate(self): return True diff --git a/src/common/stanza_session.py b/src/common/stanza_session.py index ca3b81d53..34fcd979f 100644 --- a/src/common/stanza_session.py +++ b/src/common/stanza_session.py @@ -58,7 +58,7 @@ class StanzaSession(object): self.conn = conn self.jid = jid self.type = type_ - self.resource = None + self.resource = jid.getResource() if thread_id: self.received_thread_id = True diff --git a/src/gui_interface.py b/src/gui_interface.py index b027130c3..fdf0a5b22 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -358,15 +358,9 @@ class Interface: highest = gajim.contacts.get_contact_with_highest_priority(account, jid) is_highest = (highest and highest.resource == resource) - # disconnect the session from the ctrl if the highest resource has - # changed - if (obj.was_highest and not is_highest) or \ - (not obj.was_highest and is_highest): - ctrl = self.msg_win_mgr.get_control(jid, account) - if ctrl: - ctrl.no_autonegotiation = False - ctrl.set_session(None) - ctrl.contact = highest + ctrl = self.msg_win_mgr.get_control(jid, account) + if ctrl and ctrl.session and ctrl.session.resource == resource: + ctrl.remove_session(ctrl.session) def handle_event_msgerror(self, obj): #'MSGERROR' (account, (jid, error_code, error_msg, msg, time[session])) diff --git a/src/message_control.py b/src/message_control.py index d265e5768..827447254 100644 --- a/src/message_control.py +++ b/src/message_control.py @@ -46,7 +46,8 @@ class MessageControl(object): MessageWindow """ - def __init__(self, type_id, parent_win, widget_name, contact, account, resource = None): + def __init__(self, type_id, parent_win, widget_name, contact, account, + resource=None): # dict { cb id : widget} # keep all registered callbacks of widgets, created by self.xml self.handlers = {} @@ -59,6 +60,7 @@ class MessageControl(object): self.resource = resource self.session = None + self.other_sessions = [] gajim.last_message_time[self.account][self.get_full_jid()] = 0 @@ -201,15 +203,15 @@ class MessageControl(object): if oldsession: oldsession.control = None + self.other_sessions.append(oldsession) - jid = self.contact.jid - if self.resource: - jid += '/' + self.resource + if self.session in self.other_sessions: + self.other_sessions.remove(self.session) crypto_changed = bool(session and isinstance(session, - EncryptedStanzaSession) and session.enable_encryption) != \ - bool(oldsession and isinstance(oldsession, - EncryptedStanzaSession) and oldsession.enable_encryption) + EncryptedStanzaSession) and session.enable_encryption) != \ + bool(oldsession and isinstance(oldsession, EncryptedStanzaSession) \ + and oldsession.enable_encryption) archiving_changed = bool(session and isinstance(session, ArchivingStanzaSession) and session.archiving) != \ @@ -219,12 +221,21 @@ class MessageControl(object): if crypto_changed or archiving_changed: self.print_session_details() + def remove_session(self, session): + if session != self.session: + return + last_session = None + if self.other_sessions: + last_session = self.other_sessions.pop(0) + if session not in self.other_sessions: + self.other_sessions.append(session) + if last_session: + self.session = last_session + def _nec_message_outgoing(self, obj): # Send the given message to the active tab. # Doesn't return None if error - if obj.account != self.account: - return - if self.contact.jid != obj.jid: + if obj.control != self: return obj.message = helpers.remove_invalid_xml_chars(obj.message) diff --git a/src/message_window.py b/src/message_window.py index 37eb67b5a..b3f0593ac 100644 --- a/src/message_window.py +++ b/src/message_window.py @@ -1087,6 +1087,26 @@ class MessageWindowMgr(gobject.GObject): return win.get_control(jid, acct) return None + def search_control(self, jid, account, resource=None): + """ + Search windows with this policy: + 1. try to find already opened tab for resource + 2. find the tab for this jid with ctrl.resource not set + 3. there is none + """ + fjid = jid + if resource: + jid += '/' + resource + ctrl = self.get_control(fjid, account) + if ctrl: + return ctrl + win = self.get_window(jid, account) + if win: + ctrl = win.get_control(jid, account) + if not ctrl.resource: + return ctrl + return None + def get_gc_control(self, jid, acct): """ Same as get_control. Was briefly required, is not any more. May be useful diff --git a/src/session.py b/src/session.py index a4e9de595..158bb974a 100644 --- a/src/session.py +++ b/src/session.py @@ -155,14 +155,9 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession): obj.resource == highest_contact.resource or highest_contact.show ==\ 'offline' - if not pm and is_highest: - jid_of_control = obj.jid - else: - jid_of_control = obj.fjid - if not self.control: - ctrl = gajim.interface.msg_win_mgr.get_control(jid_of_control, - self.conn.name) + ctrl = gajim.interface.msg_win_mgr.search_control(obj.jid, + obj.conn.name, obj.resource) if ctrl: self.control = ctrl self.control.set_session(self) @@ -183,8 +178,6 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession): contact = None jid = obj.jid resource = obj.resource - # if chat window will be for specific resource - resource_for_chat = resource fjid = jid @@ -211,7 +204,6 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession): else: # Default to highest prio fjid = jid - resource_for_chat = None contact = highest_contact if not contact: @@ -220,21 +212,15 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession): obj.conn.name, jid, obj.user_nick) if not self.control: - ctrl = gajim.interface.msg_win_mgr.get_control(fjid, self.conn.name) + ctrl = gajim.interface.msg_win_mgr.search_control(obj.jid, + obj.conn.name, obj.resource) if ctrl: self.control = ctrl self.control.set_session(self) else: - # if no control exists and message comes from highest prio, - # the new control shouldn't have a resource - if highest_contact and contact.resource == \ - highest_contact.resource and jid != gajim.get_jid_from_account( - self.conn.name): - fjid = jid - resource_for_chat = None + fjid = jid obj.popup = helpers.allow_popup_window(self.conn.name) - obj.resource_for_chat = resource_for_chat type_ = 'chat' event_type = 'message_received' @@ -268,9 +254,6 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession): Display the message or show notification in the roster """ contact = None - # if chat window will be for specific resource - resource_for_chat = resource - fjid = jid # Try to catch the contact with correct resource @@ -298,7 +281,6 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession): else: # Default to highest prio fjid = jid - resource_for_chat = None contact = highest_contact if not contact: @@ -312,12 +294,7 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession): self.control = ctrl self.control.set_session(self) else: - # if no control exists and message comes from highest prio, the new - # control shouldn't have a resource - if highest_contact and contact.resource == highest_contact.resource\ - and not jid == gajim.get_jid_from_account(self.conn.name): - fjid = jid - resource_for_chat = None + fjid = jid # Do we have a queue? no_queue = len(gajim.events.get_events(self.conn.name, fjid)) == 0 @@ -367,7 +344,7 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession): if popup: if not self.control: self.control = gajim.interface.new_chat(contact, - self.conn.name, resource=resource_for_chat, session=self) + self.conn.name, session=self) if len(gajim.events.get_events(self.conn.name, fjid)): self.control.read_queue()