diff --git a/ChangeLog b/ChangeLog index 3628be5e..17adda1d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -81,11 +81,23 @@ Changes since version 0.80.2: - Added support for generating pkgconfig files for WINGS, wmlib and wrlib. ("Marcelo E. Magallon" ) - Support for multiline balloons (Vitaly Ovtchinnikov ) +- Improved wsetfont (Mike FABIAN ) - Updated single-click contrib patch (steve lion and vlaad) - Updated French translations (Antoine Hulin ) - Xinerama support for Solaris - Added global menu support (see NEWS) +- Fixed sloppy focus bug +- Made maximizing behaves differently with keyboard/mouse for xinerama + (Peter Zijlstra ) +- A few leftover xinerama fixes (Peter Zijlstra ) +- Extended the 'strut' to multiple heads + (Peter Zijlstra ) +- Icon placement now takes into account the new xinerama extended 'strut' + (Peter Zijlstra ) +- Icon arrangement that takes the new extended xinerama 'strut' into account + (Peter Zijlstra ) + Changes since version 0.80.1: ............................. diff --git a/src/actions.c b/src/actions.c index b8146a92..a7c208e7 100644 --- a/src/actions.c +++ b/src/actions.c @@ -409,38 +409,27 @@ void wMaximizeWindow(WWindow *wwin, int directions) { int new_width, new_height, new_x, new_y; - WArea usableArea = wwin->screen_ptr->totalUsableArea; - WArea totalArea; + WArea usableArea, totalArea; if (WFLAGP(wwin, no_resizable)) return; - totalArea.x1 = 0; - totalArea.y1 = 0; - totalArea.x2 = wwin->screen_ptr->scr_width; - totalArea.y2 = wwin->screen_ptr->scr_height; + usableArea = totalArea = (WArea){ + 0, 0, + wwin->screen_ptr->scr_width, + wwin->screen_ptr->scr_height + }; - if (wwin->screen_ptr->xine_info.count > 0 - && !(directions & MAX_IGNORE_XINERAMA)) { + if (!(directions & MAX_IGNORE_XINERAMA)) { WScreen *scr = wwin->screen_ptr; - WMRect rect; int head; - /* XXX: - if ( keyboard) { - rect.pos.x = wwin->frame_x; - rect.pos.y = wwin->frame_y; - rect.size.width = wwin->frame->core->width; - rect.size.height = wwin->frame->core->height; + if (directions & MAX_KEYBOARD) + head = wGetHeadForWindow(wwin); + else + head = wGetHeadForPointerLocation(scr); - head = wGetHeadForRect(scr, rect); - } else - */ - head = wGetHeadForPointerLocation(scr); - - rect = wGetRectForHead(scr, head); - - usableArea = wGetUsableAreaForHead(scr, head, &totalArea); + usableArea = wGetUsableAreaForHead(scr, head, &totalArea, True); } if (WFLAGP(wwin, full_maximize)) { @@ -920,7 +909,7 @@ wIconifyWindow(WWindow *wwin) if (!wPreferences.disable_miniwindows) { if (!wwin->flags.icon_moved) { - PlaceIcon(wwin->screen_ptr, &wwin->icon_x, &wwin->icon_y); + PlaceIcon(wwin->screen_ptr, &wwin->icon_x, &wwin->icon_y, wGetHeadForWindow(wwin)); } wwin->icon = wIconCreate(wwin); @@ -1498,6 +1487,168 @@ wRefreshDesktop(WScreen *scr) } +void +wArrangeIcons(WScreen *scr, Bool arrangeAll) +{ + WWindow *wwin; + WAppIcon *aicon; + + int head; + const int heads = wXineramaHeads(scr); + + struct { + int pf; /* primary axis */ + int sf; /* secondary axis */ + int fullW; + int fullH; + int pi, si; + int sx1, sx2, sy1, sy2; /* screen boundary */ + int sw, sh; + int xo, yo; + int xs, ys; + } vars[heads]; + + int isize = wPreferences.icon_size; + + for (head = 0; head < heads; ++head) { +#if 0 + WMRect rect = wGetRectForHead(scr, head); +#else + WArea area = wGetUsableAreaForHead(scr, head, NULL, False); + WMRect rect = (WMRect){ area.x1, area.y1, area.x2-area.x1, area.y2-area.y1 }; +#endif + + vars[head].pi = vars[head].si = 0; + vars[head].sx1 = rect.pos.x; + vars[head].sy1 = rect.pos.y; + vars[head].sw = rect.size.width; + vars[head].sh = rect.size.height; + vars[head].sx2 = vars[head].sx1 + vars[head].sw; + vars[head].sy2 = vars[head].sy1 + vars[head].sh; + +#if 0 + if (scr->dock) { + if (scr->dock->on_right_side) + vars[head].sx2 -= isize + DOCK_EXTRA_SPACE; + else + vars[head].sx1 += isize + DOCK_EXTRA_SPACE; + } +#endif + + vars[head].sw = isize * (vars[head].sw/isize); + vars[head].sh = isize * (vars[head].sh/isize); + vars[head].fullW = (vars[head].sx2-vars[head].sx1)/isize; + vars[head].fullH = (vars[head].sy2-vars[head].sy1)/isize; + + /* icon yard boundaries */ + if (wPreferences.icon_yard & IY_VERT) { + vars[head].pf = vars[head].fullH; + vars[head].sf = vars[head].fullW; + } else { + vars[head].pf = vars[head].fullW; + vars[head].sf = vars[head].fullH; + } + if (wPreferences.icon_yard & IY_RIGHT) { + vars[head].xo = vars[head].sx2 - isize; + vars[head].xs = -1; + } else { + vars[head].xo = vars[head].sx1; + vars[head].xs = 1; + } + if (wPreferences.icon_yard & IY_TOP) { + vars[head].yo = vars[head].sy1; + vars[head].ys = 1; + } else { + vars[head].yo = vars[head].sy2 - isize; + vars[head].ys = -1; + } + } + +#define X ((wPreferences.icon_yard & IY_VERT) \ + ? vars[head].xo + vars[head].xs*(vars[head].si*isize) \ + : vars[head].xo + vars[head].xs*(vars[head].pi*isize)) + +#define Y ((wPreferences.icon_yard & IY_VERT) \ + ? vars[head].yo + vars[head].ys*(vars[head].pi*isize) \ + : vars[head].yo + vars[head].ys*(vars[head].si*isize)) + + + /* arrange application icons */ + aicon = scr->app_icon_list; + /* reverse them to avoid unnecessarily sliding of icons */ + while (aicon && aicon->next) + aicon = aicon->next; + + while (aicon) { + if (!aicon->docked) { + /* XXX: can: icon == NULL ? */ + /* The intention here is to place the AppIcon on the head that contains most of the applications _main_ window. */ +/* printf( "appicon: %x %x\n", aicon->icon->core->window, aicon->main_window); */ + head = wGetHeadForWindow(aicon->icon->owner); + + if (aicon->x_pos != X || aicon->y_pos != Y) { +#ifdef ANIMATIONS + if (!wPreferences.no_animations) { + SlideWindow(aicon->icon->core->window, + aicon->x_pos, aicon->y_pos, X, Y); + } +#endif /* ANIMATIONS */ + } + wAppIconMove(aicon, X, Y); + vars[head].pi++; + if (vars[head].pi >= vars[head].pf) { + vars[head].pi = 0; + vars[head].si++; + } + } + aicon = aicon->prev; + } + + /* arrange miniwindows */ + wwin = scr->focused_window; + /* reverse them to avoid unnecessarily shuffling */ + while (wwin && wwin->prev) + wwin = wwin->prev; + + while (wwin) { + if (wwin->icon && wwin->flags.miniaturized && !wwin->flags.hidden && + (wwin->frame->workspace==scr->current_workspace || + IS_OMNIPRESENT(wwin) || wPreferences.sticky_icons)) { + + head = wGetHeadForWindow(wwin); + + if (arrangeAll || !wwin->flags.icon_moved) { + if (wwin->icon_x != X || wwin->icon_y != Y) { +#ifdef ANIMATIONS + if (wPreferences.no_animations) { + XMoveWindow(dpy, wwin->icon->core->window, X, Y); + } else { + SlideWindow(wwin->icon->core->window, wwin->icon_x, + wwin->icon_y, X, Y); + } +#else + XMoveWindow(dpy, wwin->icon->core->window, X, Y); +#endif /* ANIMATIONS */ + } + wwin->icon_x = X; + wwin->icon_y = Y; + + vars[head].pi++; + if (vars[head].pi >= vars[head].pf) { + vars[head].pi = 0; + vars[head].si++; + } + } + } + if (arrangeAll) { + wwin->flags.icon_moved = 0; + } + /* we reversed the order, so we use next */ + wwin = wwin->next; + } +} + +#if 0 void wArrangeIcons(WScreen *scr, Bool arrangeAll) { @@ -1531,7 +1682,7 @@ wArrangeIcons(WScreen *scr, Bool arrangeAll) sy2 = sy1 + sh; if (scr->dock) { if (scr->dock->on_right_side) - sx2 -= isize + DOCK_EXTRA_SPACE; + sx2 -= isize + DOCK_EXTRA_SPACE; else sx1 += isize + DOCK_EXTRA_SPACE; } @@ -1543,7 +1694,6 @@ wArrangeIcons(WScreen *scr, Bool arrangeAll) sw = isize * (sw/isize); sh = isize * (sh/isize); #endif - fullW = (sx2-sx1)/isize; fullW = (sx2-sx1)/isize; fullH = (sy2-sy1)/isize; @@ -1647,7 +1797,7 @@ wArrangeIcons(WScreen *scr, Bool arrangeAll) } } } - +#endif void wSelectWindow(WWindow *wwin, Bool flag) diff --git a/src/actions.h b/src/actions.h index 1ead8c0e..e3475bfe 100644 --- a/src/actions.h +++ b/src/actions.h @@ -27,6 +27,7 @@ #define MAX_HORIZONTAL 1 #define MAX_VERTICAL 2 #define MAX_IGNORE_XINERAMA 4 +#define MAX_KEYBOARD 8 void wSetFocusTo(WScreen *scr, WWindow *wwin); diff --git a/src/application.c b/src/application.c index a201a9a7..62117ce3 100644 --- a/src/application.c +++ b/src/application.c @@ -371,7 +371,7 @@ wApplicationCreate(WScreen *scr, Window main_window) } wDockAttachIcon(clip, wapp->app_icon, x, y); } else { - PlaceIcon(scr, &x, &y); + PlaceIcon(scr, &x, &y, wGetHeadForWindow(wapp->main_window_desc)); wAppIconMove(wapp->app_icon, x, y); wLowerFrame(icon->core); } diff --git a/src/dock.c b/src/dock.c index a2407731..c2f755a7 100644 --- a/src/dock.c +++ b/src/dock.c @@ -577,7 +577,8 @@ removeIconsCallback(WMenu *menu, WMenuEntry *entry) keepit = aicon->running && wApplicationOf(aicon->main_window); wDockDetach(dock, aicon); if (keepit) { - PlaceIcon(dock->screen_ptr, &aicon->x_pos, &aicon->y_pos); + /* XXX: can: aicon->icon == NULL ? */ + PlaceIcon(dock->screen_ptr, &aicon->x_pos, &aicon->y_pos, wGetHeadForWindow(aicon->icon->owner)); XMoveWindow(dpy, aicon->icon->core->window, aicon->x_pos, aicon->y_pos); if (!dock->mapped || dock->collapsed) @@ -1261,7 +1262,8 @@ wDockDestroy(WDock *dock) int keepit = aicon->running && wApplicationOf(aicon->main_window); wDockDetach(dock, aicon); if (keepit) { - PlaceIcon(dock->screen_ptr, &aicon->x_pos, &aicon->y_pos); + /* XXX: can: aicon->icon == NULL ? */ + PlaceIcon(dock->screen_ptr, &aicon->x_pos, &aicon->y_pos, wGetHeadForWindow(aicon->icon->owner)); XMoveWindow(dpy, aicon->icon->core->window, aicon->x_pos, aicon->y_pos); if (!dock->mapped || dock->collapsed) @@ -3245,7 +3247,8 @@ retry: aicon = wAppIconCreateForDock(dock->screen_ptr, NULL, wm_instance, wm_class, TILE_NORMAL); - PlaceIcon(dock->screen_ptr, &x0, &y0); + /* XXX: can: aicon->icon == NULL ? */ + PlaceIcon(dock->screen_ptr, &x0, &y0, wGetHeadForWindow(aicon->icon->owner)); wAppIconMove(aicon, x0, y0); /* Should this always be lowered? -Dan */ if (dock->lowered) diff --git a/src/event.c b/src/event.c index 760dcb01..76a4b594 100644 --- a/src/event.c +++ b/src/event.c @@ -1141,11 +1141,11 @@ handleEnterNotify(XEvent *event) } if (event->xcrossing.window == event->xcrossing.root - && (event->xcrossing.mode == NotifyNormal || - event->xcrossing.mode == NotifyUngrab ) - && event->xcrossing.detail == NotifyInferior + && event->xcrossing.detail == NotifyNormal + && event->xcrossing.detail != NotifyInferior && wPreferences.focus_mode != WKF_CLICK) { - wSetFocusTo(scr, NULL); + + wSetFocusTo(scr, scr->focused_window); } #ifdef BALLOON_TEXT @@ -1449,7 +1449,7 @@ handleKeyPress(XEvent *event) if (wwin->flags.maximized) { wUnmaximizeWindow(wwin); } else { - wMaximizeWindow(wwin, MAX_VERTICAL|MAX_HORIZONTAL); + wMaximizeWindow(wwin, MAX_VERTICAL|MAX_HORIZONTAL|MAX_KEYBOARD); } } break; @@ -1460,7 +1460,7 @@ handleKeyPress(XEvent *event) if (wwin->flags.maximized) { wUnmaximizeWindow(wwin); } else { - wMaximizeWindow(wwin, MAX_VERTICAL); + wMaximizeWindow(wwin, MAX_VERTICAL|MAX_KEYBOARD); } } break; @@ -1471,7 +1471,7 @@ handleKeyPress(XEvent *event) if (wwin->flags.maximized) { wUnmaximizeWindow(wwin); } else { - wMaximizeWindow(wwin, MAX_HORIZONTAL); + wMaximizeWindow(wwin, MAX_HORIZONTAL|MAX_KEYBOARD); } } break; diff --git a/src/funcs.h b/src/funcs.h index 9f3c87c8..2ecc6c71 100644 --- a/src/funcs.h +++ b/src/funcs.h @@ -83,7 +83,7 @@ void wColormapAllowClientInstallation(WScreen *scr, Bool starting); Pixmap LoadIcon(WScreen *scr, char *path, char *mask, int title_height); -void PlaceIcon(WScreen *scr, int *x_ret, int *y_ret); +void PlaceIcon(WScreen *scr, int *x_ret, int *y_ret, int head); int calcIntersectionArea(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2); diff --git a/src/gnome.c b/src/gnome.c index 05f3c244..8506abff 100644 --- a/src/gnome.c +++ b/src/gnome.c @@ -49,6 +49,7 @@ #include "actions.h" #include "stacking.h" #include "client.h" +#include "xinerama.h" #include "gnome.h" @@ -420,6 +421,45 @@ wGNOMECheckClientHints(WWindow *wwin, int *layer, int *workspace) } +Bool +wGNOMEGetUsableArea(WScreen *scr, int head, WArea *area) +{ + WReservedArea *cur; + WMRect rect; + + if(!scr->reservedAreas) + return False; + + area->x1 = area->y1 = area->x2 = area->y2 = 0; + + for(cur = scr->reservedAreas ; cur ; cur = cur->next) { + WWindow * wwin = wWindowFor(cur->window); + if (wWindowTouchesHead(wwin, head)) { + if(cur->area.x1 > area->x1) + area->x1 = cur->area.x1; + if(cur->area.y1 > area->y1) + area->y1 = cur->area.y1; + if(cur->area.x2 > area->x2) + area->x2 = cur->area.x2; + if(cur->area.y2 > area->y2) + area->y2 = cur->area.y2; + } + } + + if (area->x1==0 && area->x2==0 && + area->y1==0 && area->y2==0) return False; + + rect = wGetRectForHead(scr, head); + + area->x1 = rect.pos.x + area->x1; + area->x2 = rect.pos.x + rect.size.width - area->x2; + area->y1 = rect.pos.y + area->y1; + area->y2 = rect.pos.y + rect.size.height - area->y2; + + return True; +} + + Bool wGNOMECheckInitialClientState(WWindow *wwin) { diff --git a/src/gnome.h b/src/gnome.h index 9bb09662..947c00d1 100644 --- a/src/gnome.h +++ b/src/gnome.h @@ -47,5 +47,7 @@ Bool wGNOMECheckInitialClientState(WWindow *wwin); Bool wGNOMEProxyizeButtonEvent(WScreen *scr, XEvent *event); +Bool wGNOMEGetUsableArea(WScreen *scr, int head, WArea *area); + #endif diff --git a/src/kwm.c b/src/kwm.c index cb48b05a..01c369be 100644 --- a/src/kwm.c +++ b/src/kwm.c @@ -102,8 +102,9 @@ */ /* - * TODO + * XXX * different WORKAREA for each workspace + * -- done by rebuilding usableArea at each workspace switch. */ @@ -140,6 +141,7 @@ #include "workspace.h" #include "dialog.h" #include "stacking.h" +#include "xinerama.h" #include "kwm.h" @@ -749,16 +751,18 @@ wKWMShutdown(WScreen *scr, Bool closeModules) } -void +Bool wKWMCheckClientHints(WWindow *wwin, int *layer, int *workspace) { long val; + Bool hasHint = False; if (getSimpleHint(wwin->client_win, _XA_KWM_WIN_UNSAVED_DATA, &val) && val) { wwin->client_flags.broken_close = 1; - } + hasHint = True; + } else if (getSimpleHint(wwin->client_win, _XA_KWM_WIN_DECORATION, &val)) { if (val & KWMnoFocus) { wwin->client_flags.no_focusable = 1; @@ -790,27 +794,34 @@ wKWMCheckClientHints(WWindow *wwin, int *layer, int *workspace) default: break; } - } + hasHint = True; + } else if (getSimpleHint(wwin->client_win, _XA_KWM_WIN_DESKTOP, &val)) { *workspace = val - 1; + hasHint = True; } + + return hasHint; } -void +Bool wKWMCheckClientInitialState(WWindow *wwin) { long val; WArea area; + Bool hasHint = False; if (getSimpleHint(wwin->client_win, _XA_KWM_WIN_STICKY, &val) && val) { wwin->client_flags.omnipresent = 1; - } + hasHint = True; + } else if (getSimpleHint(wwin->client_win, _XA_KWM_WIN_ICONIFIED, &val) && val) { wwin->flags.miniaturized = 1; - } + hasHint = True; + } else if (getSimpleHint(wwin->client_win, _XA_KWM_WIN_MAXIMIZED, &val)) { if (val == 2) wwin->flags.maximized = MAX_VERTICAL; @@ -818,7 +829,8 @@ wKWMCheckClientInitialState(WWindow *wwin) wwin->flags.maximized = MAX_HORIZONTAL; else if (val == 3) wwin->flags.maximized = MAX_VERTICAL|MAX_HORIZONTAL; - } + hasHint = True; + } else if (getAreaHint(wwin->client_win, _XA_KWM_WIN_GEOMETRY_RESTORE, &area) && (wwin->old_geometry.x != area.x1 || wwin->old_geometry.y != area.y1 @@ -829,7 +841,10 @@ wKWMCheckClientInitialState(WWindow *wwin) wwin->old_geometry.y = area.y1; wwin->old_geometry.width = area.x2 - area.x1; wwin->old_geometry.height = area.y2 - area.y1; + hasHint = True; } + + return hasHint; } @@ -1373,6 +1388,7 @@ wKWMCheckRootHintChange(WScreen *scr, XPropertyEvent *event) processed = True; break; } else if (event->atom == _XA_KWM_WINDOW_REGION_[i]) { +#if 0 WArea area; if (getAreaHint(scr->root_win, event->atom, &area)) { @@ -1384,6 +1400,10 @@ wKWMCheckRootHintChange(WScreen *scr, XPropertyEvent *event) wScreenUpdateUsableArea(scr); } } +#else + if ( i == scr->current_workspace % MAX_WORKSPACES) + wScreenUpdateUsableArea(scr); +#endif processed = True; break; @@ -1596,17 +1616,30 @@ wKWMUpdateClientStateHint(WWindow *wwin, WKWMStateFlag flags) Bool -wKWMGetUsableArea(WScreen *scr, WArea *area) +wKWMGetUsableArea(WScreen *scr, int head, WArea *area) { char buffer[64]; + Bool ok; + int region = scr->current_workspace % MAX_WORKSPACES; - if (_XA_KWM_WINDOW_REGION_[0]==0) { - snprintf(buffer, sizeof(buffer), "KWM_WINDOW_REGION_%d", 1); + if (_XA_KWM_WINDOW_REGION_[region]==0) { + snprintf(buffer, sizeof(buffer), "KWM_WINDOW_REGION_%d", 1+region); - _XA_KWM_WINDOW_REGION_[0] = XInternAtom(dpy, buffer, False); + _XA_KWM_WINDOW_REGION_[region] = XInternAtom(dpy, buffer, False); } - return getAreaHint(scr->root_win, _XA_KWM_WINDOW_REGION_[0], area); + ok = getAreaHint(scr->root_win, _XA_KWM_WINDOW_REGION_[region], area); + + if ( ok) { + WMRect rect = wGetRectForHead(scr, head); + + area->x1 = WMAX( area->x1, rect.pos.x); + area->x2 = WMIN( area->x2, rect.pos.x + rect.size.width); + area->y1 = WMAX( area->y1, rect.pos.y); + area->y2 = WMIN( area->y2, rect.pos.y + rect.size.height); + } + + return ok; } diff --git a/src/kwm.h b/src/kwm.h index ac8ad3fb..3aa6c7dc 100644 --- a/src/kwm.h +++ b/src/kwm.h @@ -43,9 +43,9 @@ typedef enum { void wKWMInitStuff(WScreen *scr); -Bool wKWMGetUsableArea(WScreen *scr, WArea *area); +Bool wKWMGetUsableArea(WScreen *scr, int head, WArea *area); -void wKWMCheckClientHints(WWindow *wwin, int *layer, int *workspace); +Bool wKWMCheckClientHints(WWindow *wwin, int *layer, int *workspace); Bool wKWMCheckClientHintChange(WWindow *wwin, XPropertyEvent *event); @@ -67,7 +67,7 @@ void wKWMUpdateClientStateHint(WWindow *wwin, WKWMStateFlag flags); Bool wKWMManageableClient(WScreen *scr, Window win, char *title); -void wKWMCheckClientInitialState(WWindow *wwin); +Bool wKWMCheckClientInitialState(WWindow *wwin); #ifdef not_used void wKWMSetUsableAreaHint(WScreen *scr, int workspace); diff --git a/src/moveres.c b/src/moveres.c index fe1def98..de83c3b3 100644 --- a/src/moveres.c +++ b/src/moveres.c @@ -1051,15 +1051,16 @@ updateWindowPosition(WWindow *wwin, MoveData *data, Bool doResistance, /* horizontal movement: check horizontal edge resistances */ if (dx || dy) { WMRect rect; - int i; + int i, head; /* window is the leftmost window: check against screen edge */ /* Add inter head resistance 1/2 (if needed) */ - rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr)); + head = wGetHeadForPointerLocation(scr); + rect = wGetRectForHead(scr, head); - l_edge = WMAX(scr->totalUsableArea.x1, rect.pos.x); + l_edge = WMAX(scr->totalUsableArea[head].x1, rect.pos.x); edge_l = l_edge - resist; - edge_r = WMIN(scr->totalUsableArea.x2, rect.pos.x + rect.size.width); + edge_r = WMIN(scr->totalUsableArea[head].x2, rect.pos.x + rect.size.width); r_edge = edge_r + resist; /* 1 */ @@ -1157,9 +1158,9 @@ updateWindowPosition(WWindow *wwin, MoveData *data, Bool doResistance, /* VeRT */ /* Add inter head resistance 2/2 (if needed) */ - t_edge = WMAX(scr->totalUsableArea.y1, rect.pos.y); + t_edge = WMAX(scr->totalUsableArea[head].y1, rect.pos.y); edge_t = t_edge - resist; - edge_b = WMIN(scr->totalUsableArea.y2, rect.pos.y + rect.size.height); + edge_b = WMIN(scr->totalUsableArea[head].y2, rect.pos.y + rect.size.height); b_edge = edge_b + resist; if ((data->bottomIndex >= 0) && (data->bottomIndex <= data->count)) { diff --git a/src/placement.c b/src/placement.c index 130efae5..0ac4db6c 100644 --- a/src/placement.c +++ b/src/placement.c @@ -45,10 +45,10 @@ extern WPreferences wPreferences; -#define X_ORIGIN(scr) WMAX((scr)->totalUsableArea.x1,\ +#define X_ORIGIN(scr) WMAX(usableArea.x1,\ wPreferences.window_place_origin.x) -#define Y_ORIGIN(scr) WMAX((scr)->totalUsableArea.y1,\ +#define Y_ORIGIN(scr) WMAX(usableArea.y1,\ wPreferences.window_place_origin.y) @@ -124,7 +124,7 @@ iconPosition(WCoreWindow *wcore, int sx1, int sy1, int sx2, int sy2, void -PlaceIcon(WScreen *scr, int *x_ret, int *y_ret) +PlaceIcon(WScreen *scr, int *x_ret, int *y_ret, int head) { int pf; /* primary axis */ int sf; /* secondary axis */ @@ -148,7 +148,8 @@ PlaceIcon(WScreen *scr, int *x_ret, int *y_ret) /* * Allows each head to have miniwindows */ - WMRect rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr)); + WArea area = wGetUsableAreaForHead(scr, head, NULL, False); + WMRect rect = (WMRect){ area.x1, area.y1, area.x2-area.x1, area.y2-area.y1 }; sx1 = rect.pos.x; sy1 = rect.pos.y; @@ -157,12 +158,14 @@ PlaceIcon(WScreen *scr, int *x_ret, int *y_ret) sx2 = sx1 + sw; sy2 = sy1 + sh; +#if 0 if (scr->dock) { if (scr->dock->on_right_side) sx2 -= isize + DOCK_EXTRA_SPACE; else sx1 += isize + DOCK_EXTRA_SPACE; } +#endif sw = isize * (sw/isize); sh = isize * (sh/isize); @@ -590,7 +593,7 @@ PlaceWindow(WWindow *wwin, int *x_ret, int *y_ret, int h = WMFontHeight(scr->title_font) + (wPreferences.window_title_clearance + TITLEBAR_EXTEND_SPACE) * 2; WArea usableArea = wGetUsableAreaForHead(scr, wGetHeadForPointerLocation(scr), - NULL); + NULL, True); switch (wPreferences.window_placement) { case WPM_MANUAL: diff --git a/src/screen.c b/src/screen.c index 2c62f850..e5056e90 100644 --- a/src/screen.c +++ b/src/screen.c @@ -606,6 +606,7 @@ wScreenInit(int screen_number) extern int wVisualID; long event_mask; XErrorHandler oldHandler; + int i; scr = wmalloc(sizeof(WScreen)); memset(scr, 0, sizeof(WScreen)); @@ -621,10 +622,18 @@ wScreenInit(int screen_number) scr->scr_width = WidthOfScreen(ScreenOfDisplay(dpy, screen_number)); scr->scr_height = HeightOfScreen(ScreenOfDisplay(dpy, screen_number)); - scr->usableArea.x2 = scr->scr_width; - scr->usableArea.y2 = scr->scr_height; - scr->totalUsableArea.x2 = scr->scr_width; - scr->totalUsableArea.y2 = scr->scr_height; + wInitXinerama(scr); + + scr->usableArea = (WArea *)wmalloc( sizeof(WArea)*wXineramaHeads(scr)); /* XXX: checl NULL */ + scr->totalUsableArea = (WArea *)wmalloc( sizeof(WArea)*wXineramaHeads(scr)); /* XXX: */ + + for ( i=0; iusableArea[i].x1 = scr->totalUsableArea[i].x1 = rect.pos.x; + scr->usableArea[i].y1 = scr->totalUsableArea[i].y1 = rect.pos.y; + scr->usableArea[i].x2 = scr->totalUsableArea[i].x2 = rect.pos.x + rect.size.width; + scr->usableArea[i].y2 = scr->totalUsableArea[i].y2 = rect.pos.y + rect.size.height; + } scr->fakeGroupLeaders = WMCreateArray(16); @@ -665,8 +674,6 @@ wScreenInit(int screen_number) return NULL; } - wInitXinerama(scr); - XDefineCursor(dpy, scr->root_win, wCursor[WCUR_ROOT]); /* screen descriptor for raster graphic library */ @@ -827,13 +834,155 @@ wScreenInit(int screen_number) } +void +wScreenUpdateUsableArea(WScreen *scr) +{ + /* + * scr->totalUsableArea[] will become the usableArea used for Windowplacement, + * scr->usableArea[] will be used for iconplacement, hence no iconyard nor border. + */ + int i; + unsigned long best_area = 0, tmp_area; + WArea area; + int dock_head = scr->xine_info.primary_head; + + if ( scr->dock) { + WMRect rect = { scr->dock->x_pos, scr->dock->y_pos, wPreferences.icon_size, wPreferences.icon_size }; + dock_head = wGetHeadForRect(scr, rect); + } + + for ( i=0; itotalUsableArea[i] = (WArea){ + rect.pos.x, + rect.pos.y, + rect.pos.x + rect.size.width, + rect.pos.y + rect.size.height + }; + + if ( scr->dock && dock_head==i && + (!scr->dock->lowered || wPreferences.no_window_over_dock)) { + int offset = wPreferences.icon_size + DOCK_EXTRA_SPACE; + + if ( scr->dock->on_right_side) { + scr->totalUsableArea[i].x2 -= offset; + } else { + scr->totalUsableArea[i].x1 += offset; + } + } + +#ifdef NETWM_HINTS + { + WArea area; + if ( wNETWMGetUsableArea(scr, i, &area)) { + scr->totalUsableArea[i].x1 = WMAX(scr->totalUsableArea[i].x1, area.x1); + scr->totalUsableArea[i].y1 = WMAX(scr->totalUsableArea[i].y1, area.y1); + scr->totalUsableArea[i].x2 = WMIN(scr->totalUsableArea[i].x2, area.x2); + scr->totalUsableArea[i].y2 = WMIN(scr->totalUsableArea[i].y2, area.y2); + } + } +#endif + +#ifdef GNOME_STUFF + { + WArea area; + if ( wGNOMEGetUsableArea(scr, i, &area)) { + scr->totalUsableArea[i].x1 = WMAX(scr->totalUsableArea[i].x1, area.x1); + scr->totalUsableArea[i].y1 = WMAX(scr->totalUsableArea[i].y1, area.y1); + scr->totalUsableArea[i].x2 = WMIN(scr->totalUsableArea[i].x2, area.x2); + scr->totalUsableArea[i].y2 = WMIN(scr->totalUsableArea[i].y2, area.y2); + } + } +#endif + +#ifdef KWM_HINTS + { + WArea area; + if ( wKWMGetUsableArea(scr, i, &area)) { + scr->totalUsableArea[i].x1 = WMAX(scr->totalUsableArea[i].x1, area.x1); + scr->totalUsableArea[i].y1 = WMAX(scr->totalUsableArea[i].y1, area.y1); + scr->totalUsableArea[i].x2 = WMIN(scr->totalUsableArea[i].x2, area.x2); + scr->totalUsableArea[i].y2 = WMIN(scr->totalUsableArea[i].y2, area.y2); + } + } +#endif + + scr->usableArea[i] = scr->totalUsableArea[i]; + +#if 0 + printf( "usableArea[%d]: %d %d %d %d\n", i, + scr->usableArea[i].x1, + scr->usableArea[i].x2, + scr->usableArea[i].y1, + scr->usableArea[i].y2); +#endif + + if ( wPreferences.no_window_over_icons) { + if ( wPreferences.icon_yard & IY_VERT) { + if ( wPreferences.icon_yard & IY_RIGHT) { + scr->totalUsableArea[i].x1 += wPreferences.icon_size; + } else { + scr->totalUsableArea[i].x2 -= wPreferences.icon_size; + } + } else { + if ( wPreferences.icon_yard & IY_TOP) { + scr->totalUsableArea[i].y1 += wPreferences.icon_size; + } else { + scr->totalUsableArea[i].y2 -= wPreferences.icon_size; + } + } + } + + if (scr->totalUsableArea[i].x2 - scr->totalUsableArea[i].x1 < rect.size.width/2) { + scr->totalUsableArea[i].x1 = rect.pos.x; + scr->totalUsableArea[i].x2 = rect.pos.x + rect.size.width; + } + if (scr->totalUsableArea[i].y2 - scr->totalUsableArea[i].y1 < rect.size.height/2) { + scr->totalUsableArea[i].y1 = rect.pos.y; + scr->totalUsableArea[i].y2 = rect.pos.y + rect.size.height; + } + + tmp_area = (scr->totalUsableArea[i].x2 - scr->totalUsableArea[i].x1) * + (scr->totalUsableArea[i].y2 - scr->totalUsableArea[i].y1); + + if ( tmp_area > best_area) { + best_area = tmp_area; + area = scr->totalUsableArea[i]; + } + + { + unsigned size = wPreferences.workspace_border_size; + unsigned position = wPreferences.workspace_border_position; + + if (size>0 && position!=WB_NONE) { + if (position & WB_LEFTRIGHT) { + scr->totalUsableArea[i].x1 += size; + scr->totalUsableArea[i].x2 -= size; + } + if (position & WB_TOPBOTTOM) { + scr->totalUsableArea[i].y1 += size; + scr->totalUsableArea[i].y2 -= size; + } + } + } + } + +#ifdef NETWM_HINTS + wNETWMUpdateWorkarea(scr, area); +#endif + + if (wPreferences.auto_arrange_icons) { + wArrangeIcons(scr, True); + } +} + +#if 0 void wScreenUpdateUsableArea(WScreen *scr) { scr->totalUsableArea = scr->usableArea; - if (scr->dock && (!scr->dock->lowered || wPreferences.no_window_over_dock)) { @@ -961,7 +1110,11 @@ wScreenUpdateUsableArea(WScreen *scr) } } + if (wPreferences.auto_arrange_icons) { + wArrangeIcons(scr, True); + } } +#endif void diff --git a/src/screen.h b/src/screen.h index 10d82284..f6141614 100644 --- a/src/screen.h +++ b/src/screen.h @@ -135,10 +135,10 @@ typedef struct _WScreen { WReservedArea *reservedAreas; /* used to build totalUsableArea */ - WArea usableArea; /* area of the workspace where + WArea *usableArea; /* area of the workspace where * we can put windows on, as defined * by other clients (not us) */ - WArea totalUsableArea; /* same as above, but including + WArea *totalUsableArea; /* same as above, but including * the dock and other stuff */ WMColor *black; @@ -302,7 +302,7 @@ typedef struct _WScreen { Window kwm_dock; #endif -#ifdef NET_HINTS +#ifdef NETWM_HINTS struct NetData *netdata; #endif diff --git a/src/window.c b/src/window.c index dc4c89e8..bee7d63c 100644 --- a/src/window.c +++ b/src/window.c @@ -1132,11 +1132,11 @@ wManageWindow(WScreen *scr, Window window) } else { PlaceWindow(wwin, &x, &y, width, height); } - if (wPreferences.window_placement == WPM_MANUAL) - dontBring = True; - } - else if (scr->xine_info.count && - wwin->normal_hints->flags & PPosition) { + if (wPreferences.window_placement == WPM_MANUAL) { + dontBring = True; + } + } else if (scr->xine_info.count && + (wwin->normal_hints->flags & PPosition)) { int head, flags; WMRect rect; int reposition = 0; @@ -3005,8 +3005,9 @@ wWindowDeleteSavedStatesForPID(pid_t pid) void wWindowSetOmnipresent(WWindow *wwin, Bool flag) { + if ( wwin->flags.omnipresent == flag) return; + wwin->flags.omnipresent = flag; - WMPostNotificationName(WMNChangedState, wwin, "omnipresent"); } diff --git a/src/winspector.c b/src/winspector.c index 717e39e4..9cec2677 100644 --- a/src/winspector.c +++ b/src/winspector.c @@ -748,7 +748,7 @@ makeAppIconFor(WApplication *wapp) } wDockAttachIcon(clip, wapp->app_icon, x, y); } else { - PlaceIcon(scr, &x, &y); + PlaceIcon(scr, &x, &y, wGetHeadForWindow(wapp->main_window_desc)); wAppIconMove(wapp->app_icon, x, y); } if (!clip || !wapp->app_icon->attracted || !clip->collapsed) diff --git a/src/workspace.c b/src/workspace.c index 502bf0c8..2e1387bf 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -609,6 +609,10 @@ wWorkspaceForceChange(WScreen *scr, int workspace) } } +#ifdef KWM_HINTS + wScreenUpdateUsableArea(scr); +#endif + showWorkspaceName(scr, workspace); WMPostNotificationName(WMNWorkspaceChanged, scr, (void*)workspace); diff --git a/src/xinerama.c b/src/xinerama.c index 13b4d29d..208befd5 100644 --- a/src/xinerama.c +++ b/src/xinerama.c @@ -39,7 +39,7 @@ # endif #endif - +extern WPreferences wPreferences; void wInitXinerama(WScreen *scr) @@ -55,11 +55,10 @@ wInitXinerama(WScreen *scr) unsigned char hints[MAXFRAMEBUFFERS]; int i; - if (XineramaGetInfo(dpy, scr->screen, head, hints, - &info->count)) { + if (XineramaGetInfo(dpy, scr->screen, head, hints, &info->count)) { info->screens = wmalloc(sizeof(WMRect)*(info->count+1)); - + for (i=0; icount; i++) { info->screens[i].pos.x = head[i].x; info->screens[i].pos.y = head[i].y; @@ -70,7 +69,7 @@ wInitXinerama(WScreen *scr) } # else /* !SOLARIS_XINERAMA */ if (XineramaIsActive(dpy)) { - XineramaInfo *xine_screens; + XineramaScreenInfo *xine_screens; WXineramaInfo *info = &scr->xine_info; int i; @@ -79,10 +78,10 @@ wInitXinerama(WScreen *scr) info->screens = wmalloc(sizeof(WMRect)*(info->count+1)); for (i=0; icount; i++) { - info->screens[i].pos.x = info->screens[i].x_org; - info->screens[i].pos.y = info->screens[i].y_org; - info->screens[i].size.width = info->screens[i].width; - info->screens[i].size.height = info->screens[i].height; + info->screens[i].pos.x = xine_screens[i].x_org; + info->screens[i].pos.y = xine_screens[i].y_org; + info->screens[i].size.width = xine_screens[i].width; + info->screens[i].size.height = xine_screens[i].height; } XFree(xine_screens); } @@ -125,7 +124,7 @@ wGetRectPlacementInfo(WScreen *scr, WMRect rect, int *flags) return scr->xine_info.primary_head; } - for (i = 0; i < scr->xine_info.count; i++) { + for (i = 0; i < wXineramaHeads(scr); i++) { unsigned long a; a = calcIntersectionArea(rx, ry, rw, rh, @@ -172,7 +171,7 @@ wGetHeadForRect(WScreen *scr, WMRect rect) best = -1; area = 0; - for (i = 0; i < scr->xine_info.count; i++) { + for (i = 0; i < wXineramaHeads(scr); i++) { unsigned long a; a = calcIntersectionArea(rx, ry, rw, rh, @@ -197,11 +196,36 @@ wGetHeadForRect(WScreen *scr, WMRect rect) } +Bool +wWindowTouchesHead(WWindow *wwin, int head) +{ + WScreen * scr; + WMRect rect; + int a; + + if (!wwin || !wwin->frame) + return False; + + scr = wwin->screen_ptr; + rect = wGetRectForHead(scr, head); + a = calcIntersectionArea(wwin->frame_x, wwin->frame_y, + wwin->frame->core->width, + wwin->frame->core->height, + rect.pos.x, rect.pos.y, + rect.size.width, rect.size.height); + + return (a != 0); +} + + int wGetHeadForWindow(WWindow *wwin) { WMRect rect; + if (wwin == NULL || wwin->frame == NULL) + return 0; + rect.pos.x = wwin->frame_x; rect.pos.y = wwin->frame_y; rect.size.width = wwin->frame->core->width; @@ -212,7 +236,8 @@ wGetHeadForWindow(WWindow *wwin) /* -int wGetHeadForPoint(WScreen *scr, WMPoint point, int *flags) +int +wGetHeadForPoint(WScreen *scr, WMPoint point, int *flags) { int i; @@ -298,8 +323,7 @@ wGetRectForHead(WScreen *scr, int head) rect.pos.y = scr->xine_info.screens[head].pos.y; rect.size.width = scr->xine_info.screens[head].size.width; rect.size.height = scr->xine_info.screens[head].size.height; - } else - { + } else { rect.pos.x = 0; rect.pos.y = 0; rect.size.width = scr->scr_width; @@ -310,11 +334,10 @@ wGetRectForHead(WScreen *scr, int head) } - WArea -wGetUsableAreaForHead(WScreen *scr, int head, WArea *totalAreaPtr) +wGetUsableAreaForHead(WScreen *scr, int head, WArea *totalAreaPtr, Bool noicons) { - WArea totalArea, usableArea = scr->totalUsableArea; + WArea totalArea, usableArea; WMRect rect = wGetRectForHead(scr, head); totalArea.x1 = rect.pos.x; @@ -324,10 +347,10 @@ wGetUsableAreaForHead(WScreen *scr, int head, WArea *totalAreaPtr) if (totalAreaPtr != NULL) *totalAreaPtr = totalArea; - usableArea.x1 = WMAX(totalArea.x1, usableArea.x1); - usableArea.y1 = WMAX(totalArea.y1, usableArea.y1); - usableArea.x2 = WMIN(totalArea.x2, usableArea.x2); - usableArea.y2 = WMIN(totalArea.y2, usableArea.y2); + if (head < wXineramaHeads(scr)) { + usableArea = noicons ? scr->totalUsableArea[head] : scr->usableArea[head]; + } else + usableArea = totalArea; return usableArea; } diff --git a/src/xinerama.h b/src/xinerama.h index 96053ba3..59456e0c 100644 --- a/src/xinerama.h +++ b/src/xinerama.h @@ -28,6 +28,7 @@ void wInitXinerama(WScreen *scr); +#define wXineramaHeads(scr) ((scr)->xine_info.count ? (scr)->xine_info.count : 1) #define XFLAG_NONE 0x00 #define XFLAG_DEAD 0x01 @@ -46,7 +47,7 @@ int wGetHeadForPointerLocation(WScreen *scr); WMRect wGetRectForHead(WScreen *scr, int head); -WArea wGetUsableAreaForHead(WScreen *scr, int head, WArea *totalAreaPtr); +WArea wGetUsableAreaForHead(WScreen *scr, int head, WArea *totalAreaPtr, Bool noicons); WMPoint wGetPointToCenterRectInHead(WScreen *scr, int head, int width, int height); diff --git a/util/wmsetbg.c b/util/wmsetbg.c index 37efe03e..31592cb0 100644 --- a/util/wmsetbg.c +++ b/util/wmsetbg.c @@ -133,8 +133,7 @@ initXinerama() } # else /* !SOLARIS_XINERAMA */ if (XineramaIsActive(dpy)) { - XineramaInfo *xine_screens; - WXineramaInfo *info = &scr->xine_info; + XineramaScreenInfo *xine_screens; int i; xine_screens = XineramaQueryScreens(dpy, &xineInfo.count); @@ -142,10 +141,10 @@ initXinerama() xineInfo.screens = wmalloc(sizeof(WMRect)*(xineInfo.count+1)); for (i=0; i