X-Git-Url: https://repo.or.cz/w/wmaker-crm.git/blobdiff_plain/7857f297eae5c487a43d7fb525bf2ed7a8010ad4..cf62d1591f5aef1e6760a8c0881a6de97ae26e92:/src/actions.c diff --git a/src/actions.c b/src/actions.c index e3e2249b..f9b92577 100644 --- a/src/actions.c +++ b/src/actions.c @@ -60,6 +60,10 @@ extern WPreferences wPreferences; extern Atom _XA_WM_TAKE_FOCUS; extern void ProcessPendingEvents(); +extern int calcIntersectionLength(int p1, int l1, int p2, int l2); + +static void find_Maximus_geometry(WWindow *wwin, WArea usableArea, int *new_x, + int *new_y, int *new_width, int *new_height); /******* Local Variables *******/ static struct { @@ -326,7 +330,7 @@ void wMaximizeWindow(WWindow * wwin, int directions) wUnshadeWindow(wwin); } /* Only save directions, not kbd or xinerama hints */ - directions &= (MAX_HORIZONTAL|MAX_VERTICAL|MAX_LEFTHALF|MAX_RIGHTHALF); + directions &= (MAX_HORIZONTAL | MAX_VERTICAL | MAX_LEFTHALF | MAX_RIGHTHALF | MAX_MAXIMUS); changed_h = ((wwin->flags.maximized ^ directions) & MAX_HORIZONTAL); changed_v = ((wwin->flags.maximized ^ directions) & MAX_VERTICAL); @@ -397,6 +401,9 @@ void wMaximizeWindow(WWindow * wwin, int directions) new_height -= wwin->frame->top_width + wwin->frame->bottom_width; } + if (directions & MAX_MAXIMUS) + find_Maximus_geometry(wwin, usableArea, &new_x, &new_y, &new_width, &new_height); + wWindowConstrainSize(wwin, &new_width, &new_height); wWindowCropSize(wwin, usableArea.x2 - usableArea.x1, @@ -409,6 +416,106 @@ void wMaximizeWindow(WWindow * wwin, int directions) wSoundPlay(WSOUND_MAXIMIZE); } +/* + * Maximus: tiled maximization (maximize without overlapping other windows) + * + * The window to be maximized will be denoted by w_0 (sub-index zero) + * while the windows which will stop the maximization of w_0 are denoted by w_j. + */ +static void find_Maximus_geometry(WWindow *wwin, WArea usableArea, int *new_x, int *new_y, + int *new_width, int *new_height) +{ + WWindow *tmp; + int x_0 = wwin->frame_x; + int y_0 = wwin->frame_y; + int width_0 = wwin->frame->core->width; + int height_0 = wwin->frame->core->height; + int botton_0 = y_0 + height_0; + int right_border_0 = x_0 + width_0; + int new_x_0, new_y_0, new_botton_0, new_right_border_0, new_height_0; + int x_j, y_j, width_j, height_j, botton_j, top_j, right_border_j; + int x_intsect, y_intsect; + /* Assume that the window w_0 has titlebar etc */ + int has_titlebar = 1, has_resizebar = 1, has_border = 1; + int adjust_height, adjust_width; + + /* Try to fully maximize first, then readjust later */ + new_x_0 = usableArea.x1; + new_y_0 = usableArea.y1; + new_botton_0 = usableArea.y2; + new_right_border_0 = usableArea.x2; + + if (!HAS_TITLEBAR(wwin)) + has_titlebar = 0; + if (!HAS_RESIZEBAR(wwin)) + has_resizebar = 0; + if (!HAS_BORDER(wwin)) + has_border = 0; + + /* the lengths to be subtracted if w_0 has titlebar, etc */ + adjust_height = TITLEBAR_HEIGHT * has_titlebar + + 2 * FRAME_BORDER_WIDTH * has_border + RESIZEBAR_HEIGHT * has_resizebar; + adjust_width = 2 * FRAME_BORDER_WIDTH * has_border; + + tmp = wwin; + /* TODO: Is the focused window always the last in the list? */ + while (tmp->prev) { + /* ignore windows in other workspaces or minimized */ + if (tmp->prev->frame->workspace != wwin->screen_ptr->current_workspace + || tmp->prev->flags.miniaturized) { + tmp = tmp->prev; + continue; + } + tmp = tmp->prev; + + /* set the w_j window coordinates */ + x_j = tmp->frame_x; + y_j = tmp->frame_y; + width_j = tmp->frame->core->width; + height_j = tmp->frame->core->height; + botton_j = y_j + height_j; + top_j = y_j; + right_border_j = x_j + width_j; + + /* Try to maximize in the y direction first */ + x_intsect = calcIntersectionLength(x_0, width_0, x_j, width_j); + if (x_intsect != 0) { + if (botton_j < y_0 && botton_j > new_y_0) { + /* w_0 is below the botton of w_j */ + new_y_0 = botton_j; + } + if (botton_0 < top_j && top_j < new_botton_0) { + /* The botton of w_0 is above the top of w_j */ + new_botton_0 = top_j; + } + } + + /* + * Use the updated y coordinates from the above step to account + * the possibility that the new value of y_0 will have different + * intersections with w_j + */ + new_height_0 = new_botton_0 - new_y_0 - adjust_height; + y_intsect = calcIntersectionLength(new_y_0, new_height_0, y_j, height_j); + if (y_intsect != 0) { + if (right_border_j < x_0 && right_border_j > new_x_0) { + /* w_0 is completely to the right of w_j */ + new_x_0 = right_border_j; + } + if (right_border_0 < x_j && x_j < new_right_border_0) { + /* w_0 is completely to the left of w_j */ + new_right_border_0 = x_j; + } + } + } + + new_height_0 = new_botton_0 - new_y_0 - adjust_height; + *new_x = new_x_0; + *new_y = new_y_0; + *new_height = new_height_0; + *new_width = new_right_border_0 - new_x_0 - adjust_width; +} + void wUnmaximizeWindow(WWindow * wwin) { int x, y, w, h;