+static int threshold;
+static int dclicktime;
+
+static void parse_assign(char *name, ParseToken *value)
+{
+ if (!g_ascii_strcasecmp(name, "dragthreshold")) {
+ if (value->type != TOKEN_INTEGER)
+ yyerror("invalid value");
+ else {
+ if (value->data.integer >= 0)
+ threshold = value->data.integer;
+ }
+ } else if (!g_ascii_strcasecmp(name, "doubleclicktime")) {
+ if (value->type != TOKEN_INTEGER)
+ yyerror("invalid value");
+ else {
+ if (value->data.integer >= 0)
+ dclicktime = value->data.integer;
+ }
+ } else
+ yyerror("invalid option");
+ parse_free_token(value);
+}
+
+void plugin_setup_config()
+{
+ threshold = 3;
+ dclicktime = 200;
+ parse_reg_section("mouse", mouseparse, parse_assign);
+}
+
+/* Array of GSList*s of PointerBinding*s. */
+static GSList *bound_contexts[NUM_CONTEXTS];
+
+static void grab_for_client(Client *client, gboolean grab)
+{
+ int i;
+ GSList *it;
+
+ for (i = 0; i < NUM_CONTEXTS; ++i)
+ for (it = bound_contexts[i]; it != NULL; it = it->next) {
+ /* grab/ungrab the button */
+ MouseBinding *b = it->data;
+ Window win;
+ int mode;
+ unsigned int mask;
+
+ if (i == Context_Frame) {
+ win = client->frame->window;
+ mode = GrabModeAsync;
+ mask = ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
+ } else if (i == Context_Client) {
+ win = client->frame->plate;
+ mode = GrabModeSync; /* this is handled in event */
+ mask = ButtonPressMask; /* can't catch more than this with Sync
+ mode the release event is
+ manufactured in event() */
+ } else continue;
+
+ if (grab)
+ grab_button(b->button, b->state, win, mask, mode);
+ else
+ ungrab_button(b->button, b->state, win);
+ }
+}
+
+static void grab_all_clients(gboolean grab)
+{
+ GList *it;
+
+ for (it = client_list; it != NULL; it = it->next)
+ grab_for_client(it->data, grab);
+}
+
+static void clearall()
+{
+ int i;
+ GSList *it;
+
+ for(i = 0; i < NUM_CONTEXTS; ++i) {
+ for (it = bound_contexts[i]; it != NULL; it = it->next) {
+ int j;
+
+ MouseBinding *b = it->data;
+ for (j = 0; j < NUM_MOUSEACTION; ++j)
+ if (b->action[j] != NULL)
+ action_free(b->action[j]);
+ g_free(b);
+ }
+ g_slist_free(bound_contexts[i]);
+ }
+}
+
+static void fire_button(MouseAction a, Context context, Client *c, guint state,
+ guint button, int x, int y)
+{
+ GSList *it;
+ MouseBinding *b;
+
+ for (it = bound_contexts[context]; it != NULL; it = it->next) {
+ b = it->data;
+ if (b->state == state && b->button == button)
+ break;
+ }
+ /* if not bound, then nothing to do! */
+ if (it == NULL) return;
+
+ if (b->action[a] != NULL && b->action[a]->func != NULL) {
+ b->action[a]->data.any.c = c;
+
+ g_assert(b->action[a]->func != action_moveresize);
+
+ if (b->action[a]->func == action_showmenu) {
+ b->action[a]->data.showmenu.x = x;
+ b->action[a]->data.showmenu.y = y;
+ }
+
+ b->action[a]->func(&b->action[a]->data);
+ }
+}
+
+static void fire_motion(MouseAction a, Context context, Client *c,
+ guint state, guint button, int x_root, int y_root,
+ guint32 corner)
+{
+ GSList *it;
+ MouseBinding *b;
+
+ for (it = bound_contexts[context]; it != NULL; it = it->next) {
+ b = it->data;
+ if (b->state == state && b->button == button)
+ break;
+ }
+ /* if not bound, then nothing to do! */
+ if (it == NULL) return;
+
+ if (b->action[a] != NULL && b->action[a]->func != NULL) {
+ b->action[a]->data.any.c = c;
+
+ if (b->action[a]->func == action_moveresize) {
+ b->action[a]->data.moveresize.x = x_root;
+ b->action[a]->data.moveresize.y = y_root;
+ b->action[a]->data.moveresize.button = button;
+ if (!(b->action[a]->data.moveresize.corner ==
+ prop_atoms.net_wm_moveresize_move ||
+ b->action[a]->data.moveresize.corner ==
+ prop_atoms.net_wm_moveresize_move_keyboard ||
+ b->action[a]->data.moveresize.corner ==
+ prop_atoms.net_wm_moveresize_size_keyboard))
+ b->action[a]->data.moveresize.corner = corner;
+ } else
+ g_assert_not_reached();
+
+ b->action[a]->func(&b->action[a]->data);
+ }
+}
+
+static guint32 pick_corner(int x, int y, int cx, int cy, int cw, int ch)
+{
+ if (x - cx < cw / 2) {
+ if (y - cy < ch / 2)
+ return prop_atoms.net_wm_moveresize_size_topleft;
+ else
+ return prop_atoms.net_wm_moveresize_size_bottomleft;
+ } else {
+ if (y - cy < ch / 2)
+ return prop_atoms.net_wm_moveresize_size_topright;
+ else
+ return prop_atoms.net_wm_moveresize_size_bottomright;
+ }
+}