Index: themes/default.keys/keythemerc =================================================================== --- themes/default.keys/keythemerc (revision 25832) +++ themes/default.keys/keythemerc (working copy) @@ -59,3 +59,6 @@ workspace_7_key=Control+F7 workspace_8_key=Control+F8 workspace_9_key=Control+F9 +fill_horiz_key=None +fill_vert_key=None +fill_window_key=None Index: src/settings.c =================================================================== --- src/settings.c (revision 25832) +++ src/settings.c (working copy) @@ -1336,6 +1336,9 @@ parseKeyString (dpy, &screen_info->params->keys[KEY_WORKSPACE_10], getValue ("workspace_10_key", rc)); parseKeyString (dpy, &screen_info->params->keys[KEY_WORKSPACE_11], getValue ("workspace_11_key", rc)); parseKeyString (dpy, &screen_info->params->keys[KEY_WORKSPACE_12], getValue ("workspace_12_key", rc)); + parseKeyString (dpy, &screen_info->params->keys[KEY_FILL_HORIZ], getValue ("fill_horiz_key", rc)); + parseKeyString (dpy, &screen_info->params->keys[KEY_FILL_VERT], getValue ("fill_vert_key", rc)); + parseKeyString (dpy, &screen_info->params->keys[KEY_FILL_WINDOW], getValue ("fill_window_key", rc)); myScreenUngrabKeys (screen_info); myScreenGrabKeys (screen_info); @@ -1501,6 +1504,9 @@ {"workspace_10_key", NULL, TRUE}, {"workspace_11_key", NULL, TRUE}, {"workspace_12_key", NULL, TRUE}, + {"fill_horiz_key", NULL, TRUE}, + {"fill_vert_key", NULL, TRUE}, + {"fill_window_key", NULL, TRUE}, {NULL, NULL, FALSE} }; @@ -1604,6 +1610,10 @@ { screen_info->params->double_click_action = DBL_CLICK_ACTION_MAXIMIZE; } + else if (!g_ascii_strcasecmp ("fill", value)) + { + screen_info->params->double_click_action = DBL_CLICK_ACTION_FILL; + } else { screen_info->params->double_click_action = DBL_CLICK_ACTION_NONE; Index: src/events.c =================================================================== --- src/events.c (revision 25832) +++ src/events.c (working copy) @@ -465,6 +465,15 @@ /* 'nuff for now */ return EVENT_FILTER_REMOVE; break; + case KEY_FILL_WINDOW: + clientToggleFill (c, CLIENT_FLAG_FILLED); + break; + case KEY_FILL_VERT: + clientToggleFill (c, CLIENT_FLAG_FILLED_VERT); + break; + case KEY_FILL_HORIZ: + clientToggleFill (c, CLIENT_FLAG_FILLED_HORIZ); + break; default: break; } @@ -711,6 +720,9 @@ case DBL_CLICK_ACTION_SHADE: clientToggleShaded (c); break; + case DBL_CLICK_ACTION_FILL: + clientToggleFill(c, CLIENT_FLAG_FILLED); + break; case DBL_CLICK_ACTION_HIDE: if (CLIENT_CAN_HIDE_WINDOW (c)) { Index: src/settings.h =================================================================== --- src/settings.h (revision 25832) +++ src/settings.h (working copy) @@ -103,6 +103,9 @@ KEY_WORKSPACE_10, KEY_WORKSPACE_11, KEY_WORKSPACE_12, + KEY_FILL_HORIZ, + KEY_FILL_VERT, + KEY_FILL_WINDOW, KEY_COUNT }; @@ -125,6 +128,7 @@ DBL_CLICK_ACTION_NONE, DBL_CLICK_ACTION_MAXIMIZE, DBL_CLICK_ACTION_SHADE, + DBL_CLICK_ACTION_FILL, DBL_CLICK_ACTION_HIDE }; Index: src/client.c =================================================================== --- src/client.c (revision 25832) +++ src/client.c (working copy) @@ -2002,7 +2002,7 @@ for (i = 0; i < STATE_TOGGLED; i++) { - xfwmPixmapInit (screen_info, &c->appmenu[i]); + xfwmPixmapInit (screen_info, &c->appmenu[i]); } for (i = 0; i < SIDE_TOP; i++) /* Keep SIDE_TOP for later */ @@ -5226,3 +5226,219 @@ return (c->startup_id); } #endif /* HAVE_LIBSTARTUP_NOTIFICATION */ + +void +clientToggleFill (Client * c, int fill_type) +{ + ScreenInfo *screen_info; + DisplayInfo *display_info; + GList *window_list; + Client *east_neighbour = NULL; + Client *west_neighbour = NULL; + Client *north_neighbour = NULL; + Client *south_neighbour = NULL; + + Client *c_n; + XWindowChanges wc; + int mask = 0; + int key = fill_type; + + screen_info = c->screen_info; + display_info = screen_info->display_info; + + window_list = screen_info->windows; + + + /* Store the original size */ + if (!FLAG_TEST (c->flags, CLIENT_FLAG_FILLED)) + { + c->old_y = c->y; + c->old_height = c->height; + c->old_x = c->x; + c->old_width = c->width; + } + + if (!(FLAG_TEST (c->flags, fill_type) == fill_type)) + { + FLAG_SET(c->flags, fill_type); + while (window_list) + { + /* Retrieve all windows */ + c_n = (Client *)window_list->data; + + /* Filter out all windows which are not present on the same + * workspace as the client window, aswell as the client window + * itself + */ + if ((c->win_workspace == c_n->win_workspace) && (c != window_list->data)) + { + /* Fill horizontally */ + if (FLAG_TEST (c->flags, CLIENT_FLAG_FILLED_HORIZ)) + { + mask |= CWX | CWWidth; + + /* + * check if the neigbour client (c_n) is located + * east or west of our client. + */ + if (!(((c->y + c->height) < (c_n->y - frameTop(c_n))) || ((c_n->y + c_n->height) < (c->y - frameTop(c))))) + { + if ((c_n->x + c_n->width) < c->x) + { + if (east_neighbour) + { + /* Check if c_n is closer to the client + * then the east neighbour already found + */ + if ((east_neighbour->x + east_neighbour->width) < (c_n->x + c_n->width)) + { + east_neighbour = c_n; + } + } + else + { + east_neighbour = c_n; + } + } + if ((c->x + c->width) < c_n->x) + { + /* Check if c_n is closer to the client + * then the west neighbour already found + */ + if (west_neighbour) + { + if (c_n->x < west_neighbour->x) + { + west_neighbour = c_n; + } + } + else + { + west_neighbour = c_n; + } + } + } + } + + /* Fill vertically */ + if (FLAG_TEST (c->flags, CLIENT_FLAG_FILLED_VERT)) + { + mask |= CWY | CWHeight; + + /* check if the neigbour client (c_n) is located + * north or south of our client. + */ + if (!(((c->x + c->width) < c_n->x) || ((c_n->x + c_n->width) < c->x))) + { + if ((c_n->y + c_n->height) < c->y) + { + if (north_neighbour) + { + /* Check if c_n is closer to the client + * then the north neighbour already found + */ + if ((north_neighbour->y + north_neighbour->height) < (c_n->y + c_n->height)) + { + north_neighbour = c_n; + } + } + else + { + north_neighbour = c_n; + } + } + if ((c->y + c->height) < c_n->y) + { + if (south_neighbour) + { + /* Check if c_n is closer to the client + * then the south neighbour already found + */ + if (c_n->y < south_neighbour->y) + { + south_neighbour = c_n; + } + } + else + { + south_neighbour = c_n; + } + } + } + } + } + + window_list = g_list_next(window_list); + } + + wc.x = c->x; + + /* If there are neighbours, resize to their borders. + * If not, resize to the screen-border + */ + + if (east_neighbour) + { + wc.x = east_neighbour->x + east_neighbour->width + + (frameLeft(c) + frameRight(east_neighbour)); + } + else + { + wc.x = frameLeft(c); + } + + if (west_neighbour) + { + wc.width = west_neighbour->x - wc.x - + (frameRight(c) + frameLeft(west_neighbour)); + } + else + { + wc.width = screen_info->width - wc.x - + (frameRight(c)); + } + + if (north_neighbour) + { + wc.y = north_neighbour->y + north_neighbour->height + + (frameTop(c) + frameBottom(north_neighbour)); + } + else + { + wc.y = frameTop(c); + } + + if (south_neighbour) + { + wc.height = south_neighbour->y - wc.y - + (frameTop(south_neighbour) + frameBottom(c)); + } + else + { + wc.height = screen_info->height - wc.y; + } + } + else + { + /* restore the window to it's original state */ + FLAG_UNSET(c->flags, fill_type); + switch(fill_type) + { + case CLIENT_FLAG_FILLED_HORIZ: + mask = CWX | CWWidth; + break; + case CLIENT_FLAG_FILLED_VERT: + mask = CWY | CWHeight; + break; + case CLIENT_FLAG_FILLED: + mask = CWX | CWY | CWWidth | CWHeight; + break; + } + wc.x = c->old_x; + wc.y = c->old_y; + wc.width = c->old_width; + wc.height = c->old_height; + } + + clientConfigure(c, &wc, mask, CFG_FORCE_REDRAW); +} Index: src/screen.c =================================================================== --- src/screen.c (revision 25832) +++ src/screen.c (working copy) @@ -473,6 +473,9 @@ grabKey (dpy, &screen_info->params->keys[KEY_WORKSPACE_10], screen_info->xroot); grabKey (dpy, &screen_info->params->keys[KEY_WORKSPACE_11], screen_info->xroot); grabKey (dpy, &screen_info->params->keys[KEY_WORKSPACE_12], screen_info->xroot); + grabKey (dpy, &screen_info->params->keys[KEY_FILL_HORIZ], screen_info->xroot); + grabKey (dpy, &screen_info->params->keys[KEY_FILL_VERT], screen_info->xroot); + grabKey (dpy, &screen_info->params->keys[KEY_FILL_WINDOW], screen_info->xroot); } void Index: src/client.h =================================================================== --- src/client.h (revision 25832) +++ src/client.h (working copy) @@ -139,6 +139,10 @@ #define CLIENT_FLAG_NAME_CHANGED (1L<<16) #define CLIENT_FLAG_DEMANDS_ATTENTION (1L<<17) #define CLIENT_FLAG_HAS_SHAPE (1L<<18) +#define CLIENT_FLAG_FILLED_VERT (1L<<19) +#define CLIENT_FLAG_FILLED_HORIZ (1L<<20) +#define CLIENT_FLAG_FILLED (CLIENT_FLAG_FILLED_VERT | \ + CLIENT_FLAG_FILLED_HORIZ) #define WM_FLAG_DELETE (1L<<0) #define WM_FLAG_INPUT (1L<<1) @@ -406,4 +410,6 @@ void clientXSyncRequest (Client *); #endif /* HAVE_XSYNC */ +void clientToggleFill (Client *, int); + #endif /* INC_CLIENT_H */ Index: mcs-plugin/xfwm4_shortcuteditor.c =================================================================== --- mcs-plugin/xfwm4_shortcuteditor.c (revision 25832) +++ mcs-plugin/xfwm4_shortcuteditor.c (working copy) @@ -353,6 +353,9 @@ "show_desktop_key", "cancel_key", "popup_menu_key", + "fill_horiz_key", + "fill_vert_key", + "fill_window_key", NULL }; @@ -395,6 +398,9 @@ N_("Show desktop"), N_("Cancel window action"), N_("Window operations menu"), + N_("Fill window horizontally"), + N_("Fill window vertically"), + N_("Fill window"), NULL }; Index: mcs-plugin/xfwm4_plugin.c =================================================================== --- mcs-plugin/xfwm4_plugin.c (revision 25832) +++ mcs-plugin/xfwm4_plugin.c (working copy) @@ -79,6 +79,7 @@ {N_("Shade window"), "shade"}, {N_("Hide window"), "hide"}, {N_("Maximize window"), "maximize"}, + {N_("Fill window"), "fill"}, {N_("Nothing"), "none"}, {NULL, NULL} }; @@ -1896,7 +1897,7 @@ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->box_move_check), !box_move); frame = xfce_create_framebox_with_content (_("Double click action"), - create_option_menu_box (dbl_click_values, 4, + create_option_menu_box (dbl_click_values, 5, _("Action to perform when double clicking on title bar :"), dbl_click_action, G_CALLBACK (cb_dblclick_action_value_changed), mcs_plugin)); gtk_widget_show (frame);