Re: How to put the GtkWidget to max screen size?



On Thu, 21 Dec 2000, Havoc Pennington wrote:
> "alan" <alan ielinux com> writes:
> > I set GtkWidget to max size of screen by use gtk_widget_set_usize() and
> > gtk_widget_set_uposition().
> > If I running in kde environmentis is ok.
> > but if I set widget position to (0,0), and running program in afterstop.
> > The title bar of afterstep will hide over screen.
> 
> The problem is that window managers are broken in this respect. The
> new window manager spec clarifies the correct behavior; window
> managers should unbreak themselves eventually.
> 
> > Have any other way to set GtkWidget to max size of screen.
> > And, How to know the border size and title bar height of window manager?
> > 
> 
> You can't really know this. There are some scary hacks to try to
> figure it out, but you'd have to know a lot about X.

I worked out a hack for this same problem, which seems to work.
Feel free to use it and/or comment on it's shotcomings.

Cheers,

-- 
Ali Harlow                              Email: ali avrc city ac uk
Research programmer                     Tel:   (020) 7477 8000 X 4348
Applied Vision Research Centre          Intl: +44 20 7477 8000 X 4348
City University                         Fax:   (020) 7505 5515
London                                  Intl: +44 20 7505 5515
/* ALI
 * We need to know the border width and height so that we can correctly
 * clamp dialogs to the screen. Unfortunately, GDK allows us no way to
 * dermine the border sizes before we map the window. We get around this
 * by remembering what they were for the last dialog displayed and
 * checking that they haven't changed after the window is mapped. If
 * we find we're offscreen after mapping we have to re-position the
 * window. Clumsy, but effective.
 *
 * Note: there's no way that I know of to determine the width of the
 * right border or the height of the bottom border. For now, we just
 * assume that these are both equal to the left border. Typically,
 * only the top border is different and this is a valid assumption.
 *
 * This is all further complicated by the fact that, at least under
 * the Enlightenment window manager, gtk_widget_set_uposition() sets
 * the position of the top left pixel of the border before the window
 * is mapped, but the top left pixel of the window after it is mapped.
 *
 * Note: If the window manager is set up such that gtk_widget_set_upostion()
 * always sets the position of the left left pixel of the window, and if
 * gtk_window_get_origin() returns this same position, then this code
 * will fail (gracefully) and dialogs may be positioned with their borders
 * just off-screen.
 */

static gint popup_dialog_bw = 0, popup_dialog_bh = 0;

volatile int popup_dialog_abandon;

static gint popup_dialog_timeout(gpointer data)
{
    if (!popup_dialog_abandon)
	popup_dialog_abandon++;
    return FALSE;
}

static void
popup_dialog_mapped(GtkWidget *w, gpointer data)
{
    gint screen_width, screen_height;
    GdkWindow *window = GTK_WIDGET(w)->window;
    gint x, y, nx, ny;
    data = gtk_object_get_user_data(GTK_OBJECT(w));
    if (data) {
	x = GPOINTER_TO_UINT(data) >> 16;
	y = GPOINTER_TO_UINT(data) & 0xffff;
	/* Wait for Window Manager to place window and add borders */
	popup_dialog_abandon = 0;
	gtk_timeout_add(100L, popup_dialog_timeout, 0);
	do
	{
	    gtk_main_iteration();
	    if (popup_dialog_abandon) {		/* Don't wait for ever */
		if (popup_dialog_abandon++ > 1)	/* One final check? */
		    return;
	    }
	    gdk_window_get_origin(window, &nx, &ny);
	} while (nx == 0 && ny == 0 || nx == x && ny == y);
	popup_dialog_bw = nx - x;
	popup_dialog_bh = ny - y;
	/* Do we need to re-position this window to stay on-screen? */
	screen_width = gdk_screen_width();
	screen_height = gdk_screen_height();
	if (nx + popup_dialog_bw + w->allocation.width > screen_width)
	    x = screen_width - popup_dialog_bw - w->allocation.width;
	else x = nx;
	if (ny + popup_dialog_bw + w->allocation.height > screen_height)
	    /* popup_dialog_bw because we assume bottom border same as left */
	    y = screen_height - popup_dialog_bw - w->allocation.height;
	else y = ny;
	if (x != nx || y != ny)
	    gtk_widget_set_uposition(w, x, y);
    }
}

static void
popup_dialog_realizing(GtkWidget *w, gpointer data)
{
    GdkWindow *window = GTK_WIDGET(main_window)->window;
    gint x, y, width, height, ox, oy;
    gint screen_width = gdk_screen_width(), screen_height = gdk_screen_height();

    if (w->allocation.width > screen_width ||
      w->allocation.height > screen_height) {
	/* This is going to look bad anyway, we can't centre it because
	 * a position less than 0 is not valid, so the best we can do
	 * is place the pop-up at the top left of the screen and accept
	 * that the right and/or bottom edge will be off-screen.
	 */
	x = y = 0;
    }
    else {
	gdk_window_get_geometry(window, &x, &y, &width, &height, NULL);
	gdk_window_get_origin(window, &ox, &oy);
	x += ox + (width - w->allocation.width) / 2;
	y += oy + (height - w->allocation.height) / 2;
	if (x + w->allocation.width + popup_dialog_bw > screen_width)
	    x = screen_width - popup_dialog_bw - w->allocation.width;
	if (y + w->allocation.height + popup_dialog_bw > screen_height)
	    y = screen_height - popup_dialog_bw - w->allocation.height;
	/* (x,y) is the desired position of the window,
	 * adjust to take into account the expected border. */
	x -= popup_dialog_bw;
	y -= popup_dialog_bh;
	if (x < 0) x = 0;
	if (y < 0) y = 0;
    }
    gtk_widget_set_uposition(w, x, y);
    gtk_object_set_user_data(GTK_OBJECT(w), GUINT_TO_POINTER(x << 16 | y));
}

void
nh_position_popup_dialog(GtkWidget *w)
{
    if (GTK_WIDGET_REALIZED(w))
	popup_dialog_realizing(w, 0);
    if (GTK_WIDGET_MAPPED(w))
	popup_dialog_mapped(w, 0);
    gtk_signal_connect(GTK_OBJECT(w), "realize",
	GTK_SIGNAL_FUNC(popup_dialog_realizing), 0);
    gtk_signal_connect_after(GTK_OBJECT(w), "map",
	GTK_SIGNAL_FUNC(popup_dialog_mapped), 0);
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]