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 146 147 148 149 150 151 |
#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; gboolean shrink; } Options; static gpointer setup_func(xmlNodePtr node); static gpointer setup_shrink_func(xmlNodePtr node); static gboolean run_func(ObActionsData *data, gpointer options); void action_growtoedge_startup(void) { actions_register("GrowToEdge", setup_func, g_free, run_func, NULL, NULL); actions_register("ShrinkToEdge", setup_shrink_func, g_free, run_func, NULL, NULL); } static gpointer setup_func(xmlNodePtr node) { xmlNodePtr n; Options *o; o = g_new0(Options, 1); o->dir = OB_DIRECTION_NORTH; o->shrink = FALSE; if ((n = obt_parse_find_node(node, "direction"))) { gchar *s = obt_parse_node_string(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 gpointer setup_shrink_func(xmlNodePtr node) { Options *o; o = setup_func(node); o->shrink = TRUE; return 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; } if (!o->shrink) { /* 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; } |