diff --git a/src/chat_control.py b/src/chat_control.py
index 2ab0b519146556f56e37ee5d852781215fe6f793..4e1c106c7c0a9de1ac1b6082c5fd394d33de7fd5 100644
--- a/src/chat_control.py
+++ b/src/chat_control.py
@@ -108,13 +108,18 @@ class ChatControlBase(MessageControl):
 		
 		id = self.widget.connect('key_press_event', self._on_keypress_event)
 		self.handlers[id] = self.widget
-		
+
+		widget = self.xml.get_widget('banner_eventbox')
+		id = widget.connect('button-press-event',
+			self._on_banner_eventbox_button_press_event)
+		self.handlers[id] = widget
+	
 		# Create textviews and connect signals
 		self.conv_textview = ConversationTextview(self.account)
-		self.conv_textview.show_all()
+		
 		self.conv_scrolledwindow = self.xml.get_widget(
 			'conversation_scrolledwindow')
-		self.conv_scrolledwindow.add(self.conv_textview)
+		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)
@@ -170,6 +175,12 @@ class ChatControlBase(MessageControl):
 				gajim.config.set('use_speller', False)
 
 		self.style_event_id = 0
+		self.conv_textview.tv.show()
+	# moved from ChatControl 
+	def _on_banner_eventbox_button_press_event(self, widget, event):
+		'''If right-clicked, show popup'''
+		if event.button == 3: # right click
+			self.parent_win.popup_menu(event)
 
 	def _on_send_button_clicked(self, widget):
 		'''When send button is pressed: send the current message'''
@@ -241,7 +252,7 @@ class ChatControlBase(MessageControl):
 		if event.state & gtk.gdk.CONTROL_MASK:
 			# CTRL + l|L: clear conv_textview
 			if event.keyval == gtk.keysyms.l or event.keyval == gtk.keysyms.L:
-				self.conv_textview.get_buffer().set_text('')
+				self.conv_textview.tv.get_buffer().set_text('')
 				return True
 			# CTRL + v: Paste into msg_textview
 			elif event.keyval == gtk.keysyms.v:
@@ -313,7 +324,7 @@ class ChatControlBase(MessageControl):
 			# SHIFT + PAGE_[UP|DOWN]: send to conv_textview
 			elif event.keyval == gtk.keysyms.Page_Down or \
 					event.keyval == gtk.keysyms.Page_Up:
-				self.conv_textview.emit('key_press_event', event)
+				self.conv_textview.tv.emit('key_press_event', event)
 				return True
 		elif event.state & gtk.gdk.CONTROL_MASK:
 			if event.keyval == gtk.keysyms.Tab: # CTRL + TAB
@@ -327,7 +338,7 @@ class ChatControlBase(MessageControl):
 			# we pressed a control key or ctrl+sth: we don't block
 			# the event in order to let ctrl+c (copy text) and
 			# others do their default work
