[maemo-commits] [maemo-commits] r11187 - in projects/haf/trunk/hildon-desktop: . libhildondesktop

From: subversion at stage.maemo.org subversion at stage.maemo.org
Date: Fri Apr 20 18:08:49 EEST 2007
Author: moimart
Date: 2007-04-20 18:08:48 +0300 (Fri, 20 Apr 2007)
New Revision: 11187

Modified:
   projects/haf/trunk/hildon-desktop/ChangeLog
   projects/haf/trunk/hildon-desktop/libhildondesktop/Makefile.am
   projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-popup-window.c
   projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-popup-window.h
Log:

	* libhildondesktop/hildon-desktop-popup-window.[ch]:
        - Fixed a lot of issues to get it built.
        * libhildondesktop/Makefile.am:
        - Added HildonDesktopPopupWindow to building batch
	* ChangeLog updated.



Modified: projects/haf/trunk/hildon-desktop/ChangeLog
===================================================================
--- projects/haf/trunk/hildon-desktop/ChangeLog	2007-04-20 14:46:29 UTC (rev 11186)
+++ projects/haf/trunk/hildon-desktop/ChangeLog	2007-04-20 15:08:48 UTC (rev 11187)
@@ -1,5 +1,12 @@
-2007-04-17  Johan Bilien  <johan.bilien at nokia.com>
+2007-04-20  Moises Martinez  <moises.martinez at nokia.com>
 
+	* libhildondesktop/hildon-desktop-popup-window.[ch]:
+	- Fixed a lot of issues to get it built.
+	* libhildondesktop/Makefile.am:
+	- Added HildonDesktopPopupWindow to building batch
+
+2007-04-20  Johan Bilien  <johan.bilien at nokia.com>
+
 	* libhildondesktop/hildon-home-area.c:
 	- fixed an infinite loop in some situations.
 	Fixes: NB#53973

Modified: projects/haf/trunk/hildon-desktop/libhildondesktop/Makefile.am
===================================================================
--- projects/haf/trunk/hildon-desktop/libhildondesktop/Makefile.am	2007-04-20 14:46:29 UTC (rev 11186)
+++ projects/haf/trunk/hildon-desktop/libhildondesktop/Makefile.am	2007-04-20 15:08:48 UTC (rev 11187)
@@ -13,6 +13,7 @@
 	hildon-desktop-plugin.h       \
 	hildon-desktop-panel-window.h \
 	hildon-desktop-panel-window-dialog.h \
+	hildon-desktop-popup-window.h \
 	hildon-desktop-panel.h        \
 	hildon-desktop-multiscreen.h  \
 	hildon-desktop-panel-expandable.h \
@@ -89,6 +90,8 @@
 	hildon-desktop-panel-window.c        \
 	hildon-desktop-panel-window-dialog.h \
         hildon-desktop-panel-window-dialog.c \
+	hildon-desktop-popup-window.h	     \
+	hildon-desktop-popup-window.c	     \
 	hildon-desktop-panel-expandable.h    \
 	hildon-desktop-panel-expandable.c    \
 	hildon-desktop-multiscreen.h         \

Modified: projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-popup-window.c
===================================================================
--- projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-popup-window.c	2007-04-20 14:46:29 UTC (rev 11186)
+++ projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-popup-window.c	2007-04-20 15:08:48 UTC (rev 11187)
@@ -25,6 +25,10 @@
 
 #include "hildon-desktop-popup-window.h" 
 
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkwindow.h>
+
 #define HILDON_DESKTOP_POPUP_WINDOW_GET_PRIVATE(object) \
         (G_TYPE_INSTANCE_GET_PRIVATE ((object), HILDON_DESKTOP_TYPE_POPUP_WINDOW, HildonDesktopPopupWindowPrivate))
 
