Fix use after free in menu_entry_frame_free
[dana/openbox.git] / openbox / menuframe.c
index b49a221..7868df3 100644 (file)
@@ -203,8 +203,6 @@ static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry,
 static void menu_entry_frame_free(ObMenuEntryFrame *self)
 {
     if (self) {
-        menu_entry_unref(self->entry);
-
         window_remove(self->window);
 
         XDestroyWindow(obt_display, self->text);
@@ -221,6 +219,7 @@ static void menu_entry_frame_free(ObMenuEntryFrame *self)
             g_hash_table_remove(menu_frame_map, &self->bullet);
         }
 
+        menu_entry_unref(self->entry);
         g_slice_free(ObMenuEntryFrame, self);
     }
 }
@@ -232,10 +231,18 @@ void menu_frame_move(ObMenuFrame *self, gint x, gint y)
     XMoveWindow(obt_display, self->window, self->area.x, self->area.y);
 }
 
-static void menu_frame_place_topmenu(ObMenuFrame *self, gint *x, gint *y)
+static void menu_frame_place_topmenu(ObMenuFrame *self, const GravityPoint *pos,
+                                     gint *x, gint *y, gint monitor,
+                                     gboolean user_positioned)
 {
     gint dx, dy;
 
+    screen_apply_gravity_point(x, y, self->area.width, self->area.height,
+                               pos, screen_physical_area_monitor(monitor));
+
+    if (user_positioned)
+        return;
+
     if (config_menu_middle) {
         gint myx;
 
@@ -989,20 +996,26 @@ static gboolean menu_frame_show(ObMenuFrame *self)
     return TRUE;
 }
 
-gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
-                                 gboolean mouse)
+gboolean menu_frame_show_topmenu(ObMenuFrame *self, const GravityPoint *pos,
+                                 gint monitor, gboolean mouse,
+                                 gboolean user_positioned)
 {
     gint px, py;
+    gint x, y;
 
     if (menu_frame_is_visible(self))
         return TRUE;
     if (!menu_frame_show(self))
         return FALSE;
 
-    if (self->menu->place_func)
+    if (self->menu->place_func) {
+        x = pos->x.pos;
+        y = pos->y.pos;
         self->menu->place_func(self, &x, &y, mouse, self->menu->data);
-    else
-        menu_frame_place_topmenu(self, &x, &y);
+    } else {
+        menu_frame_place_topmenu(self, pos, &x, &y, monitor,
+                                 user_positioned);
+    }
 
     menu_frame_move(self, x, y);
 
@@ -1242,9 +1255,9 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
         if (self->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) {
             /* only show if the submenu isn't already showing */
             if (oldchild_entry != self->selected) {
-                if (immediate || config_submenu_hide_delay == 0)
+                if (immediate || config_submenu_show_delay == 0)
                     menu_entry_frame_show_submenu(self->selected);
-                else if (config_submenu_hide_delay > 0) {
+                else if (config_submenu_show_delay > 0) {
                     if (submenu_show_timer)
                         g_source_remove(submenu_show_timer);
                     submenu_show_timer =