From 1c73601946ee1779c0a7a49373dd7cb6df88e16f Mon Sep 17 00:00:00 2001 From: racarr Date: Mon, 18 Dec 2006 04:22:26 +0000 Subject: Run indent.sh on beryl-plugins most of the files had such mixed coding styles it was a real pain to work with git-svn-id: file:///beryl/trunk@1849 d7aaf104-2d23-0410-ae22-9d23157bf5a3 --- beryl-plugins/src/place.c | 2116 +++++++++++++++++++++++---------------------- 1 file changed, 1093 insertions(+), 1023 deletions(-) (limited to 'beryl-plugins/src/place.c') diff --git a/beryl-plugins/src/place.c b/beryl-plugins/src/place.c index e7dbd08..331dd74 100644 --- a/beryl-plugins/src/place.c +++ b/beryl-plugins/src/place.c @@ -36,30 +36,34 @@ static int displayPrivateIndex; -typedef struct _PlaceDisplay { - int screenPrivateIndex; - // HandleEventProc handleEvent; +typedef struct _PlaceDisplay +{ + int screenPrivateIndex; + // HandleEventProc handleEvent; } PlaceDisplay; #define PLACE_SCREEN_OPTION_WORKAROUND 0 #define PLACE_SCREEN_OPTION_MODE 1 #define PLACE_SCREEN_OPTION_NUM 2 -typedef struct _PlaceScreen { - CompOption opt[PLACE_SCREEN_OPTION_NUM]; +typedef struct _PlaceScreen +{ + CompOption opt[PLACE_SCREEN_OPTION_NUM]; - DamageWindowRectProc damageWindowRect; - int placeMode; + DamageWindowRectProc damageWindowRect; + int placeMode; } PlaceScreen; -typedef enum _PlaceMode{ - PlaceModeCascade, - PlaceModeCentered, - PlaceModeRandom, - PlaceModeIntelligent, - } PlaceMode; +typedef enum _PlaceMode +{ + PlaceModeCascade, + PlaceModeCentered, + PlaceModeRandom, + PlaceModeIntelligent, +} PlaceMode; -char *placeModes[] = { N_("Cascade"),N_("Centered"),N_("Random"),N_("Intelligent") }; +char *placeModes[] = + { N_("Cascade"), N_("Centered"), N_("Random"), N_("Intelligent") }; #define PLACE_MODE_DEFAULT PlaceModeIntelligent #define NUM_PLACE_MODES 4 @@ -79,564 +83,601 @@ char *placeModes[] = { N_("Cascade"),N_("Centered"),N_("Random"),N_("Intelligent #define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption)) static Bool -placeSetScreenOption(CompScreen * screen, - char *name, CompOptionValue * value) +placeSetScreenOption (CompScreen * screen, + char *name, CompOptionValue * value) { - CompOption *o; - int index; - - PLACE_SCREEN(screen); - - o = compFindOption(ps->opt, NUM_OPTIONS(ps), name, &index); - if (!o) - return FALSE; - - switch (index) { - case PLACE_SCREEN_OPTION_WORKAROUND: - if (compSetBoolOption(o, value)) - return TRUE; - break; - case PLACE_SCREEN_OPTION_MODE: - if (compSetStringOption (o,value)) - { - int i; - for (i = 0; i < NUM_PLACE_MODES; i++) - if (strcmp (placeModes[i], o->value.s)==0) - ps->placeMode = (PlaceMode) i; - } - default: - break; - } - - return FALSE; + CompOption *o; + int index; + + PLACE_SCREEN (screen); + + o = compFindOption (ps->opt, NUM_OPTIONS (ps), name, &index); + if (!o) + return FALSE; + + switch (index) + { + case PLACE_SCREEN_OPTION_WORKAROUND: + if (compSetBoolOption (o, value)) + return TRUE; + break; + case PLACE_SCREEN_OPTION_MODE: + if (compSetStringOption (o, value)) + { + int i; + for (i = 0; i < NUM_PLACE_MODES; i++) + if (strcmp (placeModes[i], o->value.s) == 0) + ps->placeMode = (PlaceMode) i; + } + default: + break; + } + + return FALSE; } -static void placeScreenInitOptions(PlaceScreen * ps) +static void +placeScreenInitOptions (PlaceScreen * ps) { - CompOption *o; - - o = &ps->opt[PLACE_SCREEN_OPTION_WORKAROUND]; - o->name = "workarounds"; - o->group = N_(""); - o->subGroup = N_(""); - o->displayHints = ""; - o->shortDesc = N_("Workarounds"); - o->longDesc = N_("Window placement workarounds"); - o->type = CompOptionTypeBool; - o->value.b = PLACE_WORKAROUND_DEFAULT; - - o = &ps->opt[PLACE_SCREEN_OPTION_MODE]; - o->name = "place_mode"; - o->shortDesc = N_("Placement Mode"); - o->longDesc = N_("Cascade, Random or Centered"); - o->type = CompOptionTypeString; - o->value.s = strdup (placeModes[PLACE_MODE_DEFAULT]); - o->rest.s.string = placeModes; - o->rest.s.nString = NUM_PLACE_MODES; - - o = &ps->opt[PLACE_SCREEN_OPTION_MODE]; - o->name = "place_mode"; - o->group = N_(""); - o->subGroup = N_(""); - o->displayHints = ""; - o->shortDesc = N_("Placement Mode"); - o->longDesc = N_("Window placement technique"); - o->type = CompOptionTypeString; - o->value.s = strdup(placeModes[PLACE_MODE_DEFAULT]); - o->rest.s.string = placeModes; - o->rest.s.nString = NUM_PLACE_MODES; - + CompOption *o; + + o = &ps->opt[PLACE_SCREEN_OPTION_WORKAROUND]; + o->name = "workarounds"; + o->group = N_(""); + o->subGroup = N_(""); + o->displayHints = ""; + o->shortDesc = N_("Workarounds"); + o->longDesc = N_("Window placement workarounds"); + o->type = CompOptionTypeBool; + o->value.b = PLACE_WORKAROUND_DEFAULT; + + o = &ps->opt[PLACE_SCREEN_OPTION_MODE]; + o->name = "place_mode"; + o->shortDesc = N_("Placement Mode"); + o->longDesc = N_("Cascade, Random or Centered"); + o->type = CompOptionTypeString; + o->value.s = strdup (placeModes[PLACE_MODE_DEFAULT]); + o->rest.s.string = placeModes; + o->rest.s.nString = NUM_PLACE_MODES; + + o = &ps->opt[PLACE_SCREEN_OPTION_MODE]; + o->name = "place_mode"; + o->group = N_(""); + o->subGroup = N_(""); + o->displayHints = ""; + o->shortDesc = N_("Placement Mode"); + o->longDesc = N_("Window placement technique"); + o->type = CompOptionTypeString; + o->value.s = strdup (placeModes[PLACE_MODE_DEFAULT]); + o->rest.s.string = placeModes; + o->rest.s.nString = NUM_PLACE_MODES; + } -static CompOption *placeGetScreenOptions(CompScreen * screen, int *count) +static CompOption * +placeGetScreenOptions (CompScreen * screen, int *count) { - if (screen) { - PLACE_SCREEN(screen); - - *count = NUM_OPTIONS(ps); - return ps->opt; - } else { - PlaceScreen *ps = malloc(sizeof(PlaceScreen)); - placeScreenInitOptions(ps); - *count = NUM_OPTIONS(ps); - return ps->opt; - } + if (screen) + { + PLACE_SCREEN (screen); + + *count = NUM_OPTIONS (ps); + return ps->opt; + } + else + { + PlaceScreen *ps = malloc (sizeof (PlaceScreen)); + placeScreenInitOptions (ps); + *count = NUM_OPTIONS (ps); + return ps->opt; + } } -typedef enum { - PlaceLeft, - PlaceRight, - PlaceTop, - PlaceBottom +typedef enum +{ + PlaceLeft, + PlaceRight, + PlaceTop, + PlaceBottom } PlaceWindowDirection; static Bool -rectangleIntersect(XRectangle * src1, XRectangle * src2, XRectangle * dest) +rectangleIntersect (XRectangle * src1, XRectangle * src2, XRectangle * dest) { - int dest_x, dest_y; - int dest_w, dest_h; - int return_val; - - g_return_val_if_fail(src1 != NULL, FALSE); - g_return_val_if_fail(src2 != NULL, FALSE); - g_return_val_if_fail(dest != NULL, FALSE); - - return_val = FALSE; - - dest_x = MAX(src1->x, src2->x); - dest_y = MAX(src1->y, src2->y); - dest_w = - MIN(src1->x + src1->width, src2->x + src2->width) - dest_x; - dest_h = - MIN(src1->y + src1->height, src2->y + src2->height) - dest_y; - - if (dest_w > 0 && dest_h > 0) { - dest->x = dest_x; - dest->y = dest_y; - dest->width = dest_w; - dest->height = dest_h; - return_val = TRUE; - } else { - dest->width = 0; - dest->height = 0; - } - - return return_val; + int dest_x, dest_y; + int dest_w, dest_h; + int return_val; + + g_return_val_if_fail (src1 != NULL, FALSE); + g_return_val_if_fail (src2 != NULL, FALSE); + g_return_val_if_fail (dest != NULL, FALSE); + + return_val = FALSE; + + dest_x = MAX (src1->x, src2->x); + dest_y = MAX (src1->y, src2->y); + dest_w = MIN (src1->x + src1->width, src2->x + src2->width) - dest_x; + dest_h = MIN (src1->y + src1->height, src2->y + src2->height) - dest_y; + + if (dest_w > 0 && dest_h > 0) + { + dest->x = dest_x; + dest->y = dest_y; + dest->width = dest_w; + dest->height = dest_h; + return_val = TRUE; + } + else + { + dest->width = 0; + dest->height = 0; + } + + return return_val; } -static gint northwestcmp(gconstpointer a, gconstpointer b) +static gint +northwestcmp (gconstpointer a, gconstpointer b) { - CompWindow *aw = (gpointer) a; - CompWindow *bw = (gpointer) b; - int from_origin_a; - int from_origin_b; - int ax, ay, bx, by; - - ax = aw->attrib.x - aw->input.left; - ay = aw->attrib.y - aw->input.top; - - bx = bw->attrib.x - bw->input.left; - by = bw->attrib.y - bw->input.top; - - /* probably there's a fast good-enough-guess we could use here. */ - from_origin_a = sqrt(ax * ax + ay * ay); - from_origin_b = sqrt(bx * bx + by * by); - - if (from_origin_a < from_origin_b) - return -1; - else if (from_origin_a > from_origin_b) - return 1; - else - return 0; + CompWindow *aw = (gpointer) a; + CompWindow *bw = (gpointer) b; + int from_origin_a; + int from_origin_b; + int ax, ay, bx, by; + + ax = aw->attrib.x - aw->input.left; + ay = aw->attrib.y - aw->input.top; + + bx = bw->attrib.x - bw->input.left; + by = bw->attrib.y - bw->input.top; + + /* probably there's a fast good-enough-guess we could use here. */ + from_origin_a = sqrt (ax * ax + ay * ay); + from_origin_b = sqrt (bx * bx + by * by); + + if (from_origin_a < from_origin_b) + return -1; + else if (from_origin_a > from_origin_b) + return 1; + else + return 0; } static void -get_workarea_of_current_output_device(CompScreen * s, XRectangle * area) +get_workarea_of_current_output_device (CompScreen * s, XRectangle * area) { - int head; + int head; - head = screenGetCurrentOutputDev(s); - screenGetOutputDevWorkArea(s, head, area); + head = screenGetCurrentOutputDev (s); + screenGetOutputDevWorkArea (s, head, area); } -static void placeCentered(CompWindow *window, int *x, int *y){ - *x = window->screen->workArea.x + (window->screen->workArea.width - - GET_WINDOW_WIDTH(window)) /2; - *y = window->screen->workArea.y + (window->screen->workArea.height - - GET_WINDOW_HEIGHT(window)) /2; +static void +placeCentered (CompWindow * window, int *x, int *y) +{ + *x = window->screen->workArea.x + (window->screen->workArea.width + - GET_WINDOW_WIDTH (window)) / 2; + *y = window->screen->workArea.y + (window->screen->workArea.height + - GET_WINDOW_HEIGHT (window)) / 2; } -static void placeRandom(CompWindow *window, int *x, int *y){ - *x = rand() % (window->screen->workArea.width - window->screen->workArea.x); - *y = rand() % (window->screen->workArea.height - window->screen->workArea.y); +static void +placeRandom (CompWindow * window, int *x, int *y) +{ + *x = rand () % (window->screen->workArea.width - + window->screen->workArea.x); + *y = rand () % (window->screen->workArea.height - + window->screen->workArea.y); } - - + + static void -find_next_cascade(CompWindow * window, - GList * windows, int x, int y, int *new_x, int *new_y) +find_next_cascade (CompWindow * window, + GList * windows, int x, int y, int *new_x, int *new_y) { - GList *tmp; - GList *sorted; - int cascade_x, cascade_y; - int x_threshold, y_threshold; - int window_width, window_height; - int cascade_stage; - XRectangle work_area; - - sorted = g_list_copy(windows); - sorted = g_list_sort(sorted, northwestcmp); - - /* This is a "fuzzy" cascade algorithm. - * For each window in the list, we find where we'd cascade a - * new window after it. If a window is already nearly at that - * position, we move on. - */ - - /* arbitrary-ish threshold, honors user attempts to - * manually cascade. - */ + GList *tmp; + GList *sorted; + int cascade_x, cascade_y; + int x_threshold, y_threshold; + int window_width, window_height; + int cascade_stage; + XRectangle work_area; + + sorted = g_list_copy (windows); + sorted = g_list_sort (sorted, northwestcmp); + + /* This is a "fuzzy" cascade algorithm. + * For each window in the list, we find where we'd cascade a + * new window after it. If a window is already nearly at that + * position, we move on. + */ + + /* arbitrary-ish threshold, honors user attempts to + * manually cascade. + */ #define CASCADE_FUZZ 15 - x_threshold = MAX(window->input.left, CASCADE_FUZZ); - y_threshold = MAX(window->input.top, CASCADE_FUZZ); - - /* Find furthest-SE origin of all workspaces. - * cascade_x, cascade_y are the target position - * of NW corner of window frame. - */ - - get_workarea_of_current_output_device(window->screen, &work_area); - - cascade_x = MAX(0, work_area.x); - cascade_y = MAX(0, work_area.y); - - /* Find first cascade position that's not used. */ - - window_width = GET_WINDOW_WIDTH(window) + window->input.left + - window->input.right; - window_height = GET_WINDOW_HEIGHT(window) + window->input.top + - window->input.bottom; - - cascade_stage = 0; - tmp = sorted; - while (tmp != NULL) { - CompWindow *w; - int wx, wy; - - w = tmp->data; - - /* we want frame position, not window position */ - wx = w->attrib.x - w->input.left; - wy = w->attrib.y - w->input.top; - - if (ABS(wx - cascade_x) < x_threshold && - ABS(wy - cascade_y) < y_threshold) { - /* This window is "in the way", move to next cascade - * point. The new window frame should go at the origin - * of the client window we're stacking above. - */ - wx = w->attrib.x; - wy = w->attrib.y; - - cascade_x = wx; - cascade_y = wy; - - /* If we go off the screen, start over with a new cascade */ - if (((cascade_x + window_width) > - (work_area.x + work_area.width)) || - ((cascade_y + window_height) > - (work_area.y + work_area.height))) { - cascade_x = MAX(0, work_area.x); - cascade_y = MAX(0, work_area.y); - -#define CASCADE_INTERVAL 50 /* space between top-left corners of cascades */ - - cascade_stage += 1; - cascade_x += - CASCADE_INTERVAL * cascade_stage; - - /* start over with a new cascade translated to the right, - * unless we are out of space - */ - if ((cascade_x + window_width) < - (work_area.x + work_area.width)) { - tmp = sorted; - continue; - } else { - /* All out of space, this cascade_x won't work */ - cascade_x = MAX(0, work_area.x); - break; - } - } - } else { - /* Keep searching for a further-down-the-diagonal window. */ - } - - tmp = tmp->next; - } - - /* cascade_x and cascade_y will match the last window in the list - * that was "in the way" (in the approximate cascade diagonal) - */ - - g_list_free(sorted); - - /* Convert coords to position of window, not position of frame. */ - *new_x = cascade_x + window->input.left; - *new_y = cascade_y + window->input.top; + x_threshold = MAX (window->input.left, CASCADE_FUZZ); + y_threshold = MAX (window->input.top, CASCADE_FUZZ); + + /* Find furthest-SE origin of all workspaces. + * cascade_x, cascade_y are the target position + * of NW corner of window frame. + */ + + get_workarea_of_current_output_device (window->screen, &work_area); + + cascade_x = MAX (0, work_area.x); + cascade_y = MAX (0, work_area.y); + + /* Find first cascade position that's not used. */ + + window_width = GET_WINDOW_WIDTH (window) + window->input.left + + window->input.right; + window_height = GET_WINDOW_HEIGHT (window) + window->input.top + + window->input.bottom; + + cascade_stage = 0; + tmp = sorted; + while (tmp != NULL) + { + CompWindow *w; + int wx, wy; + + w = tmp->data; + + /* we want frame position, not window position */ + wx = w->attrib.x - w->input.left; + wy = w->attrib.y - w->input.top; + + if (ABS (wx - cascade_x) < x_threshold && + ABS (wy - cascade_y) < y_threshold) + { + /* This window is "in the way", move to next cascade + * point. The new window frame should go at the origin + * of the client window we're stacking above. + */ + wx = w->attrib.x; + wy = w->attrib.y; + + cascade_x = wx; + cascade_y = wy; + + /* If we go off the screen, start over with a new cascade */ + if (((cascade_x + window_width) > + (work_area.x + work_area.width)) || + ((cascade_y + window_height) > + (work_area.y + work_area.height))) + { + cascade_x = MAX (0, work_area.x); + cascade_y = MAX (0, work_area.y); + +#define CASCADE_INTERVAL 50 /* space between top-left corners of cascades */ + + cascade_stage += 1; + cascade_x += CASCADE_INTERVAL * cascade_stage; + + /* start over with a new cascade translated to the right, + * unless we are out of space + */ + if ((cascade_x + window_width) < + (work_area.x + work_area.width)) + { + tmp = sorted; + continue; + } + else + { + /* All out of space, this cascade_x won't work */ + cascade_x = MAX (0, work_area.x); + break; + } + } + } + else + { + /* Keep searching for a further-down-the-diagonal window. */ + } + + tmp = tmp->next; + } + + /* cascade_x and cascade_y will match the last window in the list + * that was "in the way" (in the approximate cascade diagonal) + */ + + g_list_free (sorted); + + /* Convert coords to position of window, not position of frame. */ + *new_x = cascade_x + window->input.left; + *new_y = cascade_y + window->input.top; } static void -find_most_freespace(CompWindow * window, - CompWindow * focus_window, - int x, int y, int *new_x, int *new_y) +find_most_freespace (CompWindow * window, + CompWindow * focus_window, + int x, int y, int *new_x, int *new_y) { - PlaceWindowDirection side; - int max_area; - int max_width, max_height, left, right, top, bottom; - int left_space, right_space, top_space, bottom_space; - int frame_size_left, frame_size_top; - XRectangle work_area; - XRectangle avoid; - XRectangle outer; - - frame_size_left = window->input.left; - frame_size_top = window->input.top; - - get_workarea_of_current_output_device(window->screen, &work_area); - - getOuterRectOfWindow(focus_window, &avoid); - getOuterRectOfWindow(window, &outer); - - /* Find the areas of choosing the various sides of the focus window */ - max_width = MIN(avoid.width, outer.width); - max_height = MIN(avoid.height, outer.height); - left_space = avoid.x - work_area.x; - right_space = - work_area.width - (avoid.x + avoid.width - work_area.x); - top_space = avoid.y - work_area.y; - bottom_space = - work_area.height - (avoid.y + avoid.height - work_area.y); - left = MIN(left_space, outer.width); - right = MIN(right_space, outer.width); - top = MIN(top_space, outer.height); - bottom = MIN(bottom_space, outer.height); - - /* Find out which side of the focus_window can show the most of the - * window - */ - side = PlaceLeft; - max_area = left * max_height; - if (right * max_height > max_area) { - side = PlaceRight; - max_area = right * max_height; - } - if (top * max_width > max_area) { - side = PlaceTop; - max_area = top * max_width; - } - if (bottom * max_width > max_area) { - side = PlaceBottom; - max_area = bottom * max_width; - } - - /* Give up if there's no where to put it - * (i.e. focus window is maximized) - */ - if (max_area == 0) - return; - - /* Place the window on the relevant side; if the whole window fits, - * make it adjacent to the focus window; if not, make sure the - * window doesn't go off the edge of the screen. - */ - switch (side) { - case PlaceLeft: - *new_y = avoid.y + frame_size_top; - if (left_space > outer.width) - *new_x = avoid.x - outer.width + frame_size_left; - else - *new_x = work_area.x + frame_size_left; - break; - case PlaceRight: - *new_y = avoid.y + frame_size_top; - if (right_space > outer.width) - *new_x = avoid.x + avoid.width + frame_size_left; - else - *new_x = - work_area.x + work_area.width - outer.width + - frame_size_left; - break; - case PlaceTop: - *new_x = avoid.x + frame_size_left; - if (top_space > outer.height) - *new_y = avoid.y - outer.height + frame_size_top; - else - *new_y = work_area.y + frame_size_top; - break; - case PlaceBottom: - *new_x = avoid.x + frame_size_left; - if (bottom_space > outer.height) - *new_y = avoid.y + avoid.height + frame_size_top; - else - *new_y = - work_area.y + work_area.height - outer.height + - frame_size_top; - break; - } + PlaceWindowDirection side; + int max_area; + int max_width, max_height, left, right, top, bottom; + int left_space, right_space, top_space, bottom_space; + int frame_size_left, frame_size_top; + XRectangle work_area; + XRectangle avoid; + XRectangle outer; + + frame_size_left = window->input.left; + frame_size_top = window->input.top; + + get_workarea_of_current_output_device (window->screen, &work_area); + + getOuterRectOfWindow (focus_window, &avoid); + getOuterRectOfWindow (window, &outer); + + /* Find the areas of choosing the various sides of the focus window */ + max_width = MIN (avoid.width, outer.width); + max_height = MIN (avoid.height, outer.height); + left_space = avoid.x - work_area.x; + right_space = work_area.width - (avoid.x + avoid.width - work_area.x); + top_space = avoid.y - work_area.y; + bottom_space = work_area.height - (avoid.y + avoid.height - work_area.y); + left = MIN (left_space, outer.width); + right = MIN (right_space, outer.width); + top = MIN (top_space, outer.height); + bottom = MIN (bottom_space, outer.height); + + /* Find out which side of the focus_window can show the most of the + * window + */ + side = PlaceLeft; + max_area = left * max_height; + if (right * max_height > max_area) + { + side = PlaceRight; + max_area = right * max_height; + } + if (top * max_width > max_area) + { + side = PlaceTop; + max_area = top * max_width; + } + if (bottom * max_width > max_area) + { + side = PlaceBottom; + max_area = bottom * max_width; + } + + /* Give up if there's no where to put it + * (i.e. focus window is maximized) + */ + if (max_area == 0) + return; + + /* Place the window on the relevant side; if the whole window fits, + * make it adjacent to the focus window; if not, make sure the + * window doesn't go off the edge of the screen. + */ + switch (side) + { + case PlaceLeft: + *new_y = avoid.y + frame_size_top; + if (left_space > outer.width) + *new_x = avoid.x - outer.width + frame_size_left; + else + *new_x = work_area.x + frame_size_left; + break; + case PlaceRight: + *new_y = avoid.y + frame_size_top; + if (right_space > outer.width) + *new_x = avoid.x + avoid.width + frame_size_left; + else + *new_x = + work_area.x + work_area.width - outer.width + frame_size_left; + break; + case PlaceTop: + *new_x = avoid.x + frame_size_left; + if (top_space > outer.height) + *new_y = avoid.y - outer.height + frame_size_top; + else + *new_y = work_area.y + frame_size_top; + break; + case PlaceBottom: + *new_x = avoid.x + frame_size_left; + if (bottom_space > outer.height) + *new_y = avoid.y + avoid.height + frame_size_top; + else + *new_y = + work_area.y + work_area.height - outer.height + + frame_size_top; + break; + } } static void -avoid_being_obscured_as_second_modal_dialog(CompWindow * window, - int *x, int *y) +avoid_being_obscured_as_second_modal_dialog (CompWindow * window, + int *x, int *y) { - /* We can't center this dialog if it was denied focus and it - * overlaps with the focus window and this dialog is modal and this - * dialog is in the same app as the focus window (*phew*...please - * don't make me say that ten times fast). See bug 307875 comment 11 - * and 12 for details, but basically it means this is probably a - * second modal dialog for some app while the focus window is the - * first modal dialog. We should probably make them simultaneously - * visible in general, but it becomes mandatory to do so due to - * buggy apps (e.g. those using gtk+ *sigh*) because in those cases - * this second modal dialog also happens to be modal to the first - * dialog in addition to the main window, while it has only let us - * know about the modal-to-the-main-window part. - */ - - CompWindow *focus_window; - - focus_window = - findWindowAtDisplay(window->screen->display, - window->screen->display->activeWindow); + /* We can't center this dialog if it was denied focus and it + * overlaps with the focus window and this dialog is modal and this + * dialog is in the same app as the focus window (*phew*...please + * don't make me say that ten times fast). See bug 307875 comment 11 + * and 12 for details, but basically it means this is probably a + * second modal dialog for some app while the focus window is the + * first modal dialog. We should probably make them simultaneously + * visible in general, but it becomes mandatory to do so due to + * buggy apps (e.g. those using gtk+ *sigh*) because in those cases + * this second modal dialog also happens to be modal to the first + * dialog in addition to the main window, while it has only let us + * know about the modal-to-the-main-window part. + */ + + CompWindow *focus_window; + + focus_window = + findWindowAtDisplay (window->screen->display, + window->screen->display->activeWindow); } static gboolean -rectangle_overlaps_some_window(XRectangle * rect, GList * windows) +rectangle_overlaps_some_window (XRectangle * rect, GList * windows) { - GList *tmp; - XRectangle dest; - - tmp = windows; - while (tmp != NULL) { - CompWindow *other = tmp->data; - XRectangle other_rect; - - switch (other->type) { - case CompWindowTypeDockMask: - case CompWindowTypeSplashMask: - case CompWindowTypeDesktopMask: - case CompWindowTypeDialogMask: - case CompWindowTypeModalDialogMask: - case CompWindowTypeFullscreenMask: - case CompWindowTypeUnknownMask: - break; - case CompWindowTypeNormalMask: - case CompWindowTypeUtilMask: - case CompWindowTypeToolbarMask: - case CompWindowTypeMenuMask: - getOuterRectOfWindow(other, &other_rect); - - if (rectangleIntersect(rect, &other_rect, &dest)) - return TRUE; - break; - } - - tmp = tmp->next; - } - - return FALSE; + GList *tmp; + XRectangle dest; + + tmp = windows; + while (tmp != NULL) + { + CompWindow *other = tmp->data; + XRectangle other_rect; + + switch (other->type) + { + case CompWindowTypeDockMask: + case CompWindowTypeSplashMask: + case CompWindowTypeDesktopMask: + case CompWindowTypeDialogMask: + case CompWindowTypeModalDialogMask: + case CompWindowTypeFullscreenMask: + case CompWindowTypeUnknownMask: + break; + case CompWindowTypeNormalMask: + case CompWindowTypeUtilMask: + case CompWindowTypeToolbarMask: + case CompWindowTypeMenuMask: + getOuterRectOfWindow (other, &other_rect); + + if (rectangleIntersect (rect, &other_rect, &dest)) + return TRUE; + break; + } + + tmp = tmp->next; + } + + return FALSE; } -static void placeIntelligent(CompWindow *w, int *x, int *y, GList *windows){ - - XRectangle wRect = RECTANGLE_FROM_WINDOW(w); - XRectangle sRect = {0,0,0,0}; - wRect.height+=w->serverBorderWidth; - - CompScreen *screen = w->screen; - - get_workarea_of_current_output_device(screen,&sRect); - - - int xi; int yi; - - for (xi = 0; xi < (sRect.width-sRect.x); xi+=10){ - wRect.x=xi; - for (yi = 0 ; yi < (sRect.height-sRect.y); yi+=10 ){ - wRect.y=yi; - - if (! rectangle_overlaps_some_window(&wRect,windows) ){ - if ( !(xi+w->serverWidth > sRect.width) || !(yi + w->serverHeight > sRect.height) ){ - *x=xi; - *y=yi; - return; - } - } - } - } - if ( wRect.width > ((sRect.width-sRect.x)/2)){ - placeCentered(w,x,y); - } else { - placeRandom(w,x,y); - } - } - -static gint leftmost_cmp(gconstpointer a, gconstpointer b) +static void +placeIntelligent (CompWindow * w, int *x, int *y, GList * windows) +{ + + XRectangle wRect = RECTANGLE_FROM_WINDOW (w); + XRectangle sRect = { 0, 0, 0, 0 }; + wRect.height += w->serverBorderWidth; + + CompScreen *screen = w->screen; + + get_workarea_of_current_output_device (screen, &sRect); + + + int xi; + int yi; + + for (xi = 0; xi < (sRect.width - sRect.x); xi += 10) + { + wRect.x = xi; + for (yi = 0; yi < (sRect.height - sRect.y); yi += 10) + { + wRect.y = yi; + + if (!rectangle_overlaps_some_window (&wRect, windows)) + { + if (!(xi + w->serverWidth > sRect.width) + || !(yi + w->serverHeight > sRect.height)) + { + *x = xi; + *y = yi; + return; + } + } + } + } + if (wRect.width > ((sRect.width - sRect.x) / 2)) + { + placeCentered (w, x, y); + } + else + { + placeRandom (w, x, y); + } +} + +static gint +leftmost_cmp (gconstpointer a, gconstpointer b) { - CompWindow *aw = (gpointer) a; - CompWindow *bw = (gpointer) b; - int ax, bx; - - ax = aw->attrib.x - aw->input.left; - bx = bw->attrib.x - bw->input.left; - - if (ax < bx) - return -1; - else if (ax > bx) - return 1; - else - return 0; + CompWindow *aw = (gpointer) a; + CompWindow *bw = (gpointer) b; + int ax, bx; + + ax = aw->attrib.x - aw->input.left; + bx = bw->attrib.x - bw->input.left; + + if (ax < bx) + return -1; + else if (ax > bx) + return 1; + else + return 0; } -static gint topmost_cmp(gconstpointer a, gconstpointer b) +static gint +topmost_cmp (gconstpointer a, gconstpointer b) { - CompWindow *aw = (gpointer) a; - CompWindow *bw = (gpointer) b; - int ay, by; - - ay = aw->attrib.y - aw->input.top; - by = bw->attrib.y - bw->input.top; - - if (ay < by) - return -1; - else if (ay > by) - return 1; - else - return 0; + CompWindow *aw = (gpointer) a; + CompWindow *bw = (gpointer) b; + int ay, by; + + ay = aw->attrib.y - aw->input.top; + by = bw->attrib.y - bw->input.top; + + if (ay < by) + return -1; + else if (ay > by) + return 1; + else + return 0; } static void -center_tile_rect_in_area(XRectangle * rect, XRectangle * work_area) +center_tile_rect_in_area (XRectangle * rect, XRectangle * work_area) { - int fluff; - - /* The point here is to tile a window such that "extra" - * space is equal on either side (i.e. so a full screen - * of windows tiled this way would center the windows - * as a group) - */ - - fluff = (work_area->width % (rect->width + 1)) / 2; - rect->x = work_area->x + fluff; - fluff = (work_area->height % (rect->height + 1)) / 3; - rect->y = work_area->y + fluff; + int fluff; + + /* The point here is to tile a window such that "extra" + * space is equal on either side (i.e. so a full screen + * of windows tiled this way would center the windows + * as a group) + */ + + fluff = (work_area->width % (rect->width + 1)) / 2; + rect->x = work_area->x + fluff; + fluff = (work_area->height % (rect->height + 1)) / 3; + rect->y = work_area->y + fluff; } static gboolean -rect_fits_in_work_area(XRectangle * work_area, XRectangle * rect) +rect_fits_in_work_area (XRectangle * work_area, XRectangle * rect) { - return ((rect->x >= work_area->x) && - (rect->y >= work_area->y) && - (rect->x + rect->width <= work_area->x + work_area->width) - && (rect->y + rect->height <= - work_area->y + work_area->height)); + return ((rect->x >= work_area->x) && + (rect->y >= work_area->y) && + (rect->x + rect->width <= work_area->x + work_area->width) + && (rect->y + rect->height <= work_area->y + work_area->height)); } /* Find the leftmost, then topmost, empty area on the workspace @@ -648,612 +689,641 @@ rect_fits_in_work_area(XRectangle * work_area, XRectangle * rect) * don't want to create a 1x1 Emacs. */ static gboolean -find_first_fit(CompWindow * window, - GList * windows, int x, int y, int *new_x, int *new_y) +find_first_fit (CompWindow * window, + GList * windows, int x, int y, int *new_x, int *new_y) { - /* This algorithm is limited - it just brute-force tries - * to fit the window in a small number of locations that are aligned - * with existing windows. It tries to place the window on - * the bottom of each existing window, and then to the right - * of each existing window, aligned with the left/top of the - * existing window in each of those cases. - */ - int retval; - GList *below_sorted; - GList *right_sorted; - GList *tmp; - XRectangle rect; - XRectangle work_area; + /* This algorithm is limited - it just brute-force tries + * to fit the window in a small number of locations that are aligned + * with existing windows. It tries to place the window on + * the bottom of each existing window, and then to the right + * of each existing window, aligned with the left/top of the + * existing window in each of those cases. + */ + int retval; + GList *below_sorted; + GList *right_sorted; + GList *tmp; + XRectangle rect; + XRectangle work_area; - retval = FALSE; + retval = FALSE; - /* Below each window */ - below_sorted = g_list_copy(windows); - below_sorted = g_list_sort(below_sorted, leftmost_cmp); - below_sorted = g_list_sort(below_sorted, topmost_cmp); + /* Below each window */ + below_sorted = g_list_copy (windows); + below_sorted = g_list_sort (below_sorted, leftmost_cmp); + below_sorted = g_list_sort (below_sorted, topmost_cmp); - /* To the right of each window */ - right_sorted = g_list_copy(windows); - right_sorted = g_list_sort(right_sorted, topmost_cmp); - right_sorted = g_list_sort(right_sorted, leftmost_cmp); + /* To the right of each window */ + right_sorted = g_list_copy (windows); + right_sorted = g_list_sort (right_sorted, topmost_cmp); + right_sorted = g_list_sort (right_sorted, leftmost_cmp); - getOuterRectOfWindow(window, &rect); + getOuterRectOfWindow (window, &rect); - get_workarea_of_current_output_device(window->screen, &work_area); + get_workarea_of_current_output_device (window->screen, &work_area); - work_area.x += (window->initialViewportX - window->screen->x) * - window->screen->width; - work_area.y += (window->initialViewportY - window->screen->y) * - window->screen->height; + work_area.x += (window->initialViewportX - window->screen->x) * + window->screen->width; + work_area.y += (window->initialViewportY - window->screen->y) * + window->screen->height; - center_tile_rect_in_area(&rect, &work_area); + center_tile_rect_in_area (&rect, &work_area); - if (rect_fits_in_work_area(&work_area, &rect) && - !rectangle_overlaps_some_window(&rect, windows)) { - *new_x = rect.x + window->input.left; - *new_y = rect.y + window->input.top; + if (rect_fits_in_work_area (&work_area, &rect) && + !rectangle_overlaps_some_window (&rect, windows)) + { + *new_x = rect.x + window->input.left; + *new_y = rect.y + window->input.top; - retval = TRUE; + retval = TRUE; - goto out; - } + goto out; + } - /* try below each window */ - tmp = below_sorted; - while (tmp != NULL) { - CompWindow *w = tmp->data; - XRectangle outer_rect; + /* try below each window */ + tmp = below_sorted; + while (tmp != NULL) + { + CompWindow *w = tmp->data; + XRectangle outer_rect; - getOuterRectOfWindow(w, &outer_rect); + getOuterRectOfWindow (w, &outer_rect); - rect.x = outer_rect.x; - rect.y = outer_rect.y + outer_rect.height; + rect.x = outer_rect.x; + rect.y = outer_rect.y + outer_rect.height; - if (rect_fits_in_work_area(&work_area, &rect) && - !rectangle_overlaps_some_window(&rect, below_sorted)) { - *new_x = rect.x + window->input.left; - *new_y = rect.y + window->input.top; + if (rect_fits_in_work_area (&work_area, &rect) && + !rectangle_overlaps_some_window (&rect, below_sorted)) + { + *new_x = rect.x + window->input.left; + *new_y = rect.y + window->input.top; - retval = TRUE; + retval = TRUE; - goto out; - } + goto out; + } - tmp = tmp->next; - } + tmp = tmp->next; + } - /* try to the right of each window */ - tmp = right_sorted; - while (tmp != NULL) { - CompWindow *w = tmp->data; - XRectangle outer_rect; + /* try to the right of each window */ + tmp = right_sorted; + while (tmp != NULL) + { + CompWindow *w = tmp->data; + XRectangle outer_rect; - getOuterRectOfWindow(w, &outer_rect); + getOuterRectOfWindow (w, &outer_rect); - rect.x = outer_rect.x + outer_rect.width; - rect.y = outer_rect.y; + rect.x = outer_rect.x + outer_rect.width; + rect.y = outer_rect.y; - if (rect_fits_in_work_area(&work_area, &rect) && - !rectangle_overlaps_some_window(&rect, right_sorted)) { - *new_x = rect.x + window->input.left; - *new_y = rect.y + window->input.top; + if (rect_fits_in_work_area (&work_area, &rect) && + !rectangle_overlaps_some_window (&rect, right_sorted)) + { + *new_x = rect.x + window->input.left; + *new_y = rect.y + window->input.top; - retval = TRUE; + retval = TRUE; - goto out; - } + goto out; + } - tmp = tmp->next; - } + tmp = tmp->next; + } - out: - g_list_free(below_sorted); - g_list_free(right_sorted); + out: + g_list_free (below_sorted); + g_list_free (right_sorted); - return retval; + return retval; } static void -placeWindow(CompWindow * window, int x, int y, int *new_x, int *new_y) +placeWindow (CompWindow * window, int x, int y, int *new_x, int *new_y) { - CompWindow *wi; - GList *windows; - XRectangle work_area; - int x0 = (window->initialViewportX - window->screen->x) * - window->screen->width; - int y0 = (window->initialViewportY - window->screen->y) * - window->screen->height; - int window_width, window_height; - - PLACE_SCREEN(window->screen); - - window_width = GET_WINDOW_WIDTH(window); - window_height = GET_WINDOW_HEIGHT(window); - - get_workarea_of_current_output_device(window->screen, &work_area); - - work_area.x += x0; - work_area.y += y0; - - windows = NULL; - - switch (window->type) { - case CompWindowTypeSplashMask: - case CompWindowTypeDialogMask: - case CompWindowTypeModalDialogMask: - case CompWindowTypeNormalMask: - /* Run placement algorithm on these. */ - break; - case CompWindowTypeDockMask: - case CompWindowTypeDesktopMask: - case CompWindowTypeUtilMask: - case CompWindowTypeToolbarMask: - case CompWindowTypeMenuMask: - case CompWindowTypeFullscreenMask: - case CompWindowTypeUnknownMask: - /* Assume the app knows best how to place these, no placement - * algorithm ever (other than "leave them as-is") - */ - goto done_no_constraints; - break; - } - - /* don't run placement algorithm on windows that can't be moved */ - if (!(window->actions & CompWindowActionMoveMask)) { - goto done_no_constraints; - } - - if (window->type & CompWindowTypeFullscreenMask) { - x = x0; - y = y0; - goto done_no_constraints; - } - - if (window->state & (CompWindowStateMaximizedVertMask | - CompWindowStateMaximizedHorzMask)) { - if (window->screen->nOutputDev == 1) { - if (window-> - state & CompWindowStateMaximizedVertMask) - y = work_area.y + window->input.top; - - if (window-> - state & CompWindowStateMaximizedHorzMask) - x = work_area.x + window->input.left; - } else { - int head = screenGetOutputDevForWindow(window); - XRectangle workArea; - - screenGetOutputDevWorkArea(window->screen, head, - &workArea); - - if (window-> - state & CompWindowStateMaximizedVertMask) - y = workArea.y + window->input.top; - - if (window-> - state & CompWindowStateMaximizedHorzMask) - x = workArea.x + window->input.left; - } - - goto done; - } - - if (ps->opt[PLACE_SCREEN_OPTION_WORKAROUND].value.b) { - /* workarounds enabled */ - - if ((window->sizeHints.flags & PPosition) || - (window->sizeHints.flags & USPosition)) { - avoid_being_obscured_as_second_modal_dialog(window, - &x, - &y); - goto done; - } - } else { - switch (window->type) { - case CompWindowTypeNormalMask: - /* Only accept USPosition on normal windows because the app is full - * of shit claiming the user set -geometry for a dialog or dock - */ - if (window->sizeHints.flags & USPosition) { - /* don't constrain with placement algorithm */ - goto done; - } - break; - case CompWindowTypeSplashMask: - case CompWindowTypeDialogMask: - case CompWindowTypeModalDialogMask: - /* Ignore even USPosition on dialogs, splashscreen */ - break; - case CompWindowTypeDockMask: - case CompWindowTypeDesktopMask: - case CompWindowTypeUtilMask: - case CompWindowTypeToolbarMask: - case CompWindowTypeMenuMask: - case CompWindowTypeFullscreenMask: - case CompWindowTypeUnknownMask: - /* Assume the app knows best how to place these. */ - if (window->sizeHints.flags & PPosition) { - goto done_no_constraints; - } - break; - } - } - - if ((window->type == CompWindowTypeDialogMask || - window->type == CompWindowTypeModalDialogMask) && - window->transientFor != None) { - /* Center horizontally, at top of parent vertically */ - - CompWindow *parent; - - parent = findWindowAtDisplay(window->screen->display, - window->transientFor); - if (parent) { - int w; - - x = parent->attrib.x; - y = parent->attrib.y; - - w = GET_WINDOW_WIDTH(parent); - - /* center of parent */ - x = x + w / 2 - window_width / 2; - - /* "visually" center window over parent, leaving twice as - * much space below as on top. - */ - y += (GET_WINDOW_HEIGHT(parent) - - window_height) / 3 + window->input.top; - - /* clip to screen if parent is visible in current viewport */ - if (parent->attrib.x < parent->screen->width && - parent->attrib.x + parent->screen->width > 0) { - XRectangle area; - - get_workarea_of_current_output_device - (window->screen, &area); - - if (x + window_width > area.x + area.width) - x = area.x + area.width - - window_width; - if (y + window_height > - area.y + area.height) - y = area.y + area.height - - window_height; - if (x < area.x) - x = area.x; - if (y < area.y) - y = area.y; - } - - avoid_being_obscured_as_second_modal_dialog(window, - &x, - &y); - - goto done_no_x_constraints; - } - } - - /* FIXME UTILITY with transient set should be stacked up - * on the sides of the parent window or something. - */ - if (window->type == CompWindowTypeDialogMask || - window->type == CompWindowTypeModalDialogMask || - window->type == CompWindowTypeSplashMask) { - /* Center on screen */ - int head; - XRectangle workArea; - - /* w = window->screen->width; - h = window->screen->height; - - x = (w - window->width) / 2; - y = (h - window->height) / 2; - */ - head = screenGetCurrentOutputDev(window->screen); - screenGetOutputDevWorkArea(window->screen, head, - &workArea); - - x = (workArea.width - window_width) / 2; - y = (workArea.height - window_height) / 2; - - goto done_check_denied_focus; - } - - /* Find windows that matter (not minimized, on same workspace - * as placed window, may be shaded - if shaded we pretend it isn't - * for placement purposes) - */ - for (wi = window->screen->windows; wi; wi = wi->next) { - if (!wi->shaded && wi->attrib.map_state != IsViewable) - continue; - - if (wi->attrib.x >= work_area.x + work_area.width || - wi->attrib.x + GET_WINDOW_WIDTH(wi) <= work_area.x || - wi->attrib.y >= work_area.y + work_area.height || - wi->attrib.y + GET_WINDOW_HEIGHT(wi) <= work_area.y) - continue; - - if (wi->attrib.override_redirect) - continue; - - if (wi->state & (CompWindowTypeDesktopMask | - CompWindowTypeDockMask | - CompWindowTypeFullscreenMask | - CompWindowTypeUnknownMask)) - continue; - - if (wi != window) - windows = g_list_prepend(windows, wi); - } - - /* "Origin" placement algorithm */ - x = x0; - y = y0; - - if (ps->placeMode == PlaceModeCascade){ - if (find_first_fit(window, windows, x, y, &x, &y)) - goto done_check_denied_focus; - - /* if the window wasn't placed at the origin of screen, - * cascade it onto the current screen - */ - find_next_cascade(window, windows, x, y, &x, &y); - } else if (ps->placeMode == PlaceModeCentered) { - placeCentered(window, &x, &y); - } else if (ps->placeMode == PlaceModeRandom) { - placeRandom(window, &x, &y); - } else { - placeIntelligent(window, &x, &y,windows); - } - - - - done_check_denied_focus: - /* If the window is being denied focus and isn't a transient of the - * focus window, we do NOT want it to overlap with the focus window - * if at all possible. This is guaranteed to only be called if the - * focus_window is non-NULL, and we try to avoid that window. - */ - if (0 /* window->denied_focus_and_not_transient */ ) { - gboolean found_fit = FALSE; - CompWindow *focus_window; - - focus_window = - findWindowAtDisplay(window->screen->display, - window->screen->display-> - activeWindow); - if (focus_window) { - XRectangle wr, fwr, overlap; - - getOuterRectOfWindow(window, &wr); - getOuterRectOfWindow(focus_window, &fwr); - - /* No need to do anything if the window doesn't overlap at all */ - found_fit = - !rectangleIntersect(&wr, &fwr, &overlap); - - /* Try to do a first fit again, this time only taking into - * account the focus window. - */ - if (!found_fit) { - GList *focus_window_list; - - focus_window_list = - g_list_prepend(NULL, focus_window); - - /* Reset x and y ("origin" placement algorithm) */ - x = 0; - y = 0; - - found_fit = - find_first_fit(window, - focus_window_list, x, y, - &x, &y); - - g_list_free(focus_window_list); - } - } - - /* If that still didn't work, just place it where we can see as much - * as possible. - */ - if (!found_fit) - find_most_freespace(window, focus_window, x, y, &x, - &y); - } - - g_list_free(windows); - - done: - if (((x + window_width + window->input.right < work_area.x + - work_area.width) && - (x + window_width + window->input.right > work_area.x)) - || - ((x - window->input.left > work_area.x) && - (x - window->input.left < work_area.x + work_area.width))) { - if (x + window_width + window->input.right > - work_area.x + work_area.width) - x = work_area.x + work_area.width - - window_width - window->input.right; - - if (x - window->input.left < work_area.x) - x = work_area.x + window->input.left; - } else { - //only use THIS code if the window is TOTALLY outside the viewport. - while (x + window_width + window->input.right > - work_area.x + work_area.width) - x -= work_area.width; - - - if (x - window->input.left < work_area.x) - x = work_area.x + window->input.left; - } - - done_no_x_constraints: - if (window->screen->nOutputDev == 1) { - if (y + window_height + window->input.bottom > - work_area.y + work_area.height) - y = work_area.y + work_area.height - - window_height - window->input.bottom; - - if (y - window->input.top < work_area.y) - y = work_area.y + window->input.top; - } else { - int head = screenGetOutputDevForWindow(window); - XRectangle workArea; - - screenGetOutputDevWorkArea(window->screen, head, - &workArea); - - if (y + window_height + window->input.bottom > - workArea.y + workArea.height) - y = workArea.y + workArea.height - window_height - - window->input.bottom; - - if (y - window->input.top < workArea.y) - y = workArea.y + window->input.top; - - } - - done_no_constraints: - *new_x = x; - *new_y = y; + CompWindow *wi; + GList *windows; + XRectangle work_area; + int x0 = (window->initialViewportX - window->screen->x) * + window->screen->width; + int y0 = (window->initialViewportY - window->screen->y) * + window->screen->height; + int window_width, window_height; + + PLACE_SCREEN (window->screen); + + window_width = GET_WINDOW_WIDTH (window); + window_height = GET_WINDOW_HEIGHT (window); + + get_workarea_of_current_output_device (window->screen, &work_area); + + work_area.x += x0; + work_area.y += y0; + + windows = NULL; + + switch (window->type) + { + case CompWindowTypeSplashMask: + case CompWindowTypeDialogMask: + case CompWindowTypeModalDialogMask: + case CompWindowTypeNormalMask: + /* Run placement algorithm on these. */ + break; + case CompWindowTypeDockMask: + case CompWindowTypeDesktopMask: + case CompWindowTypeUtilMask: + case CompWindowTypeToolbarMask: + case CompWindowTypeMenuMask: + case CompWindowTypeFullscreenMask: + case CompWindowTypeUnknownMask: + /* Assume the app knows best how to place these, no placement + * algorithm ever (other than "leave them as-is") + */ + goto done_no_constraints; + break; + } + + /* don't run placement algorithm on windows that can't be moved */ + if (!(window->actions & CompWindowActionMoveMask)) + { + goto done_no_constraints; + } + + if (window->type & CompWindowTypeFullscreenMask) + { + x = x0; + y = y0; + goto done_no_constraints; + } + + if (window->state & (CompWindowStateMaximizedVertMask | + CompWindowStateMaximizedHorzMask)) + { + if (window->screen->nOutputDev == 1) + { + if (window->state & CompWindowStateMaximizedVertMask) + y = work_area.y + window->input.top; + + if (window->state & CompWindowStateMaximizedHorzMask) + x = work_area.x + window->input.left; + } + else + { + int head = screenGetOutputDevForWindow (window); + XRectangle workArea; + + screenGetOutputDevWorkArea (window->screen, head, &workArea); + + if (window->state & CompWindowStateMaximizedVertMask) + y = workArea.y + window->input.top; + + if (window->state & CompWindowStateMaximizedHorzMask) + x = workArea.x + window->input.left; + } + + goto done; + } + + if (ps->opt[PLACE_SCREEN_OPTION_WORKAROUND].value.b) + { + /* workarounds enabled */ + + if ((window->sizeHints.flags & PPosition) || + (window->sizeHints.flags & USPosition)) + { + avoid_being_obscured_as_second_modal_dialog (window, &x, &y); + goto done; + } + } + else + { + switch (window->type) + { + case CompWindowTypeNormalMask: + /* Only accept USPosition on normal windows because the app is full + * of shit claiming the user set -geometry for a dialog or dock + */ + if (window->sizeHints.flags & USPosition) + { + /* don't constrain with placement algorithm */ + goto done; + } + break; + case CompWindowTypeSplashMask: + case CompWindowTypeDialogMask: + case CompWindowTypeModalDialogMask: + /* Ignore even USPosition on dialogs, splashscreen */ + break; + case CompWindowTypeDockMask: + case CompWindowTypeDesktopMask: + case CompWindowTypeUtilMask: + case CompWindowTypeToolbarMask: + case CompWindowTypeMenuMask: + case CompWindowTypeFullscreenMask: + case CompWindowTypeUnknownMask: + /* Assume the app knows best how to place these. */ + if (window->sizeHints.flags & PPosition) + { + goto done_no_constraints; + } + break; + } + } + + if ((window->type == CompWindowTypeDialogMask || + window->type == CompWindowTypeModalDialogMask) && + window->transientFor != None) + { + /* Center horizontally, at top of parent vertically */ + + CompWindow *parent; + + parent = findWindowAtDisplay (window->screen->display, + window->transientFor); + if (parent) + { + int w; + + x = parent->attrib.x; + y = parent->attrib.y; + + w = GET_WINDOW_WIDTH (parent); + + /* center of parent */ + x = x + w / 2 - window_width / 2; + + /* "visually" center window over parent, leaving twice as + * much space below as on top. + */ + y += (GET_WINDOW_HEIGHT (parent) - + window_height) / 3 + window->input.top; + + /* clip to screen if parent is visible in current viewport */ + if (parent->attrib.x < parent->screen->width && + parent->attrib.x + parent->screen->width > 0) + { + XRectangle area; + + get_workarea_of_current_output_device (window->screen, &area); + + if (x + window_width > area.x + area.width) + x = area.x + area.width - window_width; + if (y + window_height > area.y + area.height) + y = area.y + area.height - window_height; + if (x < area.x) + x = area.x; + if (y < area.y) + y = area.y; + } + + avoid_being_obscured_as_second_modal_dialog (window, &x, &y); + + goto done_no_x_constraints; + } + } + + /* FIXME UTILITY with transient set should be stacked up + * on the sides of the parent window or something. + */ + if (window->type == CompWindowTypeDialogMask || + window->type == CompWindowTypeModalDialogMask || + window->type == CompWindowTypeSplashMask) + { + /* Center on screen */ + int head; + XRectangle workArea; + + /* w = window->screen->width; + h = window->screen->height; + + x = (w - window->width) / 2; + y = (h - window->height) / 2; + */ + head = screenGetCurrentOutputDev (window->screen); + screenGetOutputDevWorkArea (window->screen, head, &workArea); + + x = (workArea.width - window_width) / 2; + y = (workArea.height - window_height) / 2; + + goto done_check_denied_focus; + } + + /* Find windows that matter (not minimized, on same workspace + * as placed window, may be shaded - if shaded we pretend it isn't + * for placement purposes) + */ + for (wi = window->screen->windows; wi; wi = wi->next) + { + if (!wi->shaded && wi->attrib.map_state != IsViewable) + continue; + + if (wi->attrib.x >= work_area.x + work_area.width || + wi->attrib.x + GET_WINDOW_WIDTH (wi) <= work_area.x || + wi->attrib.y >= work_area.y + work_area.height || + wi->attrib.y + GET_WINDOW_HEIGHT (wi) <= work_area.y) + continue; + + if (wi->attrib.override_redirect) + continue; + + if (wi->state & (CompWindowTypeDesktopMask | + CompWindowTypeDockMask | + CompWindowTypeFullscreenMask | + CompWindowTypeUnknownMask)) + continue; + + if (wi != window) + windows = g_list_prepend (windows, wi); + } + + /* "Origin" placement algorithm */ + x = x0; + y = y0; + + if (ps->placeMode == PlaceModeCascade) + { + if (find_first_fit (window, windows, x, y, &x, &y)) + goto done_check_denied_focus; + + /* if the window wasn't placed at the origin of screen, + * cascade it onto the current screen + */ + find_next_cascade (window, windows, x, y, &x, &y); + } + else if (ps->placeMode == PlaceModeCentered) + { + placeCentered (window, &x, &y); + } + else if (ps->placeMode == PlaceModeRandom) + { + placeRandom (window, &x, &y); + } + else + { + placeIntelligent (window, &x, &y, windows); + } + + + + done_check_denied_focus: + /* If the window is being denied focus and isn't a transient of the + * focus window, we do NOT want it to overlap with the focus window + * if at all possible. This is guaranteed to only be called if the + * focus_window is non-NULL, and we try to avoid that window. + */ + if (0 /* window->denied_focus_and_not_transient */ ) + { + gboolean found_fit = FALSE; + CompWindow *focus_window; + + focus_window = + findWindowAtDisplay (window->screen->display, + window->screen->display->activeWindow); + if (focus_window) + { + XRectangle wr, fwr, overlap; + + getOuterRectOfWindow (window, &wr); + getOuterRectOfWindow (focus_window, &fwr); + + /* No need to do anything if the window doesn't overlap at all */ + found_fit = !rectangleIntersect (&wr, &fwr, &overlap); + + /* Try to do a first fit again, this time only taking into + * account the focus window. + */ + if (!found_fit) + { + GList *focus_window_list; + + focus_window_list = g_list_prepend (NULL, focus_window); + + /* Reset x and y ("origin" placement algorithm) */ + x = 0; + y = 0; + + found_fit = + find_first_fit (window, focus_window_list, x, y, &x, &y); + + g_list_free (focus_window_list); + } + } + + /* If that still didn't work, just place it where we can see as much + * as possible. + */ + if (!found_fit) + find_most_freespace (window, focus_window, x, y, &x, &y); + } + + g_list_free (windows); + + done: + if (((x + window_width + window->input.right < work_area.x + + work_area.width) && + (x + window_width + window->input.right > work_area.x)) + || + ((x - window->input.left > work_area.x) && + (x - window->input.left < work_area.x + work_area.width))) + { + if (x + window_width + window->input.right > + work_area.x + work_area.width) + x = work_area.x + work_area.width + - window_width - window->input.right; + + if (x - window->input.left < work_area.x) + x = work_area.x + window->input.left; + } + else + { + //only use THIS code if the window is TOTALLY outside the viewport. + while (x + window_width + window->input.right > + work_area.x + work_area.width) + x -= work_area.width; + + + if (x - window->input.left < work_area.x) + x = work_area.x + window->input.left; + } + + done_no_x_constraints: + if (window->screen->nOutputDev == 1) + { + if (y + window_height + window->input.bottom > + work_area.y + work_area.height) + y = work_area.y + work_area.height + - window_height - window->input.bottom; + + if (y - window->input.top < work_area.y) + y = work_area.y + window->input.top; + } + else + { + int head = screenGetOutputDevForWindow (window); + XRectangle workArea; + + screenGetOutputDevWorkArea (window->screen, head, &workArea); + + if (y + window_height + window->input.bottom > + workArea.y + workArea.height) + y = workArea.y + workArea.height - window_height - + window->input.bottom; + + if (y - window->input.top < workArea.y) + y = workArea.y + window->input.top; + + } + + done_no_constraints: + *new_x = x; + *new_y = y; } static Bool -placeDamageWindowRect(CompWindow * w, Bool initial, BoxPtr rect) +placeDamageWindowRect (CompWindow * w, Bool initial, BoxPtr rect) { - Bool status; + Bool status; - PLACE_SCREEN(w->screen); + PLACE_SCREEN (w->screen); - UNWRAP(ps, w->screen, damageWindowRect); - status = (*w->screen->damageWindowRect) (w, initial, rect); - WRAP(ps, w->screen, damageWindowRect, placeDamageWindowRect); + UNWRAP (ps, w->screen, damageWindowRect); + status = (*w->screen->damageWindowRect) (w, initial, rect); + WRAP (ps, w->screen, damageWindowRect, placeDamageWindowRect); - if (initial && !w->attrib.override_redirect && !w->placed) { - int newX, newY; + if (initial && !w->attrib.override_redirect && !w->placed) + { + int newX, newY; - placeWindow(w, w->attrib.x, w->attrib.y, &newX, &newY); + placeWindow (w, w->attrib.x, w->attrib.y, &newX, &newY); - w->placed = TRUE; + w->placed = TRUE; - if (newX != w->attrib.x || newY != w->attrib.y) { - moveWindow(w, newX - w->attrib.x, - newY - w->attrib.y, FALSE, TRUE); - syncWindowPosition(w); - } - } + if (newX != w->attrib.x || newY != w->attrib.y) + { + moveWindow (w, newX - w->attrib.x, + newY - w->attrib.y, FALSE, TRUE); + syncWindowPosition (w); + } + } - return status; + return status; } -static Bool placeInitDisplay(CompPlugin * p, CompDisplay * d) +static Bool +placeInitDisplay (CompPlugin * p, CompDisplay * d) { - PlaceDisplay *pd; + PlaceDisplay *pd; - pd = malloc(sizeof(PlaceDisplay)); - if (!pd) - return FALSE; + pd = malloc (sizeof (PlaceDisplay)); + if (!pd) + return FALSE; - pd->screenPrivateIndex = allocateScreenPrivateIndex(d); - if (pd->screenPrivateIndex < 0) { - free(pd); - return FALSE; - } + pd->screenPrivateIndex = allocateScreenPrivateIndex (d); + if (pd->screenPrivateIndex < 0) + { + free (pd); + return FALSE; + } - d->privates[displayPrivateIndex].ptr = pd; + d->privates[displayPrivateIndex].ptr = pd; - // WRAP (pd, d, handleEvent, placeHandleEvent); + // WRAP (pd, d, handleEvent, placeHandleEvent); - return TRUE; + return TRUE; } -static void placeFiniDisplay(CompPlugin * p, CompDisplay * d) +static void +placeFiniDisplay (CompPlugin * p, CompDisplay * d) { - PLACE_DISPLAY(d); + PLACE_DISPLAY (d); - // UNWRAP (pd, d, handleEvent); + // UNWRAP (pd, d, handleEvent); - freeScreenPrivateIndex(d, pd->screenPrivateIndex); + freeScreenPrivateIndex (d, pd->screenPrivateIndex); - free(pd); + free (pd); } -static Bool placeInitScreen(CompPlugin * p, CompScreen * s) +static Bool +placeInitScreen (CompPlugin * p, CompScreen * s) { - PlaceScreen *ps; + PlaceScreen *ps; - PLACE_DISPLAY(s->display); + PLACE_DISPLAY (s->display); - ps = malloc(sizeof(PlaceScreen)); - if (!ps) - return FALSE; + ps = malloc (sizeof (PlaceScreen)); + if (!ps) + return FALSE; - placeScreenInitOptions(ps); - // addScreenBinding (s, &ps->opt[PLACE_SCREEN_OPTION_CENTER_INITIATE].value.bind); + placeScreenInitOptions (ps); + // addScreenBinding (s, &ps->opt[PLACE_SCREEN_OPTION_CENTER_INITIATE].value.bind); - WRAP(ps, s, damageWindowRect, placeDamageWindowRect); + WRAP (ps, s, damageWindowRect, placeDamageWindowRect); - s->privates[pd->screenPrivateIndex].ptr = ps; + s->privates[pd->screenPrivateIndex].ptr = ps; - return TRUE; + return TRUE; } -static void placeFiniScreen(CompPlugin * p, CompScreen * s) +static void +placeFiniScreen (CompPlugin * p, CompScreen * s) { - PLACE_SCREEN(s); + PLACE_SCREEN (s); - UNWRAP(ps, s, damageWindowRect); + UNWRAP (ps, s, damageWindowRect); - free(ps); + free (ps); } -static Bool placeInit(CompPlugin * p) +static Bool +placeInit (CompPlugin * p) { - displayPrivateIndex = allocateDisplayPrivateIndex(); - if (displayPrivateIndex < 0) - return FALSE; + displayPrivateIndex = allocateDisplayPrivateIndex (); + if (displayPrivateIndex < 0) + return FALSE; - return TRUE; + return TRUE; } -static void placeFini(CompPlugin * p) +static void +placeFini (CompPlugin * p) { - if (displayPrivateIndex >= 0) - freeDisplayPrivateIndex(displayPrivateIndex); + if (displayPrivateIndex >= 0) + freeDisplayPrivateIndex (displayPrivateIndex); } static CompPluginVTable placeVTable = { - "place", - N_("Place Windows"), - N_("Place windows at appropriate positions when mapped"), - placeInit, - placeFini, - placeInitDisplay, - placeFiniDisplay, - placeInitScreen, - placeFiniScreen, - 0, /* InitWindow */ - 0, /* FiniWindow */ - 0, /* GetDisplayOptions */ - 0, /* SetDisplayOption */ - placeGetScreenOptions, - placeSetScreenOption, - 0, - 0, - 0, - 0, - BERYL_ABI_INFO, - "beryl-plugins", - "wm" + "place", + N_("Place Windows"), + N_("Place windows at appropriate positions when mapped"), + placeInit, + placeFini, + placeInitDisplay, + placeFiniDisplay, + placeInitScreen, + placeFiniScreen, + 0, /* InitWindow */ + 0, /* FiniWindow */ + 0, /* GetDisplayOptions */ + 0, /* SetDisplayOption */ + placeGetScreenOptions, + placeSetScreenOption, + 0, + 0, + 0, + 0, + BERYL_ABI_INFO, + "beryl-plugins", + "wm" }; -CompPluginVTable *getCompPluginInfo(void) +CompPluginVTable * +getCompPluginInfo (void) { - return &placeVTable; + return &placeVTable; } -- cgit v1.1