diff --git a/gajim/chat_control_base.py b/gajim/chat_control_base.py index 9fd609bb1..600e1595b 100644 --- a/gajim/chat_control_base.py +++ b/gajim/chat_control_base.py @@ -305,13 +305,9 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): 'conversation_scrolledwindow') self.conv_scrolledwindow.add(self.conv_textview.tv) widget = self.conv_scrolledwindow.get_vadjustment() - id_ = widget.connect('value-changed', - self.on_conversation_vadjustment_value_changed) - self.handlers[id_] = widget id_ = widget.connect('changed', self.on_conversation_vadjustment_changed) self.handlers[id_] = widget - self.was_at_the_end = True self.correcting = False self.last_sent_msg = None @@ -965,7 +961,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): full_jid = self.get_full_jid() textview = self.conv_textview end = False - if self.was_at_the_end or kind == 'outgoing': + if self.conv_textview.autoscroll or kind == 'outgoing': end = True if other_tags_for_name is None: @@ -1201,7 +1197,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): if state: self.set_emoticon_popover() jid = self.contact.jid - if self.was_at_the_end: + if self.conv_textview.autoscroll: # we are at the end type_ = ['printed_' + self.type_id] if self.type_id == message_control.TYPE_GC: @@ -1221,21 +1217,14 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): else: self.send_chatstate('inactive', self.contact) - def scroll_to_end_iter(self): - self.conv_textview.scroll_to_end_iter() - return False + def scroll_to_end(self, force=False): + self.conv_textview.scroll_to_end(force) - def on_conversation_vadjustment_changed(self, adjustment): - # used to stay at the end of the textview when we shrink conversation - # textview. - if self.was_at_the_end: - self.scroll_to_end_iter() - self.was_at_the_end = (adjustment.get_upper() - adjustment.get_value()\ - - adjustment.get_page_size()) < 18 - - def on_conversation_vadjustment_value_changed(self, adjustment): - self.was_at_the_end = (adjustment.get_upper() - adjustment.get_value() \ - - adjustment.get_page_size()) < 18 + def _on_edge_reached(self, scrolledwindow, pos): + if pos != Gtk.PositionType.BOTTOM: + return + # Remove all events and set autoscroll True + self.conv_textview.autoscroll = True if self.resource: jid = self.contact.get_full_jid() else: @@ -1252,8 +1241,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): return if not self.parent_win: return - if self.conv_textview.at_the_end() and \ - self.parent_win.get_active_control() == self and \ + if self.parent_win.get_active_control() == self and \ self.parent_win.window.is_active(): # we are at the end if self.type_id == message_control.TYPE_GC: @@ -1264,6 +1252,18 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): # There were events to remove self.redraw_after_event_removed(jid) + def _on_scroll(self, widget, event): + # On scrolliung UP disable autoscroll + has_direction, direction = event.get_scroll_direction() + if has_direction and direction == Gdk.ScrollDirection.UP: + # Check if we have a Scrollbar + adjustment = self.conv_scrolledwindow.get_vadjustment() + if adjustment.get_upper() != adjustment.get_page_size(): + self.conv_textview.autoscroll = False + + def on_conversation_vadjustment_changed(self, adjustment): + self.scroll_to_end() + def redraw_after_event_removed(self, jid): """ We just removed a 'printed_*' event, redraw contact in roster or @@ -1344,7 +1344,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): """ # make the last message visible, when changing to "full view" if not state: - GLib.idle_add(self.conv_textview.scroll_to_end_iter) + self.scroll_to_end() widget.set_no_show_all(state) if state: diff --git a/gajim/conversation_textview.py b/gajim/conversation_textview.py index 8ab318afa..3129d88d3 100644 --- a/gajim/conversation_textview.py +++ b/gajim/conversation_textview.py @@ -206,7 +206,7 @@ class ConversationTextview(GObject.GObject): self.last_sent_message_id = None # last_received_message_id[name] = (msg_stanza_id, line_start_mark) self.last_received_message_id = {} - + self.autoscroll = True # connect signals id_ = self.tv.connect('populate_popup', self.on_textview_populate_popup) self.handlers[id_] = self.tv @@ -370,16 +370,9 @@ class ConversationTextview(GObject.GObject): self.tv.tagXMPP.set_property('foreground', color) self.tv.tagSthAtSth.set_property('foreground', color) - def at_the_end(self): - return gtkgui_helpers.at_the_end(self.tv.get_parent()) - - def scroll_to_end_iter(self): - buffer_ = self.tv.get_buffer() - end_iter = buffer_.get_end_iter() - if not end_iter: - return False - self.tv.scroll_to_iter(end_iter, 0, False, 1, 1) - return False # when called in an idle_add, just do it once + def scroll_to_end(self, force=False): + if self.autoscroll or force: + gtkgui_helpers.scroll_to_end(self.tv.get_parent()) def correct_message(self, correct_id, kind, name): allowed = True @@ -449,7 +442,7 @@ class ConversationTextview(GObject.GObject): buffer_.end_user_action() del self.xep0184_marks[id_] - def show_focus_out_line(self, scroll=True): + def show_focus_out_line(self): if not self.allow_focus_out_line: # if room did not receive focus-in from the last time we added # --- line then do not readd @@ -505,11 +498,7 @@ class ConversationTextview(GObject.GObject): buffer_.get_end_iter(), left_gravity=True) buffer_.end_user_action() - - if scroll: - # scroll to the end (via idle in case the scrollbar has - # appeared) - GLib.idle_add(self.scroll_to_end_iter) + self.scroll_to_end() def clear(self, tv = None): """ @@ -1231,9 +1220,9 @@ class ConversationTextview(GObject.GObject): self.last_sent_message_id = (msg_stanza_id, new_mark) if not insert_mark: - if self.at_the_end() or kind == 'outgoing': + if self.autoscroll or kind == 'outgoing': # we are at the end or we are sending something - GLib.idle_add(self.scroll_to_end_iter) + self.scroll_to_end(force=True) self.just_cleared = False buffer_.end_user_action() diff --git a/gajim/data/gui/chat_control.ui b/gajim/data/gui/chat_control.ui index 0b7ac417c..eb36a218d 100644 --- a/gajim/data/gui/chat_control.ui +++ b/gajim/data/gui/chat_control.ui @@ -1,5 +1,5 @@ - + @@ -594,6 +594,8 @@ True in False + + diff --git a/gajim/data/gui/groupchat_control.ui b/gajim/data/gui/groupchat_control.ui index 9e15ec014..6c37ae8f6 100644 --- a/gajim/data/gui/groupchat_control.ui +++ b/gajim/data/gui/groupchat_control.ui @@ -1,5 +1,5 @@ - + @@ -187,6 +187,8 @@ True in False + + diff --git a/gajim/groupchat_control.py b/gajim/groupchat_control.py index c16020a55..99c7912f3 100644 --- a/gajim/groupchat_control.py +++ b/gajim/groupchat_control.py @@ -1380,8 +1380,7 @@ class GroupchatControl(ChatControlBase): # we have full focus (we are reading it!) return - at_the_end = self.conv_textview.at_the_end() - self.conv_textview.show_focus_out_line(scroll=at_the_end) + self.conv_textview.show_focus_out_line() def needs_visual_notification(self, text): """ diff --git a/gajim/gui_interface.py b/gajim/gui_interface.py index 6ca8f423a..70d7acfd2 100644 --- a/gajim/gui_interface.py +++ b/gajim/gui_interface.py @@ -1814,8 +1814,8 @@ class Interface: w.window.present() # Using isinstance here because we want to catch all derived types if isinstance(ctrl, ChatControlBase): - tv = ctrl.conv_textview - tv.scroll_to_end_iter() + ctrl.scroll_to_end() + def join_gc_minimal(self, account, room_jid, password=None): if account is not None: diff --git a/gajim/message_window.py b/gajim/message_window.py index 99746185b..dad1a676a 100644 --- a/gajim/message_window.py +++ b/gajim/message_window.py @@ -292,16 +292,10 @@ class MessageWindow(object): self._controls[control.account][fjid] = control if self.get_num_controls() == 2: - # is first conversation_textview scrolled down ? - scrolled = False first_widget = self.notebook.get_nth_page(0) ctrl = self._widget_to_control(first_widget) - conv_textview = ctrl.conv_textview - if conv_textview.at_the_end(): - scrolled = True self.notebook.set_show_tabs(True) - if scrolled: - GLib.idle_add(conv_textview.scroll_to_end_iter) + ctrl.scroll_to_end() # Add notebook page and connect up to the tab's close button xml = gtkgui_helpers.get_gtk_builder('message_window.ui', 'chat_tab_ebox') diff --git a/gajim/roster_window.py b/gajim/roster_window.py index 05bf7eaf4..85cc20a69 100644 --- a/gajim/roster_window.py +++ b/gajim/roster_window.py @@ -2723,7 +2723,7 @@ class RosterWindow: xep0184_id=xep0184_id, additional_data=obj.additional_data) if obj.msg_log_id: pw = obj.session.control.parent_win - end = obj.session.control.was_at_the_end + end = obj.session.control.conv_textview.autoscroll if not pw or (pw.get_active_control() and obj.session.control \ == pw.get_active_control() and pw.is_active() and end): app.logger.set_read_messages([obj.msg_log_id])