new popups with subclasses, added an ObIconPopup for popups with icons, and ObPagerPopup, for a popup with a pager on it.

better logic also for the desktop layout code figuring out how many rows and columns there are.
This commit is contained in:
Dana Jansens 2003-09-12 06:00:17 +00:00
parent 5d658c98e2
commit 4be58bf137
6 changed files with 400 additions and 138 deletions

View file

@ -22,11 +22,11 @@ GList **focus_order; /* these lists are created when screen_startup
sets the number of desktops */
ObClient *focus_cycle_target;
static Popup *focus_cycle_popup;
static ObIconPopup *focus_cycle_popup;
void focus_startup(gboolean reconfig)
{
focus_cycle_popup = popup_new(TRUE);
focus_cycle_popup = icon_popup_new(TRUE);
if (!reconfig)
/* start with nothing focused */
@ -37,7 +37,7 @@ void focus_shutdown(gboolean reconfig)
{
guint i;
popup_free(focus_cycle_popup);
icon_popup_free(focus_cycle_popup);
if (!reconfig) {
for (i = 0; i < screen_num_desktops; ++i)
@ -223,22 +223,22 @@ void focus_fallback(ObFocusFallbackType type)
static void popup_cycle(ObClient *c, gboolean show)
{
if (!show) {
popup_hide(focus_cycle_popup);
icon_popup_hide(focus_cycle_popup);
} else {
Rect *a;
ObClient *p = c;
char *title;
a = screen_physical_area_monitor(0);
popup_position(focus_cycle_popup, CenterGravity,
a->x + a->width / 2, a->y + a->height / 2);
/* popup_size(focus_cycle_popup, a->height/2, a->height/16);
popup_show(focus_cycle_popup, c->title,
client_icon(c, a->height/16, a->height/16));
icon_popup_position(focus_cycle_popup, CenterGravity,
a->x + a->width / 2, a->y + a->height / 2);
/* icon_popup_size(focus_cycle_popup, a->height/2, a->height/16);
icon_popup_show(focus_cycle_popup, c->title,
client_icon(c, a->height/16, a->height/16));
*/
/* XXX the size and the font extents need to be related on some level
*/
popup_size(focus_cycle_popup, POPUP_WIDTH, POPUP_HEIGHT);
icon_popup_size(focus_cycle_popup, POPUP_WIDTH, POPUP_HEIGHT);
/* use the transient's parent's title/icon */
while (p->transient_for && p->transient_for != OB_TRAN_GROUP)
@ -252,9 +252,10 @@ static void popup_cycle(ObClient *c, gboolean show)
(p->iconic ? p->icon_title : p->title),
NULL);
popup_show(focus_cycle_popup,
(title ? title : (c->iconic ? c->icon_title : c->title)),
client_icon(p, 48, 48));
icon_popup_show(focus_cycle_popup,
(title ? title :
(c->iconic ? c->icon_title : c->title)),
client_icon(p, 48, 48));
g_free(title);
}
}

View file

@ -26,7 +26,7 @@ static guint button;
static guint32 corner;
static ObCorner lockcorner;
static Popup *popup = NULL;
static ObPopup *popup = NULL;
static void client_dest(gpointer client)
{
@ -61,7 +61,7 @@ static void popup_coords(ObClient *c, char *format, int a, int b)
c->area.width / 2,
c->frame->area.y + c->frame->size.top +
c->area.height / 2);
popup_show(popup, text, NULL);
popup_show(popup, text);
g_free(text);
}

View file

@ -189,14 +189,6 @@ int main(int argc, char **argv)
if (screen_annex()) { /* it will be ours! */
do {
event_startup(reconfigure);
grab_startup(reconfigure);
/* focus_backup is used for stacking, so this needs to come before
anything that calls stacking_add */
focus_startup(reconfigure);
window_startup(reconfigure);
sn_startup(reconfigure);
{
ObParseInst *i;
xmlDocPtr doc;
@ -218,12 +210,21 @@ int main(int argc, char **argv)
/* load the theme specified in the rc file */
{
RrTheme *theme;
if ((theme = RrThemeNew(ob_rr_inst, config_theme)))
if ((theme = RrThemeNew(ob_rr_inst, config_theme))) {
RrThemeFree(ob_rr_theme);
ob_rr_theme = theme;
}
if (ob_rr_theme == NULL)
ob_exit_with_error("Unable to load a theme.");
}
event_startup(reconfigure);
grab_startup(reconfigure);
/* focus_backup is used for stacking, so this needs to come before
anything that calls stacking_add */
focus_startup(reconfigure);
window_startup(reconfigure);
sn_startup(reconfigure);
moveresize_startup(reconfigure);
screen_startup(reconfigure);
group_startup(reconfigure);

View file

@ -3,43 +3,22 @@
#include "openbox.h"
#include "frame.h"
#include "client.h"
#include "window.h"
#include "stacking.h"
#include "screen.h"
#include "render/render.h"
#include "render/theme.h"
struct _ObPopup
{
ObWindow obwin;
Window bg;
Window icon;
Window text;
gboolean hasicon;
RrAppearance *a_bg;
RrAppearance *a_icon;
RrAppearance *a_text;
gint gravity;
gint x;
gint y;
gint w;
gint h;
gboolean mapped;
};
Popup *popup_new(gboolean hasicon)
ObPopup *popup_new(gboolean hasicon)
{
XSetWindowAttributes attrib;
Popup *self = g_new(Popup, 1);
ObPopup *self = g_new0(ObPopup, 1);
self->obwin.type = Window_Internal;
self->hasicon = hasicon;
self->a_text = NULL;
self->gravity = NorthWestGravity;
self->x = self->y = self->w = self->h = 0;
self->mapped = FALSE;
self->a_bg = self->a_icon = self->a_text = NULL;
self->a_bg = RrAppearanceCopy(ob_rr_theme->app_hilite_bg);
self->a_text = RrAppearanceCopy(ob_rr_theme->app_hilite_label);
attrib.override_redirect = True;
self->bg = XCreateWindow(ob_display, RootWindow(ob_display, ob_screen),
@ -51,54 +30,42 @@ Popup *popup_new(gboolean hasicon)
0, 0, 1, 1, 0, RrDepth(ob_rr_inst),
InputOutput, RrVisual(ob_rr_inst), 0, NULL);
if (self->hasicon)
self->icon = XCreateWindow(ob_display, self->bg,
0, 0, 1, 1, 0,
RrDepth(ob_rr_inst), InputOutput,
RrVisual(ob_rr_inst), 0, NULL);
XMapWindow(ob_display, self->text);
XMapWindow(ob_display, self->icon);
stacking_add(INTERNAL_AS_WINDOW(self));
return self;
}
void popup_free(Popup *self)
void popup_free(ObPopup *self)
{
if (self) {
XDestroyWindow(ob_display, self->bg);
XDestroyWindow(ob_display, self->text);
XDestroyWindow(ob_display, self->icon);
RrAppearanceFree(self->a_bg);
RrAppearanceFree(self->a_icon);
RrAppearanceFree(self->a_text);
stacking_remove(self);
g_free(self);
}
}
void popup_position(Popup *self, gint gravity, gint x, gint y)
void popup_position(ObPopup *self, gint gravity, gint x, gint y)
{
self->gravity = gravity;
self->x = x;
self->y = y;
}
void popup_size(Popup *self, gint w, gint h)
void popup_size(ObPopup *self, gint w, gint h)
{
self->w = w;
self->h = h;
}
void popup_size_to_string(Popup *self, gchar *text)
void popup_size_to_string(ObPopup *self, gchar *text)
{
gint textw, texth;
gint iconw;
if (!self->a_text)
self->a_text = RrAppearanceCopy(ob_rr_theme->app_hilite_label);
self->a_text->texture[0].data.text.string = text;
RrMinsize(self->a_text, &textw, &texth);
/*XXX textw += ob_rr_theme->bevel * 2;*/
@ -109,29 +76,18 @@ void popup_size_to_string(Popup *self, gchar *text)
self->w = textw + iconw + ob_rr_theme->padding * (self->hasicon ? 3 : 2);
}
void popup_set_text_align(Popup *self, RrJustify align)
void popup_set_text_align(ObPopup *self, RrJustify align)
{
if (!self->a_text)
self->a_text = RrAppearanceCopy(ob_rr_theme->app_hilite_label);
self->a_text->texture[0].data.text.justify = align;
}
void popup_show(Popup *self, gchar *text, ObClientIcon *icon)
void popup_show(ObPopup *self, gchar *text)
{
gint l, t, r, b;
gint x, y, w, h;
gint textw, texth;
gint iconw;
/* create the shit if needed */
if (!self->a_bg)
self->a_bg = RrAppearanceCopy(ob_rr_theme->app_hilite_bg);
if (self->hasicon && !self->a_icon)
self->a_icon = RrAppearanceCopy(ob_rr_theme->a_clear_tex);
if (!self->a_text)
self->a_text = RrAppearanceCopy(ob_rr_theme->app_hilite_label);
RrMargins(self->a_bg, &l, &t, &r, &b);
XSetWindowBorderWidth(ob_display, self->bg, ob_rr_theme->bwidth);
@ -139,15 +95,6 @@ void popup_show(Popup *self, gchar *text, ObClientIcon *icon)
/* set up the textures */
self->a_text->texture[0].data.text.string = text;
if (self->hasicon) {
if (icon) {
self->a_icon->texture[0].type = RR_TEXTURE_RGBA;
self->a_icon->texture[0].data.rgba.width = icon->width;
self->a_icon->texture[0].data.rgba.height = icon->height;
self->a_icon->texture[0].data.rgba.data = icon->data;
} else
self->a_icon->texture[0].type = RR_TEXTURE_NONE;
}
/* measure the shit out */
RrMinsize(self->a_text, &textw, &texth);
@ -213,23 +160,19 @@ void popup_show(Popup *self, gchar *text, ObClientIcon *icon)
ob_rr_theme->padding * (self->hasicon ? 2 : 1);
self->a_text->surface.parenty = t + ob_rr_theme->padding;
XMoveResizeWindow(ob_display, self->text,
l + iconw + ob_rr_theme->padding * (self->hasicon ? 2 : 1),
l + iconw + ob_rr_theme->padding *
(self->hasicon ? 2 : 1),
t + ob_rr_theme->padding, textw, texth);
if (self->hasicon) {
if (iconw < 1) iconw = 1; /* sanity check for crashes */
self->a_icon->surface.parent = self->a_bg;
self->a_icon->surface.parentx = l + ob_rr_theme->padding;
self->a_icon->surface.parenty = t + ob_rr_theme->padding;
XMoveResizeWindow(ob_display, self->icon,
l + ob_rr_theme->padding, t + ob_rr_theme->padding,
iconw, texth);
}
RrPaint(self->a_bg, self->bg, w, h);
RrPaint(self->a_text, self->text, textw, texth);
if (self->hasicon)
RrPaint(self->a_icon, self->icon, iconw, texth);
if (self->hasicon) {
if (iconw < 1) iconw = 1; /* sanity check for crashes */
if (self->draw_icon)
self->draw_icon(l + ob_rr_theme->padding, t + ob_rr_theme->padding,
iconw, texth, self->draw_icon_data);
}
if (!self->mapped) {
XMapWindow(ob_display, self->bg);
@ -238,10 +181,253 @@ void popup_show(Popup *self, gchar *text, ObClientIcon *icon)
}
}
void popup_hide(Popup *self)
void popup_hide(ObPopup *self)
{
if (self->mapped) {
XUnmapWindow(ob_display, self->bg);
self->mapped = FALSE;
}
}
static void icon_popup_draw_icon(gint x, gint y, gint w, gint h, gpointer data)
{
ObIconPopup *self = data;
self->a_icon->surface.parent = self->popup->a_bg;
self->a_icon->surface.parentx = x;
self->a_icon->surface.parenty = y;
XMoveResizeWindow(ob_display, self->icon, x, y, w, h);
RrPaint(self->a_icon, self->icon, w, h);
}
ObIconPopup *icon_popup_new()
{
ObIconPopup *self;
self = g_new0(ObIconPopup, 1);
self->popup = popup_new(TRUE);
self->a_icon = RrAppearanceCopy(ob_rr_theme->a_clear_tex);
self->icon = XCreateWindow(ob_display, self->popup->bg,
0, 0, 1, 1, 0,
RrDepth(ob_rr_inst), InputOutput,
RrVisual(ob_rr_inst), 0, NULL);
XMapWindow(ob_display, self->icon);
self->popup->draw_icon = icon_popup_draw_icon;
self->popup->draw_icon_data = self;
return self;
}
void icon_popup_free(ObIconPopup *self)
{
if (self) {
XDestroyWindow(ob_display, self->icon);
RrAppearanceFree(self->a_icon);
popup_free(self->popup);
g_free(self);
}
}
void icon_popup_show(ObIconPopup *self,
gchar *text, struct _ObClientIcon *icon)
{
if (icon) {
self->a_icon->texture[0].type = RR_TEXTURE_RGBA;
self->a_icon->texture[0].data.rgba.width = icon->width;
self->a_icon->texture[0].data.rgba.height = icon->height;
self->a_icon->texture[0].data.rgba.data = icon->data;
} else
self->a_icon->texture[0].type = RR_TEXTURE_NONE;
popup_show(self->popup, text);
}
static void pager_popup_draw_icon(gint px, gint py, gint w, gint h,
gpointer data)
{
ObPagerPopup *self = data;
gint x, y;
guint i;
guint rown, n;
guint horz_inc;
guint vert_inc;
guint r, c;
gint eachw, eachh;
eachw = (w - ob_rr_theme->bwidth -
(screen_desktop_layout.columns * ob_rr_theme->bwidth))
/ screen_desktop_layout.columns;
eachh = (h - ob_rr_theme->bwidth -
(screen_desktop_layout.rows * ob_rr_theme->bwidth))
/ screen_desktop_layout.rows;
/* make them squares */
eachw = eachh = MIN(eachw, eachh);
g_message("dif %d %d %d %d ",
(screen_desktop_layout.columns * (eachw + ob_rr_theme->bwidth) +
ob_rr_theme->bwidth), w,
(screen_desktop_layout.rows * (eachh + ob_rr_theme->bwidth) +
ob_rr_theme->bwidth), h);
/* center */
px += (w - (screen_desktop_layout.columns * (eachw + ob_rr_theme->bwidth) +
ob_rr_theme->bwidth)) / 2;
py += (h - (screen_desktop_layout.rows * (eachh + ob_rr_theme->bwidth) +
ob_rr_theme->bwidth)) / 2;
g_message("%d %d %d %d", px, py, eachw, eachh);
if (eachw <= 0 || eachh <= 0)
return;
switch (screen_desktop_layout.start_corner) {
case OB_CORNER_TOPLEFT:
n = 0;
switch (screen_desktop_layout.orientation) {
case OB_ORIENTATION_HORZ:
horz_inc = 1;
vert_inc = screen_desktop_layout.columns;
break;
case OB_ORIENTATION_VERT:
horz_inc = screen_desktop_layout.rows;
vert_inc = 1;
break;
}
break;
case OB_CORNER_TOPRIGHT:
n = screen_desktop_layout.columns;
switch (screen_desktop_layout.orientation) {
case OB_ORIENTATION_HORZ:
horz_inc = -1;
vert_inc = screen_desktop_layout.columns;
break;
case OB_ORIENTATION_VERT:
horz_inc = -screen_desktop_layout.rows;
vert_inc = 1;
break;
}
break;
case OB_CORNER_BOTTOMLEFT:
n = screen_desktop_layout.rows;
switch (screen_desktop_layout.orientation) {
case OB_ORIENTATION_HORZ:
horz_inc = 1;
vert_inc = -screen_desktop_layout.columns;
break;
case OB_ORIENTATION_VERT:
horz_inc = screen_desktop_layout.rows;
vert_inc = -1;
break;
}
break;
case OB_CORNER_BOTTOMRIGHT:
n = MAX(self->desks,
screen_desktop_layout.rows * screen_desktop_layout.columns);
switch (screen_desktop_layout.orientation) {
case OB_ORIENTATION_HORZ:
horz_inc = -1;
vert_inc = -screen_desktop_layout.columns;
break;
case OB_ORIENTATION_VERT:
horz_inc = -screen_desktop_layout.rows;
vert_inc = -1;
break;
}
break;
}
g_message("%d %d %d", n, horz_inc, vert_inc);
rown = n;
i = 0;
for (r = 0, y = 0; r < screen_desktop_layout.rows;
++r, y += eachh + ob_rr_theme->bwidth)
{
for (c = 0, x = 0; c < screen_desktop_layout.columns;
++c, x += eachw + ob_rr_theme->bwidth)
{
RrAppearance *a;
g_message("i %d n %d", i, n);
if (i >= self->desks)
break;
a = (n == self->curdesk ? self->hilight : self->unhilight);
a->surface.parent = self->popup->a_bg;
a->surface.parentx = x + px;
a->surface.parenty = y + py;
XMoveResizeWindow(ob_display, self->wins[i],
x + px, y + py, eachw, eachh);
RrPaint(a, self->wins[i], eachw, eachh);
n += horz_inc;
++i;
}
n = rown += vert_inc;
}
}
ObPagerPopup *pager_popup_new()
{
ObPagerPopup *self;
self = g_new(ObPagerPopup, 1);
self->popup = popup_new(TRUE);
self->desks = 0;
self->wins = g_new(Window, self->desks);
self->hilight = RrAppearanceCopy(ob_rr_theme->app_hilite_fg);
self->unhilight = RrAppearanceCopy(ob_rr_theme->app_unhilite_fg);
self->popup->draw_icon = pager_popup_draw_icon;
self->popup->draw_icon_data = self;
return self;
}
void pager_popup_free(ObPagerPopup *self)
{
if (self) {
guint i;
for (i = 0; i < self->desks; ++i)
XDestroyWindow(ob_display, self->wins[i]);
RrAppearanceFree(self->hilight);
RrAppearanceFree(self->unhilight);
popup_free(self->popup);
g_free(self);
}
}
void pager_popup_show(ObPagerPopup *self, gchar *text, guint desk)
{
guint i;
if (screen_num_desktops < self->desks)
for (i = screen_num_desktops; i < self->desks; ++i)
XDestroyWindow(ob_display, self->wins[i]);
if (screen_num_desktops != self->desks)
self->wins = g_renew(Window, self->wins, screen_num_desktops);
if (screen_num_desktops > self->desks)
for (i = self->desks; i < screen_num_desktops; ++i) {
XSetWindowAttributes attr;
attr.border_pixel = RrColorPixel(ob_rr_theme->b_color);
self->wins[i] = XCreateWindow(ob_display, self->popup->bg,
0, 0, 1, 1, ob_rr_theme->bwidth,
RrDepth(ob_rr_inst), InputOutput,
RrVisual(ob_rr_inst), CWBorderPixel,
&attr);
XMapWindow(ob_display, self->wins[i]);
}
self->desks = screen_num_desktops;
self->curdesk = desk;
popup_show(self->popup, text);
}

View file

@ -1,33 +1,100 @@
#ifndef __popup_h
#define __popup_h
#include <glib.h>
#include "window.h"
#include "render/render.h"
#include <glib.h>
struct _ObClientIcon;
#define POPUP_WIDTH 320
#define POPUP_HEIGHT 48
typedef struct _ObPopup Popup;
typedef struct _ObPopup ObPopup;
typedef struct _ObIconPopup ObIconPopup;
typedef struct _ObPagerPopup ObPagerPopup;
Popup *popup_new(gboolean hasicon);
void popup_free(Popup *self);
struct _ObPopup
{
ObWindow obwin;
Window bg;
Window text;
gboolean hasicon;
RrAppearance *a_bg;
RrAppearance *a_text;
gint gravity;
gint x;
gint y;
gint w;
gint h;
gboolean mapped;
void (*draw_icon)(gint x, gint y, gint w, gint h, gpointer data);
gpointer draw_icon_data;
};
struct _ObIconPopup
{
ObPopup *popup;
Window icon;
RrAppearance *a_icon;
};
struct _ObPagerPopup
{
ObPopup *popup;
guint desks;
guint curdesk;
Window *wins;
RrAppearance *hilight;
RrAppearance *unhilight;
};
ObPopup *popup_new(gboolean hasicon);
void popup_free(ObPopup *self);
/*! Position the popup. The gravity rules are not the same X uses for windows,
instead of the position being the top-left of the window, the gravity
specifies which corner of the popup will be placed at the given coords.
Static and Forget gravity are equivilent to NorthWest.
*/
void popup_position(Popup *self, gint gravity, gint x, gint y);
void popup_position(ObPopup *self, gint gravity, gint x, gint y);
/*! Set the sizes for the popup. When set to 0, the size will be based on
the text size. */
void popup_size(Popup *self, gint w, gint h);
void popup_size_to_string(Popup *self, gchar *text);
void popup_size(ObPopup *self, gint w, gint h);
void popup_size_to_string(ObPopup *self, gchar *text);
void popup_set_text_align(Popup *self, RrJustify align);
void popup_set_text_align(ObPopup *self, RrJustify align);
void popup_show(Popup *self, gchar *text, struct _ObClientIcon *icon);
void popup_hide(Popup *self);
void popup_show(ObPopup *self, gchar *text);
void popup_hide(ObPopup *self);
RrAppearance *popup_icon_appearance(ObPopup *self);
ObIconPopup *icon_popup_new();
void icon_popup_free(ObIconPopup *self);
void icon_popup_show(ObIconPopup *self,
gchar *text, struct _ObClientIcon *icon);
#define icon_popup_hide(p) popup_hide((p)->popup)
#define icon_popup_position(p, g, x, y) popup_position((p)->popup,(g),(x),(y))
#define icon_popup_size(p, w, h) popup_size((p)->popup,(w),(h))
#define icon_popup_size_to_string(p, s) popup_size_to_string((p)->popup,(s))
#define icon_popup_set_text_align(p, j) popup_set_text_align((p)->popup,(j))
ObPagerPopup *pager_popup_new();
void pager_popup_free(ObPagerPopup *self);
void pager_popup_show(ObPagerPopup *self, gchar *text, guint desk);
#define pager_popup_hide(p) popup_hide((p)->popup)
#define pager_popup_position(p, g, x, y) popup_position((p)->popup,(g),(x),(y))
#define pager_popup_size(p, w, h) popup_size((p)->popup,(w),(h))
#define pager_popup_size_to_string(p, s) popup_size_to_string((p)->popup,(s))
#define pager_popup_set_text_align(p, j) popup_set_text_align((p)->popup,(j))
#endif

View file

@ -41,7 +41,7 @@ Window screen_support_win;
static Rect **area; /* array of desktop holding array of xinerama areas */
static Rect *monitor_area;
static Popup *desktop_cycle_popup;
static ObPagerPopup *desktop_cycle_popup;
static gboolean replace_wm()
{
@ -252,7 +252,7 @@ void screen_startup(gboolean reconfig)
GSList *it;
guint i;
desktop_cycle_popup = popup_new(FALSE);
desktop_cycle_popup = pager_popup_new(FALSE);
if (!reconfig)
/* get the initial size */
@ -288,7 +288,7 @@ void screen_shutdown(gboolean reconfig)
{
Rect **r;
popup_free(desktop_cycle_popup);
pager_popup_free(desktop_cycle_popup);
if (!reconfig) {
XSelectInput(ob_display, RootWindow(ob_display, ob_screen),
@ -560,19 +560,18 @@ static void popup_cycle(guint d, gboolean show)
Rect *a;
if (!show) {
popup_hide(desktop_cycle_popup);
pager_popup_hide(desktop_cycle_popup);
} else {
a = screen_physical_area_monitor(0);
popup_position(desktop_cycle_popup, CenterGravity,
a->x + a->width / 2, a->y + a->height / 2);
pager_popup_position(desktop_cycle_popup, CenterGravity,
a->x + a->width / 2, a->y + a->height / 2);
/* XXX the size and the font extents need to be related on some level
*/
popup_size(desktop_cycle_popup, POPUP_WIDTH, POPUP_HEIGHT);
pager_popup_size(desktop_cycle_popup, POPUP_WIDTH, POPUP_HEIGHT);
popup_set_text_align(desktop_cycle_popup, RR_JUSTIFY_CENTER);
pager_popup_set_text_align(desktop_cycle_popup, RR_JUSTIFY_CENTER);
popup_show(desktop_cycle_popup,
screen_desktop_names[d], NULL);
pager_popup_show(desktop_cycle_popup, screen_desktop_names[d], d);
}
}
@ -723,31 +722,39 @@ void screen_update_layout()
goto screen_update_layout_bail;
}
cols = data[1];
rows = data[2];
/* fill in a zero rows/columns */
if ((data[1] == 0 && data[2] == 0) || /* both 0's is bad data.. */
(data[1] != 0 && data[2] != 0)) { /* no 0's is bad data.. */
if ((cols == 0 && rows == 0)) { /* both 0's is bad data.. */
goto screen_update_layout_bail;
} else {
if (data[1] == 0) {
data[1] = (screen_num_desktops +
screen_num_desktops % data[2]) / data[2];
} else if (data[2] == 0) {
data[2] = (screen_num_desktops +
screen_num_desktops % data[1]) / data[1];
if (cols == 0) {
cols = screen_num_desktops / rows;
if (rows * cols < screen_num_desktops)
cols++;
if (rows * cols >= screen_num_desktops + cols)
rows--;
} else if (rows == 0) {
rows = screen_num_desktops / rows;
if (cols * rows < screen_num_desktops)
rows++;
if (cols * rows >= screen_num_desktops + rows)
cols--;
}
cols = data[1];
rows = data[2];
}
/* bounds checking */
if (orient == OB_ORIENTATION_HORZ) {
rows = MIN(rows, screen_num_desktops);
cols = MIN(cols, ((screen_num_desktops +
(screen_num_desktops % rows)) / rows));
cols = MIN(screen_num_desktops, cols);
rows = MIN(rows, (screen_num_desktops + cols - 1) / cols);
cols = screen_num_desktops / rows +
!!(screen_num_desktops % rows);
} else {
cols = MIN(cols, screen_num_desktops);
rows = MIN(rows, ((screen_num_desktops +
(screen_num_desktops % cols)) / cols));
rows = MIN(screen_num_desktops, rows);
cols = MIN(cols, (screen_num_desktops + rows - 1) / rows);
rows = screen_num_desktops / cols +
!!(screen_num_desktops % cols);
}
valid = TRUE;