+pressbutton(struct swm_region *r, union arg *args)
+{
+ XTestFakeButtonEvent(display, args->id, True, CurrentTime);
+ XTestFakeButtonEvent(display, args->id, False, CurrentTime);
+}
+
+void
+raise_toggle(struct swm_region *r, union arg *args)
+{
+ if (r && r->ws == NULL)
+ return;
+
+ r->ws->always_raise = !r->ws->always_raise;
+
+ /* bring floaters back to top */
+ if (r->ws->always_raise == 0)
+ stack();
+}
+
+void
+iconify(struct swm_region *r, union arg *args)
+{
+ union arg a;
+
+ if (r->ws->focus == NULL)
+ return;
+ unmap_window(r->ws->focus);
+ update_iconic(r->ws->focus, 1);
+ stack();
+ if (focus_mode == SWM_FOCUS_DEFAULT)
+ drain_enter_notify();
+ r->ws->focus = NULL;
+ a.id = SWM_ARG_ID_FOCUSCUR;
+ focus(r, &a);
+}
+
+unsigned char *
+get_win_name(Display *dpy, Window win, Atom wname, Atom stype,
+ unsigned long *slen)
+{
+ int status, retfmt;
+ unsigned long nitems, nbytes, nextra;
+ unsigned char *prop = NULL;
+ Atom rettype;
+
+ status = XGetWindowProperty(dpy, win, wname, 0L, 0L, False, stype,
+ &rettype, &retfmt, &nitems, &nbytes, &prop);
+ if (status != Success)
+ return (NULL);
+ XFree(prop);
+
+ status = XGetWindowProperty(dpy, win, wname, 0L, nbytes, False,
+ stype, &rettype, &retfmt, &nitems, &nextra, &prop);
+ if (status != Success) {
+ XFree(prop);
+ return (NULL);
+ }
+ if (rettype != stype) {
+ XFree(prop);
+ return (NULL);
+ }
+ *slen = nitems;
+ return (prop);
+}
+
+void
+uniconify(struct swm_region *r, union arg *args)
+{
+ struct ws_win *win;
+ FILE *lfile;
+ unsigned char *name;
+ int count = 0;
+ unsigned long len;
+
+ DNPRINTF(SWM_D_MISC, "uniconify\n");
+
+ if (r && r->ws == NULL)
+ return;
+
+ /* make sure we have anything to uniconify */
+ TAILQ_FOREACH(win, &r->ws->winlist, entry) {
+ if (win->ws == NULL)
+ continue; /* should never happen */
+ if (win->iconic == 0)
+ continue;
+ count++;
+ }
+ if (count == 0)
+ return;
+
+ search_r = r;
+ search_resp_action = SWM_SEARCH_UNICONIFY;
+
+ spawn_select(r, args, "search", &searchpid);
+
+ if ((lfile = fdopen(select_list_pipe[1], "w")) == NULL)
+ return;
+
+ TAILQ_FOREACH(win, &r->ws->winlist, entry) {
+ if (win->ws == NULL)
+ continue; /* should never happen */
+ if (win->iconic == 0)
+ continue;
+
+ name = get_win_name(display, win->id, a_wmname, a_string,
+ &len);
+ if (name == NULL)
+ continue;
+ fprintf(lfile, "%s.%lu\n", name, win->id);
+ XFree(name);
+ }
+
+ fclose(lfile);
+}
+
+void
+search_resp_uniconify(char *resp, unsigned long len)
+{
+ unsigned char *name;
+ struct ws_win *win;
+ char *s;
+
+ DNPRINTF(SWM_D_MISC, "search_resp_uniconify: resp %s\n", resp);
+
+ TAILQ_FOREACH(win, &search_r->ws->winlist, entry) {
+ if (win->iconic == 0)
+ continue;
+ name = get_win_name(display, win->id, a_wmname, a_string, &len);
+ if (name == NULL)
+ continue;
+ if (asprintf(&s, "%s.%lu", name, win->id) == -1) {
+ XFree(name);
+ continue;
+ }
+ XFree(name);
+ if (strncmp(s, resp, len) == 0) {
+ /* XXX this should be a callback to generalize */
+ update_iconic(win, 0);
+ free(s);
+ break;
+ }
+ free(s);
+ }
+}
+
+#define MAX_RESP_LEN 1024
+
+void
+search_do_resp(void)
+{
+ ssize_t rbytes;
+ char *resp;
+ unsigned long len;
+
+ DNPRINTF(SWM_D_MISC, "search_do_resp:\n");
+
+ search_resp = 0;
+ searchpid = 0;
+
+ if ((resp = calloc(1, MAX_RESP_LEN + 1)) == NULL) {
+ fprintf(stderr, "search: calloc\n");
+ goto done;
+ }
+
+ rbytes = read(select_resp_pipe[0], resp, MAX_RESP_LEN);
+ if (rbytes <= 0) {
+ fprintf(stderr, "search: read error: %s\n", strerror(errno));
+ goto done;
+ }
+ resp[rbytes] = '\0';
+ len = strlen(resp);
+
+ switch (search_resp_action) {
+ case SWM_SEARCH_UNICONIFY:
+ search_resp_uniconify(resp, len);
+ break;
+ }
+
+done:
+ search_resp_action = SWM_SEARCH_NONE;
+ close(select_resp_pipe[0]);
+ free(resp);
+}
+
+void