X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fmenuframe.c;h=a95e46fca4e1ccc9bd300037feb7ffed9ad6c196;hb=e0e1d4ba7e150b215b55029ddbff3c824b94caf7;hp=9d635f95d7cf92b3a6098ce4c03e14971bc261ef;hpb=0c41ab3c208970a68e9d0e0d0471c450542e23a3;p=chaz%2Fopenbox diff --git a/openbox/menuframe.c b/openbox/menuframe.c index 9d635f95..a95e46fc 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -209,21 +209,77 @@ void menu_frame_move(ObMenuFrame *self, gint x, gint y) XMoveWindow(ob_display, self->window, self->area.x, self->area.y); } -void menu_frame_place_topmenu(ObMenuFrame *self, gint x, gint y) +static void menu_frame_place_topmenu(ObMenuFrame *self, gint *x, gint *y) { - if (self->client && x < 0 && y < 0) { - x = self->client->frame->area.x + self->client->frame->size.left; - y = self->client->frame->area.y + self->client->frame->size.top; + gint dx, dy; + + if (config_menu_middle) { + gint myx; + + myx = *x; + *y -= self->area.height / 2; + + /* try to the right of the cursor */ + menu_frame_move_on_screen(self, myx, *y, &dx, &dy); + self->direction_right = TRUE; + if (dx != 0) { + /* try to the left of the cursor */ + myx = *x - self->area.width; + menu_frame_move_on_screen(self, myx, *y, &dx, &dy); + self->direction_right = FALSE; + } + if (dx != 0) { + /* if didnt fit on either side so just use what it says */ + myx = *x; + menu_frame_move_on_screen(self, myx, *y, &dx, &dy); + self->direction_right = TRUE; + } + *x = myx + dx; + *y += dy; } else { - if (config_menu_middle) - y -= self->area.height / 2; + gint myx, myy; + + myx = *x; + myy = *y; + + /* try to the bottom right of the cursor */ + menu_frame_move_on_screen(self, myx, myy, &dx, &dy); + self->direction_right = TRUE; + if (dx != 0 || dy != 0) { + /* try to the bottom left of the cursor */ + myx = *x - self->area.width; + myy = *y; + menu_frame_move_on_screen(self, myx, myy, &dx, &dy); + self->direction_right = FALSE; + } + if (dx != 0 || dy != 0) { + /* try to the top right of the cursor */ + myx = *x; + myy = *y - self->area.height; + menu_frame_move_on_screen(self, myx, myy, &dx, &dy); + self->direction_right = TRUE; + } + if (dx != 0 || dy != 0) { + /* try to the top left of the cursor */ + myx = *x - self->area.width; + myy = *y - self->area.height; + menu_frame_move_on_screen(self, myx, myy, &dx, &dy); + self->direction_right = FALSE; + } + if (dx != 0 || dy != 0) { + /* if didnt fit on either side so just use what it says */ + myx = *x; + myy = *y; + menu_frame_move_on_screen(self, myx, myy, &dx, &dy); + self->direction_right = TRUE; + } + *x = myx + dx; + *y = myy + dy; } - menu_frame_move(self, x, y); } -void menu_frame_place_submenu(ObMenuFrame *self) +static void menu_frame_place_submenu(ObMenuFrame *self, gint *x, gint *y) { - gint x, y; gint overlap; gint bwidth; @@ -231,20 +287,20 @@ void menu_frame_place_submenu(ObMenuFrame *self) bwidth = ob_rr_theme->mbwidth; if (self->direction_right) - x = self->parent->area.x + self->parent->area.width - overlap - bwidth; + *x = self->parent->area.x + self->parent->area.width - + overlap - bwidth; else - x = self->parent->area.x - self->area.width + overlap + bwidth; + *x = self->parent->area.x - self->area.width + overlap + bwidth; - y = self->parent->area.y + self->parent_entry->area.y; + *y = self->parent->area.y + self->parent_entry->area.y; if (config_menu_middle) - y -= (self->area.height - (bwidth * 2) - self->item_h) / 2; + *y -= (self->area.height - (bwidth * 2) - self->item_h) / 2; else - y += overlap; - - menu_frame_move(self, x, y); + *y += overlap; } -void menu_frame_move_on_screen(ObMenuFrame *self, gint *dx, gint *dy) +void menu_frame_move_on_screen(ObMenuFrame *self, gint x, gint y, + gint *dx, gint *dy) { Rect *a = NULL; gint pos, half; @@ -259,16 +315,16 @@ void menu_frame_move_on_screen(ObMenuFrame *self, gint *dx, gint *dy) /* if in the bottom half then check this stuff first, will keep the bottom edge of the menu visible */ if (pos > half) { - *dx = MAX(*dx, a->x - self->area.x); - *dy = MAX(*dy, a->y - self->area.y); + *dx = MAX(*dx, a->x - x); + *dy = MAX(*dy, a->y - y); } - *dx = MIN(*dx, (a->x + a->width) - (self->area.x + self->area.width)); - *dy = MIN(*dy, (a->y + a->height) - (self->area.y + self->area.height)); + *dx = MIN(*dx, (a->x + a->width) - (x + self->area.width)); + *dy = MIN(*dy, (a->y + a->height) - (y + self->area.height)); /* if in the top half then check this stuff last, will keep the top edge of the menu visible */ if (pos <= half) { - *dx = MAX(*dx, a->x - self->area.x); - *dy = MAX(*dy, a->y - self->area.y); + *dx = MAX(*dx, a->x - x); + *dy = MAX(*dy, a->y - y); } } @@ -318,8 +374,9 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self) self->a_text_selected : self->a_text_normal)); text_a->texture[0].data.text.string = self->entry->data.normal.label; - if (self->frame->menu->show_all_shortcuts || - self->entry->data.normal.shortcut > 0) + if (self->entry->data.normal.shortcut && + (self->frame->menu->show_all_shortcuts || + self->entry->data.normal.shortcut_position > 0)) { text_a->texture[0].data.text.shortcut = TRUE; text_a->texture[0].data.text.shortcut_pos = @@ -333,7 +390,9 @@ static void menu_entry_frame_render(ObMenuEntryFrame *self) self->a_text_normal); sub = self->entry->data.submenu.submenu; text_a->texture[0].data.text.string = sub ? sub->title : ""; - if (self->frame->menu->show_all_shortcuts || sub->shortcut > 0) { + if (sub->shortcut && (self->frame->menu->show_all_shortcuts || + sub->shortcut_position > 0)) + { text_a->texture[0].data.text.shortcut = TRUE; text_a->texture[0].data.text.shortcut_pos = sub->shortcut_position; } else @@ -510,7 +569,7 @@ static void menu_frame_render(ObMenuFrame *self) gint l, t, r, b; e->a_text_normal->texture[0].data.text.string = ""; - RrMinsize(e->a_text_normal, &tw, &th); + RrMinSize(e->a_text_normal, &tw, &th); tw += 2*PADDING; th += 2*PADDING; self->item_h = th; @@ -572,7 +631,7 @@ static void menu_frame_render(ObMenuFrame *self) switch (e->entry->type) { case OB_MENU_ENTRY_TYPE_NORMAL: text_a->texture[0].data.text.string = e->entry->data.normal.label; - RrMinsize(text_a, &tw, &th); + RrMinSize(text_a, &tw, &th); tw = MIN(tw, MAX_MENU_WIDTH); if (e->entry->data.normal.icon_data || @@ -582,7 +641,7 @@ static void menu_frame_render(ObMenuFrame *self) case OB_MENU_ENTRY_TYPE_SUBMENU: sub = e->entry->data.submenu.submenu; text_a->texture[0].data.text.string = sub ? sub->title : ""; - RrMinsize(text_a, &tw, &th); + RrMinSize(text_a, &tw, &th); tw = MIN(tw, MAX_MENU_WIDTH); if (e->entry->data.normal.icon_data || @@ -595,7 +654,7 @@ static void menu_frame_render(ObMenuFrame *self) if (e->entry->data.separator.label != NULL) { e->a_text_title->texture[0].data.text.string = e->entry->data.separator.label; - RrMinsize(e->a_text_title, &tw, &th); + RrMinSize(e->a_text_title, &tw, &th); tw = MIN(tw, MAX_MENU_WIDTH); th = ob_rr_theme->menu_title_height + (ob_rr_theme->mbwidth - PADDING) *2; @@ -692,16 +751,6 @@ static gboolean menu_frame_show(ObMenuFrame *self) { GList *it; - if (menu_frame_visible == NULL) { - /* no menus shown yet */ - if (!grab_pointer(TRUE, TRUE, OB_CURSOR_POINTER)) - return FALSE; - if (!grab_keyboard(TRUE)) { - grab_pointer(FALSE, TRUE, OB_CURSOR_POINTER); - return FALSE; - } - } - /* determine if the underlying menu is already visible */ for (it = menu_frame_visible; it; it = g_list_next(it)) { ObMenuFrame *f = it->data; @@ -710,7 +759,18 @@ static gboolean menu_frame_show(ObMenuFrame *self) } if (!it) { if (self->menu->update_func) - self->menu->update_func(self, self->menu->data); + if (!self->menu->update_func(self, self->menu->data)) + return FALSE; + } + + if (menu_frame_visible == NULL) { + /* no menus shown yet */ + if (!grab_pointer(TRUE, TRUE, OB_CURSOR_POINTER)) + return FALSE; + if (!grab_keyboard(TRUE)) { + grab_pointer(FALSE, TRUE, OB_CURSOR_POINTER); + return FALSE; + } } menu_frame_update(self); @@ -720,9 +780,9 @@ static gboolean menu_frame_show(ObMenuFrame *self) return TRUE; } -gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y) +gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y, + gint button) { - gint dx, dy; guint i; if (menu_frame_is_visible(self)) @@ -730,8 +790,6 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y) if (!menu_frame_show(self)) return FALSE; - menu_frame_place_topmenu(self, x, y); - /* find the monitor the menu is on */ for (i = 0; i < screen_num_monitors; ++i) { Rect *a = screen_physical_area_monitor(i); @@ -741,8 +799,12 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y) } } - menu_frame_move_on_screen(self, &dx, &dy); - menu_frame_move(self, self->area.x + dx, self->area.y + dy); + if (self->menu->place_func) + self->menu->place_func(self, &x, &y, button, self->menu->data); + else + menu_frame_place_topmenu(self, &x, &y); + + menu_frame_move(self, x, y); XMapWindow(ob_display, self->window); @@ -753,7 +815,7 @@ gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent, ObMenuEntryFrame *parent_entry) { ObMenuEntryFrame *e; - gint dx, dy; + gint x, y, dx, dy; if (menu_frame_is_visible(self)) return TRUE; @@ -770,29 +832,16 @@ gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent, if (!menu_frame_show(self)) return FALSE; - menu_frame_place_submenu(self); - menu_frame_move_on_screen(self, &dx, &dy); - - if (dx == 0) { - menu_frame_move(self, self->area.x, self->area.y + dy); - } else { - gboolean dir; + menu_frame_place_submenu(self, &x, &y); + menu_frame_move_on_screen(self, x, y, &dx, &dy); - /* flip the direction in which we're placing submenus */ - if (dx > 0) - dir = TRUE; - else - dir = FALSE; - - /* if it changed, then replace the menu on the opposite side, - and try keep it on the screen too */ - if (dir != self->direction_right) { - self->direction_right = dir; - menu_frame_place_submenu(self); - menu_frame_move_on_screen(self, &dx, &dy); - menu_frame_move(self, self->area.x + dx, self->area.y + dy); - } + if (dx != 0) { + /*try the other side */ + self->direction_right = !self->direction_right; + menu_frame_place_submenu(self, &x, &y); + menu_frame_move_on_screen(self, x, y, &dx, &dy); } + menu_frame_move(self, x + dx, y + dy); XMapWindow(ob_display, self->window);