[Deskbar] Cuemiac popup using focus-out-event is broken with sloppy focus



Hi !

According to a recent bug, the popup we use is broken when you use
sloppy pointer focus. An effet of this problem is also that we can't use
selection-on-hover for cuemiac and history widget properly without
running into problems.

The *right* way to handle the situation, like the volume applet
dropdown, or date applet calendar dropdown, or simple Gtk Menus, is the
use the 'X grabbing' thing.

That means no one else can receive keyboard and mouse actions other than
the widget designed for grabbing pointer/keyboard. Clicks and strokes
made outside the widget are redirected as button-press-event's on the
grabbing widget allowing to popdown when a click is made outside the
widget, just like regular menu behave.

This is the behavior we want, and playing like we do, with
focus-out-event is a hack.

That said, i tried to understand volume applet dropdown grabbing code
which is fairly straughtforward, and i attach the patch i made up.

Unfortunately it appears to work only randomly, for unknown reasons.
Right now it correctly grabs mouse and keyboard, which means once the
popup is displayed and focused, the ony thing you can do is hitting
escape.

Outside clicks to dismiss the popup are somehow not working, or working
only in some cases..

As i do not fully understand the focus trickery we use to get the
correct feel of deskbar, and the implications of it, i turn my eye over
Mikkel, so maybe he can try this at home, and understand what's going
on..

I think we should really have this nice and clean behavior in 2.14
release, so we need to get it in good shape..

Raf
? deskbar-applet-addressbook-search.patch
? grab-patch.diff
? data/mozilla-search.gladep
? data/prefs-dialog.gladep
? data/smart-bookmarks.gladep
Index: deskbar/DeskbarApplet.py
===================================================================
RCS file: /cvs/gnome/deskbar-applet/deskbar/DeskbarApplet.py,v
retrieving revision 1.36
diff -u -p -r1.36 DeskbarApplet.py
--- deskbar/DeskbarApplet.py	22 Feb 2006 15:32:27 -0000	1.36
+++ deskbar/DeskbarApplet.py	1 Mar 2006 22:26:22 -0000
@@ -91,7 +91,7 @@ class DeskbarApplet:
 			context.module.connect ('query-ready', lambda sender, qstring, matches: self.dispatch_matches([(qstring, match) for match in matches]))	
 	
 	def on_match_selected (self, sender, text, match):
-		print "match selected",match
+		print "Match selected: ",match
 		self.on_stop_query()
 		match.action(text)
 		get_deskbar_history().add(text, match)
@@ -279,11 +279,12 @@ class DeskbarApplet:
 	def on_ui_changed (self, value):
 		if value is None or value.type != gconf.VALUE_STRING:
 			return
-			
+		
+		self.ui.close_view()
 		self.applet.remove (self.ui.get_view())
 		#FIXME: Should we clean up signals and stuff on the old UI?
 		
-		ui_name = value.get_string()	
+		ui_name = value.get_string()
 
 		# Check for cairo otherwise cuemiac isn't available at all
 		if not hasattr(gtk.gdk.Drawable, 'cairo_create'):