-			self.conv_textview.emit('key_press_event', event)
+			self.conv_textview.tv.emit('key_press_event', event)
 		return False
 
 	def _on_message_textview_mykeypress_event(self, widget, event_keyval,
@@ -394,7 +405,7 @@ class ChatControlBase(MessageControl):
 			return False
 
 		if message == '/clear':
-			self.conv_textview.clear() # clear conversation
+			self.conv_textview.tv.clear() # clear conversation
 			self.clear(self.msg_textview) # clear message textview too
 			return True
 		elif message == '/compact':
@@ -501,7 +512,7 @@ class ChatControlBase(MessageControl):
 
 	def update_font(self):
 		font = pango.FontDescription(gajim.config.get('conversation_font'))
-		self.conv_textview.modify_font(font)
+		self.conv_textview.tv.modify_font(font)
 		self.msg_textview.modify_font(font)
 
 	def update_tags(self):
@@ -516,7 +527,7 @@ class ChatControlBase(MessageControl):
 		'''When history menuitem is pressed: call history window'''
 		if not jid:
 			jid = self.contact.jid
-		
+
 		if gajim.interface.instances['logs'].has_key(jid):
 			gajim.interface.instances['logs'][jid].window.present()
 		else:
@@ -569,7 +580,7 @@ class ChatControlBase(MessageControl):
 			return
 
 		min_height = self.conv_scrolledwindow.get_property('height-request')
-		conversation_height = self.conv_textview.window.get_size()[1]
+		conversation_height = self.conv_textview.tv.window.get_size()[1]
 		message_height = msg_textview.window.get_size()[1]
 		message_width = msg_textview.window.get_size()[0]
 		# new tab is not exposed yet
@@ -731,11 +742,6 @@ class ChatControl(ChatControlBase):
 		id = message_tv_buffer.connect('changed', self._on_message_tv_buffer_changed)
 		self.handlers[id] = message_tv_buffer
 		
-		widget = self.xml.get_widget('banner_eventbox')
-		id = widget.connect('button-press-event', 
-			self._on_banner_eventbox_button_press_event)
-		self.handlers[id] = widget
-
 		widget = self.xml.get_widget('avatar_eventbox')
 		id = widget.connect('enter-notify-event', self.on_avatar_eventbox_enter_notify_event)
 		self.handlers[id] = widget
@@ -1198,19 +1204,25 @@ class ChatControl(ChatControlBase):
 		
 		
 		# connect signals
-		history_menuitem.connect('activate', 
+		id = history_menuitem.connect('activate', 
 			self._on_history_menuitem_activate)
-		send_file_menuitem.connect('activate', 
+		self.handlers[id] = history_menuitem
+		id = send_file_menuitem.connect('activate', 
 			self._on_send_file_menuitem_activate)
-		compact_view_menuitem.connect('activate', 
+		self.handlers[id] = send_file_menuitem 
+		id = compact_view_menuitem.connect('activate', 
 			self._on_compact_view_menuitem_activate)
-		add_to_roster_menuitem.connect('activate', 
+		self.handlers[id] = compact_view_menuitem 
+		id = add_to_roster_menuitem.connect('activate', 
 			self._on_add_to_roster_menuitem_activate)
-		toggle_gpg_menuitem.connect('activate', 
+		self.handlers[id] = add_to_roster_menuitem 
+		id = toggle_gpg_menuitem.connect('activate', 
 			self._on_toggle_gpg_menuitem_activate)
-		information_menuitem.connect('activate', 
+		self.handlers[id] = toggle_gpg_menuitem 
+		id = information_menuitem.connect('activate', 
 			self._on_contact_information_menuitem_activate)
-		menu.connect('selection-done', gtkgui_helpers.destroy_widget)	
+		self.handlers[id] = information_menuitem
+		menu.connect('selection-done', lambda w:w.destroy())	
 		return menu
 
 	def send_chatstate(self, state, contact = None):
@@ -1311,8 +1323,11 @@ class ChatControl(ChatControlBase):
 		# remove all register handlers on wigets, created by self.xml
 		# to prevent circular references among objects
 		for i in self.handlers.keys():
-			self.handlers[i].disconnect(i)
+			if self.handlers[i].handler_is_connected(i):
+				self.handlers[i].disconnect(i)
 			del self.handlers[i]
+		self.conv_textview.del_handlers()
+		self.msg_textview.destroy()
 		
 
 	def allow_shutdown(self):
@@ -1334,11 +1349,6 @@ class ChatControl(ChatControlBase):
 		# update chatstate in tab for this chat
 		self.parent_win.redraw_tab(self, self.contact.chatstate)
 
-	def _on_banner_eventbox_button_press_event(self, widget, event):
-		'''If right-clicked, show popup'''
-		if event.button == 3: # right click
-			self.parent_win.popup_menu(event)
-
 	def set_control_active(self, state):
 		ChatControlBase.set_control_active(self, state)
 		# send chatstate inactive to the one we're leaving
diff --git a/src/conversation_textview.py b/src/conversation_textview.py
index baa27de7454d0493d7e91415d7b990b903360dfe..19832ded462e95a8efb565fce22fa85beba5f25e 100644
--- a/src/conversation_textview.py
+++ b/src/conversation_textview.py
@@ -44,33 +44,38 @@ gtk.glade.textdomain(APP)
 
 GTKGUI_GLADE = 'gtkgui.glade'
 
-class ConversationTextview(gtk.TextView):
+class ConversationTextview:
 	'''Class for the conversation textview (where user reads already said messages)
 	for chat/groupchat windows'''
 	def __init__(self, account):
-		gtk.TextView.__init__(self)
+		# no need to inherit TextView, use it as property is safer
+		self.tv = gtk.TextView()
 
 		# set properties
-		self.set_border_width(1)
-		self.set_accepts_tab(True)
-		self.set_editable(False)
-		self.set_cursor_visible(False)
-		self.set_wrap_mode(gtk.WRAP_WORD)
-		self.set_left_margin(2)
-		self.set_right_margin(2)
+		self.tv.set_border_width(1)
+		self.tv.set_accepts_tab(True)
+		self.tv.set_editable(False)
+		self.tv.set_cursor_visible(False)
+		self.tv.set_wrap_mode(gtk.WRAP_WORD)
+		self.tv.set_left_margin(2)
+		self.tv.set_right_margin(2)
+		self.handlers = {}
 
 		# connect signals
-		self.connect('motion_notify_event', self.on_textview_motion_notify_event)
-		self.connect('populate_popup', self.on_textview_populate_popup)
-		self.connect('button_press_event', self.on_textview_button_press_event)
+		id = self.tv.connect('motion_notify_event', self.on_textview_motion_notify_event)
+		self.handlers[id] = self.tv
+		id = self.tv.connect('populate_popup', self.on_textview_populate_popup)
+		self.handlers[id] = self.tv
+		id = self.tv.connect('button_press_event', self.on_textview_button_press_event)
+		self.handlers[id] = self.tv
 
 		self.account = account
 		self.change_cursor = None
 		self.last_time_printout = 0
 
 		font = pango.FontDescription(gajim.config.get('conversation_font'))
-		self.modify_font(font)
-		buffer = self.get_buffer()
+		self.tv.modify_font(font)
+		buffer = self.tv.get_buffer()
 		end_iter = buffer.get_end_iter()
 		buffer.create_mark('end', end_iter, False)
 
@@ -105,12 +110,14 @@ class ConversationTextview(gtk.TextView):
 		color = gajim.config.get('urlmsgcolor')
 		tag.set_property('foreground', color)
 		tag.set_property('underline', pango.UNDERLINE_SINGLE)
-		tag.connect('event', self.hyperlink_handler, 'url')
+		id = tag.connect('event', self.hyperlink_handler, 'url')
+		self.handlers[id] = tag
 
 		tag = buffer.create_tag('mail')
 		tag.set_property('foreground', color)
 		tag.set_property('underline', pango.UNDERLINE_SINGLE)
-		tag.connect('event', self.hyperlink_handler, 'mail')
+		id = tag.connect('event', self.hyperlink_handler, 'mail')
+		self.handlers[id] = tag
 
 		tag = buffer.create_tag('bold')
 		tag.set_property('weight', pango.WEIGHT_BOLD)
@@ -125,6 +132,14 @@ class ConversationTextview(gtk.TextView):
 
 		self.line_tooltip = tooltips.BaseTooltip()
 
+	def del_handlers(self):
+		for i in self.handlers.keys():
+			self.handlers[i].disconnect(i)
+		del self.handlers
+		self.tv.destroy()
+		#TODO
+		# self.line_tooltip.destroy()
+	
 	def update_tags(self):
 		self.tagIn.set_property('foreground', gajim.config.get('inmsgcolor'))
 		self.tagOut.set_property('foreground', gajim.config.get('outmsgcolor'))
@@ -132,44 +147,44 @@ class ConversationTextview(gtk.TextView):
 			gajim.config.get('statusmsgcolor'))
 
 	def at_the_end(self):
-		buffer = self.get_buffer()
+		buffer = self.tv.get_buffer()
 		end_iter = buffer.get_end_iter()
-		end_rect = self.get_iter_location(end_iter)
-		visible_rect = self.get_visible_rect()
+		end_rect = self.tv.get_iter_location(end_iter)
+		visible_rect = self.tv.get_visible_rect()
 		if end_rect.y <= (visible_rect.y + visible_rect.height):
 			return True
 		return False
 
 	def scroll_to_end(self):
-		parent = self.get_parent()
-		buffer = self.get_buffer()
-		self.scroll_to_mark(buffer.get_mark('end'), 0, True, 0, 1)
+		parent = self.tv.get_parent()
+		buffer = self.tv.get_buffer()
+		self.tv.scroll_to_mark(buffer.get_mark('end'), 0, True, 0, 1)
 		adjustment = parent.get_hadjustment()
 		adjustment.set_value(0)
 		return False # when called in an idle_add, just do it once
 
 	def bring_scroll_to_end(self, diff_y = 0):
 		''' scrolls to the end of textview if end is not visible '''
-		buffer = self.get_buffer()
+		buffer = self.tv.get_buffer()
 		end_iter = buffer.get_end_iter()
-		end_rect = self.get_iter_location(end_iter)
-		visible_rect = self.get_visible_rect()
+		end_rect = self.tv.get_iter_location(end_iter)
+		visible_rect = self.tv.get_visible_rect()
 		# scroll only if expected end is not visible
 		if end_rect.y >= (visible_rect.y + visible_rect.height + diff_y):
 			gobject.idle_add(self.scroll_to_end_iter)
 
 	def scroll_to_end_iter(self):
-		buffer = self.get_buffer()
+		buffer = self.tv.get_buffer()
 		end_iter = buffer.get_end_iter()
-		self.scroll_to_iter(end_iter, 0, False, 1, 1)
+		self.tv.scroll_to_iter(end_iter, 0, False, 1, 1)
 		return False # when called in an idle_add, just do it once
 
 	def show_line_tooltip(self):
-		pointer = self.get_pointer()
-		x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer[0],
+		pointer = self.tv.get_pointer()
+		x, y = self.tv.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer[0],
 			pointer[1])
-		tags = self.get_iter_at_location(x, y).get_tags()
-		tag_table = self.get_buffer().get_tag_table()
+		tags = self.tv.get_iter_at_location(x, y).get_tags()
+		tag_table = self.tv.get_buffer().get_tag_table()
 		over_line = False
 		for tag in tags:
 			if tag == tag_table.lookup('focus-out-line'):
@@ -177,26 +192,26 @@ class ConversationTextview(gtk.TextView):
 				break
 		if over_line and not self.line_tooltip.win:
 			# check if the current pointer is still over the line
-			position = self.window.get_origin()
-			win = self.get_toplevel()
+			position = self.tv.window.get_origin()
+			win = self.tv.get_toplevel()
 			self.line_tooltip.show_tooltip(_('Text below this line is what has '
 			'been said since the last time you paid attention to this group chat'),	8, position[1] + pointer[1])
 
 	def on_textview_motion_notify_event(self, widget, event):
 		'''change the cursor to a hand when we are over a mail or an url'''
-		pointer_x, pointer_y, spam = self.window.get_pointer()
-		x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer_x,
+		pointer_x, pointer_y, spam = self.tv.window.get_pointer()
+		x, y = self.tv.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer_x,
 			pointer_y)
-		tags = self.get_iter_at_location(x, y).get_tags()
+		tags = self.tv.get_iter_at_location(x, y).get_tags()
 		if self.change_cursor:
-			self.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
+			self.tv.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
 				gtk.gdk.Cursor(gtk.gdk.XTERM))
 			self.change_cursor = None
-		tag_table = self.get_buffer().get_tag_table()
+		tag_table = self.tv.get_buffer().get_tag_table()
 		over_line = False
 		for tag in tags:
 			if tag in (tag_table.lookup('url'), tag_table.lookup('mail')):
-				self.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
+				self.tv.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
 					gtk.gdk.Cursor(gtk.gdk.HAND2))
 				self.change_cursor = tag
 			elif tag == tag_table.lookup('focus-out-line'):
@@ -209,13 +224,13 @@ class ConversationTextview(gtk.TextView):
 		if over_line and not self.line_tooltip.win:
 			self.line_tooltip.timeout = gobject.timeout_add(500,
 				self.show_line_tooltip)
-			self.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
+			self.tv.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
 				gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
 			self.change_cursor = tag
 
 	def clear(self, tv = None):
 		'''clear text in the textview'''
-		buffer = self.get_buffer()
+		buffer = self.tv.get_buffer()
 		start, end = buffer.get_bounds()
 		buffer.delete(start, end)
 
@@ -231,7 +246,8 @@ class ConversationTextview(gtk.TextView):
 		menu.prepend(item)
 		item = gtk.ImageMenuItem(gtk.STOCK_CLEAR)
 		menu.prepend(item)
-		item.connect('activate', self.clear)
+		id = item.connect('activate', self.clear)
+		self.handlers[id] = item
 		if self.selected_phrase:
 			s = self.selected_phrase
 			if len(s) > 25:
@@ -249,7 +265,8 @@ class ConversationTextview(gtk.TextView):
 				link = 'http://%s.wikipedia.org/wiki/Special:Search?search=%s'\
 					% (gajim.LANG, self.selected_phrase)
 			item = gtk.MenuItem(_('Read _Wikipedia Article'))
-			item.connect('activate', self.visit_url_from_menuitem, link)
+			id = item.connect('activate', self.visit_url_from_menuitem, link)
+			self.handlers[id] = item
 			submenu.append(item)
 
 			item = gtk.MenuItem(_('Look it up in _Dictionary'))
@@ -263,7 +280,8 @@ class ConversationTextview(gtk.TextView):
 				else:
 					link = 'http://%s.wiktionary.org/wiki/Special:Search?search=%s'\
 						% (gajim.LANG, self.selected_phrase)
-				item.connect('activate', self.visit_url_from_menuitem, link)
+				id = item.connect('activate', self.visit_url_from_menuitem, link)
+				self.handlers[id] = item
 			else:
 				if dict_link.find('%s') == -1:
 					#we must have %s in the url if not WIKTIONARY
@@ -271,7 +289,8 @@ class ConversationTextview(gtk.TextView):
 					item.set_property('sensitive', False)
 				else:
 					link = dict_link % self.selected_phrase
-					item.connect('activate', self.visit_url_from_menuitem, link)
+					id = item.connect('activate', self.visit_url_from_menuitem, link)
+					self.handlers[id] = item
 			submenu.append(item)
 
 
@@ -283,7 +302,8 @@ class ConversationTextview(gtk.TextView):
 			else:
 				item = gtk.MenuItem(_('Web _Search for it'))
 				link =  search_link % self.selected_phrase
-				item.connect('activate', self.visit_url_from_menuitem, link)
+				id = item.connect('activate', self.visit_url_from_menuitem, link)
+				self.handlers[id] = item
 			submenu.append(item)
 
 		menu.show_all()
@@ -297,10 +317,10 @@ class ConversationTextview(gtk.TextView):
 		if event.button != 3: # if not right click
 			return False
 
-		win = self.get_window(gtk.TEXT_WINDOW_TEXT)
-		x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT,
+		win = self.tv.get_window(gtk.TEXT_WINDOW_TEXT)
+		x, y = self.tv.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT,
 			int(event.x), int(event.y))
-		iter = self.get_iter_at_location(x, y)
+		iter = self.tv.get_iter_at_location(x, y)
 		tags = iter.get_tags()
 
 
@@ -313,7 +333,7 @@ class ConversationTextview(gtk.TextView):
 		# we check if sth was selected and if it was we assign
 		# selected_phrase variable
 		# so on_conversation_textview_populate_popup can use it
-		buffer = self.get_buffer()
+		buffer = self.tv.get_buffer()
 		return_val = buffer.get_selection_bounds()
 		if return_val: # if sth was selected when we right-clicked
 			# get the selected text
@@ -352,8 +372,10 @@ class ConversationTextview(gtk.TextView):
 		menu = xml.get_widget('chat_context_menu')
 		childs = menu.get_children()
 		if kind == 'url':
-			childs[0].connect('activate', self.on_copy_link_activate, text)
-			childs[1].connect('activate', self.on_open_link_activate, kind, text)
+			id = childs[0].connect('activate', self.on_copy_link_activate, text)
+			self.handlers[id] = childs[0]
+			id = childs[1].connect('activate', self.on_open_link_activate, kind, text)
+			self.handlers[id] = childs[1]
 			childs[2].hide() # copy mail address
 			childs[3].hide() # open mail composer
 			childs[4].hide() # jid section separator
@@ -361,11 +383,15 @@ class ConversationTextview(gtk.TextView):
 			childs[6].hide() # join group chat
 			childs[7].hide() # add to roster
 		else: # It's a mail or a JID
-			childs[2].connect('activate', self.on_copy_link_activate, text)
-			childs[3].connect('activate', self.on_open_link_activate, kind, text)
-			childs[5].connect('activate', self.on_start_chat_activate, text)
-			childs[6].connect('activate',
+			id = childs[2].connect('activate', self.on_copy_link_activate, text)
+			self.handlers[id] = childs[2]
+			id = childs[3].connect('activate', self.on_open_link_activate, kind, text)
+			self.handlers[id] = childs[3]
+			id = childs[5].connect('activate', self.on_start_chat_activate, text)
+			self.handlers[id] = childs[5]
+			id = childs[6].connect('activate',
 				self.on_join_group_chat_menuitem_activate, text)
+			self.handlers[id] = childs[6]
 
 			allow_add = False
 			c = gajim.contacts.get_first_contact_from_jid(self.account, text)
@@ -376,7 +402,8 @@ class ConversationTextview(gtk.TextView):
 				allow_add = True
 
 			if allow_add:
-				childs[7].connect('activate', self.on_add_to_roster_activate, text)
+				id = childs[7].connect('activate', self.on_add_to_roster_activate, text)
+				self.handlers[id] = childs[7]
 				childs[7].show() # show add to roster menuitem
 			else:
 				childs[7].hide() # hide add to roster menuitem
@@ -396,7 +423,7 @@ class ConversationTextview(gtk.TextView):
 			# we get the end of the tag
 			while not end_iter.ends_tag(texttag):
 				end_iter.forward_char()
-			word = self.get_buffer().get_text(begin_iter, end_iter).decode('utf-8')
+			word = self.tv.get_buffer().get_text(begin_iter, end_iter).decode('utf-8')
 			if event.button == 3: # right click
 				self.make_link_menu(event, kind, word)
 			else:
@@ -411,7 +438,7 @@ class ConversationTextview(gtk.TextView):
 		after *last* special text, so we can print it in
 		print_conversation_line()'''
 
-		buffer = self.get_buffer()
+		buffer = self.tv.get_buffer()
 
 		start = 0
 		end = 0
@@ -445,7 +472,7 @@ class ConversationTextview(gtk.TextView):
 		use_other_tags = True
 		show_ascii_formatting_chars = \
 			gajim.config.get('show_ascii_formatting_chars')
-		buffer = self.get_buffer()
+		buffer = self.tv.get_buffer()
 
 		possible_emot_ascii_caps = special_text.upper() # emoticons keys are CAPS
 		if gajim.config.get('emoticons_theme') and \
@@ -458,7 +485,7 @@ class ConversationTextview(gtk.TextView):
 			img.set_from_file(gajim.interface.emoticons[emot_ascii])
 			img.show()
 			#add with possible animation
-			self.add_child_at_anchor(img, anchor)
+			self.tv.add_child_at_anchor(img, anchor)
 		elif special_text.startswith('http://') or \
 			special_text.startswith('www.') or \
 			special_text.startswith('ftp://') or \
@@ -533,7 +560,7 @@ class ConversationTextview(gtk.TextView):
 			buffer.insert_with_tags_by_name(end_iter, special_text, *all_tags)
 
 	def print_empty_line(self):
-		buffer = self.get_buffer()
+		buffer = self.tv.get_buffer()
 		end_iter = buffer.get_end_iter()
 		buffer.insert(end_iter, '\n')
 
@@ -546,7 +573,7 @@ class ConversationTextview(gtk.TextView):
 		# kind = info, we print things as if it was a status: same color, ...
 		if kind == 'info':
 			kind = 'status'
-		buffer = self.get_buffer()
+		buffer = self.tv.get_buffer()
 		buffer.begin_user_action()
 		end_iter = buffer.get_end_iter()
 		at_the_end = False
@@ -620,7 +647,7 @@ class ConversationTextview(gtk.TextView):
 
 	def print_name(self, name, kind, other_tags_for_name):
 		if name:
-			buffer = self.get_buffer()
+			buffer = self.tv.get_buffer()
 			end_iter = buffer.get_end_iter()
 			name_tags = other_tags_for_name[:] # create a new list
 			name_tags.append(kind)
@@ -632,14 +659,14 @@ class ConversationTextview(gtk.TextView):
 	def print_subject(self, subject):
 		if subject: # if we have subject, show it too!
 			subject = _('Subject: %s\n') % subject
-			buffer = self.get_buffer()
+			buffer = self.tv.get_buffer()
 			end_iter = buffer.get_end_iter()
 			buffer.insert(end_iter, subject)
 			self.print_empty_line()
 
 	def print_real_text(self, text, text_tags = [], name = None):
 		'''this adds normal and special text. call this to add text'''
-		buffer = self.get_buffer()
+		buffer = self.tv.get_buffer()
 		# /me is replaced by name if name is given
 		if name and (text.startswith('/me ') or text.startswith('/me\n')):
 			text = '* ' + name + text[3:]
diff --git a/src/groupchat_control.py b/src/groupchat_control.py
index c1b65f44d2e1df75407667aa53165f39a1565d78..93ebde200e1895bcb7f364c2ae0a8f7d2371f018 100644
--- a/src/groupchat_control.py
+++ b/src/groupchat_control.py
@@ -299,7 +299,7 @@ class GroupchatControl(ChatControlBase):
 		self.got_disconnected() #init some variables
 
 		self.update_ui()
-		self.conv_textview.grab_focus()
+		self.conv_textview.tv.grab_focus()
 		self.widget.show_all()
 
 	def notify_on_new_messages(self):
@@ -568,7 +568,7 @@ class GroupchatControl(ChatControlBase):
 			return
 
 		print_focus_out_line = False
-		buffer = self.conv_textview.get_buffer()
+		buffer = self.conv_textview.tv.get_buffer()
 
 		if self.focus_out_end_iter_offset is None:
 			# this happens only first time we focus out on this room
@@ -1179,7 +1179,8 @@ class GroupchatControl(ChatControlBase):
 		# remove all register handlers on wigets, created by self.xml
 		# to prevent circular references among objects
 		for i in self.handlers.keys():
-			self.handlers[i].disconnect(i)
+			if self.handlers[i].handler_is_connected(i):
+				self.handlers[i].disconnect(i)
 			del self.handlers[i]
 
 	def allow_shutdown(self):
diff --git a/src/gtkgui.glade b/src/gtkgui.glade
index 3a841cb6e7d4b7a7e0afc635d3a179e189e092d7..fb46bfd26c00f4b83ea1e2562c9d98decd53ce99 100644
--- a/src/gtkgui.glade
+++ b/src/gtkgui.glade
@@ -18028,9 +18028,6 @@ Maybe I'll refactor later</property>
   <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
   <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
   <property name="focus_on_map">True</property>
-  <signal name="delete_event" handler="_on_window_delete" last_modification_time="Thu, 12 Jan 2006 02:55:53 GMT"/>
-  <signal name="destroy" handler="_on_window_destroy" last_modification_time="Thu, 12 Jan 2006 02:56:25 GMT"/>
-  <signal name="focus_in_event" handler="_on_window_focus" last_modification_time="Thu, 12 Jan 2006 02:56:55 GMT"/>
 
   <child>
     <widget class="GtkAlignment" id="msg_window_alignment">
@@ -18623,7 +18620,6 @@ Status message</property>
 		      <property name="can_focus">True</property>
 		      <property name="relief">GTK_RELIEF_NONE</property>
 		      <property name="focus_on_click">True</property>
-		      <signal name="clicked" handler="on_close_button_clicked" last_modification_time="Sat, 12 Mar 2005 00:12:43 GMT"/>
 
 		      <child>
 			<widget class="GtkImage" id="image1329">
@@ -18674,7 +18670,6 @@ Status message</property>
 		      <property name="visible">True</property>
 		      <property name="visible_window">True</property>
 		      <property name="above_child">False</property>
-		      <signal name="button_press_event" handler="on_banner_eventbox_button_press_event" last_modification_time="Mon, 08 Aug 2005 15:32:39 GMT"/>
 
 		      <child>
 			<widget class="GtkLabel" id="banner_name_label">
@@ -18694,7 +18689,6 @@ topic</property>
 			  <property name="width_chars">-1</property>
 			  <property name="single_line_mode">False</property>
 			  <property name="angle">0</property>
-			  <signal name="button_press_event" handler="on_banner_label_button_press_event" last_modification_time="Sun, 07 Aug 2005 15:07:13 GMT"/>
 			</widget>
 		      </child>
 		    </widget>
@@ -18856,7 +18850,6 @@ topic</property>
 			  <property name="can_focus">True</property>
 			  <property name="relief">GTK_RELIEF_NORMAL</property>
 			  <property name="focus_on_click">True</property>
-			  <signal name="clicked" handler="on_emoticons_button_clicked" last_modification_time="Thu, 17 Nov 2005 18:06:37 GMT"/>
 
 			  <child>
 			    <widget class="GtkHBox" id="hbox3014">
@@ -19114,7 +19107,6 @@ topic</property>
 	      <property name="visible">True</property>
 	      <property name="visible_window">False</property>
 	      <property name="above_child">False</property>
-	      <signal name="button_press_event" handler="on_tab_eventbox_button_press_event" last_modification_time="Thu, 04 Aug 2005 09:38:11 GMT"/>
 
 	      <child>
 		<widget class="GtkHBox" id="hbox3017">
@@ -19170,7 +19162,6 @@ topic</property>
 		      <property name="can_focus">True</property>
 		      <property name="relief">GTK_RELIEF_NONE</property>
 		      <property name="focus_on_click">True</property>
-		      <signal name="clicked" handler="on_close_button_clicked" last_modification_time="Sat, 12 Mar 2005 00:12:43 GMT"/>
 
 		      <child>
 			<widget class="GtkImage" id="image1347">
diff --git a/src/gtkgui_helpers.py b/src/gtkgui_helpers.py
index 4eb81e31fdcf6af85bc7ed2c2895ea717c2a567d..c8b68dba0ea6b2053b2fff0e75fbf918bcf9a291 100644
--- a/src/gtkgui_helpers.py
+++ b/src/gtkgui_helpers.py
@@ -47,12 +47,13 @@ screen_h = gtk.gdk.screen_height()
 
 def popup_emoticons_under_button(menu, button, parent_win):
 	''' pops emoticons menu under button, which is in parent_win'''
+	window_x1, window_y1 = parent_win.get_origin()
 	def position_menu_under_button(menu):
 		# inline function, which will not keep refs, when used as CB
 		button_x, button_y = button.allocation.x, button.allocation.y
 		
 		# now convert them to X11-relative
-		window_x, window_y = parent_win.get_origin()
+		window_x, window_y = window_x1, window_y1
 		x = window_x + button_x
 		y = window_y + button_y
 
@@ -70,7 +71,7 @@ def popup_emoticons_under_button(menu, button, parent_win):
 		# push_in is True so all the menuitems are always inside screen
 		push_in = True
 		return (x, y, push_in)
-	
+
 	menu.popup(None, None, position_menu_under_button, 1, 0)
 	
 def get_theme_font_for_option(theme, option):
diff --git a/src/history_window.py b/src/history_window.py
index d06127e6a77a6b02fc66ce8e2e6126bd94800b75..86308cddc2c51a148eb6cff90f7d48b7ab833d11 100644
--- a/src/history_window.py
+++ b/src/history_window.py
@@ -69,8 +69,8 @@ class HistoryWindow:
 		self.calendar = xml.get_widget('calendar')
 		scrolledwindow = xml.get_widget('scrolledwindow')
 		self.history_textview = conversation_textview.ConversationTextview(account)
-		scrolledwindow.add(self.history_textview)
-		self.history_buffer = self.history_textview.get_buffer()
+		scrolledwindow.add(self.history_textview.tv)
+		self.history_buffer = self.history_textview.tv.get_buffer()
 		self.history_buffer.create_tag('highlight', background = 'yellow')
 		self.query_entry = xml.get_widget('query_entry')
 		self.search_button = xml.get_widget('search_button')
@@ -142,6 +142,7 @@ class HistoryWindow:
 			# if user destroys the window, and we have a generator filling mark days
 			# stop him!
 			gobject.source_remove(self.mark_days_idle_call_id)
+		self.history_textview.del_handlers()
 		del gajim.interface.instances['logs'][self.jid]
 
 	def on_close_button_clicked(self, widget):
@@ -391,4 +392,4 @@ class HistoryWindow:
 				
 			match_start_mark = self.history_buffer.create_mark('match_start',
 				match_start_iter, True)
-			self.history_textview.scroll_to_mark(match_start_mark, 0, True)
+			self.history_textview.tv.scroll_to_mark(match_start_mark, 0, True)
diff --git a/src/message_textview.py b/src/message_textview.py
index a30b9e25873615af02682f976176e0bb96220d4a..0affa4dc9b81cf1dd5125c7ef0d5b3e216c4979b 100644
--- a/src/message_textview.py
+++ b/src/message_textview.py
@@ -50,6 +50,9 @@ class MessageTextView(gtk.TextView):
 		self.set_pixels_above_lines(2)
 		self.set_pixels_below_lines(2)
 
+	def destroy(self):
+		import gc
+		gobject.idle_add(lambda:gc.collect())
 if gobject.pygtk_version < (2, 8, 0):
 	gobject.type_register(MessageTextView)
 
diff --git a/src/message_window.py b/src/message_window.py
index c61dbe012c85be9f5e23e4b0c9525dfa5479ae32..2f9ec7e2a81df547d809df7e6d28a6fe3dd34790 100644
--- a/src/message_window.py
+++ b/src/message_window.py
@@ -55,11 +55,19 @@ class MessageWindow:
 		self.account = acct
 		# If None, the window is not tied to any specific type
 		self.type = type
+		# dict { handler id: widget}. Keeps callbacks, which
+		# lead to cylcular references
+		self.handlers = {}
 
 		self.widget_name = 'message_window'
 		self.xml = gtk.glade.XML(GTKGUI_GLADE, self.widget_name, APP)
-		self.xml.signal_autoconnect(self)
 		self.window = self.xml.get_widget(self.widget_name)
+		id = self.window.connect('delete-event', self._on_window_delete)
+		self.handlers[id] = self.window
+		id = self.window.connect('destroy', self._on_window_destroy)
+		self.handlers[id] = self.window
+		id = self.window.connect('focus-in-event', self._on_window_focus)
+		self.handlers[id] = self.window
 
 		# gtk+ doesn't make use of the motion notify on gtkwindow by default
 		# so this line adds that
@@ -67,10 +75,12 @@ class MessageWindow:
 		self.alignment = self.xml.get_widget('alignment')
 
 		self.notebook = self.xml.get_widget('notebook')
-		self.notebook.connect('switch-page',
+		id = self.notebook.connect('switch-page',
 			self._on_notebook_switch_page)
-		self.notebook.connect('key-press-event',
+		self.handlers[id] = self.notebook
+		id = self.notebook.connect('key-press-event',
 			self._on_notebook_key_press)
+		self.handlers[id] = self.notebook
 
 		# Remove the glade pages
 		while self.notebook.get_n_pages():
@@ -96,6 +106,8 @@ class MessageWindow:
 		# set up DnD
 		self.hid = self.notebook.connect('drag_data_received',
 			self.on_tab_label_drag_data_received_cb)
+		self.handlers[self.hid] = self.notebook
+		
 		self.notebook.drag_dest_set(gtk.DEST_DEFAULT_ALL, self.DND_TARGETS,
 			gtk.gdk.ACTION_MOVE)
 
@@ -133,6 +145,11 @@ class MessageWindow:
 		for ctrl in self.controls():
 			ctrl.shutdown()
 		self._controls.clear()
+		for i in self.handlers.keys():
+			if self.handlers[i].handler_is_connected(i):
+				self.handlers[i].disconnect(i)
+			del self.handlers[i]
+		del self.handlers
 
 	def new_tab(self, control):
 		if not self._controls.has_key(control.account):
@@ -499,6 +516,7 @@ class MessageWindow:
 		tab_label = self.notebook.get_tab_label(child)
 		tab_label.dnd_handler = tab_label.connect('drag_data_get', 
 							  self.on_tab_label_drag_data_get_cb)
+		self.handlers[tab_label.dnd_handler] = tab_label
 		tab_label.drag_source_set(gtk.gdk.BUTTON1_MASK, self.DND_TARGETS,
 					 gtk.gdk.ACTION_MOVE)
 		tab_label.page_num = self.notebook.page_num(child)