+static void get_row_col(guint d, guint *r, guint *c)
+{
+ switch (screen_desktop_layout.orientation) {
+ case OB_ORIENTATION_HORZ:
+ switch (screen_desktop_layout.start_corner) {
+ case OB_CORNER_TOPLEFT:
+ *r = d / screen_desktop_layout.columns;
+ *c = d % screen_desktop_layout.columns;
+ break;
+ case OB_CORNER_BOTTOMLEFT:
+ *r = screen_desktop_layout.rows - 1 -
+ d / screen_desktop_layout.columns;
+ *c = d % screen_desktop_layout.columns;
+ break;
+ case OB_CORNER_TOPRIGHT:
+ *r = d / screen_desktop_layout.columns;
+ *c = screen_desktop_layout.columns - 1 -
+ d % screen_desktop_layout.columns;
+ break;
+ case OB_CORNER_BOTTOMRIGHT:
+ *r = screen_desktop_layout.rows - 1 -
+ d / screen_desktop_layout.columns;
+ *c = screen_desktop_layout.columns - 1 -
+ d % screen_desktop_layout.columns;
+ break;
+ }
+ break;
+ case OB_ORIENTATION_VERT:
+ switch (screen_desktop_layout.start_corner) {
+ case OB_CORNER_TOPLEFT:
+ *r = d % screen_desktop_layout.rows;
+ *c = d / screen_desktop_layout.rows;
+ break;
+ case OB_CORNER_BOTTOMLEFT:
+ *r = screen_desktop_layout.rows - 1 -
+ d % screen_desktop_layout.rows;
+ *c = d / screen_desktop_layout.rows;
+ break;
+ case OB_CORNER_TOPRIGHT:
+ *r = d % screen_desktop_layout.rows;
+ *c = screen_desktop_layout.columns - 1 -
+ d / screen_desktop_layout.rows;
+ break;
+ case OB_CORNER_BOTTOMRIGHT:
+ *r = screen_desktop_layout.rows - 1 -
+ d % screen_desktop_layout.rows;
+ *c = screen_desktop_layout.columns - 1 -
+ d / screen_desktop_layout.rows;
+ break;
+ }
+ break;
+ }
+}
+
+static guint translate_row_col(guint r, guint c)
+{
+ switch (screen_desktop_layout.orientation) {
+ case OB_ORIENTATION_HORZ:
+ switch (screen_desktop_layout.start_corner) {
+ case OB_CORNER_TOPLEFT:
+ return r % screen_desktop_layout.rows *
+ screen_desktop_layout.columns +
+ c % screen_desktop_layout.columns;
+ case OB_CORNER_BOTTOMLEFT:
+ return (screen_desktop_layout.rows - 1 -
+ r % screen_desktop_layout.rows) *
+ screen_desktop_layout.columns +
+ c % screen_desktop_layout.columns;
+ case OB_CORNER_TOPRIGHT:
+ return r % screen_desktop_layout.rows *
+ screen_desktop_layout.columns +
+ (screen_desktop_layout.columns - 1 -
+ c % screen_desktop_layout.columns);
+ case OB_CORNER_BOTTOMRIGHT:
+ return (screen_desktop_layout.rows - 1 -
+ r % screen_desktop_layout.rows) *
+ screen_desktop_layout.columns +
+ (screen_desktop_layout.columns - 1 -
+ c % screen_desktop_layout.columns);
+ }
+ case OB_ORIENTATION_VERT:
+ switch (screen_desktop_layout.start_corner) {
+ case OB_CORNER_TOPLEFT:
+ return c % screen_desktop_layout.columns *
+ screen_desktop_layout.rows +
+ r % screen_desktop_layout.rows;
+ case OB_CORNER_BOTTOMLEFT:
+ return c % screen_desktop_layout.columns *
+ screen_desktop_layout.rows +
+ (screen_desktop_layout.rows - 1 -
+ r % screen_desktop_layout.rows);
+ case OB_CORNER_TOPRIGHT:
+ return (screen_desktop_layout.columns - 1 -
+ c % screen_desktop_layout.columns) *
+ screen_desktop_layout.rows +
+ r % screen_desktop_layout.rows;
+ case OB_CORNER_BOTTOMRIGHT:
+ return (screen_desktop_layout.columns - 1 -
+ c % screen_desktop_layout.columns) *
+ screen_desktop_layout.rows +
+ (screen_desktop_layout.rows - 1 -
+ r % screen_desktop_layout.rows);
+ }
+ }
+ g_assert_not_reached();
+ return 0;
+}
+
+static gboolean hide_desktop_popup_func(gpointer data)
+{
+ pager_popup_hide(desktop_popup);
+ return FALSE; /* don't repeat */
+}
+
+void screen_show_desktop_popup(guint d, gboolean perm)
+{
+ const Rect *a;
+
+ /* 0 means don't show the popup */
+ if (!config_desktop_popup_time) return;
+
+ a = screen_physical_area_primary(FALSE);
+ pager_popup_position(desktop_popup, CenterGravity,
+ a->x + a->width / 2, a->y + a->height / 2);
+ pager_popup_icon_size_multiplier(desktop_popup,
+ (screen_desktop_layout.columns /
+ screen_desktop_layout.rows) / 2,
+ (screen_desktop_layout.rows/
+ screen_desktop_layout.columns) / 2);
+ pager_popup_max_width(desktop_popup,
+ MAX(a->width/3, POPUP_WIDTH));
+ pager_popup_show(desktop_popup, screen_desktop_names[d], d);
+
+ obt_main_loop_timeout_remove(ob_main_loop, hide_desktop_popup_func);
+ if (!perm && !desktop_popup_perm)
+ /* only hide if its not already being show permanently */
+ obt_main_loop_timeout_add(ob_main_loop,
+ config_desktop_popup_time * 1000,
+ hide_desktop_popup_func, desktop_popup,
+ g_direct_equal, NULL);
+ if (perm)
+ desktop_popup_perm = TRUE;
+}
+
+void screen_hide_desktop_popup(void)
+{
+ obt_main_loop_timeout_remove_data(ob_main_loop, hide_desktop_popup_func,
+ desktop_popup, FALSE);
+ pager_popup_hide(desktop_popup);
+ desktop_popup_perm = FALSE;
+}
+
+guint screen_find_desktop(guint from, ObDirection dir,
+ gboolean wrap, gboolean linear)
+{
+ guint r, c;
+ guint d;
+
+ d = from;
+ get_row_col(d, &r, &c);
+ if (linear) {
+ switch (dir) {
+ case OB_DIRECTION_EAST:
+ if (d < screen_num_desktops - 1)
+ ++d;
+ else if (wrap)
+ d = 0;
+ else
+ return from;
+ break;
+ case OB_DIRECTION_WEST:
+ if (d > 0)
+ --d;
+ else if (wrap)
+ d = screen_num_desktops - 1;
+ else
+ return from;
+ break;
+ default:
+ g_assert_not_reached();
+ return from;
+ }
+ } else {
+ switch (dir) {
+ case OB_DIRECTION_EAST:
+ ++c;
+ if (c >= screen_desktop_layout.columns) {
+ if (wrap)
+ c = 0;
+ else
+ return from;
+ }
+ d = translate_row_col(r, c);
+ if (d >= screen_num_desktops) {
+ if (wrap)
+ ++c;
+ else
+ return from;
+ }
+ break;
+ case OB_DIRECTION_WEST:
+ --c;
+ if (c >= screen_desktop_layout.columns) {
+ if (wrap)
+ c = screen_desktop_layout.columns - 1;
+ else
+ return from;
+ }
+ d = translate_row_col(r, c);
+ if (d >= screen_num_desktops) {
+ if (wrap)
+ --c;
+ else
+ return from;
+ }
+ break;
+ case OB_DIRECTION_SOUTH:
+ ++r;
+ if (r >= screen_desktop_layout.rows) {
+ if (wrap)
+ r = 0;
+ else
+ return from;
+ }
+ d = translate_row_col(r, c);
+ if (d >= screen_num_desktops) {
+ if (wrap)
+ ++r;
+ else
+ return from;
+ }
+ break;
+ case OB_DIRECTION_NORTH:
+ --r;
+ if (r >= screen_desktop_layout.rows) {
+ if (wrap)
+ r = screen_desktop_layout.rows - 1;
+ else
+ return from;
+ }
+ d = translate_row_col(r, c);
+ if (d >= screen_num_desktops) {
+ if (wrap)
+ --r;
+ else
+ return from;
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ return from;
+ }
+
+ d = translate_row_col(r, c);
+ }
+ return d;
+}
+
+static gboolean screen_validate_layout(ObDesktopLayout *l)
+{
+ if (l->columns == 0 && l->rows == 0) /* both 0's is bad data.. */
+ return FALSE;
+
+ /* fill in a zero rows/columns */
+ if (l->columns == 0) {
+ l->columns = screen_num_desktops / l->rows;
+ if (l->rows * l->columns < screen_num_desktops)
+ l->columns++;
+ if (l->rows * l->columns >= screen_num_desktops + l->columns)
+ l->rows--;
+ } else if (l->rows == 0) {
+ l->rows = screen_num_desktops / l->columns;
+ if (l->columns * l->rows < screen_num_desktops)
+ l->rows++;
+ if (l->columns * l->rows >= screen_num_desktops + l->rows)
+ l->columns--;
+ }
+
+ /* bounds checking */
+ if (l->orientation == OB_ORIENTATION_HORZ) {
+ l->columns = MIN(screen_num_desktops, l->columns);
+ l->rows = MIN(l->rows,
+ (screen_num_desktops + l->columns - 1) / l->columns);
+ l->columns = screen_num_desktops / l->rows +
+ !!(screen_num_desktops % l->rows);
+ } else {
+ l->rows = MIN(screen_num_desktops, l->rows);
+ l->columns = MIN(l->columns,
+ (screen_num_desktops + l->rows - 1) / l->rows);
+ l->rows = screen_num_desktops / l->columns +
+ !!(screen_num_desktops % l->columns);
+ }
+ return TRUE;
+}
+
+void screen_update_layout(void)
+
+{
+ ObDesktopLayout l;
+ guint32 *data;
+ guint num;
+
+ screen_desktop_layout.orientation = OB_ORIENTATION_HORZ;
+ screen_desktop_layout.start_corner = OB_CORNER_TOPLEFT;