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

From: subversion at stage.maemo.org subversion at stage.maemo.org
Date: Fri Aug 3 18:13:03 EEST 2007
Author: jobi
Date: 2007-08-03 18:13:00 +0300 (Fri, 03 Aug 2007)
New Revision: 13012

Modified:
   projects/haf/trunk/hildon-desktop/ChangeLog
   projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-home-item.c
   projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-home-item.h
   projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-home-area.c
Log:

2007-08-03  Johan Bilien  <johan.bilien at nokia.com>

	* libhildondesktop/hildon-desktop-home-item.[ch]:
	- added _lower / _raise
	- create an event box on top of the applet. Catch all clicks,
	and propagate them if they are later found not to be drags
	- handle context-sensitive menu
	Fixes: NB#61309



Modified: projects/haf/trunk/hildon-desktop/ChangeLog
===================================================================
--- projects/haf/trunk/hildon-desktop/ChangeLog	2007-08-03 11:54:30 UTC (rev 13011)
+++ projects/haf/trunk/hildon-desktop/ChangeLog	2007-08-03 15:13:00 UTC (rev 13012)
@@ -1,3 +1,12 @@
+2007-08-03  Johan Bilien  <johan.bilien at nokia.com>
+
+	* libhildondesktop/hildon-desktop-home-item.[ch]:
+	- added _lower / _raise
+	- create an event box on top of the applet. Catch all clicks,
+	and propagate them if they are later found not to be drags
+	- handle context-sensitive menu
+	Fixes: NB#61309
+
 2007-08-03  Lucas Rocha  <lucas.rocha at nokia.com>
 
 	* libhildondesktop/hildon-desktop-popup-menu.c: activate menu item on

Modified: projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-home-item.c
===================================================================
--- projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-home-item.c	2007-08-03 11:54:30 UTC (rev 13011)
+++ projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-home-item.c	2007-08-03 15:13:00 UTC (rev 13012)
@@ -30,6 +30,8 @@
 #include "hildon-home-area.h"
 #include "hildon-desktop-marshalers.h"
 
+#include <glib/gi18n.h>
+
 #include <gtk/gtkicontheme.h>
 
 #include <X11/extensions/Xrender.h>
@@ -58,6 +60,9 @@
 
 #define LAYOUT_MODE_HIGHLIGHT_WIDTH 4
 
+#define HH_CLOSE                  (dgettext("hildon-home-image-viewer", "ws_me_close"))
+#define HH_SETTINGS               (dgettext("hildon-home-image-viewer", "ws_me_settings"))
+
 #define HILDON_DESKTOP_HOME_ITEM_GET_PRIVATE(obj) \
   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_DESKTOP_TYPE_HOME_ITEM, HildonDesktopHomeItemPriv));
 
@@ -85,6 +90,8 @@
   gboolean      layout_mode;
   HildonDesktopHomeItemResizeType resize_type;
 
+  GtkWidget    *menu;
+
   GdkPixbuf    *close_button;
   GdkWindow    *close_button_window;
   GdkPixbuf    *resize_handle;
@@ -215,7 +222,6 @@
                                     HildonDesktopHomeItemState   state,
                                     GdkEventButton              *button);
 
-
 GType
 hildon_desktop_home_item_resize_type_get_type (void)
 {
@@ -464,6 +470,8 @@
       error = NULL;
     }
 
+
+
 }
 
 static void
@@ -471,6 +479,7 @@
 {
   HildonDesktopHomeItemPriv    *priv;
   HildonDesktopHomeItemClass   *klass;
+  GtkWidget                    *menu_item;
 
   klass = G_TYPE_INSTANCE_GET_CLASS ((self),
                                      HILDON_DESKTOP_TYPE_HOME_ITEM,
@@ -486,8 +495,19 @@
       priv->close_button = klass->close_button;
     }
 
-  gtk_widget_add_events (GTK_WIDGET (self), GDK_VISIBILITY_NOTIFY_MASK);
+  priv->menu = gtk_menu_new ();
+  menu_item = gtk_menu_item_new_with_label (HH_CLOSE);
+  g_signal_connect_swapped (menu_item, "activate",
+                            G_CALLBACK (gtk_widget_destroy),
+                            self);
+  gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menu_item);
+  gtk_widget_show (menu_item);
 
