Set a special window property for windows with menus
[hildon] / hildon / hildon-window.c
index d524946..990a2bd 100644 (file)
 
 /**
  * SECTION:hildon-window
- * @short_description: Widget representing a top-level window in the Hildon framework.
+ * @short_description: Top-level window in the Hildon framework.
  * @see_also: #HildonProgram, #HildonStackableWindow
  *
- * #HildonWindow is a GTK widget which represents a top-level
+ * #HildonWindow is a top-level
  * window in the Hildon framework. It is derived from #GtkWindow
  * and provides additional commodities specific to the Hildon
  * framework.
@@ -95,6 +95,7 @@
 #include                                        "hildon-app-menu-private.h"
 #include                                        "hildon-find-toolbar.h"
 #include                                        "hildon-defines.h"
+#include                                        "hildon-private.h"
 
 #define                                         _(String) gettext(String)
 
 
 #define                                         CAN_HIBERNATE_PROPERTY "_HILDON_ABLE_TO_HIBERNATE"
 
+#define                                         LEGACY_MENU_PROPERTY_NAME  "_HILDON_WM_WINDOW_TYPE"
+#define                                         LEGACY_MENU_PROPERTY_VALUE "_HILDON_WM_WINDOW_TYPE_LEGACY_MENU"
+
 #define TITLE_SEPARATOR                         " - "
 
 typedef void                                    (*HildonWindowSignal) (HildonWindow *, gint, gpointer);
@@ -1162,7 +1166,7 @@ hildon_window_key_press_event                   (GtkWidget *widget,
         case HILDON_HARDKEY_ESC:
             if (!priv->escape_timeout)
             {
-                priv->escape_timeout = g_timeout_add 
+                priv->escape_timeout = gdk_threads_add_timeout
                     (HILDON_WINDOW_LONG_PRESS_TIME,
                      hildon_window_escape_timeout, widget);
             }
@@ -1241,6 +1245,36 @@ hildon_window_focus_out_event                   (GtkWidget *widget,
   return GTK_WIDGET_CLASS (hildon_window_parent_class)->focus_out_event (widget, event);
 }
 
+static void
+set_legacy_menu_type                            (GtkMenu  *menu,
+                                                 gboolean  set)
+{
+    GdkWindow *gdkwin = GTK_WIDGET (menu->toplevel)->window;
+    GdkAtom property = gdk_atom_intern_static_string (LEGACY_MENU_PROPERTY_NAME);
+    if (set) {
+        GdkAtom type = gdk_x11_xatom_to_atom (XA_ATOM);
+        GdkAtom value = gdk_atom_intern_static_string (LEGACY_MENU_PROPERTY_VALUE);
+        gdk_property_change (gdkwin, property, type, 32,
+                             GDK_PROP_MODE_REPLACE, (const guchar *) &value, 1);
+    } else {
+        gdk_property_delete (gdkwin, property);
+    }
+}
+
+static void
+legacy_menu_realized                            (GtkMenu *menu)
+{
+    set_legacy_menu_type (menu, TRUE);
+    g_signal_handlers_disconnect_by_func (menu, legacy_menu_realized, NULL);
+}
+
+static void
+legacy_menu_unmapped                            (GtkMenu *menu)
+{
+    set_legacy_menu_type (menu, FALSE);
+    g_signal_handlers_disconnect_by_func (menu, legacy_menu_unmapped, NULL);
+}
+
 /*
  * The menu popuping needs a menu popup-function
  */
@@ -1545,6 +1579,18 @@ hildon_window_toggle_gtk_menu                   (HildonWindow *self,
             HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self);
             g_list_free (menu_children);
 
+            /* Set the 'legacy app menu' property when the widget is realized */
+            if (GTK_WIDGET_REALIZED (menu)) {
+                set_legacy_menu_type (menu, TRUE);
+            } else {
+                g_signal_connect (menu, "realize",
+                                  G_CALLBACK (legacy_menu_realized), NULL);
+            }
+
+            /* Remove it when it's unmapped */
+            g_signal_connect (menu, "unmap",
+                              G_CALLBACK (legacy_menu_unmapped), NULL);
+
             /* Apply right theming */
             gtk_widget_set_name (GTK_WIDGET (menu), "menu_force_with_corners");
 
@@ -1649,8 +1695,6 @@ hildon_window_escape_timeout                    (gpointer data)
 
     g_assert (priv);
 
-    GDK_THREADS_ENTER ();
-
     /* Send fake event, simulation a situation that user
        pressed 'x' from the corner */
     event = gdk_event_new(GDK_DELETE);
@@ -1662,8 +1706,6 @@ hildon_window_escape_timeout                    (gpointer data)
 
     priv->escape_timeout = 0;
 
-    GDK_THREADS_LEAVE ();
-
     return FALSE;
 }
 
@@ -1917,6 +1959,25 @@ hildon_window_add_accel_group (HildonWindow *self,
     gtk_window_add_accel_group (GTK_WINDOW (self), accel_group);
 }
 
+static void
+do_set_has_menu (GtkWindow *window,
+                 gpointer   boolptr)
+{
+    gboolean has_menu = GPOINTER_TO_INT (boolptr);
+    hildon_gtk_window_set_clear_window_flag (window, "_HILDON_WM_WINDOW_MENU_INDICATOR",
+                                             XA_INTEGER, has_menu);
+    g_signal_handlers_disconnect_matched (window, G_SIGNAL_MATCH_FUNC,
+                                          0, 0, NULL, do_set_has_menu, NULL);
+}
+
+void
+hildon_window_set_menu_flag (HildonWindow *window,
+                             gboolean   has_menu)
+{
+    hildon_gtk_window_set_flag (GTK_WINDOW (window), (HildonFlagFunc) do_set_has_menu,
+                                GUINT_TO_POINTER (has_menu));
+}
+
 /**
  * hildon_window_set_main_menu:
  * @self: A #HildonWindow
@@ -1942,6 +2003,8 @@ hildon_window_set_main_menu (HildonWindow* self,
 
     priv = HILDON_WINDOW_GET_PRIVATE (self);
 
+    hildon_window_set_menu_flag (self, menu != NULL);
+
     if (priv->menu != NULL)
     {
        accel_group = gtk_menu_get_accel_group (priv->menu);
@@ -2047,6 +2110,8 @@ hildon_window_set_app_menu                      (HildonWindow  *self,
 
     old_menu = priv->app_menu;
 
+    hildon_window_set_menu_flag (self, menu != NULL);
+
     /* Add new menu */
     priv->app_menu = menu;
     if (menu)