@@ -39,7 +43,7 @@
 
 enum
 {
-  POPUP_N_SIGNALS;
+  POPUP_N_SIGNALS
 };
 
 static GObject *hildon_desktop_popup_window_constructor (GType gtype, 
@@ -63,35 +67,50 @@
 static void hildon_desktop_popup_window_show_all (GtkWidget *widget);
 static void hildon_desktop_popup_window_hide_all (GtkWidget *widget);
 
-static gboolean hildon_desktop_popup_window_focus (GtkWidget *widget);
+static gboolean hildon_desktop_popup_window_enter_notify (GtkWidget *widget, GdkEventCrossing *event);
+static gboolean hildon_desktop_popup_window_leave_notify (GtkWidget *widget, GdkEventCrossing *event);
 
 static gboolean hildon_desktop_popup_window_visibility_notify (GtkWidget          *widget,
 				                               GdkEventVisibility *event,
 			        		               gpointer            data);
 
-struct _HildonDesktopPopupWindow 
+static gboolean hildon_desktop_popup_window_composited_leave_notify (GtkWidget *widget,
+						     		     GdkEventCrossing *event,
+						     		     HildonDesktopPopupWindow *popup);
+
+static gboolean
+hildon_desktop_popup_window_button_release_event (GtkWidget *widget, GdkEventButton *event);
+
+struct _HildonDesktopPopupWindowPrivate 
 {
   GtkWidget	   	          **extra_panes;
   guint				    n_extra_panes;
   GtkOrientation 		    orientation;
   HildonDesktopPopupWindowDirection direction;
-}
 
+  HDPopupWindowPositionFunc	    position_func;
+  gpointer			    position_func_data;
+
+  gboolean 			    have_xgrab;
+
+  GtkWidget			   *attached_widget;
+};
+
 static void 
-hildon_desktop_popup_window_init (GObject *object)
+hildon_desktop_popup_window_init (HildonDesktopPopupWindow *popup)
 {
-  HildonDesktopPopupWindow *popup = HILDON_DESKTOP_POPUP_WINDOW (object);
+  popup->priv = HILDON_DESKTOP_POPUP_WINDOW_GET_PRIVATE (popup);
 
-  popup->priv = HILDON_DESKTOP_POPUP_WINDOW_GET_PRIVATE (object);
-
   popup->priv->extra_panes   = NULL;
   popup->priv->n_extra_panes = 0;
 
+  popup->priv->have_xgrab = FALSE;
 
+  popup->priv->attached_widget = NULL;
 }
 
 static void 
