예제 #1
0
void menu_frame_move_on_screen(ObMenuFrame *self, gint x, gint y,
                               gint *dx, gint *dy)
{
    const Rect *a = NULL;
    Rect search = self->area;
    gint pos, half, monitor;

    *dx = *dy = 0;
    RECT_SET_POINT(search, x, y);

    if (self->parent)
        monitor = self->parent->monitor;
    else
        monitor = screen_find_monitor(&search);

    a = screen_physical_area_monitor(monitor);

    half = g_list_length(self->entries) / 2;
    pos = g_list_index(self->entries, self->selected);

    /* 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 - x);
        *dy = MAX(*dy, a->y - y);
    }
    *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 - x);
        *dy = MAX(*dy, a->y - y);
    }
}
예제 #2
0
파일: moveresize.c 프로젝트: ahtik/openbox
static void do_edge_warp(gint x, gint y)
{
    guint i;
    ObDirection dir;

    if (!config_mouse_screenedgetime) return;

    dir = -1;

    for (i = 0; i < screen_num_monitors; ++i) {
        const Rect *a = screen_physical_area_monitor(i);

        if (!RECT_CONTAINS(*a, x, y))
            continue;

        if (x == RECT_LEFT(*a)) dir = OB_DIRECTION_WEST;
        if (x == RECT_RIGHT(*a)) dir = OB_DIRECTION_EAST;
        if (y == RECT_TOP(*a)) dir = OB_DIRECTION_NORTH;
        if (y == RECT_BOTTOM(*a)) dir = OB_DIRECTION_SOUTH;

        /* try check for xinerama boundaries */
        if ((x + 1 == RECT_LEFT(*a) || x - 1 == RECT_RIGHT(*a)) &&
            (dir == OB_DIRECTION_WEST || dir == OB_DIRECTION_EAST))
        {
            dir = -1;
        }
        if ((y + 1 == RECT_TOP(*a) || y - 1 == RECT_BOTTOM(*a)) &&
            (dir == OB_DIRECTION_NORTH || dir == OB_DIRECTION_SOUTH))
        {
            dir = -1;
        }
    }

    if (dir != edge_warp_dir) {
        cancel_edge_warp();
        if (dir != (ObDirection)-1) {
            edge_warp_odd = TRUE; /* switch on the first timeout */
            edge_warp_timer = g_timeout_add(config_mouse_screenedgetime,
                                            edge_warp_delay_func, NULL);
        }
        edge_warp_dir = dir;
    }
}
예제 #3
0
/* Always return FALSE because its not interactive */
static gboolean run_func(ObActionsData *data, gpointer options)
{
    Options *o = options;
    GravityPoint position = { { 0, }, };
    gint monitor = -1;

    if (o->use_position) {
        if (o->monitor >= 0)
            monitor = o->monitor;
        else switch (o->monitor_type) {
            case OB_PLACE_MONITOR_ANY:
            case OB_PLACE_MONITOR_PRIMARY:
                monitor = screen_monitor_primary(FALSE);
                break;
            case OB_PLACE_MONITOR_MOUSE:
                monitor = screen_monitor_pointer();
                break;
            case OB_PLACE_MONITOR_ACTIVE:
                monitor = screen_monitor_active();
                break;
            case OB_PLACE_MONITOR_ALL:
                monitor = screen_num_monitors;
                break;
            default:
                g_assert_not_reached();
        }

        position = o->position;
    } else {
        const Rect *allmon;
        monitor = screen_num_monitors;
        allmon = screen_physical_area_monitor(monitor);
        position.x.pos = data->x - allmon->x;
        position.y.pos = data->y - allmon->y;
    }

    /* you cannot call ShowMenu from inside a menu */
    if (data->uact != OB_USER_ACTION_MENU_SELECTION && o->name)
        menu_show(o->name, &position, monitor,
                  data->button != 0, o->use_position, data->client);

    return FALSE;
}
예제 #4
0
static void menu_frame_update(ObMenuFrame *self)
{
    GList *mit, *fit;
    const Rect *a;
    gint h;

    menu_pipe_execute(self->menu);
    menu_find_submenus(self->menu);

    self->selected = NULL;

    /* start at show_from */
    mit = g_list_nth(self->menu->entries, self->show_from);

    /* go through the menu's and frame's entries and connect the frame entries
       to the menu entries */
    for (fit = self->entries; mit && fit;
         mit = g_list_next(mit), fit = g_list_next(fit))
    {
        ObMenuEntryFrame *f = fit->data;
        f->entry = mit->data;
    }

    /* if there are more menu entries than in the frame, add them */
    while (mit) {
        ObMenuEntryFrame *e = menu_entry_frame_new(mit->data, self);
        self->entries = g_list_append(self->entries, e);
        mit = g_list_next(mit);
    }

    /* if there are more frame entries than menu entries then get rid of
       them */
    while (fit) {
        GList *n = g_list_next(fit);
        menu_entry_frame_free(fit->data);
        self->entries = g_list_delete_link(self->entries, fit);
        fit = n;
    }

    /* * make the menu fit on the screen */

    /* calculate the height of the menu */
    h = 0;
    for (fit = self->entries; fit; fit = g_list_next(fit))
        h += menu_entry_frame_get_height(fit->data,
                                         fit == self->entries,
                                         g_list_next(fit) == NULL);
    /* add the border at the top and bottom */
    h += ob_rr_theme->mbwidth * 2;

    a = screen_physical_area_monitor(self->monitor);

    if (h > a->height) {
        GList *flast, *tmp;
        gboolean last_entry = TRUE;

        /* take the height of our More... entry into account */
        h += menu_entry_frame_get_height(NULL, FALSE, TRUE);

        /* start at the end of the entries */
        flast = g_list_last(self->entries);

        /* pull out all the entries from the frame that don't
           fit on the screen, leaving at least 1 though */
        while (h > a->height && g_list_previous(flast) != NULL) {
            /* update the height, without this entry */
            h -= menu_entry_frame_get_height(flast->data, FALSE, last_entry);

            /* destroy the entry we're not displaying */
            tmp = flast;
            flast = g_list_previous(flast);
            menu_entry_frame_free(tmp->data);
            self->entries = g_list_delete_link(self->entries, tmp);

            /* only the first one that we see is the last entry in the menu */
            last_entry = FALSE;
        };

        {
            ObMenuEntry *more_entry;
            ObMenuEntryFrame *more_frame;
            /* make the More... menu entry frame which will display in this
               frame.
               if self->menu->more_menu is NULL that means that this is already
               More... menu, so just use ourself.
            */
            more_entry = menu_get_more((self->menu->more_menu ?
                                        self->menu->more_menu :
                                        self->menu),
                                       /* continue where we left off */
                                       self->show_from +
                                       g_list_length(self->entries));
            more_frame = menu_entry_frame_new(more_entry, self);
            /* make it get deleted when the menu frame goes away */
            menu_entry_unref(more_entry);

            /* add our More... entry to the frame */
            self->entries = g_list_append(self->entries, more_frame);
        }
    }

    menu_frame_render(self);
}
예제 #5
0
static void menu_frame_place_topmenu(ObMenuFrame *self, const GravityPoint *pos,
                                     gint *x, gint *y, gint monitor,
                                     gboolean user_positioned)
{
    gint dx, dy;

    screen_apply_gravity_point(x, y, self->area.width, self->area.height,
                               pos, screen_physical_area_monitor(monitor));

    if (user_positioned)
        return;

    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 {
        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;
    }
}
예제 #6
0
파일: popup.c 프로젝트: ahtik/openbox
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);
        }
    }
}