Commit c16f5c6a authored by Jiri (George) Lebl's avatar Jiri (George) Lebl Committed by George Lebl

Make sure menus appear within xinerama boundaries. Those that don't like

Wed Jan 23 18:20:13 2002  George Lebl <jirka@5z.com>

	* menu.[ch], menu-util.c, applet.c, foobar-widget.c:  Make sure
	  menus appear within xinerama boundaries.  Those that don't like
	  menu.c style of coding should NOT look at this code.  But it
	  works.

	* multiscreen-stuff.c: reorder the screens in the fake debugging
	  setup.

	* basep-widget.c: fix screen_change signal signature

	* foobar-widget.c: add some corners.  Yay we half look like a mac
	  now.  Now if we could only get bottom corners as well.  Maybe
	  in time.
parent eef89428
Wed Jan 23 18:20:13 2002 George Lebl <jirka@5z.com>
* menu.[ch], menu-util.c, applet.c, foobar-widget.c: Make sure
menus appear within xinerama boundaries. Those that don't like
menu.c style of coding should NOT look at this code. But it
works.
* multiscreen-stuff.c: reorder the screens in the fake debugging
setup.
* basep-widget.c: fix screen_change signal signature
* foobar-widget.c: add some corners. Yay we half look like a mac
now. Now if we could only get bottom corners as well. Maybe
in time.
2002-01-23 Padraig O'Briain <padraig.obriain@sun.com>
* applet.c: Add applet_do_popup_menu() and applet_popup_menu() to
......
......@@ -433,7 +433,7 @@ setup_an_item(AppletUserMenu *menu,
/* if the item is a submenu and doesn't have it's menu
created yet*/
} else if(!menu->submenu) {
menu->submenu = gtk_menu_new ();
menu->submenu = panel_menu_new ();
}
if(menu->submenu) {
......@@ -495,7 +495,7 @@ add_to_submenus (AppletInfo *info,
}
if (s_menu->submenu == NULL) {
s_menu->submenu = gtk_menu_new ();
s_menu->submenu = panel_menu_new ();
/*a more elegant way to do this should be done
when I don't want to go to sleep */
if (s_menu->menuitem != NULL) {
......@@ -553,7 +553,7 @@ applet_setup_panel_menu (gboolean is_basep)
setup_menuitem (menuitem, NULL, _("Panel"));
}
panel_menu = gtk_menu_new ();
panel_menu = panel_menu_new ();
make_panel_submenu (panel_menu, TRUE, is_basep);
......@@ -569,7 +569,7 @@ panel_applet_create_menu (AppletInfo *info,
GtkWidget *menuitem;
GList *l;
info->menu = g_object_ref (gtk_menu_new ());
info->menu = g_object_ref (panel_menu_new ());
gtk_object_sink (GTK_OBJECT (info->menu));
if (!commie_mode) {
......@@ -686,7 +686,6 @@ applet_show_menu (AppletInfo *info,
if (!GTK_WIDGET_REALIZED (info->menu))
gtk_widget_show (info->menu);
/* FIXME - off panel popups, should be automatic with new gtk-menu? */
gtk_menu_popup (GTK_MENU (info->menu),
NULL,
NULL,
......
......@@ -246,7 +246,7 @@ basep_widget_class_init (BasePWidgetClass *klass)
G_STRUCT_OFFSET (BasePWidgetClass, screen_change),
NULL,
NULL,
panel_marshal_VOID__ENUM,
panel_marshal_VOID__INT,
G_TYPE_NONE,
1,
G_TYPE_INT);
......
......@@ -172,8 +172,6 @@ append_actions_menu (GtkWidget *menu_bar)
menu = panel_menu_new ();
menu = panel_menu_new ();
item = pixmap_menu_item_new (_("Run..."), "gnome-run.png",
FALSE /* force_image */);
gtk_tooltips_set_tip (panel_tooltips, item,
......@@ -608,6 +606,11 @@ set_the_task_submenu (FoobarWidget *foo, GtkWidget *item)
foo->task_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), foo->task_menu);
/*g_message ("setting...");*/
g_object_set_data (G_OBJECT (foo->task_menu),
"menu_panel", foo->panel);
g_signal_connect (G_OBJECT (foo->task_menu), "show",
G_CALLBACK (panel_make_sure_menu_within_screen),
NULL);
g_signal_connect (G_OBJECT (foo->task_menu), "show",
G_CALLBACK (our_gtk_menu_position),
NULL);
......@@ -975,12 +978,12 @@ setup_task_menu (FoobarWidget *foo)
static void
foobar_widget_instance_init (FoobarWidget *foo)
{
/*gchar *path;*/
char *path;
GtkWindow *window = GTK_WINDOW (foo);
/*GtkWidget *bufmap;*/
GtkWidget *bufmap;
GtkWidget *menu_bar, *bar;
GtkWidget *menu, *menuitem;
/*GtkWidget *align;*/
GtkWidget *align;
gint flags;
foo->screen = 0;
......@@ -1019,15 +1022,14 @@ foobar_widget_instance_init (FoobarWidget *foo)
foo->hbox = gtk_hbox_new (FALSE, 0);
gtk_container_add(GTK_CONTAINER(foo->ebox), foo->hbox);
#if 0
path = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP,
"panel/corner1.png", TRUE, NULL);
bufmap = gnome_pixmap_new_from_file (path);
g_free (path);
align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
gtk_container_add (GTK_CONTAINER (align), bufmap);
gtk_box_pack_start (GTK_BOX (foo->hbox), align, FALSE, FALSE, 0);
#endif
path = panel_pixmap_discovery ("panel-corner-left.png", FALSE /* fallback */);
if (path != NULL) {
bufmap = gtk_image_new_from_file (path);
g_free (path);
align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
gtk_container_add (GTK_CONTAINER (align), bufmap);
gtk_box_pack_start (GTK_BOX (foo->hbox), align, FALSE, FALSE, 0);
}
menu_bar = gtk_menu_bar_new ();
gtk_widget_set_name (menu_bar,
......@@ -1073,15 +1075,14 @@ foobar_widget_instance_init (FoobarWidget *foo)
g_object_set_data (G_OBJECT (menu_bar), "menu_panel", foo->panel);
#if 0
path = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP,
"panel/corner2.png", TRUE, NULL);
bufmap = gnome_pixmap_new_from_file (path);
g_free (path);
align = gtk_alignment_new (1.0, 0.0, 1.0, 0.0);
gtk_container_add (GTK_CONTAINER (align), bufmap);
gtk_box_pack_end (GTK_BOX (foo->hbox), align, FALSE, FALSE, 0);
#endif
path = panel_pixmap_discovery ("panel-corner-right.png", FALSE /* fallback */);
if (path != NULL) {
bufmap = gtk_image_new_from_file (path);
g_free (path);
align = gtk_alignment_new (1.0, 0.0, 1.0, 0.0);
gtk_container_add (GTK_CONTAINER (align), bufmap);
gtk_box_pack_end (GTK_BOX (foo->hbox), align, FALSE, FALSE, 0);
}
bar = menu_bar = gtk_menu_bar_new ();
gtk_widget_set_name (menu_bar,
......
......@@ -108,35 +108,9 @@ panel_menu_position (GtkMenu *menu,
else if (*y > wy + w->allocation.height)
*y = wy + w->allocation.height;
/* FIXME - new gtk menus ??
if ( ! global_config.off_panel_popups) {
panel_standard_menu_pos (menu, x, y, data);
return;
} */
if (TRUE) {
panel_standard_menu_pos (menu, x, y, data);
return;
}
gtk_widget_get_pointer(w, x, y);
if (BASEP_IS_WIDGET (w)) {
basep_widget_get_menu_pos(BASEP_WIDGET(w),
GTK_WIDGET(menu),
x,y,wx,wy,
w->allocation.width,
w->allocation.height);
} else if (FOOBAR_IS_WIDGET (w)) {
GtkRequisition req;
FoobarWidget *foo = FOOBAR_WIDGET (w);
gtk_widget_get_child_requisition (GTK_WIDGET (menu), &req);
*x = MIN (*x,
multiscreen_width (foo->screen) +
multiscreen_x (foo->screen) - req.width);
*y = w->allocation.height + multiscreen_y (foo->screen);
}
*push_in = TRUE;
panel_standard_menu_pos (menu, x, y, data);
}
void
......
......@@ -377,6 +377,9 @@ get_panel_from_menu_data(GtkWidget *menu, gboolean must_have)
g_warning("Menu is on crack");
}
menu = gtk_menu_get_attach_widget (GTK_MENU (menu))->parent;
/* only GtkMenu's qualify */
if ( ! GTK_IS_MENU (menu))
menu = NULL;
}
if (must_have) {
g_warning("Something went quite terribly wrong and we can't "
......@@ -453,6 +456,218 @@ pixmaps_changed (GConfClient* client,
g_list_free (list);
}
typedef struct
{
GtkMenuPositionFunc orig_func;
gpointer orig_data;
} MenuReposition;
/* XXX:
* Stolen mostly from GTK+ and modified for our purposes of multiscreen
* things. Kind of evil, but oh well */
static void
our_menu_item_position_menu (GtkMenu *menu,
int screen_width,
int screen_height,
int screen_basex,
int screen_basey,
int *x,
int *y)
{
GtkMenuItem *menu_item;
GtkWidget *widget;
GtkWidget *parent_menu_item;
int twidth, theight;
int tx, ty;
g_return_if_fail (menu != NULL);
g_return_if_fail (x != NULL);
g_return_if_fail (y != NULL);
menu_item = GTK_MENU_ITEM (menu->parent_menu_item);
widget = GTK_WIDGET (menu_item);
twidth = GTK_WIDGET (menu)->requisition.width;
theight = GTK_WIDGET (menu)->requisition.height;
if ( ! gdk_window_get_origin (widget->window, &tx, &ty)) {
g_warning ("Menu not on screen");
return;
}
tx -= screen_basex;
ty -= screen_basey;
tx += widget->allocation.x;
ty += widget->allocation.y;
switch (menu_item->submenu_placement)
{
case GTK_TOP_BOTTOM:
if ((ty + widget->allocation.height + theight) <= screen_height)
ty += widget->allocation.height;
else if ((ty - theight) >= 0)
ty -= theight;
else if (screen_height - (ty + widget->allocation.height) > ty)
ty += widget->allocation.height;
else
ty -= theight;
break;
case GTK_LEFT_RIGHT:
menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
parent_menu_item = GTK_MENU (widget->parent)->parent_menu_item;
if (parent_menu_item)
menu_item->submenu_direction = GTK_MENU_ITEM (parent_menu_item)->submenu_direction;
switch (menu_item->submenu_direction)
{
case GTK_DIRECTION_LEFT:
if ((tx - twidth) >= 0)
tx -= twidth;
else
{
menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
tx += widget->allocation.width - 5;
}
break;
case GTK_DIRECTION_RIGHT:
if ((tx + widget->allocation.width + twidth - 5) <= screen_width)
tx += widget->allocation.width - 5;
else
{
menu_item->submenu_direction = GTK_DIRECTION_LEFT;
tx -= twidth;
}
break;
}
ty += widget->allocation.height / 4;
/* If the height of the menu doesn't fit we move it upward. */
ty = CLAMP (ty, 0, MAX (0, screen_height - theight));
break;
}
/* If we have negative, tx, here it is because we can't get
* the menu all the way on screen. Favor the left portion.
*/
tx = CLAMP (tx, 0, MAX (0, screen_width - twidth));
*x = tx + screen_basex;
*y = ty + screen_basey;
}
static void
menu_on_screen (GtkMenu *menu,
gint *x,
gint *y,
gboolean *push_in,
gpointer data)
{
MenuReposition *repo = data;
int screen;
int screen_width, screen_height, screen_basex, screen_basey;
GtkRequisition req;
PanelWidget *menu_panel = get_panel_from_menu_data
(GTK_WIDGET (menu), FALSE /* must_have */);
gtk_widget_get_child_requisition (GTK_WIDGET (menu), &req);
if (menu_panel != NULL) {
screen = multiscreen_screen_from_panel
(menu_panel->panel_parent);
} else {
screen = multiscreen_screen_from_pos (*x, *y);
}
if (screen < 0) {
screen_width = gdk_screen_width ();
screen_height = gdk_screen_height ();
screen_basex = 0;
screen_basey = 0;
} else {
screen_width = multiscreen_width (screen);
screen_height = multiscreen_height (screen);
screen_basex = multiscreen_x (screen);
screen_basey = multiscreen_y (screen);
}
if (repo->orig_func != NULL) {
repo->orig_func (menu, x, y, push_in, repo->orig_data);
if (menu->parent_menu_item != NULL) {
/* This is a submenu so behave submenuish */
if (*x < screen_basex ||
*x + req.width > screen_basex + screen_width ||
*y < screen_basey ||
*y + req.height > screen_basey + screen_height) {
/* Offscreen! EVIL, ignore the position
* and recalculate using our hack */
our_menu_item_position_menu (menu,
screen_width,
screen_height,
screen_basex,
screen_basey,
x,
y);
}
} else {
/* just make sure the menu is within screen */
*x -= screen_basex;
*y -= screen_basey;
if ((*x + req.width) > screen_width)
*x -= ((*x + req.width) - screen_width);
if (*x < 0)
*x = 0;
if ((*y + req.height) > screen_height)
*y -= ((*y + req.height) - screen_height);
if (*y < 0)
*y = 0;
*x += screen_basex;
*y += screen_basey;
}
} else {
*x -= screen_basex;
*y -= screen_basey;
*x = CLAMP (*x - 2, 0, MAX (0, screen_width - req.width));
*y = CLAMP (*y - 2, 0, MAX (0, screen_height - req.height));
*x += screen_basex;
*y += screen_basey;
*push_in = TRUE;
}
}
void
panel_make_sure_menu_within_screen (GtkMenu *menu)
{
MenuReposition *repo;
/* if already set to a standard pos func, just ignore */
if (menu->position_func == menu_on_screen ||
menu->position_func == panel_menu_position ||
menu->position_func == applet_menu_position)
return;
repo = g_new0 (MenuReposition, 1);
g_object_weak_ref (G_OBJECT (menu),
(GWeakNotify) g_free,
repo);
repo->orig_func = menu->position_func;
repo->orig_data = menu->position_func_data;
menu->position_func = menu_on_screen;
menu->position_func_data = repo;
our_gtk_menu_position (menu);
}
GtkWidget *
panel_menu_new (void)
{
......@@ -461,6 +676,8 @@ panel_menu_new (void)
panel_gconf_notify_add_while_alive (PANEL_MENU_HAVE_ICONS_KEY,
pixmaps_changed,
G_OBJECT (menu));
g_signal_connect_after (G_OBJECT (menu), "show",
G_CALLBACK (panel_make_sure_menu_within_screen), NULL);
return menu;
}
......
......@@ -135,6 +135,8 @@ void panel_load_menu_image_deferred (GtkWidget *image_menu_item,
const char *image_filename,
const char *fallback_image_filename,
gboolean force_image);
/* Note, bind the following on 'show' or some such */
void panel_make_sure_menu_within_screen (GtkMenu *menu);
G_END_DECLS
......
......@@ -53,14 +53,14 @@ multiscreen_init (void)
/* fake xinerama setup for debugging */
screens = 2;
rectangles = g_new0 (GdkRectangle, 2);
rectangles[1].x = 0;
rectangles[1].y = 0;
rectangles[1].width = gdk_screen_width () / 2;
rectangles[1].height = gdk_screen_height () / 2;
rectangles[0].x = gdk_screen_width () / 2;
rectangles[0].y = gdk_screen_height () / 2;
rectangles[0].width = gdk_screen_width () - rectangles[0].x;
rectangles[0].height = gdk_screen_height () - rectangles[0].y;
rectangles[0].x = 0;
rectangles[0].y = 0;
rectangles[0].width = gdk_screen_width () / 2;
rectangles[0].height = gdk_screen_height () / 2;
rectangles[1].x = gdk_screen_width () / 2;
rectangles[1].y = gdk_screen_height () / 2;
rectangles[1].width = gdk_screen_width () - rectangles[0].x;
rectangles[1].height = gdk_screen_height () - rectangles[0].y;
initialized = TRUE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment