WPrefs.app/WindowHandling.c | 10 +++- src/WindowMaker.h | 2 + src/defaults.c | 2 + src/placement.c | 129 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 1 deletions(-) diff --git a/WPrefs.app/WindowHandling.c b/WPrefs.app/WindowHandling.c index 730d38a..973c262 100644 --- a/WPrefs.app/WindowHandling.c +++ b/WPrefs.app/WindowHandling.c @@ -77,7 +77,9 @@ static char *placements[] = { "random", "manual", "cascade", - "smart" + "smart", + "smartmouse", + "mouse" }; @@ -137,6 +139,10 @@ getPlacement(char *str) return 3; else if (strcasecmp(str, "smart")==0) return 4; + else if (strcasecmp(str, "smartmouse")==0) + return 5; + else if (strcasecmp(str, "mouse")==0) + return 6; else wwarning(_("bad option value %s in WindowPlacement. Using default value"), str); @@ -252,6 +258,8 @@ createPanel(Panel *p) WMAddPopUpButtonItem(panel->placP, _("Manual")); WMAddPopUpButtonItem(panel->placP, _("Cascade")); WMAddPopUpButtonItem(panel->placP, _("Smart")); + WMAddPopUpButtonItem(panel->placP, _("SmartMouse")); + WMAddPopUpButtonItem(panel->placP, _("Mouse")); panel->porigL = WMCreateLabel(panel->placF); WMResizeWidget(panel->porigL, 120, 32); diff --git a/src/WindowMaker.h b/src/WindowMaker.h index 84d2856..e234478 100644 --- a/src/WindowMaker.h +++ b/src/WindowMaker.h @@ -169,6 +169,8 @@ typedef enum { #define WPM_SMART 2 #define WPM_RANDOM 3 #define WPM_AUTO 4 +#define WPM_SMARTMOUSE 5 +#define WPM_MOUSE 6 /* text justification */ #define WTJ_CENTER 0 diff --git a/src/defaults.c b/src/defaults.c index 1c40d62..22eb7ae 100644 --- a/src/defaults.c +++ b/src/defaults.c @@ -238,6 +238,8 @@ static WOptionEnumeration sePlacements[] = { {"Cascade", WPM_CASCADE, 0}, {"Random", WPM_RANDOM, 0}, {"Manual", WPM_MANUAL, 0}, + {"SmartMouse", WPM_SMARTMOUSE, 0}, + {"Mouse", WPM_MOUSE, 0}, {NULL, 0, 0} }; diff --git a/src/placement.c b/src/placement.c index 737d6b5..8080ab0 100644 --- a/src/placement.c +++ b/src/placement.c @@ -416,6 +416,127 @@ smartPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret, *y_ret = min_isect_y; } +static void +smartmousePlaceWindow(WWindow *wwin, int *x_ret, int *y_ret, + unsigned int width, unsigned int height, + WArea usableArea) +{ + WScreen *scr = wwin->screen_ptr; + int test_x = 0, test_y = usableArea.y1; + int from_x, to_x, from_y, to_y; + int pointer_x, pointer_y; + double rad, min_rad = INT_MAX; + int sx; + int min_isect, min_isect_x, min_isect_y; + int sum_isect; + + if (wwin->frame) { + height += wwin->frame->top_width + wwin->frame->bottom_width; + } else { + if (HAS_TITLEBAR(wwin)) height += 18; + if (HAS_RESIZEBAR(wwin)) height += 8; + } + if (HAS_BORDER(wwin)) { + height += 2; + width += 2; + } + + sx = usableArea.x1; + + min_isect = INT_MAX; + min_isect_x = sx; + min_isect_y = test_y; + + { + Window win; + int tint; + unsigned int tuint; + + XQueryPointer(dpy, scr->root_win, &win, &win, + &pointer_x, &pointer_y, + &tint, &tint, &tuint); + } + +#define SQ(x) ((x)*(x)) +#define RAD() sqrt( SQ(test_x + width/2 - pointer_x) + \ + SQ(test_y + height/2 - pointer_y)) + + while (((test_y + height) < usableArea.y2)) { + test_x = sx; + while ((test_x + width) < usableArea.x2) { + sum_isect = calcSumOfCoveredAreas(wwin, test_x, test_y, + width, height); + rad = RAD(); + if ( sum_isect < min_isect || + (sum_isect == min_isect && rad < min_rad)) { + min_rad = rad; + min_isect = sum_isect; + min_isect_x = test_x; + min_isect_y = test_y; + } + + test_x += PLACETEST_HSTEP; + } + test_y += PLACETEST_VSTEP; + } + + from_x = min_isect_x - PLACETEST_HSTEP + 1; + from_x = WMAX(from_x, usableArea.x1); + to_x = min_isect_x + PLACETEST_HSTEP; + if (to_x + width > usableArea.x2) + to_x = usableArea.x2 - width; + + from_y = min_isect_y - PLACETEST_VSTEP + 1; + from_y = WMAX(from_y, usableArea.y1); + to_y = min_isect_y + PLACETEST_VSTEP; + if (to_y + height > usableArea.y2) + to_y = usableArea.y2 - height; + + for (test_x = from_x; test_x < to_x; test_x++) { + for (test_y = from_y; test_y < to_y; test_y++) { + sum_isect = calcSumOfCoveredAreas(wwin, test_x, test_y, + width, height); + rad = RAD(); + if ( sum_isect < min_isect || + (sum_isect == min_isect && rad < min_rad)) { + min_rad = rad; + min_isect = sum_isect; + min_isect_x = test_x; + min_isect_y = test_y; + } + } + } + + *x_ret = min_isect_x; + *y_ret = min_isect_y; +} + +static void +mousePlaceWindow(WWindow *wwin, int *x_ret, int *y_ret, + unsigned int width, unsigned int height, WArea usableArea) +{ + WScreen *scr = wwin->screen_ptr; + int pointer_x, pointer_y; + + { + Window win; + int tint; + unsigned int tuint; + + XQueryPointer(dpy, scr->root_win, &win, &win, + &pointer_x, &pointer_y, + &tint, &tint, &tuint); + } + + *x_ret = pointer_x - width/2; + *y_ret = pointer_y - height/2; + + if ( *x_ret < usableArea.x1) *x_ret = usableArea.x1; + else if ( *x_ret + width > usableArea.x2) *x_ret = usableArea.x2 - width; + + if ( *y_ret < usableArea.y1) *y_ret = usableArea.y1; + else if ( *y_ret + height > usableArea.y2) *y_ret = usableArea.y2 - height; +} static Bool autoPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret, @@ -610,6 +731,14 @@ PlaceWindow(WWindow *wwin, int *x_ret, int *y_ret, smartPlaceWindow(wwin, x_ret, y_ret, width, height, usableArea); break; + case WPM_SMARTMOUSE: + smartmousePlaceWindow(wwin, x_ret, y_ret, width, height, usableArea); + break; + + case WPM_MOUSE: + mousePlaceWindow(wwin, x_ret, y_ret, width, height, usableArea); + break; + case WPM_AUTO: if (autoPlaceWindow(wwin, x_ret, y_ret, width, height, 0, usableArea)) {