+  gtk_widget_tap_and_hold_setup (GTK_WIDGET (self),
+                                 priv->menu,
+                                 NULL,
+                                 0);
+
 }
 
 static void
@@ -643,7 +663,8 @@
           | GDK_BUTTON_RELEASE_MASK
           | GDK_EXPOSURE_MASK
           | GDK_ENTER_NOTIFY_MASK
-          | GDK_LEAVE_NOTIFY_MASK;
+          | GDK_LEAVE_NOTIFY_MASK
+          | GDK_SUBSTRUCTURE_MASK;
 
       attributes.wclass = GDK_INPUT_OUTPUT;
       attributes.colormap = gtk_widget_get_colormap (widget);
@@ -657,6 +678,14 @@
 
       gdk_window_set_user_data (widget->window, widget);
 
+      attributes.wclass = GDK_INPUT_ONLY;
+      attributes_mask = GDK_WA_X | GDK_WA_Y;
+
+      priv->event_window = gdk_window_new (parent_window,
+                                           &attributes,
+                                           attributes_mask);
+      gdk_window_set_user_data (priv->event_window, widget);
+
       if (priv->layout_mode_sucks)
         {
           if (priv->resize_handle)
@@ -700,12 +729,11 @@
                priv->resize_handle_height
               );
 
-          gdk_window_set_events (widget->window,
-                                 gdk_window_get_events(widget->window) |
-                                 GDK_SUBSTRUCTURE_MASK);
+#if 0
           gdk_window_add_filter (widget->window,
                                  (GdkFilterFunc)window_event_filter,
                                  widget);
+#endif
         }
 
     }
@@ -781,9 +809,24 @@
 hildon_desktop_home_item_tap_and_hold (GtkWidget *widget)
 {
   HildonDesktopHomeItemPriv    *priv;
+  static GtkWidget             *menu_item = NULL;
 
   priv = HILDON_DESKTOP_HOME_ITEM_GET_PRIVATE (widget);
 
+  if (!menu_item)
+  {
+    menu_item = hildon_desktop_home_item_get_settings_menu_item (HILDON_DESKTOP_HOME_ITEM (widget));
+
+    if (GTK_IS_MENU_ITEM (menu_item))
+    {
+      gtk_label_set_text (GTK_LABEL (GTK_BIN (menu_item)->child),
+                          HH_SETTINGS);
+      gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->menu), menu_item);
+      gtk_widget_show (menu_item);
+    }
+  }
+
+
   /* If we were in moving or resizing, we should stop */
   if (priv->state != HILDON_DESKTOP_HOME_ITEM_STATE_NORMAL)
     {
@@ -897,7 +940,7 @@
                                         GtkAllocation *allocation)
 {
   HildonDesktopHomeItemPriv      *priv;
-  priv = HILDON_DESKTOP_HOME_ITEM_GET_PRIVATE (HILDON_DESKTOP_HOME_ITEM(widget));
+  priv = HILDON_DESKTOP_HOME_ITEM_GET_PRIVATE (widget);
 
   widget->allocation = *allocation;
 
@@ -919,11 +962,13 @@
                                 allocation->height);
 
       if (GDK_IS_WINDOW (priv->event_window))
+      {
         gdk_window_move_resize (priv->event_window,
-                                0,
-                                0,
+                                allocation->x,
+                                allocation->y,
                                 allocation->width,
                                 allocation->height);
+      }
 
     }
 
