Ejemplo n.º 1
0
void popup_delay_show(ObPopup *self, gulong msec, gchar *text)
{
    gint l, t, r, b;
    gint x, y, w, h;
    guint m;
    gint emptyx, emptyy; /* empty space between elements */
    gint textx, texty, textw, texth;
    gint iconx, icony, iconw, iconh;
    const Rect *area;
    Rect mon;
    gboolean hasicon = self->hasicon;

    /* when there is no icon and the text is not parent relative, then
       fill the whole dialog with the text appearance, don't use the bg at all
    */
    if (hasicon || self->a_text->surface.grad == RR_SURFACE_PARENTREL)
        RrMargins(self->a_bg, &l, &t, &r, &b);
    else
        l = t = r = b = 0;

    /* set up the textures */
    self->a_text->texture[0].data.text.string = text;

    /* measure the text out */
    if (text[0] != '\0') {
        RrMinSize(self->a_text, &textw, &texth);
    } else {
        textw = 0;
        texth = RrMinHeight(self->a_text);
    }

    /* get the height, which is also used for the icon width */
    emptyy = t + b + ob_rr_theme->paddingy * 2;
    if (self->h)
        texth = self->h - emptyy;
    h = texth * self->iconhm + emptyy;

    if (self->textw)
        textw = self->textw;

    iconx = textx = l + ob_rr_theme->paddingx;

    emptyx = l + r + ob_rr_theme->paddingx * 2;
    if (hasicon) {
        iconw = texth * self->iconwm;
        iconh = texth * self->iconhm;
        textx += iconw + ob_rr_theme->paddingx;
        if (textw)
            emptyx += ob_rr_theme->paddingx; /* between the icon and text */
        icony = (h - iconh - emptyy) / 2 + t + ob_rr_theme->paddingy;
    } else
        iconw = 0;

    texty = (h - texth - emptyy) / 2 + t + ob_rr_theme->paddingy;

    /* when there is no icon, then fill the whole dialog with the text
       appearance
    */
    if (!hasicon)
    {
        textx = texty = 0;
        texth += emptyy;
        textw += emptyx;
        emptyx = emptyy = 0;
    }

    w = textw + emptyx + iconw;
    /* cap it at maxw/minw */
    if (self->maxw) w = MIN(w, self->maxw);
    if (self->minw) w = MAX(w, self->minw);
    textw = w - emptyx - iconw;

    /* sanity checks to avoid crashes! */
    if (w < 1) w = 1;
    if (h < 1) h = 1;
    if (texth < 1) texth = 1;

    /* set up the x coord */
    x = self->x;
    switch (self->gravity) {
    case NorthGravity: case CenterGravity: case SouthGravity:
        x -= w / 2;
        break;
    case NorthEastGravity: case EastGravity: case SouthEastGravity:
        x -= w;
        break;
    }

    /* set up the y coord */
    y = self->y;
    switch (self->gravity) {
    case WestGravity: case CenterGravity: case EastGravity:
        y -= h / 2;
        break;
    case SouthWestGravity: case SouthGravity: case SouthEastGravity:
        y -= h;
        break;
    }

    /* Find the monitor which contains the biggest part of the popup.
     * If the popup is completely off screen, limit it to the intersection
     * of all monitors and then try again. If it's still off screen, put it
     * on monitor 0. */
    RECT_SET(mon, x, y, w, h);
    m = screen_find_monitor(&mon);
    area = screen_physical_area_monitor(m);

    x=MAX(MIN(x, area->x+area->width-w),area->x);
    y=MAX(MIN(y, area->y+area->height-h),area->y);

    if (m == screen_num_monitors) {
        RECT_SET(mon, x, y, w, h);
        m = screen_find_monitor(&mon);
        if (m == screen_num_monitors)
            m = 0;
        area = screen_physical_area_monitor(m);

        x=MAX(MIN(x, area->x+area->width-w),area->x);
        y=MAX(MIN(y, area->y+area->height-h),area->y);
    }

    /* set the windows/appearances up */
    XMoveResizeWindow(obt_display, self->bg, x, y, w, h);
    /* when there is no icon and the text is not parent relative, then
       fill the whole dialog with the text appearance, don't use the bg at all
    */
    if (hasicon || self->a_text->surface.grad == RR_SURFACE_PARENTREL)
        RrPaint(self->a_bg, self->bg, w, h);

    if (textw) {
        self->a_text->surface.parent = self->a_bg;
        self->a_text->surface.parentx = textx;
        self->a_text->surface.parenty = texty;
        XMoveResizeWindow(obt_display, self->text, textx, texty, textw, texth);
        RrPaint(self->a_text, self->text, textw, texth);
    }

    if (hasicon)
        self->draw_icon(iconx, icony, iconw, iconh, self->draw_icon_data);

    /* do the actual showing */
    if (!self->mapped) {
        if (msec) {
            /* don't kill previous show timers */
            if (!self->delay_mapped) {
                self->delay_timer =
                    g_timeout_add(msec, popup_show_timeout, self);
                self->delay_mapped = TRUE;
            }
        } else {
            popup_show_timeout(self);
        }
    }
}
Ejemplo n.º 2
0
/* XXX: Make this more general */
static GdkPixbuf* preview_menu(RrTheme *theme)
{
    RrAppearance *title;
    RrAppearance *title_text;

    RrAppearance *menu;
    RrAppearance *background;

    RrAppearance *normal;
    RrAppearance *disabled;
    RrAppearance *selected;
    RrAppearance *bullet; /* for submenu */

    GdkPixmap *pixmap;
    GdkPixbuf *pixbuf;

    /* width and height of the whole menu */
    gint width, height;
    gint x, y;
    gint title_h;
    gint tw, th;
    gint bw, bh;
    gint unused;

    /* set up appearances */
    title = theme->a_menu_title;

    title_text = theme->a_menu_text_title;
    title_text->surface.parent = title;
    title_text->texture[0].data.text.string = "Menu";

    normal = theme->a_menu_text_normal;
    normal->texture[0].data.text.string = "Normal";

    disabled = theme->a_menu_text_disabled;
    disabled->texture[0].data.text.string = "Disabled";

    selected = theme->a_menu_text_selected;
    selected->texture[0].data.text.string = "Selected";

    bullet = theme->a_menu_bullet_normal;

    /* determine window size */
    RrMinSize(normal, &width, &th);
    width += th + PADDING; /* make space for the bullet */
    //height = th;

    width += 2*theme->mbwidth + 2*PADDING;

    /* get minimum title size */
    RrMinSize(title, &tw, &title_h);

    /* size of background behind each text line */
    bw = width - 2*theme->mbwidth;
    //title_h += 2*PADDING;
    title_h = theme->menu_title_height;

    RrMinSize(normal, &unused, &th);
    bh = th + 2*PADDING;

    height = title_h + 3*bh + 3*theme->mbwidth;

    //height += 3*th + 3*theme->mbwidth + 5*PADDING;

    /* set border */
    pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
    gdk_pixbuf_fill(pixbuf, rr_color_pixel(theme->menu_border_color));

    /* draw title */
    x = y = theme->mbwidth;
    theme_pixmap_paint(title, bw, title_h);

    /* draw title text */
    title_text->surface.parentx = 0;
    title_text->surface.parenty = 0;

    theme_pixmap_paint(title_text, bw, title_h);

    pixmap = gdk_pixmap_foreign_new(title_text->pixmap);
    pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
                                          gdk_colormap_get_system(),
                                          0, 0, x, y, bw, title_h);

    /* menu appears after title */
    y += theme->mbwidth + title_h;

    /* fill in menu appearance, used as the parent to every menu item's bg */
    menu = theme->a_menu;
    th = height - 3*theme->mbwidth - title_h;
    theme_pixmap_paint(menu, bw, th);

    pixmap = gdk_pixmap_foreign_new(menu->pixmap);
    pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
                                          gdk_colormap_get_system(),
                                          0, 0, x, y, bw, th);

    /* fill in background appearance, used as the parent to text items */
    background = theme->a_menu_normal;
    background->surface.parent = menu;
    background->surface.parentx = 0;
    background->surface.parenty = 0;

    /* draw background for normal entry */
    theme_pixmap_paint(background, bw, bh);
    pixmap = gdk_pixmap_foreign_new(background->pixmap);
    pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
                                          gdk_colormap_get_system(),
                                          0, 0, x, y, bw, bh);

    /* draw normal entry */
    normal->surface.parent = background;
    normal->surface.parentx = PADDING;
    normal->surface.parenty = PADDING;
    x += PADDING;
    y += PADDING;
    RrMinSize(normal, &tw, &th);
    theme_pixmap_paint(normal, tw, th);
    pixmap = gdk_pixmap_foreign_new(normal->pixmap);
    pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
                                          gdk_colormap_get_system(),
                                          0, 0, x, y, tw, th);

    /* draw bullet */
    RrMinSize(normal, &tw, &th);
    bullet->surface.parent = background;
    bullet->surface.parentx = bw - th;
    bullet->surface.parenty = PADDING;
    theme_pixmap_paint(bullet, th, th);
    pixmap = gdk_pixmap_foreign_new(bullet->pixmap);
    pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
                                          gdk_colormap_get_system(),
                                          0, 0, width - theme->mbwidth - th, y,
                                          th, th);

    y += th + 2*PADDING;

    /* draw background for disabled entry */
    background->surface.parenty = bh;
    theme_pixmap_paint(background, bw, bh);
    pixmap = gdk_pixmap_foreign_new(background->pixmap);
    pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
                                          gdk_colormap_get_system(),
                                          0, 0, x - PADDING, y - PADDING,
                                          bw, bh);

    /* draw disabled entry */
    RrMinSize(disabled, &tw, &th);
    disabled->surface.parent = background;
    disabled->surface.parentx = PADDING;
    disabled->surface.parenty = PADDING;
    theme_pixmap_paint(disabled, tw, th);
    pixmap = gdk_pixmap_foreign_new(disabled->pixmap);
    pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
                                          gdk_colormap_get_system(),
                                          0, 0, x, y, tw, th);

    y += th + 2*PADDING;

    /* draw background for selected entry */
    background = theme->a_menu_selected;
    background->surface.parent = menu;
    background->surface.parentx = 2*bh;

    theme_pixmap_paint(background, bw, bh);
    pixmap = gdk_pixmap_foreign_new(background->pixmap);
    pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
                                          gdk_colormap_get_system(),
                                          0, 0, x - PADDING, y - PADDING,
                                          bw, bh);

    /* draw selected entry */
    RrMinSize(selected, &tw, &th);
    selected->surface.parent = background;
    selected->surface.parentx = PADDING;
    selected->surface.parenty = PADDING;
    theme_pixmap_paint(selected, tw, th);
    pixmap = gdk_pixmap_foreign_new(selected->pixmap);
    pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, pixmap,
                                          gdk_colormap_get_system(),
                                          0, 0, x, y, tw, th);

    return pixbuf;
}
Ejemplo n.º 3
0
static void prompt_layout(ObPrompt *self)
{
    gint l, r, t, b;
    gint i;
    gint allbuttonsw, allbuttonsh, buttonx;
    gint w, h;
    gint maxw;

    RrMargins(prompt_a_bg, &l, &t, &r, &b);
    l += OUTSIDE_MARGIN;
    t += OUTSIDE_MARGIN;
    r += OUTSIDE_MARGIN;
    b += OUTSIDE_MARGIN;

    {
        const Rect *area = screen_physical_area_all_monitors();
        maxw = MIN(MAX_WIDTH, area->width*4/5);
    }

    /* find the button sizes and how much space we need for them */
    allbuttonsw = allbuttonsh = 0;
    for (i = 0; i < self->n_buttons; ++i) {
        gint bw, bh;

        prompt_a_button->texture[0].data.text.string = self->button[i].text;
        prompt_a_focus->texture[0].data.text.string = self->button[i].text;
        prompt_a_press->texture[0].data.text.string = self->button[i].text;
        prompt_a_pfocus->texture[0].data.text.string = self->button[i].text;
        RrMinSize(prompt_a_button, &bw, &bh);
        self->button[i].width = bw;
        self->button[i].height = bh;
        RrMinSize(prompt_a_focus, &bw, &bh);
        self->button[i].width = MAX(self->button[i].width, bw);
        self->button[i].height = MAX(self->button[i].height, bh);
        RrMinSize(prompt_a_press, &bw, &bh);
        self->button[i].width = MAX(self->button[i].width, bw);
        self->button[i].height = MAX(self->button[i].height, bh);
        RrMinSize(prompt_a_pfocus, &bw, &bh);
        self->button[i].width = MAX(self->button[i].width, bw);
        self->button[i].height = MAX(self->button[i].height, bh);

        self->button[i].width += BUTTON_HMARGIN * 2;
        self->button[i].height += BUTTON_VMARGIN * 2;

        allbuttonsw += self->button[i].width + (i > 0 ? BUTTON_SEPARATION : 0);
        allbuttonsh = MAX(allbuttonsh, self->button[i].height);
    }

    self->msg_wbound = MAX(allbuttonsw, maxw);

    /* measure the text message area */
    prompt_a_msg->texture[0].data.text.string = self->msg.text;
    prompt_a_msg->texture[0].data.text.maxwidth = self->msg_wbound;
    RrMinSize(prompt_a_msg, &self->msg.width, &self->msg.height);

    /* width and height inside the outer margins */
    w = MAX(self->msg.width, allbuttonsw);
    h = self->msg.height + MSG_BUTTON_SEPARATION + allbuttonsh;

    /* position the text message */
    self->msg.x = l + (w - self->msg.width) / 2;
    self->msg.y = t;

    /* position the button buttons on the right of the dialog */
    buttonx = l + w;
    for (i = self->n_buttons - 1; i >= 0; --i) {
        self->button[i].x = buttonx - self->button[i].width;
        buttonx -= self->button[i].width + BUTTON_SEPARATION;
        self->button[i].y = t + h - allbuttonsh;
        self->button[i].y += (allbuttonsh - self->button[i].height) / 2;
    }

    /* size and position the toplevel window */
    prompt_resize(self, w + l + r, h + t + b);

    /* move and resize the internal windows */
    XMoveResizeWindow(obt_display, self->msg.window,
                      self->msg.x, self->msg.y,
                      self->msg.width, self->msg.height);
    for (i = 0; i < self->n_buttons; ++i)
        XMoveResizeWindow(obt_display, self->button[i].window,
                          self->button[i].x, self->button[i].y,
                          self->button[i].width, self->button[i].height);
}
Ejemplo n.º 4
0
/* XXX: Make this more general */
static GdkPixbuf* preview_menu(RrTheme *theme)
{
    RrAppearance *title;
    RrAppearance *title_text;

    RrAppearance *menu;
    RrAppearance *background;

    RrAppearance *normal;
    RrAppearance *disabled;
    RrAppearance *selected;
    RrAppearance *bullet; /* for submenu */

    cairo_surface_t *surface;
    GdkScreen *screen;
    Display *xdisplay;
    Visual *xvisual;
    GdkPixbuf *pixbuf, *tmp_pixbuf;

    /* width and height of the whole menu */
    gint width, height;
    gint x, y;
    gint title_h;
    gint tw, th;
    gint bw, bh;
    gint unused;

    screen = gdk_screen_get_default();
    xdisplay = gdk_x11_get_default_xdisplay();
    xvisual = gdk_x11_visual_get_xvisual(gdk_screen_get_system_visual(screen));

    /* set up appearances */
    title = theme->a_menu_title;

    title_text = theme->a_menu_text_title;
    title_text->surface.parent = title;
    title_text->texture[0].data.text.string = "Menu";

    normal = theme->a_menu_text_normal;
    normal->texture[0].data.text.string = "Normal";

    disabled = theme->a_menu_text_disabled;
    disabled->texture[0].data.text.string = "Disabled";

    selected = theme->a_menu_text_selected;
    selected->texture[0].data.text.string = "Selected";

    bullet = theme->a_menu_bullet_normal;

    /* determine window size */
    RrMinSize(normal, &width, &th);
    width += th + PADDING; /* make space for the bullet */

    width += 2*theme->mbwidth + 2*PADDING;

    /* get minimum title size */
    RrMinSize(title, &tw, &title_h);

    /* size of background behind each text line */
    bw = width - 2*theme->mbwidth;
    //title_h += 2*PADDING;
    title_h = theme->menu_title_height;

    RrMinSize(normal, &unused, &th);
    bh = th + 2*PADDING;

    height = title_h + 3*bh + 3*theme->mbwidth;

    /* set border */
    pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
    gdk_pixbuf_fill(pixbuf, rr_color_pixel(theme->menu_border_color));
    tmp_pixbuf = gdk_pixbuf_copy(pixbuf);

    /* menu appears after inside the border */
    x = y = theme->mbwidth;

    /* fill in menu appearance, used as the parent to every menu item's bg */
    menu = theme->a_menu;
    th = height - 2 * theme->mbwidth;
    theme_pixmap_paint(menu, bw, th);

    /* draw title, it appears at the top of the menu background */
    title->surface.parent = theme->a_menu;
    title->surface.parentx = 0;
    title->surface.parenty = 0;
    theme_pixmap_paint(title, bw, title_h);

    /* draw title text */
    title_text->surface.parentx = 0;
    title_text->surface.parenty = 0;

    theme_pixmap_paint(title_text, bw, title_h);

    surface = cairo_xlib_surface_create(xdisplay, title_text->pixmap,
                                        xvisual,
                                        bw, title_h);
    tmp_pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, bw, title_h);
    cairo_surface_destroy(surface);
    gdk_pixbuf_copy_area(tmp_pixbuf, 0, 0, bw, title_h, pixbuf, x, y);

    y += title_h + theme->mbwidth;

    /* fill in background appearance, used as the parent to text items */
    background = theme->a_menu_normal;
    background->surface.parent = menu;
    background->surface.parentx = x - theme->mbwidth;
    background->surface.parenty = y - theme->mbwidth;

    /* draw background for normal entry */
    theme_pixmap_paint(background, bw, bh);
    surface = cairo_xlib_surface_create(xdisplay, background->pixmap,
                                        xvisual,
                                        bw, bh);
    tmp_pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, bw, bh);
    cairo_surface_destroy(surface);
    gdk_pixbuf_copy_area(tmp_pixbuf, 0, 0, bw, bh, pixbuf, x, y);

    /* draw normal entry */
    normal->surface.parent = background;
    normal->surface.parentx = PADDING;
    normal->surface.parenty = PADDING;
    RrMinSize(normal, &tw, &th);
    theme_pixmap_paint(normal, tw, th);
    surface = cairo_xlib_surface_create(xdisplay, normal->pixmap,
                                        xvisual,
                                        tw, th);
    tmp_pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, tw, th);
    cairo_surface_destroy(surface);
    gdk_pixbuf_copy_area(tmp_pixbuf, 0, 0, tw, th, pixbuf,
                         x + PADDING, y + PADDING);

    /* draw bullet */
    RrMinSize(normal, &tw, &th);
    bullet->surface.parent = background;
    bullet->surface.parentx = bw - th;
    bullet->surface.parenty = PADDING;
    theme_pixmap_paint(bullet, th, th);
    surface = cairo_xlib_surface_create(xdisplay, bullet->pixmap,
                                        xvisual,
                                        th, th);
    tmp_pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, th, th);
    cairo_surface_destroy(surface);
    gdk_pixbuf_copy_area(tmp_pixbuf, 0, 0, th, th, pixbuf,
                         width - theme->mbwidth - th, y + PADDING);

    y += th + 2*PADDING;

    /* draw background for disabled entry */
    background->surface.parent = menu;
    background->surface.parentx = x - theme->mbwidth;
    background->surface.parenty = y - theme->mbwidth;
    theme_pixmap_paint(background, bw, bh);
    surface = cairo_xlib_surface_create(xdisplay, background->pixmap,
                                        xvisual,
                                        bw, bh);
    tmp_pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, bw, bh);
    cairo_surface_destroy(surface);
    gdk_pixbuf_copy_area(tmp_pixbuf, 0, 0, bw, bh, pixbuf, x, y);

    /* draw disabled entry */
    RrMinSize(disabled, &tw, &th);
    disabled->surface.parent = background;
    disabled->surface.parentx = PADDING;
    disabled->surface.parenty = PADDING;
    theme_pixmap_paint(disabled, tw, th);
    surface = cairo_xlib_surface_create(xdisplay, disabled->pixmap,
                                        xvisual,
                                        tw, th);
    tmp_pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, tw, th);
    cairo_surface_destroy(surface);
    gdk_pixbuf_copy_area(tmp_pixbuf, 0, 0, tw, th, pixbuf,
                         x + PADDING, y + PADDING);

    y += th + 2*PADDING;

    /* draw background for selected entry */
    background = theme->a_menu_selected;
    background->surface.parent = menu;
    background->surface.parentx = x - theme->mbwidth;
    background->surface.parenty = y - theme->mbwidth;

    theme_pixmap_paint(background, bw, bh);
    surface = cairo_xlib_surface_create(xdisplay, background->pixmap,
                                        xvisual,
                                        bw, bh);
    tmp_pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, bw, bh);
    cairo_surface_destroy(surface);
    gdk_pixbuf_copy_area(tmp_pixbuf, 0, 0, bw, bh, pixbuf, x, y);

    /* draw selected entry */
    RrMinSize(selected, &tw, &th);
    selected->surface.parent = background;
    selected->surface.parentx = PADDING;
    selected->surface.parenty = PADDING;
    theme_pixmap_paint(selected, tw, th);
    surface = cairo_xlib_surface_create(xdisplay, selected->pixmap,
                                        xvisual,
                                        tw, th);
    tmp_pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, tw, th);
    cairo_surface_destroy(surface);
    gdk_pixbuf_copy_area(tmp_pixbuf, 0, 0, tw, th, pixbuf,
                         x + PADDING, y + PADDING);
    g_object_unref(tmp_pixbuf);

    return pixbuf;
}