+ event_end_ignore_all_enters(ignore_start);
+
+ if (event_curtime != CurrentTime)
+ screen_desktop_user_time = event_curtime;
+}
+
+void screen_add_desktop(gboolean current)
+{
+ screen_set_num_desktops(screen_num_desktops+1);
+
+ /* move all the clients over */
+ if (current) {
+ GList *it;
+
+ for (it = client_list; it; it = g_list_next(it)) {
+ ObClient *c = it->data;
+ if (c->desktop != DESKTOP_ALL && c->desktop >= screen_desktop &&
+ /* don't move direct children, they'll be moved with their
+ parent - which will have to be on the same desktop */
+ !client_direct_parent(c))
+ {
+ ob_debug("moving window %s\n", c->title);
+ client_set_desktop(c, c->desktop+1, FALSE, TRUE);
+ }
+ }
+ }
+}
+
+void screen_remove_desktop(gboolean current)
+{
+ guint rmdesktop, movedesktop;
+ GList *it, *stacking_copy;
+
+ if (screen_num_desktops <= 1) return;
+
+ /* what desktop are we removing and moving to? */
+ if (current)
+ rmdesktop = screen_desktop;
+ else
+ rmdesktop = screen_num_desktops - 1;
+ if (rmdesktop < screen_num_desktops - 1)
+ movedesktop = rmdesktop + 1;
+ else
+ movedesktop = rmdesktop;
+
+ /* make a copy of the list cuz we're changing it */
+ stacking_copy = g_list_copy(stacking_list);
+ for (it = g_list_last(stacking_copy); it; it = g_list_previous(it)) {
+ if (WINDOW_IS_CLIENT(it->data)) {
+ ObClient *c = it->data;
+ guint d = c->desktop;
+ if (d != DESKTOP_ALL && d >= movedesktop &&
+ /* don't move direct children, they'll be moved with their
+ parent - which will have to be on the same desktop */
+ !client_direct_parent(c))
+ {
+ ob_debug("moving window %s\n", c->title);
+ client_set_desktop(c, c->desktop - 1, TRUE, TRUE);
+ }
+ /* raise all the windows that are on the current desktop which
+ is being merged */
+ if ((screen_desktop == rmdesktop - 1 ||
+ screen_desktop == rmdesktop) &&
+ (d == DESKTOP_ALL || d == screen_desktop))
+ {
+ stacking_raise(CLIENT_AS_WINDOW(c));
+ ob_debug("raising window %s\n", c->title);
+ }
+ }
+ }
+
+ /* act like we're changing desktops */
+ if (screen_desktop < screen_num_desktops - 1) {
+ gint d = screen_desktop;
+ screen_desktop = screen_last_desktop;
+ screen_set_desktop(d, TRUE);
+ ob_debug("fake desktop change\n");
+ }
+
+ screen_set_num_desktops(screen_num_desktops-1);
+}
+
+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;
+}
+
+void screen_desktop_popup(guint d, gboolean show)
+{
+ Rect *a;
+
+ if (!show) {
+ pager_popup_hide(desktop_cycle_popup);
+ } else {
+ a = screen_physical_area_active();
+ pager_popup_position(desktop_cycle_popup, CenterGravity,
+ a->x + a->width / 2, a->y + a->height / 2);
+ pager_popup_icon_size_multiplier(desktop_cycle_popup,
+ (screen_desktop_layout.columns /
+ screen_desktop_layout.rows) / 2,
+ (screen_desktop_layout.rows/
+ screen_desktop_layout.columns) / 2);
+ pager_popup_max_width(desktop_cycle_popup,
+ MAX(a->width/3, POPUP_WIDTH));
+ pager_popup_show(desktop_cycle_popup, screen_desktop_names[d], d);
+ }
+}
+
+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;
+}
+
+guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
+ gboolean dialog, gboolean done, gboolean cancel)
+{
+ static guint d = (guint)-1;
+ guint ret;
+
+ if (d == (guint)-1)
+ d = screen_desktop;
+
+ if ((!cancel && !done) || !dialog)
+ d = screen_find_desktop(d, dir, wrap, linear);
+
+ if (dialog && !cancel && !done)
+ screen_desktop_popup(d, TRUE);
+ else
+ screen_desktop_popup(0, FALSE);
+ ret = d;
+
+ if (!dialog || cancel || done)
+ d = (guint)-1;