place the client menu at the top left of the window when opening it with a key binding.
change how the first menus are placed. place them like other people place menus. maybe this is good, maybe it is bad, we will see..
This commit is contained in:
parent
853a5b6b04
commit
26879183e9
6 changed files with 175 additions and 60 deletions
|
@ -1732,7 +1732,7 @@ void action_showmenu(union ActionData *data)
|
||||||
{
|
{
|
||||||
if (data->showmenu.name) {
|
if (data->showmenu.name) {
|
||||||
menu_show(data->showmenu.name, data->any.x, data->any.y,
|
menu_show(data->showmenu.name, data->any.x, data->any.y,
|
||||||
data->showmenu.any.c);
|
data->any.button, data->showmenu.any.c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -157,6 +157,69 @@ static void send_to_update(ObMenuFrame *frame, gpointer data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void client_menu_place(ObMenuFrame *frame, gint *x, gint *y,
|
||||||
|
gint button, gpointer data)
|
||||||
|
{
|
||||||
|
gint dx, dy;
|
||||||
|
|
||||||
|
if (button == 0 && frame->client) {
|
||||||
|
*x = frame->client->frame->area.x;
|
||||||
|
|
||||||
|
/* try below the titlebar */
|
||||||
|
*y = frame->client->frame->area.y + frame->client->frame->size.top -
|
||||||
|
frame->client->frame->bwidth;
|
||||||
|
menu_frame_move_on_screen(frame, *x, *y, &dx, &dy);
|
||||||
|
if (dy != 0) {
|
||||||
|
/* try above the titlebar */
|
||||||
|
*y = frame->client->frame->area.y + frame->client->frame->bwidth -
|
||||||
|
frame->area.height;
|
||||||
|
menu_frame_move_on_screen(frame, *x, *y, &dx, &dy);
|
||||||
|
}
|
||||||
|
if (dy != 0) {
|
||||||
|
/* didnt fit either way, use move on screen's values */
|
||||||
|
*y = frame->client->frame->area.y + frame->client->frame->size.top;
|
||||||
|
menu_frame_move_on_screen(frame, *x, *y, &dx, &dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
*x += dx;
|
||||||
|
*y += dy;
|
||||||
|
} else {
|
||||||
|
gint myx, myy;
|
||||||
|
|
||||||
|
myx = *x;
|
||||||
|
myy = *y;
|
||||||
|
|
||||||
|
/* try to the bottom right of the cursor */
|
||||||
|
menu_frame_move_on_screen(frame, myx, myy, &dx, &dy);
|
||||||
|
if (dx != 0 || dy != 0) {
|
||||||
|
/* try to the bottom left of the cursor */
|
||||||
|
myx = *x - frame->area.width;
|
||||||
|
myy = *y;
|
||||||
|
menu_frame_move_on_screen(frame, myx, myy, &dx, &dy);
|
||||||
|
}
|
||||||
|
if (dx != 0 || dy != 0) {
|
||||||
|
/* try to the top right of the cursor */
|
||||||
|
myx = *x;
|
||||||
|
myy = *y - frame->area.height;
|
||||||
|
menu_frame_move_on_screen(frame, myx, myy, &dx, &dy);
|
||||||
|
}
|
||||||
|
if (dx != 0 || dy != 0) {
|
||||||
|
/* try to the top left of the cursor */
|
||||||
|
myx = *x - frame->area.width;
|
||||||
|
myy = *y - frame->area.height;
|
||||||
|
menu_frame_move_on_screen(frame, myx, myy, &dx, &dy);
|
||||||
|
}
|
||||||
|
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(frame, myx, myy, &dx, &dy);
|
||||||
|
}
|
||||||
|
*x = myx + dx;
|
||||||
|
*y = myy + dy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void client_menu_startup()
|
void client_menu_startup()
|
||||||
{
|
{
|
||||||
GSList *acts;
|
GSList *acts;
|
||||||
|
@ -189,6 +252,7 @@ void client_menu_startup()
|
||||||
menu = menu_new(CLIENT_MENU_NAME, _("Client menu"), TRUE, NULL);
|
menu = menu_new(CLIENT_MENU_NAME, _("Client menu"), TRUE, NULL);
|
||||||
menu_show_all_shortcuts(menu, TRUE);
|
menu_show_all_shortcuts(menu, TRUE);
|
||||||
menu_set_update_func(menu, client_update);
|
menu_set_update_func(menu, client_update);
|
||||||
|
menu_set_place_func(menu, client_menu_place);
|
||||||
|
|
||||||
menu_add_submenu(menu, CLIENT_SEND_TO, SEND_TO_MENU_NAME);
|
menu_add_submenu(menu, CLIENT_SEND_TO, SEND_TO_MENU_NAME);
|
||||||
|
|
||||||
|
|
|
@ -360,7 +360,7 @@ void menu_free(ObMenu *menu)
|
||||||
g_hash_table_remove(menu_hash, menu->name);
|
g_hash_table_remove(menu_hash, menu->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_show(gchar *name, gint x, gint y, ObClient *client)
|
void menu_show(gchar *name, gint x, gint y, gint button, ObClient *client)
|
||||||
{
|
{
|
||||||
ObMenu *self;
|
ObMenu *self;
|
||||||
ObMenuFrame *frame;
|
ObMenuFrame *frame;
|
||||||
|
@ -379,7 +379,7 @@ void menu_show(gchar *name, gint x, gint y, ObClient *client)
|
||||||
menu_frame_hide_all();
|
menu_frame_hide_all();
|
||||||
|
|
||||||
frame = menu_frame_new(self, client);
|
frame = menu_frame_new(self, client);
|
||||||
if (!menu_frame_show_topmenu(frame, x, y))
|
if (!menu_frame_show_topmenu(frame, x, y, button))
|
||||||
menu_frame_free(frame);
|
menu_frame_free(frame);
|
||||||
else if (frame->entries) {
|
else if (frame->entries) {
|
||||||
ObMenuEntryFrame *e = frame->entries->data;
|
ObMenuEntryFrame *e = frame->entries->data;
|
||||||
|
@ -515,6 +515,11 @@ void menu_set_destroy_func(ObMenu *self, ObMenuDestroyFunc func)
|
||||||
self->destroy_func = func;
|
self->destroy_func = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void menu_set_place_func(ObMenu *self, ObMenuPlaceFunc func)
|
||||||
|
{
|
||||||
|
self->place_func = func;
|
||||||
|
}
|
||||||
|
|
||||||
ObMenuEntry* menu_find_entry_id(ObMenu *self, gint id)
|
ObMenuEntry* menu_find_entry_id(ObMenu *self, gint id)
|
||||||
{
|
{
|
||||||
ObMenuEntry *ret = NULL;
|
ObMenuEntry *ret = NULL;
|
||||||
|
|
|
@ -41,6 +41,13 @@ typedef void (*ObMenuUpdateFunc)(struct _ObMenuFrame *frame, gpointer data);
|
||||||
typedef void (*ObMenuExecuteFunc)(struct _ObMenuEntry *entry,
|
typedef void (*ObMenuExecuteFunc)(struct _ObMenuEntry *entry,
|
||||||
guint state, gpointer data, Time time);
|
guint state, gpointer data, Time time);
|
||||||
typedef void (*ObMenuDestroyFunc)(struct _ObMenu *menu, gpointer data);
|
typedef void (*ObMenuDestroyFunc)(struct _ObMenu *menu, gpointer data);
|
||||||
|
/*! @param x is the mouse x coordinate. on return it should be the x coordinate
|
||||||
|
for the menu
|
||||||
|
@param y is the mouse y coordinate. on return it should be the y coordinate
|
||||||
|
for the menu
|
||||||
|
*/
|
||||||
|
typedef void (*ObMenuPlaceFunc)(struct _ObMenuFrame *frame, gint *x, gint *y,
|
||||||
|
gint button, gpointer data);
|
||||||
|
|
||||||
struct _ObMenu
|
struct _ObMenu
|
||||||
{
|
{
|
||||||
|
@ -70,6 +77,7 @@ struct _ObMenu
|
||||||
ObMenuUpdateFunc update_func;
|
ObMenuUpdateFunc update_func;
|
||||||
ObMenuExecuteFunc execute_func;
|
ObMenuExecuteFunc execute_func;
|
||||||
ObMenuDestroyFunc destroy_func;
|
ObMenuDestroyFunc destroy_func;
|
||||||
|
ObMenuPlaceFunc place_func;
|
||||||
|
|
||||||
/* Pipe-menu parent, we get destroyed when it is destroyed */
|
/* Pipe-menu parent, we get destroyed when it is destroyed */
|
||||||
ObMenu *pipe_creator;
|
ObMenu *pipe_creator;
|
||||||
|
@ -144,11 +152,13 @@ void menu_pipe_execute(ObMenu *self);
|
||||||
|
|
||||||
void menu_show_all_shortcuts(ObMenu *self, gboolean show);
|
void menu_show_all_shortcuts(ObMenu *self, gboolean show);
|
||||||
|
|
||||||
void menu_show(gchar *name, gint x, gint y, struct _ObClient *client);
|
void menu_show(gchar *name, gint x, gint y, gint button,
|
||||||
|
struct _ObClient *client);
|
||||||
|
|
||||||
void menu_set_update_func(ObMenu *menu, ObMenuUpdateFunc func);
|
void menu_set_update_func(ObMenu *menu, ObMenuUpdateFunc func);
|
||||||
void menu_set_execute_func(ObMenu *menu, ObMenuExecuteFunc func);
|
void menu_set_execute_func(ObMenu *menu, ObMenuExecuteFunc func);
|
||||||
void menu_set_destroy_func(ObMenu *menu, ObMenuDestroyFunc func);
|
void menu_set_destroy_func(ObMenu *menu, ObMenuDestroyFunc func);
|
||||||
|
void menu_set_place_func(ObMenu *menu, ObMenuPlaceFunc func);
|
||||||
|
|
||||||
/* functions for building menus */
|
/* functions for building menus */
|
||||||
/*! @param allow_shortcut this should be false when the label is coming from
|
/*! @param allow_shortcut this should be false when the label is coming from
|
||||||
|
|
|
@ -209,21 +209,69 @@ void menu_frame_move(ObMenuFrame *self, gint x, gint y)
|
||||||
XMoveWindow(ob_display, self->window, self->area.x, self->area.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) {
|
gint dx, dy;
|
||||||
x = self->client->frame->area.x + self->client->frame->size.left;
|
|
||||||
y = self->client->frame->area.y + self->client->frame->size.top;
|
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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
*x = myx + dx;
|
||||||
|
*y += dy;
|
||||||
} else {
|
} else {
|
||||||
if (config_menu_middle)
|
gint myx, myy;
|
||||||
y -= self->area.height / 2;
|
|
||||||
|
myx = *x;
|
||||||
|
myy = *y;
|
||||||
|
|
||||||
|
/* try to the bottom right of the cursor */
|
||||||
|
menu_frame_move_on_screen(self, myx, *y, &dx, &dy);
|
||||||
|
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, *y, &dx, &dy);
|
||||||
|
}
|
||||||
|
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, *y, &dx, &dy);
|
||||||
|
}
|
||||||
|
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, *y, &dx, &dy);
|
||||||
|
}
|
||||||
|
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, *y, &dx, &dy);
|
||||||
|
}
|
||||||
|
*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 overlap;
|
||||||
gint bwidth;
|
gint bwidth;
|
||||||
|
|
||||||
|
@ -231,20 +279,20 @@ void menu_frame_place_submenu(ObMenuFrame *self)
|
||||||
bwidth = ob_rr_theme->mbwidth;
|
bwidth = ob_rr_theme->mbwidth;
|
||||||
|
|
||||||
if (self->direction_right)
|
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
|
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)
|
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
|
else
|
||||||
y += overlap;
|
*y += overlap;
|
||||||
|
|
||||||
menu_frame_move(self, x, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
Rect *a = NULL;
|
||||||
gint pos, half;
|
gint pos, half;
|
||||||
|
@ -259,16 +307,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
|
/* if in the bottom half then check this stuff first, will keep the bottom
|
||||||
edge of the menu visible */
|
edge of the menu visible */
|
||||||
if (pos > half) {
|
if (pos > half) {
|
||||||
*dx = MAX(*dx, a->x - self->area.x);
|
*dx = MAX(*dx, a->x - x);
|
||||||
*dy = MAX(*dy, a->y - self->area.y);
|
*dy = MAX(*dy, a->y - y);
|
||||||
}
|
}
|
||||||
*dx = MIN(*dx, (a->x + a->width) - (self->area.x + self->area.width));
|
*dx = MIN(*dx, (a->x + a->width) - (x + self->area.width));
|
||||||
*dy = MIN(*dy, (a->y + a->height) - (self->area.y + self->area.height));
|
*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
|
/* if in the top half then check this stuff last, will keep the top
|
||||||
edge of the menu visible */
|
edge of the menu visible */
|
||||||
if (pos <= half) {
|
if (pos <= half) {
|
||||||
*dx = MAX(*dx, a->x - self->area.x);
|
*dx = MAX(*dx, a->x - x);
|
||||||
*dy = MAX(*dy, a->y - self->area.y);
|
*dy = MAX(*dy, a->y - y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -723,9 +771,9 @@ static gboolean menu_frame_show(ObMenuFrame *self)
|
||||||
return TRUE;
|
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;
|
guint i;
|
||||||
|
|
||||||
if (menu_frame_is_visible(self))
|
if (menu_frame_is_visible(self))
|
||||||
|
@ -733,8 +781,6 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y)
|
||||||
if (!menu_frame_show(self))
|
if (!menu_frame_show(self))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
menu_frame_place_topmenu(self, x, y);
|
|
||||||
|
|
||||||
/* find the monitor the menu is on */
|
/* find the monitor the menu is on */
|
||||||
for (i = 0; i < screen_num_monitors; ++i) {
|
for (i = 0; i < screen_num_monitors; ++i) {
|
||||||
Rect *a = screen_physical_area_monitor(i);
|
Rect *a = screen_physical_area_monitor(i);
|
||||||
|
@ -744,8 +790,12 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
menu_frame_move_on_screen(self, &dx, &dy);
|
if (self->menu->place_func)
|
||||||
menu_frame_move(self, self->area.x + dx, self->area.y + dy);
|
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);
|
XMapWindow(ob_display, self->window);
|
||||||
|
|
||||||
|
@ -756,7 +806,7 @@ gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
|
||||||
ObMenuEntryFrame *parent_entry)
|
ObMenuEntryFrame *parent_entry)
|
||||||
{
|
{
|
||||||
ObMenuEntryFrame *e;
|
ObMenuEntryFrame *e;
|
||||||
gint dx, dy;
|
gint x, y, dx, dy;
|
||||||
|
|
||||||
if (menu_frame_is_visible(self))
|
if (menu_frame_is_visible(self))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -773,29 +823,16 @@ gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
|
||||||
if (!menu_frame_show(self))
|
if (!menu_frame_show(self))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
menu_frame_place_submenu(self);
|
menu_frame_place_submenu(self, &x, &y);
|
||||||
menu_frame_move_on_screen(self, &dx, &dy);
|
menu_frame_move_on_screen(self, x, y, &dx, &dy);
|
||||||
|
|
||||||
if (dx == 0) {
|
if (dx != 0) {
|
||||||
menu_frame_move(self, self->area.x, self->area.y + dy);
|
/*try the other side */
|
||||||
} else {
|
self->direction_right = !self->direction_right;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
menu_frame_move(self, x + dx, y + dy);
|
||||||
|
|
||||||
XMapWindow(ob_display, self->window);
|
XMapWindow(ob_display, self->window);
|
||||||
|
|
||||||
|
|
|
@ -111,12 +111,11 @@ ObMenuFrame* menu_frame_new(struct _ObMenu *menu, struct _ObClient *client);
|
||||||
void menu_frame_free(ObMenuFrame *self);
|
void menu_frame_free(ObMenuFrame *self);
|
||||||
|
|
||||||
void menu_frame_move(ObMenuFrame *self, gint x, gint y);
|
void menu_frame_move(ObMenuFrame *self, gint x, gint y);
|
||||||
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);
|
||||||
|
|
||||||
void menu_frame_place_topmenu(ObMenuFrame *self, gint x, gint y);
|
gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
|
||||||
void menu_frame_place_submenu(ObMenuFrame *self);
|
gint button);
|
||||||
|
|
||||||
gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y);
|
|
||||||
gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
|
gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
|
||||||
ObMenuEntryFrame *parent_entry);
|
ObMenuEntryFrame *parent_entry);
|
||||||
void menu_frame_hide(ObMenuFrame *self);
|
void menu_frame_hide(ObMenuFrame *self);
|
||||||
|
|
Loading…
Reference in a new issue