@@ -962,7 +1007,7 @@
                                              gint width,
                                              gint height)
 {
-  HildonDesktopHomeItemPriv      *priv;
+  HildonDesktopHomeItemPriv *priv;
   GdkWindowAttr              attributes;
   gint                       attributes_mask;
   GdkWindow                 *window;
@@ -980,7 +1025,7 @@
   attributes.wclass = icon?GDK_INPUT_OUTPUT:GDK_INPUT_ONLY;
   attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
 
-  window = gdk_window_new (w->window,
+  window = gdk_window_new (priv->event_window,
                            &attributes,
                            attributes_mask);
 
@@ -1037,7 +1082,8 @@
 
   if (aevent->type == MapNotify)
     {
-      HildonDesktopHomeItemPriv *priv = HILDON_DESKTOP_HOME_ITEM_GET_PRIVATE (applet);
+      HildonDesktopHomeItemPriv *priv =
+          HILDON_DESKTOP_HOME_ITEM_GET_PRIVATE (applet);
       /* The applet created a child window, we need to make sure that
        * we remain on top */
       if (GDK_IS_WINDOW (priv->event_window))
@@ -1434,6 +1480,168 @@
     }
 }
 
+static GList *
+get_ordered_children (GdkWindow *window)
+{
+  Window      *children, root, parent;
+  guint        i, n_children = 0;
+  GList        *ret = NULL;
+
+  gdk_error_trap_push ();
+  XQueryTree (GDK_DISPLAY (),
+              GDK_WINDOW_XID (window),
+              &root,
+              &parent,
+              &children,
+              &n_children);
+
+  if (gdk_error_trap_pop ())
+    return NULL;
+
+  for (i = 0; i < n_children; i++)
+  {
+    GdkWindow *window = gdk_window_lookup (children[i]);
+    if (window)
+      ret = g_list_append (ret, window);
+  }
+
+  XFree (children);
+  return ret;
+}
+
+/* Borrowed from libmokoui */
+static GdkWindow *
+hildon_desktop_home_item_get_window_at (HildonDesktopHomeItem *item,
+                                        gint x, gint y,
+                                        gint *tx, gint *ty)
+{
+  /* Find the GdkWindow at the given point, by recursing from a given
+   * parent GdkWindow. Optionally return the co-ordinates transformed
+   * relative to the child window.
+   */
+  gint width, height;
+  GdkWindow    *window;
+
+  if (!GTK_WIDGET_REALIZED (item))
+    return NULL;
+
+  window = GTK_WIDGET (item)->window;
+
+  gdk_drawable_get_size (window, &width, &height);
+
+  if ((x < 0) || (x >= width) || (y < 0) || (y >= height))
+    return NULL;
+
+  /*g_debug ("Finding window at (%d, %d) in %p", x, y, window);*/
+
+  while (window)
+  {
+    gint        child_x = 0, child_y = 0;
+    GList      *c, *children = get_ordered_children (window);
+    GdkWindow  *old_window = window;
+
+    for (c = children; c; c = c->next)
+    {
+      GdkWindow *child = c->data;
+      gint wx, wy;
+
+      gdk_window_get_geometry (child,
+                               &wx, &wy,
+                               &width, &height,
+                               NULL);
+      /*g_debug ("Child: %p, (%dx%d+%d,%d) click: %d,%d", child,
+        width, height, wx, wy, x, y);*/
+
+      if ((x >= wx) && (x < (wx + width)) &&
+          (y >= wy) && (y < (wy + height)))
+      {
+        child_x = x - wx;
+        child_y = y - wy;
+        window = child;
+      }
+    }
+
+    g_list_free (children);
+    /*g_debug ("\\|/");*/
+    if (window == old_window)
+    {
+      break;
+    }
+
+    x = child_x;
+    y = child_y;
+  }
+
+  if (tx) *tx = x;
+  if (ty) *ty = y;
+
+  /*g_debug ("Returning: %p", window);*/
+
+  return window;
+}
+
+static void
+hildon_desktop_home_item_propagate_button (HildonDesktopHomeItem *item)
+{
+  HildonDesktopHomeItemPriv    *priv =
+      HILDON_DESKTOP_HOME_ITEM_GET_PRIVATE (item);
+  gint                  x, y;
+  GdkEventCrossing     *crossing_event;
+  GdkEventButton       *event;
+  GdkWindow            *child;
+
+  gdk_window_raise (GTK_WIDGET (item)->window);
+  gdk_window_raise (priv->event_window);
+
+  child = hildon_desktop_home_item_get_window_at (item,
+                                                  priv->last_click_event->x,
+                                                  priv->last_click_event->y,
+                                                  &x, &y);
+
+  if (!child)
+    return;
+
+  event = priv->last_click_event;
+
+  event->x = x;
+  event->y = y;
+
+  /* Send synthetic enter event */
+  crossing_event = (GdkEventCrossing *) gdk_event_new (GDK_ENTER_NOTIFY);
+  ((GdkEventAny *)crossing_event)->type = GDK_ENTER_NOTIFY;
+  ((GdkEventAny *)crossing_event)->window = g_object_ref (child);
+  ((GdkEventAny *)crossing_event)->send_event = FALSE;
+  crossing_event->subwindow = g_object_ref (child);
+  crossing_event->time = event->time;
+  crossing_event->x = event->x;
+  crossing_event->y = event->y;
+  crossing_event->x_root = event->x_root;
+  crossing_event->y_root = event->y_root;
+  crossing_event->mode = GDK_CROSSING_NORMAL;
+  crossing_event->detail = GDK_NOTIFY_UNKNOWN;
+  crossing_event->focus = FALSE;
+  crossing_event->state = 0;
+  gdk_event_put ((GdkEvent *)crossing_event);
+
+  /* Send synthetic click (button press/release) event */
+  ((GdkEventAny *)event)->window = g_object_ref (child);
+  ((GdkEventAny *)event)->type = GDK_BUTTON_PRESS;
+  gdk_event_put ((GdkEvent *)event);
+  ((GdkEventAny *)event)->window = g_object_ref (child);
+  ((GdkEventAny *)event)->type = GDK_BUTTON_RELEASE;
+  gdk_event_put ((GdkEvent *)event);
+
+  /* Send synthetic leave event */
+  ((GdkEventAny *)crossing_event)->type = GDK_LEAVE_NOTIFY;
+  ((GdkEventAny *)crossing_event)->window = g_object_ref (child);
+  crossing_event->subwindow = g_object_ref (child);
+  crossing_event->window = g_object_ref (child);
+  crossing_event->detail = GDK_NOTIFY_UNKNOWN;
+  gdk_event_put ((GdkEvent *)crossing_event);
+  gdk_event_free ((GdkEvent *)crossing_event);
+
+}
+
 static gboolean
 hildon_desktop_home_item_click_timeout (HildonDesktopHomeItem *item)
 {
@@ -1454,6 +1662,10 @@
 
   priv = HILDON_DESKTOP_HOME_ITEM_GET_PRIVATE (HILDON_DESKTOP_HOME_ITEM (w));
 
+  if (event->window != priv->event_window &&
+      event->window != priv->resize_handle_window)
+    return FALSE;
+
   if (!priv->layout_mode_sucks && !priv->layout_mode)
     {
       if (GTK_WIDGET_CLASS (parent_class)->button_press_event)
@@ -1462,6 +1674,7 @@
         return FALSE;
     }
 
+
   /* Check if we clicked the close button */
   if (event->window == priv->close_button_window)
     {
@@ -1506,14 +1719,26 @@
   HildonDesktopHomeItemPriv      *priv;
 
   priv = HILDON_DESKTOP_HOME_ITEM_GET_PRIVATE (widget);
+  hildon_desktop_home_item_raise (HILDON_DESKTOP_HOME_ITEM (widget));
 
+  if (event->window != priv->event_window &&
+      event->window != priv->resize_handle_window)
+    return FALSE;
+
   if (priv->click_timeout)
     {
       g_source_remove (priv->click_timeout);
       priv->click_timeout = 0;
+      hildon_desktop_home_item_propagate_button (HILDON_DESKTOP_HOME_ITEM (widget));
       return FALSE;
     }
 
+  if (priv->last_click_event)
+  {
+    gdk_event_free ((GdkEvent *)priv->last_click_event);
+    priv->last_click_event = NULL;
+  }
+
   if (!priv->layout_mode_sucks && !priv->layout_mode)
     {
       if  (GTK_WIDGET_CLASS (parent_class)->button_release_event)
@@ -1622,7 +1847,6 @@
 
           if (event)
             {
-              gdk_window_raise (widget->window);
               gdk_pointer_grab (event->window,
                                 FALSE,
                                 GDK_BUTTON_PRESS_MASK |
@@ -1652,6 +1876,7 @@
           if (event)
             {
               gdk_window_raise (widget->window);
+              gdk_window_raise (priv->event_window);
               gdk_pointer_grab (event->window,
                                 FALSE,
                                 GDK_BUTTON_PRESS_MASK |
@@ -1802,16 +2027,20 @@
 GtkWidget *
 hildon_desktop_home_item_get_settings_menu_item (HildonDesktopHomeItem *applet)
 {
-  HildonDesktopHomeItemPriv      *priv;
-  GtkWindow                 *window;
-  GtkWidget                 *item = NULL;
-  g_return_val_if_fail (applet, NULL);
+  HildonDesktopHomeItemPriv    *priv;
+  GtkWidget                    *top_level;
+  GtkWidget                    *item = NULL;
 
+  g_return_val_if_fail (HILDON_DESKTOP_IS_HOME_ITEM (applet), NULL);
+
   priv = HILDON_DESKTOP_HOME_ITEM_GET_PRIVATE (applet);
 
-  window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (applet)));
+  top_level = gtk_widget_get_toplevel (GTK_WIDGET (applet));
 
-  g_signal_emit_by_name (applet, "settings", window, &item);
+  g_signal_emit_by_name (applet,
+                         "settings",
+                         GTK_IS_WINDOW (top_level)?top_level:NULL,
+                         &item);
 
   return item;
 }
@@ -1841,3 +2070,37 @@
   else
     g_signal_emit_by_name (applet, "foreground");
 }
+
+void
+hildon_desktop_home_item_raise (HildonDesktopHomeItem *item)
+{
+  HildonDesktopHomeItemPriv *priv;
+  g_return_if_fail (HILDON_DESKTOP_IS_HOME_ITEM (item));
+
+  if (!GTK_WIDGET_REALIZED (item))
+    return;
+
+  priv = HILDON_DESKTOP_HOME_ITEM_GET_PRIVATE (item);
+
+  gdk_window_raise (GTK_WIDGET (item)->window);
+  gdk_window_raise (priv->event_window);
+  gtk_widget_queue_draw (GTK_WIDGET (item));
+
+}
+
+void
+hildon_desktop_home_item_lower (HildonDesktopHomeItem *item)
+{
+  HildonDesktopHomeItemPriv *priv;
+  g_return_if_fail (HILDON_DESKTOP_IS_HOME_ITEM (item));
+
+  if (!GTK_WIDGET_REALIZED (item))
+    return;
+
+  priv = HILDON_DESKTOP_HOME_ITEM_GET_PRIVATE (item);
+
+  gdk_window_lower (priv->event_window);
+  gdk_window_lower (GTK_WIDGET (item)->window);
+  gtk_widget_queue_draw (GTK_WIDGET (item));
+
+}

Modified: projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-home-item.h
===================================================================
--- projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-home-item.h	2007-08-03 11:54:30 UTC (rev 13011)
+++ projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-desktop-home-item.h	2007-08-03 15:13:00 UTC (rev 13012)
@@ -132,7 +132,8 @@
 void        hildon_desktop_home_item_set_is_background
                                                 (HildonDesktopHomeItem *applet,
                                                  gboolean is_background);
-        
+void        hildon_desktop_home_item_raise      (HildonDesktopHomeItem *item);
+void        hildon_desktop_home_item_lower      (HildonDesktopHomeItem *item);
 
 G_END_DECLS
 #endif /* HILDON_DESKTOP_HOME_ITEM_H */

Modified: projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-home-area.c
===================================================================
--- projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-home-area.c	2007-08-03 11:54:30 UTC (rev 13011)
+++ projects/haf/trunk/hildon-desktop/libhildondesktop/hildon-home-area.c	2007-08-03 15:13:00 UTC (rev 13012)
@@ -1531,8 +1531,8 @@
   for (child = priv->children_data; child ; child = child->next)
     {
       ChildData        *data = child->data;
-      if (GTK_WIDGET_REALIZED (data->widget))
-        gdk_window_raise (data->widget->window);
+      if (HILDON_DESKTOP_IS_HOME_ITEM (data->widget))
+        hildon_desktop_home_item_raise (HILDON_DESKTOP_HOME_ITEM (data->widget));
     }
 }
 


More information about the maemo-commits mailing list