openbox/actions/growtoedge.c (raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
#include "openbox/actions.h" #include "openbox/misc.h" #include "openbox/client.h" #include "openbox/frame.h" #include "openbox/screen.h" #include <glib.h> typedef struct { ObDirection dir; } Options; static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node); static void free_func(gpointer options); static gboolean run_func(ObActionsData *data, gpointer options); void action_growtoedge_startup(void) { actions_register("GrowToEdge", setup_func, free_func, run_func, NULL, NULL); } static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node) { xmlNodePtr n; Options *o; o = g_new0(Options, 1); o->dir = OB_DIRECTION_NORTH; if ((n = parse_find_node("direction", node))) { gchar *s = parse_string(doc, n); if (!g_ascii_strcasecmp(s, "north") || !g_ascii_strcasecmp(s, "up")) o->dir = OB_DIRECTION_NORTH; else if (!g_ascii_strcasecmp(s, "south") || !g_ascii_strcasecmp(s, "down")) o->dir = OB_DIRECTION_SOUTH; else if (!g_ascii_strcasecmp(s, "west") || !g_ascii_strcasecmp(s, "left")) o->dir = OB_DIRECTION_WEST; else if (!g_ascii_strcasecmp(s, "east") || !g_ascii_strcasecmp(s, "right")) o->dir = OB_DIRECTION_EAST; g_free(s); } return o; } static void free_func(gpointer options) { Options *o = options; g_free(o); } static gboolean do_grow(ObActionsData *data, gint x, gint y, gint w, gint h) { gint realw, realh, lw, lh; realw = w; realh = h; client_try_configure(data->client, &x, &y, &realw, &realh, &lw, &lh, TRUE); /* if it's going to be resized smaller than it intended, don't move the window over */ if (x != data->client->area.x) x += w - realw; if (y != data->client->area.y) y += h - realh; if (x != data->client->area.x || y != data->client->area.y || realw != data->client->area.width || realh != data->client->area.height) { actions_client_move(data, TRUE); client_move_resize(data->client, x, y, realw, realh); actions_client_move(data, FALSE); return TRUE; } return FALSE; } /* Always return FALSE because its not interactive */ static gboolean run_func(ObActionsData *data, gpointer options) { Options *o = options; gint x, y, w, h; ObDirection opp; gint half; if (!data->client || /* don't allow vertical resize if shaded */ ((o->dir == OB_DIRECTION_NORTH || o->dir == OB_DIRECTION_SOUTH) && data->client->shaded)) { return FALSE; } /* try grow */ client_find_resize_directional(data->client, o->dir, TRUE, &x, &y, &w, &h); if (do_grow(data, x, y, w, h)) return FALSE; /* we couldn't grow, so try shrink! */ opp = (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH : (o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH : (o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST : OB_DIRECTION_EAST))); client_find_resize_directional(data->client, opp, FALSE, &x, &y, &w, &h); switch (opp) { case OB_DIRECTION_NORTH: half = data->client->area.y + data->client->area.height / 2; if (y > half) { h += y - half; y = half; } break; case OB_DIRECTION_SOUTH: half = data->client->area.height / 2; if (h < half) h = half; break; case OB_DIRECTION_WEST: half = data->client->area.x + data->client->area.width / 2; if (x > half) { w += x - half; x = half; } break; case OB_DIRECTION_EAST: half = data->client->area.width / 2; if (w < half) w = half; break; default: g_assert_not_reached(); } if (do_grow(data, x, y, w, h)) return FALSE; return FALSE; } |