-hildon_desktop_popup_window_class_init (HildonDesktopPopupWindow *popup_class)
+hildon_desktop_popup_window_class_init (HildonDesktopPopupWindowClass *popup_class)
 {
   GObjectClass *object_class   = G_OBJECT_CLASS (popup_class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (popup_class);
@@ -102,17 +121,17 @@
 
   widget_class->enter_notify_event      = hildon_desktop_popup_window_enter_notify;
   widget_class->leave_notify_event      = hildon_desktop_popup_window_leave_notify;
+  widget_class->button_release_event    = hildon_desktop_popup_window_button_release_event;
 
-  widget_class->focus = hildon_desktop_popup_window_focus;
 	  
   widget_class->realize    = hildon_desktop_popup_window_realize;
   widget_class->unrealize  = hildon_desktop_popup_window_unrealize;
-  widget_class->show       = hildon_desktop_popup_show;
-  widget_class->hide       = hildon_desktop_popup_hide;
-  widget_class->show_all   = hildon_desktop_popup_show_all;
-  widget_class->hide_all   = hildon_desktop_popup_hide_all;
+  widget_class->show       = hildon_desktop_popup_window_show;
+  widget_class->hide       = hildon_desktop_popup_window_hide;
+  widget_class->show_all   = hildon_desktop_popup_window_show_all;
+  widget_class->hide_all   = hildon_desktop_popup_window_hide_all;
   
-  g_type_class_add_private (g_object_class, sizeof (HildonDesktopPopupWindowPrivate));
+  g_type_class_add_private (object_class, sizeof (HildonDesktopPopupWindowPrivate));
 
   g_object_class_install_property (object_class,
                                    PROP_POPUP_N_PANES,
@@ -165,25 +184,23 @@
 
   GTK_WINDOW (popup)->type = GTK_WINDOW_POPUP;
 
-  gtk_window_set_type_hint (GTK_WINDOW (popup), GDK_WINDOW_TYPE_HINT_POPUP);
+  gtk_window_set_type_hint (GTK_WINDOW (popup), GDK_WINDOW_TYPE_HINT_MENU);
 
   g_signal_connect (popup,
-		    "visibility_notify_envent",
+		    "visibility-notify-event",
 		    G_CALLBACK (hildon_desktop_popup_window_visibility_notify),
 		    NULL);
 
   gtk_widget_push_composite_child ();
 
-  popup->priv->extra_panes = g_new0 (GtkWindow *, popup->priv->n_extra_panes);
+  popup->priv->extra_panes = g_new0 (GtkWidget *, popup->priv->n_extra_panes);
 
   for (i=0; i < popup->priv->n_extra_panes; i++)
   {	  
     popup->priv->extra_panes[i] = gtk_window_new (GTK_WINDOW_POPUP);
 
-    g_signal_connect (popup->priv->extra_panes[i],
-		      "enter-notify-event",
-		      G_CALLBACK (hildon_desktop_popup_window_composited_enter_notify),
-		      (gpointer)popup);
+    gtk_window_set_type_hint (GTK_WINDOW (popup->priv->extra_panes[i]),
+		    	      GDK_WINDOW_TYPE_HINT_MENU);
 
     g_signal_connect (popup->priv->extra_panes[i],
 		      "leave-notify-event",
@@ -272,24 +289,19 @@
     gtk_widget_hide_all (popup->priv->extra_panes[i]);
 }
 
-static gboolean 
-hildon_desktop_popup_window_focus (GtkWidget *widget)
-{
-  /* What focus? */
-  return FALSE;
-}
-
 static gboolean
 hildon_desktop_popup_window_enter_notify (GtkWidget        *widget,
 		                          GdkEventCrossing *event)
 {
   HildonDesktopPopupWindow *popup = HILDON_DESKTOP_POPUP_WINDOW (widget);
 
+  g_debug ("%s enter_notify %p",__FILE__,popup);
   /* We have to grab the pointer in here, we should get this when we come from
    * a composited window
    */ 
   
-  return TRUE;	
+  return 
+    GTK_WIDGET_CLASS (hildon_desktop_popup_window_parent_class)->enter_notify_event (widget, event);	
 }
 
 static gboolean 
@@ -301,21 +313,13 @@
  /* We have to ungrab the pointer in here, we should get this when we go to
   * a composited window
   */
+  g_debug ("%s leave_notify %p",__FILE__,popup);
   
-  return TRUE;	
+  return 
+    GTK_WIDGET_CLASS (hildon_desktop_popup_window_parent_class)->leave_notify_event (widget, event);	
 }
 
 static gboolean 
-hildon_desktop_popup_window_composited_enter_notify (GtkWidget *widget,
-						     GdkEventCrossing *event,
-						     HildonDesktopPopupWindow *popup)
-{
-
-
-  return TRUE;
-}
-
-static gboolean 
 hildon_desktop_popup_window_composited_leave_notify (GtkWidget *widget,
 						     GdkEventCrossing *event,
 						     HildonDesktopPopupWindow *popup)
@@ -332,15 +336,159 @@
 {
   HildonDesktopPopupWindow *popup = HILDON_DESKTOP_POPUP_WINDOW (widget);
 
+  g_debug ("%s visibility_notify %p",__FILE__,popup);
   /* We have to close every window when called this but also we have to 
    * track if our composited windows are not the responsibles for the 
    * visibility-notify
    */
+  GdkScreen *screen;
+  GList *stack;
+  gboolean deactivate;
+
+  if (event->state == GDK_VISIBILITY_UNOBSCURED)
+    return FALSE;
+
+  screen = gtk_widget_get_screen (widget);
+
+  deactivate = FALSE;
+
+  /* Inspect windows above us */
+  stack = gdk_screen_get_window_stack (screen);
   
-  return TRUE;	
+  if (stack != NULL)
+  {
+     GList *iter;
+
+     iter = g_list_last (stack);
+
+     while (iter)
+     { 
+       GdkWindow *win = iter->data;
+       GdkWindowTypeHint type;
+
+       if (win == widget->window)
+         break;
+
+       gdk_error_trap_push ();
+
+       type = gdk_window_get_type_hint (win);
+ 
+      if (!gdk_error_trap_pop () && 
+ 	  /*type != GDK_WINDOW_TYPE_HINT_MESSAGE && */
+          type != GDK_WINDOW_TYPE_HINT_MENU)
+      {
+        /* A non-message and non-menu window above us; close. */
+        deactivate = TRUE;
+        break;
+      }
+
+      iter = iter->prev;
+    }
+
+    g_list_foreach (stack, (GFunc) g_object_unref, NULL);
+    g_list_free (stack);
+  }
+
+  if (deactivate)
+  {
+    hildon_desktop_popup_window_popdown (popup);
+    return TRUE;
+  }
+
+  return FALSE;
 }
 
+static gboolean
+hildon_desktop_popup_window_button_release_event (GtkWidget *widget,
+                                                  GdkEventButton *event)
+{
+  HildonDesktopPopupWindow *popup = HILDON_DESKTOP_POPUP_WINDOW (widget);  	
+  gboolean in_panes_area  = FALSE,
+           in_window_area = FALSE;
+  gint x,y,w,h,i;
+
+  if (!event)
+    return FALSE;
+
+  gtk_widget_get_pointer (widget, &x, &y);
+
+  w = widget->allocation.width;
+  h = widget->allocation.height;
+
+  /* Pointer on window popup area */
+  if ((x >= 0) && (x <= w) && (y >= 0) && (y <= h))
+    in_window_area = TRUE;
+  else
+  {
+     for (i=0; i < popup->priv->n_extra_panes; i++)
+     {	     
+       w = popup->priv->extra_panes[i]->allocation.width;
+       h = popup->priv->extra_panes[i]->allocation.height;
+
+       gtk_widget_get_pointer (popup->priv->extra_panes[i], &x, &y);
+
+       /* Pointer on button area  */
+       if ((x >= 0) && (x <= w) && (y >= 0) && (y <= h))
+         in_panes_area = TRUE;
+
+       break;
+     }
+  }
+
+  /* Event outside of popup or in button area, close in clean way */
+  if (!in_panes_area || in_window_area)
+    hildon_desktop_popup_window_popdown (popup);
+
+  return TRUE;
+}
+
 static void 
+hildon_desktop_popup_window_calculate_position (HildonDesktopPopupWindow *popup)
+{
+  gint x=0,y=0,i;
+  GtkRequisition req;
+
+  gtk_widget_size_request (GTK_WIDGET (popup), &req);
+
+  if (popup->priv->position_func)
+  {
+    (* popup->priv->position_func) (popup, &x, &y, popup->priv->position_func_data);
+  }	  
+
+  gtk_window_move (GTK_WINDOW (popup), x, y);
+
+  if (popup->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+  {
+    if (popup->priv->direction == HD_POPUP_WINDOW_DIRECTION_RIGHT_BOTTOM)
+      for (i=0; i < popup->priv->n_extra_panes; i++)
+        gtk_window_move (GTK_WINDOW (popup->priv->extra_panes[i]),
+			 req.width*(i+1) + x,
+			 y);
+    else
+    if (popup->priv->direction == HD_POPUP_WINDOW_DIRECTION_LEFT_TOP)	    
+      for (i=0; i < popup->priv->n_extra_panes; i++)
+        gtk_window_move (GTK_WINDOW (popup->priv->extra_panes[i]),
+                         req.width*(i+1) - x,
+                         y);
+  }	  
+  else
+  if (popup->priv->orientation == GTK_ORIENTATION_VERTICAL)
+  {
+    if (popup->priv->direction == HD_POPUP_WINDOW_DIRECTION_RIGHT_BOTTOM)
+      for (i=0; i < popup->priv->n_extra_panes; i++)
+        gtk_window_move (GTK_WINDOW (popup->priv->extra_panes[i]),
+			 x,
+			 req.height*(i+1) + y);
+    else
+    if (popup->priv->direction == HD_POPUP_WINDOW_DIRECTION_LEFT_TOP)	    
+      for (i=0; i < popup->priv->n_extra_panes; i++)
+        gtk_window_move (GTK_WINDOW (popup->priv->extra_panes[i]),
+                         x,
+                         req.height*(i+1) - y);
+  } 
+}	
+
+static void 
 hildon_desktop_popup_window_get_property (GObject *object, 
                                           guint prop_id, 
                                           GValue *value, 
@@ -397,10 +545,69 @@
   }
 }
 
+static GdkWindow *
+popup_window_grab_transfer_window_get (HildonDesktopPopupWindow *popup)
+{
+  GdkWindow *window = 
+    g_object_get_data (G_OBJECT (popup),
+		       "popup-window-transfer-window");
+
+  if (!window)
+  {
+    GdkWindowAttr attributes;
+    gint attributes_mask;
+
+    attributes.x = -100;
+    attributes.y = -100;
+    attributes.width = 10;
+    attributes.height = 10;
+    attributes.window_type = GDK_WINDOW_TEMP;
+    attributes.wclass = GDK_INPUT_ONLY;
+    attributes.override_redirect = TRUE;
+    attributes.event_mask = 0;
+
+    attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
+
+    window = gdk_window_new (gtk_widget_get_root_window (GTK_WIDGET (popup)),
+                             &attributes, attributes_mask);
+    gdk_window_set_user_data (window, popup);
+
+    gdk_window_show (window);
+
+    g_object_set_data (G_OBJECT (popup), "popup-window-transfer-window", window);
+  }
+
+  return window;
+}
+
+static gboolean
+popup_grab_on_window (GdkWindow *window,
+                      guint32    activate_time,
+                      gboolean   grab_keyboard)
+{
+  if ((gdk_pointer_grab (window, TRUE,
+                         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+                         GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
+                         GDK_POINTER_MOTION_MASK,
+                         NULL, NULL, activate_time) == 0))
+  {
+    if (!grab_keyboard || gdk_keyboard_grab (window, TRUE, activate_time) == 0)
+      return TRUE;
+    else
+    {
+      gdk_display_pointer_ungrab 
+        (gdk_drawable_get_display (window), activate_time);
+      return FALSE;
+    }
+  }
+
+  return FALSE;
+}
+
 GtkWidget *
-hildon_desktop_popup_window (guint n_panes,
-			     GtkOrientation orientation,
-			     HildonDesktopPopupWindowDirection direction)
+hildon_desktop_popup_window_new (guint n_panes,
+			         GtkOrientation orientation,
+			         HildonDesktopPopupWindowDirection direction)
 {
   return GTK_WIDGET (g_object_new (HILDON_DESKTOP_TYPE_POPUP_WINDOW,
 			  	   "n-panes",n_panes,
@@ -425,8 +632,53 @@
 
 void 
 hildon_desktop_popup_window_popup (HildonDesktopPopupWindow *popup,
-				   GtkMenuPositionFunc func)
+				   HDPopupWindowPositionFunc func,
+				   gpointer		     func_data,
+				   guint32 		     activate_time)
 {
+  GdkWindow *transfer_window;
+  GtkWidget *parent_toplevel;
+	
+  g_assert (HILDON_DESKTOP_IS_POPUP_WINDOW (popup));
+	
+  popup->priv->position_func      = func;
+  popup->priv->position_func_data = func_data;
 
+  transfer_window = popup_window_grab_transfer_window_get (popup);
 
+  if (popup_grab_on_window (transfer_window, activate_time, TRUE))
+    popup->priv->have_xgrab = TRUE;
+
+  if (popup->priv->attached_widget)
+  {
+    parent_toplevel = gtk_widget_get_toplevel (popup->priv->attached_widget);
+
+    if (parent_toplevel && GTK_IS_WINDOW (parent_toplevel))
+    {
+      register gint i;
+      gtk_window_set_transient_for (GTK_WINDOW (popup),
+                                    GTK_WINDOW (parent_toplevel));
+ 
+      for (i=0; i < popup->priv->n_extra_panes; i++)
+        gtk_window_set_transient_for (GTK_WINDOW (popup->priv->extra_panes[i]),
+				      GTK_WINDOW (parent_toplevel));
+    }
+  }
+
+  hildon_desktop_popup_window_calculate_position (popup);
+
+  gtk_widget_show (GTK_WIDGET (popup));
+
+  popup_grab_on_window (GTK_WIDGET (popup)->window, activate_time, TRUE); /* Should always succeed */
+
+  gtk_grab_add (GTK_WIDGET (popup));
 }
+
+void 
+hildon_desktop_popup_window_popdown (HildonDesktopPopupWindow *popup)
+{
+  gtk_widget_hide (GTK_WIDGET (popup));
+
+  gtk_grab_remove (GTK_WIDGET (popup));
+}
+

Modified: projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-popup-window.h
===================================================================
--- projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-popup-window.h	2007-04-20 14:46:29 UTC (rev 11186)
+++ projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-popup-window.h	2007-04-20 15:08:48 UTC (rev 11187)
@@ -27,15 +27,19 @@
 #define __HILDON_DESKTOP_POPUP_WINDOW_H__
 
 #include <gtk/gtkwindow.h>
+#include <gdk/gdk.h>
 
-#include <gtk/gtkmenu.h> /*Only for GtkMenuPositionFunc*/
-
 G_BEGIN_DECLS
 
 typedef struct _HildonDesktopPopupWindow HildonDesktopPopupWindow;
 typedef struct _HildonDesktopPopupWindowClass HildonDesktopPopupWindowClass;
 typedef struct _HildonDesktopPopupWindowPrivate HildonDesktopPopupWindowPrivate;
 
+typedef void (*HDPopupWindowPositionFunc) (HildonDesktopPopupWindow   *window,
+                            	           gint      		      *x,
+                                           gint      		      *y,
+                                           gpointer   		      user_data);
+
 typedef enum 
 {
   HD_POPUP_WINDOW_DIRECTION_LEFT_TOP,
@@ -58,24 +62,29 @@
 
 struct _HildonDesktopPopupWindowClass
 {
+  GtkWindowClass		parent_class;
   /* */	
-}
+};
 
 GType 
 hildon_desktop_popup_window_get_type (void);
 
 GtkWidget *
-hildon_desktop_popup_window (guint n_panes,
-			     GtkOrientation orientation,
-			     HildonDesktopPopupWindowDirection direction);
+hildon_desktop_popup_window_new (guint n_panes,
+			         GtkOrientation orientation,
+			         HildonDesktopPopupWindowDirection direction);
 
 GtkWidget *
 hildon_desktop_popup_window_get_pane (HildonDesktopPopupWindow *popup, gint pane);
 
 void 
 hildon_desktop_popup_window_popup (HildonDesktopPopupWindow *popup,
-				   GtkMenuPositionFunc func);
+				   HDPopupWindowPositionFunc func,
+				   gpointer                  func_data,
+				   guint32 		     activate_time);
 
+void 
+hildon_desktop_popup_window_popdown (HildonDesktopPopupWindow *popup);
 
 G_BEGIN_DECLS
 


More information about the maemo-commits mailing list