Index: deskbar/ui/DeskbarUI.py
===================================================================
RCS file: /cvs/gnome/deskbar-applet/deskbar/ui/DeskbarUI.py,v
retrieving revision 1.9
diff -u -p -r1.9 DeskbarUI.py
--- deskbar/ui/DeskbarUI.py	22 Feb 2006 15:10:05 -0000	1.9
+++ deskbar/ui/DeskbarUI.py	1 Mar 2006 22:26:22 -0000
@@ -94,6 +94,12 @@ class DeskbarUI (gobject.GObject):
 		Return the widget to be displayed for this UI.
 		"""
 		raise NotImplementedError
+	
+	def close_view(self):
+		"""
+		Closes every popup or window owned by the UI, because the ui is going to change
+		"""
+		pass
 		
 if gtk.pygtk_version < (2,8,0):
 	gobject.type_register(DeskbarUI)
Index: deskbar/ui/cuemiac/Cuemiac.py
===================================================================
RCS file: /cvs/gnome/deskbar-applet/deskbar/ui/cuemiac/Cuemiac.py,v
retrieving revision 1.59
diff -u -p -r1.59 Cuemiac.py
--- deskbar/ui/cuemiac/Cuemiac.py	24 Feb 2006 20:28:48 -0000	1.59
+++ deskbar/ui/cuemiac/Cuemiac.py	1 Mar 2006 22:26:22 -0000
@@ -630,6 +630,7 @@ class CuemiacUI (DeskbarUI):
 		self.cview.connect_after ("cursor-changed", lambda treeview : self.update_entry_icon())
 		self.history_popup.connect ("match-selected", self.on_match_selected, True)
 		self.history_popup.connect ("key-press-event", self.on_history_key_press)		
+		self.popup.connect("button-press-event", self.on_popup_button_event)
 		
 		self.screen_height = self.popup.get_screen().get_height ()
 		self.screen_width = self.popup.get_screen().get_width ()
@@ -649,6 +650,11 @@ class CuemiacUI (DeskbarUI):
 		
 		self.applet.set_applet_flags(gnomeapplet.EXPAND_MINOR)
 		self.applet.set_flags(gtk.CAN_FOCUS)
+	
+	def close_view(self):
+		self.deskbar_button.button_arrow.set_active (False)
+		self.deskbar_button.button_main.set_active (False)
+		self.emit ("stop-query")
 		
 	def update_entry_icon (self, icon=None):
 		if icon == None:
@@ -697,10 +703,21 @@ class CuemiacUI (DeskbarUI):
 				self.popup.present ()
 			
 			self.entry.grab_focus ()
+			
+			self.popup.grab_add ()
+			gtk.gdk.pointer_grab (self.popup.window,True,gtk.gdk.BUTTON_PRESS_MASK|gtk.gdk.BUTTON_RELEASE_MASK|gtk.gdk.POINTER_MOTION_MASK)
+			gtk.gdk.keyboard_grab (self.popup.window, True)
 		else:
 			self.popup.hide ()
 			self.emit ("stop-query")
 	
+	def on_popup_button_event (self, popup, event):
+		print 'Event,',event
+		gtk.gdk.keyboard_ungrab (0)
+		gtk.gdk.pointer_ungrab (0)
+		self.popup.grab_remove ()
+		self.popup.hide()
+		
 	def receive_focus (self, time):
 		# Toggle expandedness of the popup
 		self.deskbar_button.button_main.set_active(not self.deskbar_button.button_main.get_active())
Index: deskbar/ui/entriac/CuemiacEntryUI.py
===================================================================
RCS file: /cvs/gnome/deskbar-applet/deskbar/ui/entriac/CuemiacEntryUI.py,v
retrieving revision 1.10
diff -u -p -r1.10 CuemiacEntryUI.py
--- deskbar/ui/entriac/CuemiacEntryUI.py	1 Mar 2006 13:07:05 -0000	1.10
+++ deskbar/ui/entriac/CuemiacEntryUI.py	1 Mar 2006 22:26:22 -0000
@@ -82,18 +82,13 @@ class CuemiacEntryUI (DeskbarUI):
 		self.cview.connect_after ("cursor-changed", lambda treeview : self.update_entry_icon())
 		self.history_popup.connect ("match-selected", self.on_match_selected, True)
 		self.history_popup.connect ("key-press-event", self.on_history_key_press)		
+		self.popup.connect("button-press-event", self.on_popup_button_event)
 		
 		self.screen_height = self.popup.get_screen().get_height ()
 		self.screen_width = self.popup.get_screen().get_width ()
 		self.max_window_height = int (0.8 * self.screen_height)
 		self.max_window_width = int (0.6 * self.screen_width)
 
-		# Setup a bunch of window hiding conditions
-		self.focus_out_from_cuemiac = False
-		self.cview.connect ("focus-out-event", self.on_focus_out_event)
-		self.entry.connect ("focus-out-event", self.on_focus_out_event)
-		self.history_popup.connect ("focus-out-event", lambda *args: self.history_popup.hide())
-
 		self.scroll_win.show_all ()
 		self.icon_entry.show_all ()
 		self.history_popup.get_child().show ()
@@ -112,6 +107,10 @@ class CuemiacEntryUI (DeskbarUI):
 		
 		self.applet.set_flags(gtk.CAN_FOCUS)
 	
+	def close_view(self):
+		self.hide_window (self.popup)
+		self.emit ("stop-query")
+		
 	def on_config_width(self, value=None):
 		if value != None and value.type == gconf.VALUE_INT:
 			self.config_width = value.get_int()
@@ -158,7 +157,16 @@ class CuemiacEntryUI (DeskbarUI):
 			self.popup.present_with_time (time)
 		elif not self.popup.get_property("visible"):
 			self.popup.present_with_time (gtk.get_current_event_time())
-			self.focus_out_from_cuemiac = True
+		
+		self.popup.grab_add ()
+		gtk.gdk.pointer_grab (self.popup.window,True,gtk.gdk.BUTTON_PRESS_MASK|gtk.gdk.BUTTON_RELEASE_MASK|gtk.gdk.POINTER_MOTION_MASK)
+		gtk.gdk.keyboard_grab (self.popup.window, True)
+	
+	def on_popup_button_event (self, popup, event):
+		gtk.gdk.keyboard_ungrab ()
+		gtk.gdk.pointer_ungrab ()
+		self.popup.grab_remove ()
+		self.popup.hide()
 	
 	def hide_window (self, window, time=None):
 		self.cview.get_selection().unselect_all ()
@@ -295,12 +303,10 @@ class CuemiacEntryUI (DeskbarUI):
 			
 		if event.keyval == 65362: # Up
 			self.focus_last_match (event.time)
-			self.focus_out_from_cuemiac = True
 			return True
 			
 		if event.keyval == 65364: # Down
 			self.focus_first_match (event.time)
-			self.focus_out_from_cuemiac = True
 			return True
 
 		return False
@@ -356,13 +362,6 @@ class CuemiacEntryUI (DeskbarUI):
 		# FIXME check that selection is not cat or nest, and then activate			
 		self.on_match_selected(widget, self.model[iter][self.model.MATCHES])
 		
-	def on_focus_out_event(self, widget, event):
-		if not self.focus_out_from_cuemiac:
-			#self.hide_window(self.popup)
-			self.popup.hide()
-		else:
-			self.focus_out_from_cuemiac = False
-		
 	def on_cview_key_press (self, cview, event):
 		path, column = cview.get_cursor ()
 		# If this is an ordinary keystroke, or there is no selection in the cview,
@@ -377,14 +376,12 @@ class CuemiacEntryUI (DeskbarUI):
 				self.cview.get_selection().unselect_all ()
 				self.applet.request_focus (long(event.time))
 				self.entry.grab_focus ()
-				self.focus_out_from_cuemiac = True
 				
 		elif model.paths_equal (path, cview.last_visible_path()):
 			if event.keyval == 65364: # Down
 				self.cview.get_selection().unselect_all ()
 				self.applet.request_focus (long(event.time))
 				self.entry.grab_focus ()
-				self.focus_out_from_cuemiac = True
 				
 		return False	
 		


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]