From 34e819738b344a992a1dbfd6cdd165e0c8ddb3a9 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Fri, 27 Jun 2003 04:20:30 +0000 Subject: [PATCH] xinerama support --- openbox/client.c | 95 +++++++---- openbox/client.h | 2 + openbox/dock.c | 25 +-- openbox/extensions.c | 41 +++++ openbox/extensions.h | 6 +- openbox/focus.c | 2 +- openbox/geom.h | 10 +- openbox/menu.c | 23 ++- openbox/menu.h | 1 + openbox/moveresize.c | 12 +- openbox/screen.c | 290 ++++++++++++++++++++------------ openbox/screen.h | 10 +- plugins/menu/client_menu.c | 2 + plugins/placement/placement.c | 3 +- plugins/resistance/resistance.c | 6 +- 15 files changed, 361 insertions(+), 167 deletions(-) diff --git a/openbox/client.c b/openbox/client.c index e704237f..11e42a0e 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -288,13 +288,13 @@ void client_manage(Window window) stacking_add(CLIENT_AS_WINDOW(self)); } - screen_update_struts(); - dispatch_client(Event_Client_New, self, 0, 0); /* make sure the window is visible */ client_move_onscreen(self); + screen_update_areas(); + client_showhide(self); if (activate) client_activate(self); @@ -347,7 +347,7 @@ void client_unmanage(Client *self) /* once the client is out of the list, update the struts to remove it's influence */ - screen_update_struts(); + screen_update_areas(); /* tell our parent(s) that we're gone */ if (self->transient_for == TRAN_GROUP) { /* transient of group */ @@ -440,6 +440,7 @@ void client_move_onscreen(Client *self) Rect *a; int x = self->frame->area.x, y = self->frame->area.y; + /* XXX watch for xinerama dead areas */ a = screen_area(self->desktop); if (x >= a->x + a->width - 1) x = a->x + a->width - self->frame->area.width; @@ -1297,7 +1298,7 @@ void client_update_strut(Client *self) /* updating here is pointless while we're being mapped cuz we're not in the client list yet */ if (self->frame) - screen_update_struts(); + screen_update_areas(); } void client_update_icons(Client *self) @@ -1620,35 +1621,47 @@ void client_configure(Client *self, Corner anchor, int x, int y, int w, int h, #ifdef VIDMODE int dot; XF86VidModeModeLine mode; +#endif + Rect *a; + guint i; - if (extensions_vidmode && + i = client_xinerama_area(self); + a = screen_physical_area_xinerama(i); + +#ifdef VIDMODE + if (i == 0 && /* primary head */ + extensions_vidmode && + XF86VidModeGetViewPort(ob_display, ob_screen, &x, &y) && + /* get the mode last so the mode.privsize isnt freed incorrectly */ XF86VidModeGetModeLine(ob_display, ob_screen, &dot, &mode)) { + x += a->x; + y += a->y; w = mode.hdisplay; h = mode.vdisplay; if (mode.privsize) XFree(mode.private); - } else { -#else - w = screen_physical_size.width; - h = screen_physical_size.height; -#endif -#ifdef VIDMODE - } - if (!(extensions_vidmode && - XF86VidModeGetViewPort(ob_display, ob_screen, &x, &y))) { - x = y = 0; + } else #endif + { + x = a->x; + y = a->y; + w = a->width; + h = a->height; } + user = FALSE; /* ignore that increment etc shit when in fullscreen */ } else { + Rect *a; + + a = screen_area_xinerama(self->desktop, client_xinerama_area(self)); + /* set the size and position if maximized */ if (self->max_horz) { - x = screen_area(self->desktop)->x - self->frame->size.left; - w = screen_area(self->desktop)->width; + x = a->x - self->frame->size.left; + w = a->width; } if (self->max_vert) { - y = screen_area(self->desktop)->y; - h = screen_area(self->desktop)->height - - self->frame->size.top - self->frame->size.bottom; + y = a->y; + h = a->height - self->frame->size.top - self->frame->size.bottom; } } @@ -1841,14 +1854,14 @@ void client_fullscreen(Client *self, gboolean fs, gboolean savearea) } else { guint num; gint32 *dimensions; + Rect *a; /* pick some fallbacks... */ - x = screen_area(self->desktop)->x + - screen_area(self->desktop)->width / 4; - y = screen_area(self->desktop)->y + - screen_area(self->desktop)->height / 4; - w = screen_area(self->desktop)->width / 2; - h = screen_area(self->desktop)->height / 2; + a = screen_area_xinerama(self->desktop, 0); + x = a->x + a->width / 4; + y = a->y + a->height / 4; + w = a->width / 2; + h = a->height / 2; if (PROP_GETA32(self->window, openbox_premax, cardinal, (guint32**)&dimensions, &num)) { @@ -1930,7 +1943,7 @@ void client_iconify(Client *self, gboolean iconic, gboolean curdesk) } client_change_state(self); client_showhide(self); - screen_update_struts(); + screen_update_areas(); dispatch_client(iconic ? Event_Client_Unmapped : Event_Client_Mapped, self, 0, 0); @@ -1998,17 +2011,17 @@ void client_maximize(Client *self, gboolean max, int dir, gboolean savearea) } else { guint num; gint32 *dimensions; + Rect *a; /* pick some fallbacks... */ + a = screen_area_xinerama(self->desktop, 0); if (dir == 0 || dir == 1) { /* horz */ - x = screen_area(self->desktop)->x + - screen_area(self->desktop)->width / 4; - w = screen_area(self->desktop)->width / 2; + x = a->x + a->width / 4; + w = a->width / 2; } if (dir == 0 || dir == 2) { /* vert */ - y = screen_area(self->desktop)->y + - screen_area(self->desktop)->height / 4; - h = screen_area(self->desktop)->height / 2; + y = a->y + a->height / 4; + h = a->height / 2; } if (PROP_GETA32(self->window, openbox_premax, cardinal, @@ -2112,7 +2125,7 @@ void client_set_desktop(Client *self, guint target, gboolean donthide) /* raise if it was not already on the desktop */ if (old != DESKTOP_ALL) stacking_raise(CLIENT_AS_WINDOW(self)); - screen_update_struts(); + screen_update_areas(); /* add to the new desktop(s) */ if (config_focus_new) @@ -2548,3 +2561,17 @@ void client_set_layer(Client *self, int layer) client_calc_layer(self); client_change_state(self); /* reflect this in the state hints */ } + +guint client_xinerama_area(Client *self) +{ + guint i; + + for (i = 0; i < screen_num_xin_areas; ++i) { + Rect *area = screen_physical_area_xinerama(i); + if (RECT_INTERSECTS_RECT(*area, self->frame->area)) + break; + } + if (i == screen_num_xin_areas) i = 0; + g_assert(i < screen_num_xin_areas); + return i; +} diff --git a/openbox/client.h b/openbox/client.h index ff7f67c7..495eef81 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -506,4 +506,6 @@ Client *client_find_directional(Client *c, Direction dir); */ void client_set_layer(Client *self, int layer); +guint client_xinerama_area(Client *self); + #endif diff --git a/openbox/dock.c b/openbox/dock.c index d46f7674..4166ba22 100644 --- a/openbox/dock.c +++ b/openbox/dock.c @@ -151,6 +151,7 @@ void dock_configure() int spot; int gravity; int minw, minh; + Rect *a; RrMinsize(dock->a_frame, &minw, &minh); @@ -190,6 +191,8 @@ void dock_configure() dock->w += ob_rr_theme->bwidth * 2; dock->h += ob_rr_theme->bwidth * 2; + a = screen_physical_area(); + /* calculate position */ switch (config_dock_pos) { case DockPos_Floating: @@ -203,38 +206,38 @@ void dock_configure() gravity = NorthWestGravity; break; case DockPos_Top: - dock->x = screen_physical_size.width / 2; + dock->x = a->width / 2; dock->y = 0; gravity = NorthGravity; break; case DockPos_TopRight: - dock->x = screen_physical_size.width; + dock->x = a->width; dock->y = 0; gravity = NorthEastGravity; break; case DockPos_Left: dock->x = 0; - dock->y = screen_physical_size.height / 2; + dock->y = a->height / 2; gravity = WestGravity; break; case DockPos_Right: - dock->x = screen_physical_size.width; - dock->y = screen_physical_size.height / 2; + dock->x = a->width; + dock->y = a->height / 2; gravity = EastGravity; break; case DockPos_BottomLeft: dock->x = 0; - dock->y = screen_physical_size.height; + dock->y = a->height; gravity = SouthWestGravity; break; case DockPos_Bottom: - dock->x = screen_physical_size.width / 2; - dock->y = screen_physical_size.height; + dock->x = a->width / 2; + dock->y = a->height; gravity = SouthGravity; break; case DockPos_BottomRight: - dock->x = screen_physical_size.width; - dock->y = screen_physical_size.height; + dock->x = a->width; + dock->y = a->height; gravity = SouthEastGravity; break; } @@ -370,7 +373,7 @@ void dock_configure() dock->w += ob_rr_theme->bwidth * 2; dock->h += ob_rr_theme->bwidth * 2; - screen_update_struts(); + screen_update_areas(); } void dock_app_configure(DockApp *app, int w, int h) diff --git a/openbox/extensions.c b/openbox/extensions.c index be1ac547..ddcb83bb 100644 --- a/openbox/extensions.c +++ b/openbox/extensions.c @@ -1,5 +1,7 @@ #include "openbox.h" +#include "geom.h" #include "extensions.h" +#include "screen.h" gboolean extensions_xkb = FALSE; int extensions_xkb_event_basep; @@ -7,6 +9,7 @@ gboolean extensions_shape = FALSE; int extensions_shape_event_basep; gboolean extensions_xinerama = FALSE; int extensions_xinerama_event_basep; +gboolean extensions_xinerama_active = FALSE; gboolean extensions_randr = FALSE; int extensions_randr_event_basep; gboolean extensions_vidmode = FALSE; @@ -33,6 +36,7 @@ void extensions_query_all() extensions_xinerama = XineramaQueryExtension(ob_display, &extensions_xinerama_event_basep, &junk); + extensions_xinerama_active = XineramaIsActive(ob_display); #endif #ifdef XRANDR @@ -47,3 +51,40 @@ void extensions_query_all() &junk); #endif } + +void extensions_xinerama_screens(Rect **xin_areas, guint *nxin) +{ + guint i; + gint l, r, t, b; +#ifdef XINERAMA + if (extensions_xinerama_active) { + guint i; + gint n; + XineramaScreenInfo *info = XineramaQueryScreens(ob_display, &n); + *nxin = n; + *xin_areas = g_new(Rect, *nxin + 1); + for (i = 0; i < *nxin; ++i) + RECT_SET((*xin_areas)[i], info[i].x_org, info[i].y_org, + info[i].width, info[i].height); + } else +#endif + { + *nxin = 1; + *xin_areas = g_new(Rect, *nxin + 1); + RECT_SET((*xin_areas)[0], 0, 0, + screen_physical_size.width, screen_physical_size.height); + } + + /* returns one extra with the total area in it */ + l = (*xin_areas)[0].x; + t = (*xin_areas)[0].y; + r = (*xin_areas)[0].x + (*xin_areas)[0].width - 1; + b = (*xin_areas)[0].y + (*xin_areas)[0].height - 1; + for (i = 1; i < *nxin; ++i) { + l = MIN(l, (*xin_areas)[i].x); + t = MIN(l, (*xin_areas)[i].y); + r = MIN(r, (*xin_areas)[0].x + (*xin_areas)[0].width - 1); + b = MIN(b, (*xin_areas)[0].y + (*xin_areas)[0].height - 1); + } + RECT_SET((*xin_areas)[*nxin], l, t, r - l + 1, b - t + 1); +} diff --git a/openbox/extensions.h b/openbox/extensions.h index cda1bf7e..c07076e7 100644 --- a/openbox/extensions.h +++ b/openbox/extensions.h @@ -33,6 +33,8 @@ extern int extensions_shape_event_basep; extern gboolean extensions_xinerama; /*! Base for events for the Xinerama extension */ extern int extensions_xinerama_event_basep; +/*! Is Xinerama enabled? */ +extern gboolean extensions_xinerama_active; /*! Does the display have the RandR extension? */ extern gboolean extensions_randr; @@ -45,5 +47,7 @@ extern gboolean extensions_vidmode; extern int extensions_vidmode_event_basep; void extensions_query_all(); - + +void extensions_xinerama_screens(Rect **xin_areas, guint *nxin); + #endif diff --git a/openbox/focus.c b/openbox/focus.c index 0a88865a..ad18d974 100644 --- a/openbox/focus.c +++ b/openbox/focus.c @@ -247,7 +247,7 @@ static void popup_cycle(Client *c, gboolean show) Client *p = c; char *title; - a = screen_area(c->desktop); + a = screen_physical_area_xinerama(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); diff --git a/openbox/geom.h b/openbox/geom.h index a4c1752a..5f2c030c 100644 --- a/openbox/geom.h +++ b/openbox/geom.h @@ -34,8 +34,14 @@ typedef struct Rect { (r1).height == (r2).height) #define RECT_CONTAINS(r, x, y) \ - (x >= (r).x && x < (r).x + (r).width && \ - y >= (r).y && y < (r).y + (r).height) + ((x) >= (r).x && (x) < (r).x + (r).width && \ + (y) >= (r).y && (y) < (r).y + (r).height) +#define RECT_CONTAINS_RECT(r, o) \ + ((o).x >= (r).x && (o).x + (o).width <= (r).x + (r).width && \ + (o).y >= (r).y && (o).y + (o).height <= (r).y + (r).height) +#define RECT_INTERSECTS_RECT(r, o) \ + ((o).x < (r).x + (r).width && (o).x + (o).width > (r).x && \ + (o).y < (r).y + (r).height && (o).y + (o).height > (r).y) typedef struct Strut { int left; diff --git a/openbox/menu.c b/openbox/menu.c index 15a6cc50..9993b350 100644 --- a/openbox/menu.c +++ b/openbox/menu.c @@ -398,11 +398,22 @@ void menu_entry_fire(MenuEntry *self) */ void menu_control_show(Menu *self, int x, int y, Client *client) { + guint i; + Rect *a = NULL; + g_assert(!self->invalid); - POINT_SET(self->location, - MIN(x, screen_physical_size.width - self->size.width), - MIN(y, screen_physical_size.height - self->size.height)); + for (i = 0; i < screen_num_xin_areas; ++i) { + a = screen_physical_area_xinerama(i); + if (RECT_CONTAINS(*a, x, y)) + break; + } + g_assert(a != NULL); + self->xin_area = i; + + POINT_SET(self->location, + MIN(x, a->x + a->width - 1 - self->size.width), + MIN(y, a->y + a->height - 1 - self->size.height)); XMoveWindow(ob_display, self->frame, self->location.x, self->location.y); if (!self->shown) { @@ -416,6 +427,8 @@ void menu_control_show(Menu *self, int x, int y, Client *client) { void menu_control_mouseover(MenuEntry *self, gboolean enter) { int x; + Rect *a; + self->hilite = enter; if (enter) { @@ -436,7 +449,9 @@ void menu_control_mouseover(MenuEntry *self, gboolean enter) { /* need to get the width. is this bad?*/ menu_render(self->submenu); - if (self->submenu->size.width + x >= screen_physical_size.width) + a = screen_physical_area_xinerama(self->parent->xin_area); + + if (self->submenu->size.width + x >= a->x + a->width) x = self->parent->location.x - self->submenu->size.width - ob_rr_theme->bwidth; diff --git a/openbox/menu.h b/openbox/menu.h index ea5d7454..9ca78880 100644 --- a/openbox/menu.h +++ b/openbox/menu.h @@ -55,6 +55,7 @@ typedef struct Menu { int item_h; Point location; Size size; + guint xin_area; /* index of the xinerama head/area */ /* plugin stuff */ char *plugin; diff --git a/openbox/moveresize.c b/openbox/moveresize.c index 287d4ec0..570283c4 100644 --- a/openbox/moveresize.c +++ b/openbox/moveresize.c @@ -49,7 +49,6 @@ void moveresize_startup() popup = popup_new(FALSE); popup_size_to_string(popup, "W: 0000 W: 0000"); - popup_position(popup, NorthWestGravity, POPUP_X, POPUP_Y); attrib.save_under = True; opaque_window.win = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0, @@ -80,8 +79,12 @@ void moveresize_shutdown() static void popup_coords(char *format, int a, int b) { char *text; + Rect *area; text = g_strdup_printf(format, a, b); + area = screen_physical_area_xinerama(0); + popup_position(popup, NorthWestGravity, + POPUP_X + area->x, POPUP_Y + area->y); popup_show(popup, text, NULL); g_free(text); } @@ -89,6 +92,7 @@ static void popup_coords(char *format, int a, int b) void moveresize_start(Client *c, int x, int y, guint b, guint32 cnr) { Cursor cur; + Rect *a; g_assert(!moveresize_in_progress); @@ -147,8 +151,10 @@ void moveresize_start(Client *c, int x, int y, guint b, guint32 cnr) grab_pointer(TRUE, cur); grab_keyboard(TRUE); - XResizeWindow(ob_display, opaque_window.win, screen_physical_size.width, - screen_physical_size.height); + a = screen_physical_area(); + + XMoveResizeWindow(ob_display, opaque_window.win, + a->x, a->y, a->width, a->height); stacking_raise(INTERNAL_AS_WINDOW(&opaque_window)); if (corner == prop_atoms.net_wm_moveresize_move || corner == prop_atoms.net_wm_moveresize_move_keyboard) { diff --git a/openbox/screen.c b/openbox/screen.c index a1bf55fa..53ba2702 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -31,14 +31,16 @@ ButtonPressMask | ButtonReleaseMask | ButtonMotionMask) guint screen_num_desktops = 0; +guint screen_num_xin_areas = 0; guint screen_desktop = 0; Size screen_physical_size; gboolean screen_showing_desktop; DesktopLayout screen_desktop_layout; char **screen_desktop_names = NULL; -static Rect *area = NULL; -static Strut *strut = NULL; +static Rect **area = NULL; /* array of desktop holding array of + xinerama areas */ +static Rect *xin_areas = NULL; static Window support_window = None; #ifdef USE_LIBSN @@ -49,7 +51,6 @@ static Timer *sn_timer = NULL; static void sn_event_func(SnMonitorEvent *event, void *data); #endif -static void screen_update_area(); static void set_root_cursor(); static gboolean running; @@ -212,6 +213,8 @@ void screen_startup() void screen_shutdown() { + Rect **r; + XSelectInput(ob_display, ob_root, NoEventMask); PROP_ERASE(ob_root, openbox_pid); /* we're not running here no more! */ @@ -221,7 +224,8 @@ void screen_shutdown() XDestroyWindow(ob_display, support_window); g_strfreev(screen_desktop_names); - g_free(strut); + for (r = area; *r; ++r) + g_free(*r); g_free(area); } @@ -231,17 +235,15 @@ void screen_resize(int w, int h) guint32 geometry[2]; /* Set the _NET_DESKTOP_GEOMETRY hint */ - geometry[0] = w; - geometry[1] = h; + screen_physical_size.width = geometry[0] = w; + screen_physical_size.height = geometry[1] = h; PROP_SETA32(ob_root, net_desktop_geometry, cardinal, geometry, 2); - screen_physical_size.width = geometry[0]; - screen_physical_size.height = geometry[1]; if (ob_state == State_Starting) return; dock_configure(); - screen_update_struts(); + screen_update_areas(); for (it = client_list; it; it = it->next) client_move_onscreen(it->data); @@ -288,7 +290,7 @@ void screen_set_num_desktops(guint num) } /* change our struts/area to match (after moving windows) */ - screen_update_struts(); + screen_update_areas(); dispatch_ob(Event_Ob_NumDesktops, num, old); @@ -500,129 +502,205 @@ void screen_install_colormap(Client *client, gboolean install) } } -void screen_update_struts() +void screen_update_areas() { + guint i, x; + guint32 *dims; + Rect **old_area = area; + Rect **rit; GList *it; - guint i; - - g_free(strut); - strut = g_new0(Strut, screen_num_desktops + 1); - - for (it = client_list; it != NULL; it = it->next) { - Client *c = it->data; - if (c->iconic) continue; /* these dont count in the strut */ - - if (c->desktop == 0xffffffff) { - for (i = 0; i < screen_num_desktops; ++i) - STRUT_ADD(strut[i], c->strut); - } else { - g_assert(c->desktop < screen_num_desktops); - STRUT_ADD(strut[c->desktop], c->strut); - } - /* apply to the 'all desktops' strut */ - STRUT_ADD(strut[screen_num_desktops], c->strut); - } - - for (i = 0; i < screen_num_desktops; ++i) - STRUT_ADD(strut[i], dock_strut); - screen_update_area(); -} + g_free(xin_areas); + extensions_xinerama_screens(&xin_areas, &screen_num_xin_areas); -static void screen_update_area() -{ - guint i; - guint32 *dims; + if (area) { + for (i = 0; area[i]; ++i) + g_free(area[i]); + g_free(area); + } - g_free(area); - area = g_new0(Rect, screen_num_desktops + 1); + area = g_new(Rect*, screen_num_desktops + 2); + for (i = 0; i < screen_num_desktops + 1; ++i) + area[i] = g_new(Rect, screen_num_xin_areas + 1); + area[i] = NULL; dims = g_new(guint32, 4 * screen_num_desktops); + + rit = old_area; for (i = 0; i < screen_num_desktops + 1; ++i) { - Rect old_area = area[i]; -/* - #ifdef XINERAMA - // reset to the full areas - if (isXineramaActive()) - xineramaUsableArea = getXineramaAreas(); - #endif // XINERAMA -*/ + Strut s; + int l, r, t, b; + + /* calc the xinerama areas */ + for (x = 0; x < screen_num_xin_areas; ++x) { + area[i][x] = xin_areas[x]; + if (x == 0) { + l = xin_areas[x].x; + t = xin_areas[x].y; + r = xin_areas[x].x + xin_areas[x].width - 1; + b = xin_areas[x].y + xin_areas[x].height - 1; + } else { + l = MIN(l, xin_areas[x].x); + t = MIN(t, xin_areas[x].y); + r = MAX(r, xin_areas[x].x + xin_areas[x].width - 1); + b = MAX(b, xin_areas[x].y + xin_areas[x].height - 1); + } + } + RECT_SET(area[i][x], l, t, r - l + 1, b - t + 1); + + /* apply struts */ + STRUT_SET(s, 0, 0, 0, 0); + for (it = client_list; it; it = it->next) + STRUT_ADD(s, ((Client*)it->data)->strut); + STRUT_ADD(s, dock_strut); + + if (s.left) { + int o; + + /* find the left-most xin heads, i do this in 2 loops :| */ + o = area[i][0].x; + for (x = 1; x < screen_num_xin_areas; ++x) + o = MIN(o, area[i][x].x); + + for (x = 0; x < screen_num_xin_areas; ++x) { + int edge = o + s.left - area[i][x].x; + if (edge > 0) { + area[i][x].x += edge; + area[i][x].width -= edge; + } + } - RECT_SET(area[i], strut[i].left, strut[i].top, - screen_physical_size.width - (strut[i].left + - strut[i].right), - screen_physical_size.height - (strut[i].top + - strut[i].bottom)); - -/* - #ifdef XINERAMA - if (isXineramaActive()) { - // keep each of the ximerama-defined areas inside the strut - RectList::iterator xit, xend = xineramaUsableArea.end(); - for (xit = xineramaUsableArea.begin(); xit != xend; ++xit) { - if (xit->x() < usableArea.x()) { - xit->setX(usableArea.x()); - xit->setWidth(xit->width() - usableArea.x()); - } - if (xit->y() < usableArea.y()) { - xit->setY(usableArea.y()); - xit->setHeight(xit->height() - usableArea.y()); - } - if (xit->x() + xit->width() > usableArea.width()) - xit->setWidth(usableArea.width() - xit->x()); - if (xit->y() + xit->height() > usableArea.height()) - xit->setHeight(usableArea.height() - xit->y()); - } - } - #endif // XINERAMA -*/ - if (!RECT_EQUAL(old_area, area[i])) { - /* the area has changed, adjust all the maximized windows */ + area[i][screen_num_xin_areas].x += s.left; + area[i][screen_num_xin_areas].width -= s.left; + } + if (s.top) { + int o; + + /* find the left-most xin heads, i do this in 2 loops :| */ + o = area[i][0].y; + for (x = 1; x < screen_num_xin_areas; ++x) + o = MIN(o, area[i][x].y); + + for (x = 0; x < screen_num_xin_areas; ++x) { + int edge = o + s.top - area[i][x].y; + if (edge > 0) { + area[i][x].y += edge; + area[i][x].height -= edge; + } + } + + area[i][screen_num_xin_areas].y += s.top; + area[i][screen_num_xin_areas].height -= s.top; + } + if (s.right) { + int o; + + /* find the bottom-most xin heads, i do this in 2 loops :| */ + o = area[i][0].x + area[i][0].width - 1; + for (x = 1; x < screen_num_xin_areas; ++x) + o = MAX(o, area[i][x].x + area[i][x].width - 1); + + for (x = 0; x < screen_num_xin_areas; ++x) { + int edge = (area[i][x].x + area[i][x].width - 1) - + (o - s.right); + if (edge > 0) + area[i][x].width -= edge; + } + + area[i][screen_num_xin_areas].width -= s.right; + } + if (s.bottom) { + int o; + + /* find the bottom-most xin heads, i do this in 2 loops :| */ + o = area[i][0].y + area[i][0].height - 1; + for (x = 1; x < screen_num_xin_areas; ++x) + o = MAX(o, area[i][x].y + area[i][x].height - 1); + + for (x = 0; x < screen_num_xin_areas; ++x) { + int edge = (area[i][x].y + area[i][x].height - 1) - + (o - s.bottom); + if (edge > 0) + area[i][x].height -= edge; + } + + area[i][screen_num_xin_areas].height -= s.bottom; + } + + /* XXX when dealing with partial struts, if its in a single + xinerama area, then only subtract it from that area's space + for (x = 0; x < screen_num_xin_areas; ++x) { GList *it; + + + do something smart with it for the 'all xinerama areas' one... + for (it = client_list; it; it = it->next) { - Client *c = it->data; - if (i < screen_num_desktops) { - if (c->desktop == i) - client_reconfigure(c); - } else { - /* the 'all desktops' size */ - if (c->desktop == DESKTOP_ALL) - client_reconfigure(c); - } - } - } - /* don't set these for the 'all desktops' area */ - if (i < screen_num_desktops) { - dims[(i * 4) + 0] = area[i].x; - dims[(i * 4) + 1] = area[i].y; - dims[(i * 4) + 2] = area[i].width; - dims[(i * 4) + 3] = area[i].height; - } + XXX if gunna test this shit, then gotta worry about when + the client moves between xinerama heads.. + + if (RECT_CONTAINS_RECT(((Client*)it->data)->frame->area, + area[i][x])) { + + } + } + } + */ + + /* XXX optimize when this is run? */ + + /* the area has changed, adjust all the maximized + windows */ + for (it = client_list; it; it = it->next) { + Client *c = it->data; + if (i < screen_num_desktops) { + if (c->desktop == i) + client_reconfigure(c); + } else if (c->desktop == DESKTOP_ALL) + client_reconfigure(c); + } + if (i < screen_num_desktops) { + /* don't set these for the 'all desktops' area */ + dims[(i * 4) + 0] = area[i][screen_num_xin_areas].x; + dims[(i * 4) + 1] = area[i][screen_num_xin_areas].y; + dims[(i * 4) + 2] = area[i][screen_num_xin_areas].width; + dims[(i * 4) + 3] = area[i][screen_num_xin_areas].height; + } } PROP_SETA32(ob_root, net_workarea, cardinal, dims, 4 * screen_num_desktops); + g_free(dims); } Rect *screen_area(guint desktop) { - if (desktop >= screen_num_desktops) { - if (desktop == DESKTOP_ALL) - return &area[screen_num_desktops]; - return NULL; - } - return &area[desktop]; + return screen_area_xinerama(desktop, screen_num_xin_areas); } -Strut *screen_strut(guint desktop) +Rect *screen_area_xinerama(guint desktop, guint head) { + if (head > screen_num_xin_areas) + return NULL; if (desktop >= screen_num_desktops) { if (desktop == DESKTOP_ALL) - return &strut[screen_num_desktops]; + return &area[screen_num_desktops][head]; return NULL; } - return &strut[desktop]; + return &area[desktop][head]; +} + +Rect *screen_physical_area() +{ + return screen_physical_area_xinerama(screen_num_xin_areas); +} + +Rect *screen_physical_area_xinerama(guint head) +{ + if (head > screen_num_xin_areas) + return NULL; + return &xin_areas[head]; } static void set_root_cursor() diff --git a/openbox/screen.h b/openbox/screen.h index f493bd82..21d05e47 100644 --- a/openbox/screen.h +++ b/openbox/screen.h @@ -10,6 +10,8 @@ struct Client; /*! The number of available desktops */ extern guint screen_num_desktops; +/*! The number of virtual "xinerama" screens/heads */ +extern guint screen_num_xin_areas; /*! The current desktop */ extern guint screen_desktop; /*! The size of the screen */ @@ -64,10 +66,14 @@ void screen_update_desktop_names(); it handles the root colormap. */ void screen_install_colormap(struct Client *client, gboolean install); -void screen_update_struts(); +void screen_update_areas(); + +Rect *screen_physical_area(); + +Rect *screen_physical_area_xinerama(guint head); Rect *screen_area(guint desktop); -Strut *screen_strut(guint desktop); +Rect *screen_area_xinerama(guint desktop, guint head); #endif diff --git a/plugins/menu/client_menu.c b/plugins/menu/client_menu.c index 50ebc7cf..aa09495b 100644 --- a/plugins/menu/client_menu.c +++ b/plugins/menu/client_menu.c @@ -50,6 +50,8 @@ void client_menu_show(Menu *self, int x, int y, Client *client) newy = MAX(client->frame->area.y + client->frame->size.top, y); newy -= ob_rr_theme->bwidth; + /* XXX do xinerama shit like in menu.c! im not coding it now because + this function isnt even being used right now... */ POINT_SET(self->location, MIN(x, screen_physical_size.width - self->size.width - ob_rr_theme->bwidth * 2), diff --git a/plugins/placement/placement.c b/plugins/placement/placement.c index 889168b9..5f962e47 100644 --- a/plugins/placement/placement.c +++ b/plugins/placement/placement.c @@ -32,7 +32,8 @@ static void place_random(Client *c) if (ob_state == State_Starting) return; - area = screen_area(c->desktop); + area = screen_area_xinerama(c->desktop, + g_random_int_range(0, screen_num_xin_areas)); l = area->x; t = area->y; diff --git a/plugins/resistance/resistance.c b/plugins/resistance/resistance.c index 91c10c0e..8d493637 100644 --- a/plugins/resistance/resistance.c +++ b/plugins/resistance/resistance.c @@ -32,6 +32,7 @@ static void resist_move(Client *c, int *x, int *y) { GList *it; Rect *area; + guint i; int l, t, r, b; /* requested edges */ int al, at, ar, ab; /* screen area edges */ int cl, ct, cr, cb; /* current edges */ @@ -107,7 +108,8 @@ static void resist_move(Client *c, int *x, int *y) } /* get the screen boundaries */ - area = screen_area(c->desktop); + area = screen_area_xinerama(c->desktop, client_xinerama_area(c)); + al = area->x; at = area->y; ar = al + area->width - 1; @@ -117,7 +119,7 @@ static void resist_move(Client *c, int *x, int *y) if (cl >= al && l < al && l >= al - resistance) *x = al; else if (cr <= ar && r > ar && r <= ar + resistance) - *x = ar - w + 1; + *x = ar - w + 1; if (ct >= at && t < at && t >= at - resistance) *y = at; else if (cb <= ab && b > ab && b < ab + resistance) -- 2.39.2