2 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3 * Copyright (C) 2004-2009 Kim Woelders
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies of the Software, its documentation and marketing & publicity
14 * materials, and acknowledgment shall be given in the documentation, materials
15 * and software packages that this Software was used.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #include "borders.h" /* FIXME - Should not be here */
34 #include "hints.h" /* FIXME - Should not be here */
42 #define ENABLE_IPC_INSERT_KEYS 0
44 #define SS(s) ((s) ? (s) : NoText)
45 static const char NoText[] = "-NONE-";
47 static char *ipc_bufptr = NULL;
48 static size_t ipc_bufsiz = 0;
49 static char ipc_active = 0;
69 IpcPrintGetBuffer(void)
73 ipc_bufptr[ipc_bufsiz] = '\0';
78 IpcPrintf(const char *fmt, ...)
80 char tmp[FILEPATH_LEN_MAX];
88 len = Evsnprintf(tmp, sizeof(tmp), fmt, args);
91 ipc_bufptr = EREALLOC(char, ipc_bufptr, ipc_bufsiz + len + 1);
93 memcpy(ipc_bufptr + ipc_bufsiz, tmp, len);
98 SetEwinBoolean(const char *txt, char *item, const char *value, int set)
102 vnew = vold = *item != 0; /* Remember old value */
104 if (value == NULL || value[0] == '\0')
106 else if (!strcmp(value, "on"))
108 else if (!strcmp(value, "off"))
110 else if (!strcmp(value, "?"))
111 IpcPrintf("%s: %s", txt, (vold) ? "on" : "off");
113 IpcPrintf("Error: %s", value);
125 /* The IPC functions */
128 IPC_Screen(const char *params)
139 sscanf(p, "%1000s %n", param, &l);
143 if (!p || !strncmp(param, "list", 2))
147 else if (!strncmp(param, "size", 2))
149 IpcPrintf("Screen %d size %dx%d\n", Dpy.screen,
150 WinGetW(VROOT), WinGetH(VROOT));
152 else if (!strcmp(param, "split"))
158 sscanf(p, "%u %u\n", &nx, &ny);
164 IPC_Nop(const char *params __UNUSED__)
169 /* Should be elsewhere */
171 IPC_Border_CB_List(Border * b, void *data __UNUSED__)
173 IpcPrintf("%s\n", BorderGetName(b));
177 IPC_Border(const char *params)
181 IpcPrintf("Please specify...\n");
185 if (!strncmp(params, "list", 2))
187 BordersForeach(IPC_Border_CB_List, NULL);
192 IPC_DialogOK(const char *params)
195 DialogOKstr(_("Message"), params);
197 IpcPrintf("Error: No text for dialog specified\n");
201 CfgStrlistIndex(const char **list, const char *str)
205 for (i = 0; list[i]; i++)
206 if (!strcmp(list[i], str))
211 static const char *MovResCfgMoveModes[] = {
212 "opaque", "lined", "box", "shaded", "semi-solid", "translucent", NULL
215 static const char *MovResCfgResizeModes[] = {
216 "opaque", "lined", "box", "shaded", "semi-solid", NULL
219 static const char *MovResCfgInfoModes[] = {
220 "never", "center", "corner", NULL
224 IPC_MoveResize(const char *params)
232 IpcPrintf("Please specify...\n");
236 param1[0] = param2[0] = '\0';
237 sscanf(params, "%31s %31s", param1, param2);
239 if (!strncmp(param1, "move", 2))
241 if (param2[0] == '\n' || param2[0] == '?')
243 if (Conf.movres.mode_move < 0 || Conf.movres.mode_move > 5)
244 Conf.movres.mode_move = 0;
245 IpcPrintf("Move mode: %s\n",
246 MovResCfgMoveModes[Conf.movres.mode_move]);
250 i = CfgStrlistIndex(MovResCfgMoveModes, param2);
253 Conf.movres.mode_move = i;
257 IpcPrintf("Move mode not found: %s\n", param2);
261 else if (!strncmp(param1, "resize", 2))
263 if (param2[0] == '\n' || param2[0] == '?')
265 if (Conf.movres.mode_resize < 0 || Conf.movres.mode_resize > 4)
266 Conf.movres.mode_resize = 0;
267 IpcPrintf("Resize mode: %s\n",
268 MovResCfgResizeModes[Conf.movres.mode_resize]);
272 i = CfgStrlistIndex(MovResCfgResizeModes, param2);
275 Conf.movres.mode_resize = i;
279 IpcPrintf("Resize mode not found: %s\n", param2);
283 else if (!strncmp(param1, "info", 2))
285 if (param2[0] == '\n' || param2[0] == '?')
287 if (Conf.movres.mode_info < 0 || Conf.movres.mode_info > 2)
288 Conf.movres.mode_info = 1;
289 IpcPrintf("Info mode: %s\n",
290 MovResCfgInfoModes[Conf.movres.mode_info]);
294 i = CfgStrlistIndex(MovResCfgInfoModes, param2);
297 Conf.movres.mode_info = i;
301 IpcPrintf("Info mode not found: %s\n", param2);
308 IPC_WinList(const char *params)
310 static const char *const TxtPG[] = { "NW", "NE", "SW", "SE" };
321 sscanf(params, "%8s %n", format, &num);
324 if (!match || !match[0])
327 lst = EwinsFindByExpr(match, &num, NULL);
330 IpcPrintf("No windows matching %s\n", match);
334 for (i = 0; i < num; i++)
340 IpcPrintf("%#lx : %s\n", EwinGetClientXwin(e),
341 SS(EwinGetIcccmName(e)));
345 IpcPrintf("%#lx : %s :: %d : %d %d : %d %d %dx%d\n",
346 EwinGetClientXwin(e), SS(EwinGetIcccmName(e)),
347 (EoIsSticky(e)) ? -1 : (int)EoGetDeskNum(e), e->area_x,
348 e->area_y, EoGetX(e), EoGetY(e), EoGetW(e), EoGetH(e));
352 IpcPrintf("%#10lx : %5d %5d %4dx%4d :: %2d : %d %d : %s\n",
353 EwinGetClientXwin(e), EoGetX(e), EoGetY(e), EoGetW(e),
354 EoGetH(e), (EoIsSticky(e)) ? -1 : (int)EoGetDeskNum(e),
355 e->area_x, e->area_y, SS(EwinGetIcccmName(e)));
360 ("%#10lx : %5d %5d %4dx%4d :: %2d : %s %4d,%4d %2d,%2d : %s\n",
361 EwinGetClientXwin(e), EoGetX(e), EoGetY(e), EoGetW(e),
362 EoGetH(e), (EoIsSticky(e)) ? -1 : (int)EoGetDeskNum(e),
363 TxtPG[e->place.gravity & 3], e->place.gx, e->place.gy,
364 e->place.ax, e->place.ay, SS(EwinGetIcccmName(e)));
369 ("%#10lx : %5d %5d %4dx%4d :: %2d : \"%s\" \"%s\" : \"%s\" : \"%s\"\n",
370 EwinGetClientXwin(e), EoGetX(e), EoGetY(e), EoGetW(e),
371 EoGetH(e), (EoIsSticky(e)) ? -1 : (int)EoGetDeskNum(e),
372 SS(EwinGetIcccmCName(e)), SS(EwinGetIcccmClass(e)),
373 SS(EwinGetIcccmName(e)), SS(e->icccm.wm_role));
382 doMoveConstrained(EWin * ewin, const char *params)
384 return ActionMoveStart(ewin, 0, params, 1, 0);
388 doMoveNoGroup(EWin * ewin, const char *params)
390 return ActionMoveStart(ewin, 0, params, 0, 1);
394 doSwapMove(EWin * ewin, const char *params)
397 return ActionMoveStart(ewin, 0, params, 0, 0);
401 doMoveConstrainedNoGroup(EWin * ewin, const char *params)
403 return ActionMoveStart(ewin, 0, params, 1, 1);
407 static Timer *op_timer = NULL;
410 OpacityTimeout(void *data)
412 EWin *ewin = (EWin *) data;
414 if (!EwinFindByPtr(ewin)) /* May be gone */
417 if (ewin->state.active)
418 EoChangeOpacity(ewin, ewin->props.focused_opacity);
421 ewin->state.show_coords = 0;
427 IpcWinop(const WinOp * wop, EWin * ewin, const char *prm)
429 char param1[128], param2[128];
434 param1[0] = param2[0] = '\0';
435 sscanf(prm, "%128s %128s", param1, param2);
440 /* We should not get here */
441 IpcPrintf("Error: unknown operation");
447 IpcPrintf("Error: no border specified");
450 if (!strcmp(param1, "?"))
452 IpcPrintf("window border: %s", BorderGetName(ewin->border));
455 EwinOpSetBorder(ewin, OPSRC_USER, param1);
461 IpcPrintf("Error: no title specified");
464 if (!strcmp(prm, "?"))
466 IpcPrintf("title: %s", EwinGetIcccmName(ewin));
469 HintsSetWindowName(EwinGetClientWin(ewin), prm);
473 EwinOpClose(ewin, OPSRC_USER);
477 EwinOpKill(ewin, OPSRC_USER);
480 case EWIN_OP_ICONIFY:
481 on = ewin->state.iconified;
482 if (SetEwinBoolean("window iconified", &on, param1, 1))
483 EwinOpIconify(ewin, OPSRC_USER, on);
491 on = ewin->state.shaded;
492 if (SetEwinBoolean(wop->name, &on, param1, 1))
493 EwinOpShade(ewin, OPSRC_USER, on);
497 on = EoIsSticky(ewin);
498 if (SetEwinBoolean(wop->name, &on, param1, 1))
499 EwinOpStick(ewin, OPSRC_USER, on);
503 if (!strcmp(param1, "?"))
505 IpcPrintf("focused: %s", (ewin == GetFocusEwin())? "yes" : "no");
508 EwinOpActivate(ewin, OPSRC_USER, 1);
514 IpcPrintf("Error: no desktop supplied");
517 if (!strncmp(param1, "next", 1))
519 EwinOpMoveToDesk(ewin, OPSRC_USER, EoGetDesk(ewin), 1);
521 else if (!strncmp(param1, "prev", 1))
523 EwinOpMoveToDesk(ewin, OPSRC_USER, EoGetDesk(ewin), -1);
525 else if (!strcmp(param1, "?"))
527 IpcPrintf("window desk: %d", EoGetDeskNum(ewin));
531 EwinOpMoveToDesk(ewin, OPSRC_USER, NULL, atoi(param1));
538 IpcPrintf("Error: no area supplied");
541 if (!strcmp(param1, "?"))
543 IpcPrintf("window area: %d %d", ewin->area_x, ewin->area_y);
545 else if (!strcmp(param1, "move"))
548 sscanf(prm, "%*s %i %i", &a, &b);
549 EwinMoveToArea(ewin, ewin->area_x + a, ewin->area_y + b);
555 sscanf(param1, "%i", &a);
556 sscanf(param2, "%i", &b);
557 EwinMoveToArea(ewin, a, b);
564 IpcPrintf("Error: no coords supplied");
567 if (!strcmp(param1, "ptr"))
569 ActionMoveStart(ewin, 0, 0, Mode.nogroup);
571 else if (!strcmp(param1, "kbd"))
573 ActionMoveStart(ewin, 1, 0, Mode.nogroup);
575 else if (!strcmp(param1, "?"))
577 IpcPrintf("window location: %d %d", EoGetX(ewin), EoGetY(ewin));
579 else if (!strcmp(param1, "??"))
581 IpcPrintf("client location: %d %d",
582 EoGetX(ewin) + ewin->border->border.left,
583 EoGetY(ewin) + ewin->border->border.top);
589 sscanf(param1, "%i", &a);
590 sscanf(param2, "%i", &b);
591 EwinOpMove(ewin, OPSRC_USER, a, b);
599 if (!strcmp(param1, "ptr"))
601 ActionResizeStart(ewin, 0, MODE_RESIZE);
603 else if (!strcmp(param1, "ptr-h"))
605 ActionResizeStart(ewin, 0, MODE_RESIZE_H);
607 else if (!strcmp(param1, "ptr-v"))
609 ActionResizeStart(ewin, 0, MODE_RESIZE_V);
611 else if (!strcmp(param1, "kbd"))
613 ActionResizeStart(ewin, 1, MODE_RESIZE);
615 else if (!strcmp(param1, "?"))
617 IpcPrintf("window size: %d %d", ewin->client.w, ewin->client.h);
619 else if (!strcmp(param1, "??"))
621 IpcPrintf("frame size: %d %d", EoGetW(ewin), EoGetH(ewin));
627 sscanf(param1, "%i", &a);
628 sscanf(param2, "%i", &b);
629 EwinOpResize(ewin, OPSRC_USER, a, b);
633 case EWIN_OP_MOVE_REL:
637 sscanf(prm, "%i %i", &a, &b);
640 EwinOpMove(ewin, OPSRC_USER, a, b);
643 case EWIN_OP_SIZE_REL:
647 sscanf(prm, "%i %i", &a, &b);
650 EwinOpResize(ewin, OPSRC_USER, a, b);
653 case EWIN_OP_MAX_WIDTH:
654 MaxSizeHV(ewin, param1, 1, 0);
657 case EWIN_OP_MAX_HEIGHT:
658 MaxSizeHV(ewin, param1, 0, 1);
661 case EWIN_OP_MAX_SIZE:
662 MaxSizeHV(ewin, param1, 1, 1);
665 case EWIN_OP_FULLSCREEN:
666 on = ewin->state.fullscreen;
667 if (SetEwinBoolean(wop->name, &on, param1, 1))
668 EwinOpFullscreen(ewin, OPSRC_USER, on);
679 if (!strcmp(param1, "?"))
681 IpcPrintf("window layer: %d", EoGetLayer(ewin));
685 EwinOpSetLayer(ewin, OPSRC_USER, val);
689 EwinOpRaise(ewin, OPSRC_USER);
693 EwinOpLower(ewin, OPSRC_USER);
696 case EWIN_OP_OPACITY:
697 a = OpacityToPercent(ewin->ewmh.opacity);
698 if (!strcmp(param1, "?"))
700 IpcPrintf("opacity: %u", a);
704 sscanf(param1, "%i", &b);
705 if ((param1[0] == '+') || (param1[0] == '-'))
707 a = (b < 0) ? 1 : (b > 100) ? 100 : b;
708 EwinOpSetOpacity(ewin, OPSRC_USER, a);
709 if (a && ewin->state.active)
711 EoChangeOpacity(ewin, OpacityFromPercent(a));
713 if (ewin->props.focused_opacity)
714 TIMER_ADD(op_timer, 0.001 * 700, OpacityTimeout, ewin);
716 if (ewin->state.in_action)
717 CoordsShowOpacity(ewin);
720 case EWIN_OP_FOCUSED_OPACITY:
721 a = OpacityToPercent(ewin->props.focused_opacity);
722 if (!strcmp(param1, "?"))
724 IpcPrintf("focused_opacity: %u", a);
728 sscanf(param1, "%i", &b);
729 if ((param1[0] == '+') || (param1[0] == '-'))
731 a = (b < 0) ? 0 : (b > 100) ? 100 : b;
732 EwinOpSetFocusedOpacity(ewin, OPSRC_USER, a);
733 if (ewin->state.in_action)
734 CoordsShowOpacity(ewin);
738 SnapshotEwinParse(ewin, prm);
741 case EWIN_OP_SKIP_LISTS:
742 on = ewin->props.skip_ext_task;
743 if (SetEwinBoolean(wop->name, &on, param1, 1))
744 EwinOpSkipLists(ewin, OPSRC_USER, on);
747 case EWIN_OP_NEVER_USE_AREA:
748 on = ewin->props.never_use_area;
749 SetEwinBoolean(wop->name, &on, param1, 1);
750 ewin->props.never_use_area = on;
751 goto ewin_update_snap_flags;
753 case EWIN_OP_FOCUS_CLICK:
754 on = ewin->props.focusclick;
755 SetEwinBoolean(wop->name, &on, param1, 1);
756 ewin->props.focusclick = on;
757 goto ewin_update_snap_flags;
759 case EWIN_OP_AUTOSHADE:
760 on = ewin->props.autoshade;
761 SetEwinBoolean(wop->name, &on, param1, 1);
762 ewin->props.autoshade = on;
763 goto ewin_update_snap_flags;
765 case EWIN_OP_NO_BUTTON_GRABS:
766 on = ewin->props.no_button_grabs;
767 if (SetEwinBoolean(wop->name, &on, param1, 1))
769 ewin->props.no_button_grabs = on;
770 if (ewin->props.no_button_grabs)
771 UnGrabButtonGrabs(EoGetWin(ewin));
773 GrabButtonGrabs(EoGetWin(ewin));
775 goto ewin_update_snap_flags;
777 case EWIN_OP_INH_APP_FOCUS:
778 on = EwinInhGetApp(ewin, focus);
779 SetEwinBoolean(wop->name, &on, param1, 1);
780 EwinInhSetApp(ewin, focus, on);
781 goto ewin_update_snap_flags;
783 case EWIN_OP_INH_APP_MOVE:
784 on = EwinInhGetApp(ewin, move);
785 SetEwinBoolean(wop->name, &on, param1, 1);
786 EwinInhSetApp(ewin, move, on);
787 goto ewin_update_snap_flags;
789 case EWIN_OP_INH_APP_SIZE:
790 on = EwinInhGetApp(ewin, size);
791 SetEwinBoolean(wop->name, &on, param1, 1);
792 EwinInhSetApp(ewin, size, on);
793 goto ewin_update_snap_flags;
795 case EWIN_OP_INH_USER_CLOSE:
796 on = EwinInhGetUser(ewin, close);
797 SetEwinBoolean(wop->name, &on, param1, 1);
798 EwinInhSetUser(ewin, close, on);
799 goto ewin_update_state_hints;
801 case EWIN_OP_INH_USER_MOVE:
802 on = EwinInhGetUser(ewin, move);
803 SetEwinBoolean(wop->name, &on, param1, 1);
804 EwinInhSetUser(ewin, move, on);
805 goto ewin_update_state_hints;
807 case EWIN_OP_INH_USER_SIZE:
808 on = EwinInhGetUser(ewin, size);
809 SetEwinBoolean(wop->name, &on, param1, 1);
810 EwinInhSetUser(ewin, size, on);
811 goto ewin_update_state_hints;
813 case EWIN_OP_INH_WM_FOCUS:
814 on = EwinInhGetWM(ewin, focus);
815 SetEwinBoolean(wop->name, &on, param1, 1);
816 EwinInhSetWM(ewin, focus, on);
817 goto ewin_update_state;
821 on = EoGetFade(ewin);
822 if (SetEwinBoolean(wop->name, &on, param1, 1))
827 on = EoGetShadow(ewin);
828 if (SetEwinBoolean(wop->name, &on, param1, 1))
829 EoChangeShadow(ewin, on);
832 case EWIN_OP_NO_REDIRECT:
833 on = EoGetNoRedirect(ewin);
834 on = ewin->o.noredir;
835 if (SetEwinBoolean(wop->name, &on, param1, 1))
836 EoSetNoRedirect(ewin, on);
839 ewin_update_snap_flags:
840 SnapshotEwinUpdate(ewin, SNAP_USE_FLAGS);
844 EwinStateUpdate(ewin);
847 ewin_update_state_hints:
848 EwinStateUpdate(ewin);
849 HintsSetWindowState(ewin);
858 IPC_WinOps(const char *params)
869 IpcPrintf("Error: no window specified");
873 match[0] = operation[0] = '\0';
875 sscanf(params, "%128s %128s %n", match, operation, &num);
880 IpcPrintf("Error: no operation specified");
884 wop = EwinOpFind(operation);
887 IpcPrintf("Error: unknown operation");
891 lst = EwinsFindByExpr(match, &num, &flags);
894 IpcPrintf("No windows matching %s\n", match);
901 for (i = 0; i < num; i++)
902 IpcWinop(wop, lst[i], p);
910 IPC_Remember(const char *params)
917 IpcPrintf("Error: no parameters\n");
923 sscanf(params, "%x %n", &window, &l);
927 ewin = EwinFindByClient(window);
930 IpcPrintf("Error: Window not found: %#x\n", window);
934 SnapshotEwinParse(ewin, params + l);
941 IPC_ForceSave(const char *params __UNUSED__)
947 IPC_Exec(const char *params)
950 execApplication(params, EXEC_SET_LANG | EXEC_SET_STARTUP_ID);
952 IpcPrintf("exec what?\n");
956 IPC_Restart(const char *params __UNUSED__)
958 SessionExit(EEXIT_RESTART, NULL);
962 IPC_Exit(const char *params)
971 sscanf(params, "%1000s %n", param1, &l);
972 p2 = (l > 0) ? params + l : NULL;
975 SessionExit(EEXIT_EXIT, NULL);
976 else if (!strcmp(param1, "logout"))
977 SessionExit(EEXIT_LOGOUT, NULL);
978 else if (!strcmp(param1, "restart"))
979 SessionExit(EEXIT_RESTART, NULL);
980 else if (!strcmp(param1, "theme"))
981 SessionExit(EEXIT_THEME, p2);
982 else if (!strcmp(param1, "exec"))
983 SessionExit(EEXIT_EXEC, p2);
988 IPC_About(const char *params __UNUSED__)
995 IPC_Version(const char *params __UNUSED__)
997 IpcPrintf("%s %s\n", e_wm_name, e_wm_version);
1001 IPC_Debug(const char *params)
1012 sscanf(p, "%1000s %n", param, &l);
1015 if (!strncmp(param, "event", 2))
1019 else if (!strncmp(param, "grab", 2))
1022 sscanf(p, "%1000s %n", param, &l);
1025 if (!strcmp(param, "?"))
1027 IpcPrintf("Pointer grab on=%d win=%#lx\n",
1028 Mode.grabs.pointer_grab_active,
1029 Mode.grabs.pointer_grab_window);
1031 else if (!strncmp(param, "allow", 2))
1034 sscanf(p, "%d", &l);
1035 XAllowEvents(disp, l, CurrentTime);
1036 IpcPrintf("XAllowEvents\n");
1038 else if (!strncmp(param, "unset", 2))
1040 GrabPointerRelease();
1041 IpcPrintf("Ungrab\n");
1044 else if (!strncmp(param, "sync", 2))
1047 sscanf(p, "%1000s %n", param, &l);
1049 if (!strncmp(param, "on", 2))
1051 XSynchronize(disp, True);
1052 IpcPrintf("Sync on\n");
1054 else if (!strncmp(param, "off", 2))
1056 XSynchronize(disp, False);
1057 IpcPrintf("Sync off\n");
1063 IPC_Set(const char *params)
1065 ConfigurationSet(params);
1069 IPC_Show(const char *params)
1071 ConfigurationShow(params);
1075 EwinShowInfo(const EWin * ewin)
1079 EwinBorderGetSize(ewin, &bl, &br, &bt, &bb);
1081 IpcPrintf("WM_NAME %s\n"
1084 "WM_CLASS name.class %s.%s\n"
1085 "WM_WINDOW_ROLE %s\n"
1087 "WM_CLIENT_MACHINE %s\n"
1088 "Client window %#10lx x,y %4i,%4i wxh %4ix%4i\n"
1089 "Container window %#10lx\n"
1090 "Frame window %#10lx x,y %4i,%4i wxh %4ix%4i\n"
1092 "Named pixmap %#10lx\n"
1094 "Border %s lrtb %i,%i,%i,%i\n"
1095 "Icon window, pixmap, mask %#10lx, %#10lx, %#10lx\n"
1096 "Is group leader %i Window group leader %#lx Client leader %#10lx\n"
1097 "Has transients %i Transient type %i Transient for %#10lx\n"
1098 "No resize H/V %i/%i Shaped %i\n"
1099 "Base, min, max, inc w/h %ix%i, %ix%i, %ix%i %ix%i\n"
1100 "Aspect min, max %5.5f, %5.5f\n"
1101 "Struts lrtb %i,%i,%i,%i\n"
1102 "MWM border %i resizeh %i title %i menu %i minimize %i maximize %i\n"
1103 "NeedsInput %i TakeFocus %i FocusNever %i FocusClick %i\n"
1104 "NeverUseArea %i FixedPos %i FixedSize %i\n"
1105 "Desktop %i Layer %i(%i)\n"
1106 "Iconified %i Sticky %i Shaded %i Docked %i\n"
1107 "State %i Shown %i Visibility %i Active %i\n"
1108 "Member of groups %i\n"
1110 "Opacity %3i(%x) Focused Opacity %3i\n"
1111 "Shadow %i Fade %i NoRedirect %i\n"
1116 SS(EwinGetIcccmName(ewin)),
1117 SS(ewin->ewmh.wm_name),
1118 SS(ewin->icccm.wm_icon_name),
1119 SS(EwinGetIcccmCName(ewin)), SS(EwinGetIcccmClass(ewin)),
1120 SS(ewin->icccm.wm_role),
1121 SS(ewin->icccm.wm_command),
1122 SS(ewin->icccm.wm_machine),
1123 EwinGetClientXwin(ewin),
1124 ewin->client.x, ewin->client.y, ewin->client.w, ewin->client.h,
1125 EwinGetContainerXwin(ewin),
1127 EoGetX(ewin), EoGetY(ewin), EoGetW(ewin), EoGetH(ewin),
1131 EwinBorderGetName(ewin), bl, br, bt, bb,
1132 ewin->icccm.icon_win,
1133 ewin->icccm.icon_pmap, ewin->icccm.icon_mask,
1134 EwinIsWindowGroupLeader(ewin), EwinGetWindowGroup(ewin),
1135 ewin->icccm.client_leader, EwinGetTransientCount(ewin),
1136 EwinIsTransient(ewin), EwinGetTransientFor(ewin),
1137 ewin->props.no_resize_h, ewin->props.no_resize_v,
1138 ewin->state.shaped, ewin->icccm.base_w, ewin->icccm.base_h,
1139 ewin->icccm.width_min, ewin->icccm.height_min,
1140 ewin->icccm.width_max, ewin->icccm.height_max,
1141 ewin->icccm.w_inc, ewin->icccm.h_inc,
1142 ewin->icccm.aspect_min, ewin->icccm.aspect_max,
1143 ewin->strut.left, ewin->strut.right,
1144 ewin->strut.top, ewin->strut.bottom,
1145 ewin->mwm.decor_border, ewin->mwm.decor_resizeh,
1146 ewin->mwm.decor_title, ewin->mwm.decor_menu,
1147 ewin->mwm.decor_minimize, ewin->mwm.decor_maximize,
1148 ewin->icccm.need_input, ewin->icccm.take_focus,
1149 EwinInhGetWM(ewin, focus), ewin->props.focusclick,
1150 ewin->props.never_use_area, EwinInhGetUser(ewin, move),
1151 EwinInhGetUser(ewin, size), EoGetDeskNum(ewin),
1152 EoGetLayer(ewin), ewin->o.ilayer,
1153 ewin->state.iconified, EoIsSticky(ewin), ewin->state.shaded,
1154 ewin->state.docked, ewin->state.state, EoIsShown(ewin),
1155 ewin->state.visibility, ewin->state.active, ewin->num_groups,
1156 OpacityToPercent(ewin->ewmh.opacity)
1158 , EoGetOpacity(ewin),
1159 OpacityToPercent(ewin->props.focused_opacity), EoGetShadow(ewin),
1160 EoGetFade(ewin), EoGetNoRedirect(ewin)
1166 IPC_EwinInfo(const char *params)
1168 char match[FILEPATH_LEN_MAX];
1175 sscanf(params, "%1000s", match);
1177 lst = EwinsFindByExpr(match, &num, NULL);
1180 IpcPrintf("No windows matching %s\n", match);
1184 for (i = 0; i < num; i++)
1186 EwinShowInfo(lst[i]);
1195 IPC_ObjInfo(const char *params __UNUSED__)
1198 EObj *const *lst, *eo;
1200 lst = EobjListStackGet(&num);
1203 ("Num Window De T V Shape Dsk S F L Pos Size C R Name\n");
1204 for (i = 0; i < num; i++)
1208 (" %2d %#9lx %2d %d %d %2d/%2d %3d %d %d %3d %5d,%5d %4dx%4d %d %d %s\n",
1209 i, EobjGetXwin(eo), WinGetDepth(EobjGetWin(eo)), eo->type,
1210 eo->shown, eo->shaped, EShapeCheck(EobjGetWin(eo)), eo->desk->num,
1211 eo->sticky, eo->floating, eo->ilayer,
1212 EobjGetX(eo), EobjGetY(eo), EobjGetW(eo), EobjGetH(eo),
1214 (eo->cmhook) ? 1 : 0, !eo->noredir
1223 IPC_Reparent(const char *params)
1225 char param1[FILEPATH_LEN_MAX];
1226 char param2[FILEPATH_LEN_MAX];
1232 sscanf(params, "%100s %100s", param1, param2);
1234 ewin = EwinFindByExpr(param1);
1235 enew = EwinFindByExpr(param2);
1237 IpcPrintf("No matching client or target EWin found\n");
1239 EwinReparent(ewin, EwinGetClientWin(enew));
1243 IPC_Warp(const char *params)
1251 if (!strcmp(params, "?"))
1253 EQueryPointer(NULL, &x, &y, NULL, NULL);
1254 IpcPrintf("Pointer location: %d %d\n", x, y);
1256 else if (!strncmp(params, "abs", 3))
1258 sscanf(params, "%*s %i %i", &x, &y);
1259 EXWarpPointer(WinGetXwin(VROOT), x, y);
1261 else if (!strncmp(params, "rel", 3))
1263 sscanf(params, "%*s %i %i", &x, &y);
1264 EXWarpPointer(None, x, y);
1266 else if (!strncmp(params, "scr", 3))
1268 x = (Dpy.screen + 1) % ScreenCount(disp);
1269 sscanf(params, "%*s %i", &x);
1270 if (x >= 0 && x < ScreenCount(disp))
1272 EXWarpPointer(RootWindow(disp, x), DisplayWidth(disp, x) / 2,
1273 DisplayHeight(disp, x) / 2);
1274 /* IIRC warping to a different screen once did cause
1275 * LeaveNotify's on the current root window. This does not
1276 * happen in xorg 1.5.3 (and probably other versions).
1277 * So, check and focus out if left. */
1283 sscanf(params, "%i %i", &x, &y);
1284 EXWarpPointer(None, x, y);
1288 #if ENABLE_IPC_INSERT_KEYS
1295 static const struct _keyset ks[] = {
1322 {"a", ShiftMask, "A"},
1323 {"b", ShiftMask, "B"},
1324 {"c", ShiftMask, "C"},
1325 {"d", ShiftMask, "D"},
1326 {"e", ShiftMask, "E"},
1327 {"f", ShiftMask, "F"},
1328 {"g", ShiftMask, "G"},
1329 {"h", ShiftMask, "H"},
1330 {"i", ShiftMask, "I"},
1331 {"j", ShiftMask, "J"},
1332 {"k", ShiftMask, "K"},
1333 {"l", ShiftMask, "L"},
1334 {"m", ShiftMask, "M"},
1335 {"n", ShiftMask, "N"},
1336 {"o", ShiftMask, "O"},
1337 {"p", ShiftMask, "P"},
1338 {"q", ShiftMask, "Q"},
1339 {"r", ShiftMask, "R"},
1340 {"s", ShiftMask, "S"},
1341 {"t", ShiftMask, "T"},
1342 {"u", ShiftMask, "U"},
1343 {"v", ShiftMask, "V"},
1344 {"w", ShiftMask, "W"},
1345 {"x", ShiftMask, "X"},
1346 {"y", ShiftMask, "Y"},
1347 {"z", ShiftMask, "Z"},
1361 {"bracketleft", 0, "["},
1362 {"bracketright", 0, "]"},
1363 {"backslash", 0, "\\\\"},
1364 {"semicolon", 0, "\\s"},
1365 {"apostrophe", 0, "\\a"},
1369 {"grave", ShiftMask, "~"},
1370 {"1", ShiftMask, "!"},
1371 {"2", ShiftMask, "@"},
1372 {"3", ShiftMask, "#"},
1373 {"4", ShiftMask, "$"},
1374 {"5", ShiftMask, "%"},
1375 {"6", ShiftMask, "^"},
1376 {"7", ShiftMask, "&"},
1377 {"8", ShiftMask, "*"},
1378 {"9", ShiftMask, "("},
1379 {"0", ShiftMask, ")"},
1380 {"minus", ShiftMask, "_"},
1381 {"equal", ShiftMask, "+"},
1382 {"bracketleft", ShiftMask, "{"},
1383 {"bracketright", ShiftMask, "}"},
1384 {"backslash", ShiftMask, "|"},
1385 {"semicolon", ShiftMask, ":"},
1386 {"apostrophe", ShiftMask, "\\q"},
1387 {"comma", ShiftMask, "<"},
1388 {"period", ShiftMask, ">"},
1389 {"slash", ShiftMask, "?"},
1390 {"space", ShiftMask, " "},
1391 {"Return", ShiftMask, "\\n"},
1392 {"Tab", ShiftMask, "\\t"}
1396 IPC_InsertKeys(const char *params, Client * c __UNUSED__)
1407 XGetInputFocus(disp, &win, &rev);
1411 SoundPlay(SOUND_INSERT_KEYS);
1413 for (i = 0; i < (int)strlen(s); i++)
1417 ev.x = Mode.events.cx;
1418 ev.y = Mode.events.cy;
1419 ev.x_root = Mode.events.cx;
1420 ev.y_root = Mode.events.cy;
1421 for (j = 0; j < (int)(sizeof(ks) / sizeof(struct _keyset)); j++)
1423 if (strncmp(ks[j].ch, &(s[i]), strlen(ks[j].ch)))
1426 i += strlen(ks[j].ch) - 1;
1427 ev.keycode = EKeynameToKeycode(ks[j].sym);
1428 ev.state = ks[j].state;
1430 EXSendEvent(win, 0, (XEvent *) & ev);
1431 ev.type = KeyRelease;
1432 EXSendEvent(win, 0, (XEvent *) & ev);
1437 #endif /* ENABLE_IPC_INSERT_KEYS */
1440 * Compatibility stuff - DO NOT USE
1443 IPC_Compat(const char *params)
1455 sscanf(params, "%127s %n", param1, &len);
1459 if (!strcmp(param1, "goto_desktop"))
1462 IpcPrintf("Current Desktop: %d\n", DesksGetCurrentNum());
1464 else if (!strcmp(param1, "num_desks"))
1467 IpcPrintf("Number of Desks: %d\n", DesksGetNumber());
1470 else if (!strcmp(param1, "cm"))
1472 DialogOK(_("Message"), _("e16 was built without %s support"),
1477 else if (!strcmp(param1, "sound"))
1479 DialogOK(_("Message"), _("e16 was built without %s support"),
1494 /* the format of an IPC member of the IPC array is as follows:
1498 * "quick-help explanation",
1499 * "extended help data"
1500 * "may go on for several lines, be sure\n"
1501 * "to add line feeds when you need them and to \"quote\"\n"
1505 * when you add a function into this array, make sure you also add it into
1506 * the declarations above and also put the function in this file. PLEASE
1507 * if you add a new function in, add help to it also. since my end goal
1508 * is going to be to have this whole IPC usable by an end-user or to your
1509 * scripter, it should be easy to learn to use without having to crack
1510 * open the source code.
1513 static void IPC_Help(const char *params);
1515 static const IpcItem IPCArray[] = {
1519 "Gives you this help screen",
1520 "Additional parameters will retrieve help on many topics - "
1521 "\"help <command>\"." "\n" "use \"help all\" for a list of commands.\n"},
1525 "Displays the current version of Enlightenment running",
1530 "IPC No-operation - returns nop",
1534 IPC_About, "about", NULL, "Show E info", NULL},
1536 IPC_Cfg, "configure", "cfg", "Configuration dialogs", NULL},
1542 " exec <command> Execute command\n"},
1546 "Restart Enlightenment",
1551 "Exit Enlightenment",
1552 " exit Exit immediately\n"
1553 " exit logout Show logout dialog\n"
1554 " exit restart Restart\n"
1555 " exit theme <theme> Restart with new theme\n"
1556 " exit exec <program> Exit and start program\n"},
1560 "Force Enlightenment to save settings now",
1565 "Change a property of a specific window",
1566 "Use \"win_op <windowid> <property> <value>\" to change the property of a window\n"
1567 "You can use the \"window_list\" command to retrieve a list of available windows\n"
1568 "You can use ? after most of these commands to receive the current\n"
1569 "status of that flag\n"
1570 "Available win_op commands are:\n"
1571 " win_op <windowid> border <BORDERNAME>\n"
1572 " win_op <windowid> title <title>\n"
1573 " win_op <windowid> <close/kill>\n"
1574 " win_op <windowid> <focus/iconify/alone/shade/stick>\n"
1576 " win_op <windowid> <fade/shadow>\n"
1578 " win_op <windowid> desk <desktochangeto/next/prev>\n"
1579 " win_op <windowid> area <x> <y>\n"
1580 " win_op <windowid> <move/size> <x> <y> or <kbd/ptr>\n"
1581 " (you can use ? and ?? to retreive client and frame locations)\n"
1582 " win_op <windowid> <mr/sr> <x> <y> (incremental move/size)\n"
1583 " win_op <windowid> toggle_<width/height/size> <conservative/available/xinerama>\n"
1584 " win_op <windowid> <fullscreen/zoom>\n"
1585 " win_op <windowid> layer <0-100,4=normal>\n"
1586 " win_op <windowid> <raise/lower>\n"
1587 " win_op <windowid> opacity [+|-]<1-100(100=opaque)> (+/-: incremental change)\n"
1589 " win_op <windowid> focused_opacity [+|-]<0-100(0=follow opacity, 100=opaque)>\n"
1591 " win_op <windowid> snap <what>\n"
1592 " <what>: all, none, border, command, desktop, dialog, group, icon,\n"
1593 " layer, location, opacity, shade, shadow, size, sticky\n"
1594 " win_op <windowid> <focusclick/never_use_area/no_button_grabs/skiplists>\n"
1595 " win_op <windowid> <no_app_focus/move/size>\n"
1596 " win_op <windowid> <no_user_close/move/size>\n"
1597 " win_op <windowid> <no_wm_focus>\n"
1598 "<windowid> may be substituted with \"current\" to use the current window\n"},
1601 "window_list", "wl",
1602 "Get a list of managed application windows",
1603 "The window list can be shown in a number of different formats:\n"
1604 " window_list \"windowid : title\"\n"
1605 " window_list all \"windowid : x y w x h :: desk : area_x area_y : title\"\n"
1606 " window_list ext \"windowid : title :: desk : area_x area_y : x y wxh\"\n"
1607 " window_list prop \"windowid : x y w x h :: desk : name class Title\"\n"},
1611 "Show/set Window move/resize/geometry info modes",
1612 " movres move <?/opaque/lined/box/shaded/semi-solid/translucent>\n"
1613 " movres resize <?/opaque/lined/box/shaded/semi-solid>\n"
1614 " movres info <?/never/center/corner>\n"},
1618 "Pop up a dialog box with an OK button",
1619 "Use \"dialog_ok <message>\" to pop up a dialog box\n"},
1621 IPC_Border, "border", NULL, "List available borders", NULL},
1623 IPC_Screen, "screen", NULL, "Return screen information",
1624 " screen list List screens\n"
1625 " screen size Show current screen size\n"
1626 " screen split nx ny Simulate xinerama by subdividing screen\n"},
1629 "list_remember", "rl",
1630 "Retrieve a list of remembered windows and their attributes",
1635 "Set debug options",
1636 " debug events <EvNo>:<EvNo>...\n"},
1638 IPC_Set, "set", NULL, "Set configuration parameter", NULL},
1640 IPC_Show, "show", "sh", "Show configuration parameter(s)", NULL},
1642 IPC_EwinInfo, "win_info", "wi", "Show client window info", NULL},
1644 IPC_ObjInfo, "obj_info", "oi", "Show window object info", NULL},
1649 " reparent <windowid> <new parent>\n"},
1653 "Remembers parameters for client windows (obsolete)",
1654 " remember <windowid> <parameter>...\n"
1655 "For compatibility with epplets only. In stead use\n"
1656 " wop <windowid> snap <parameter>...\n"},
1660 "Warp/query pointer",
1661 " warp ? Get pointer position\n"
1662 " warp abs <x> <y> Set pointer position\n"
1663 " warp rel <x> <y> Move pointer relative to current position\n"
1664 " warp scr [<i>] Move pointer to other screen (default next)\n"
1665 " warp <x> <y> Same as \"warp rel\"\n"},
1666 #if ENABLE_IPC_INSERT_KEYS
1670 "Send key events to focused window",
1671 " keys <string>\n"},
1675 static int ipc_item_count = 0;
1676 static const IpcItem **ipc_item_list = NULL;
1678 static const IpcItem **
1679 IPC_GetList(int *pnum)
1682 const IpcItem **lst;
1686 /* Must be re-generated if modules are ever added/removed */
1687 *pnum = ipc_item_count;
1688 return ipc_item_list;
1691 num = sizeof(IPCArray) / sizeof(IpcItem);
1692 lst = EMALLOC(const IpcItem *, num);
1694 for (i = 0; i < num; i++)
1695 lst[i] = &IPCArray[i];
1697 ModulesGetIpcItems(&lst, &num);
1699 ipc_item_count = num;
1700 ipc_item_list = lst;
1705 /* The IPC Handler */
1706 /* this is the function that actually loops through the IPC array
1707 * and finds the command that you were trying to run, and then executes it.
1708 * you shouldn't have to touch this function
1712 IpcExec(const char *params)
1717 const IpcItem **lst, *ipc;
1719 if (EDebug(EDBUG_TYPE_IPC))
1720 Eprintf("IpcExec: %s\n", params);
1725 sscanf(params, "%100s %n", cmd, &num);
1726 prm = (num > 0 && params[num]) ? params + num : NULL;
1728 lst = IPC_GetList(&num);
1731 for (i = 0; i < num; i++)
1734 if (!(ipc->nick && !strcmp(cmd, ipc->nick)) && strcmp(cmd, ipc->name))
1744 ok = IPC_Compat(params);
1750 IpcExecReply(const char *params, IpcReplyFunc * reply, void *data)
1755 ok = IpcExec(params);
1756 reply(data, IpcPrintGetBuffer());
1763 EFunc(EWin * ewin, const char *params)
1767 SetContextEwin(ewin);
1768 ok = IpcExec(params);
1769 SetContextEwin(NULL);
1775 doEFuncDeferred(void *data)
1777 void **prm = (void **)data;
1780 ewin = (EWin *) prm[0];
1781 if (ewin && !EwinFindByPtr(ewin))
1784 EFunc(ewin, (const char *)prm[1]);
1793 EFuncDefer(EWin * ewin, const char *cmd)
1798 prm = EMALLOC(void *, 2);
1803 prm[1] = Estrdup(cmd);
1805 TIMER_ADD(defer_timer, 0.0, doEFuncDeferred, prm);
1809 ipccmp(void *p1, void *p2)
1811 return strcmp(((IpcItem *) p1)->name, ((IpcItem *) p2)->name);
1815 IPC_Help(const char *params)
1818 const IpcItem **lst, *ipc;
1821 lst = IPC_GetList(&num);
1823 IpcPrintf(_("Enlightenment IPC Commands Help\n"));
1827 IpcPrintf(_("Use \"help all\" for descriptions of each command\n"
1828 "Use \"help <command>\" for an individual description\n\n"));
1829 IpcPrintf(_("Commands currently available:\n"));
1831 Quicksort((void **)lst, 0, num - 1, ipccmp);
1833 for (i = 0; i < num; i++)
1836 nick = (ipc->nick) ? ipc->nick : "";
1837 IpcPrintf(" %-16s %-4s ", ipc->name, nick);
1844 else if (!strcmp(params, "all"))
1847 ("Use \"help full\" for full descriptions of each command\n"));
1848 IpcPrintf(_("Use \"help <command>\" for an individual description\n"));
1849 IpcPrintf(_("Commands currently available:\n"));
1850 IpcPrintf(_(" <command> : <description>\n"));
1852 for (i = 0; i < num; i++)
1855 nick = (ipc->nick) ? ipc->nick : "";
1856 IpcPrintf("%18s %4s: %s\n", ipc->name, nick, ipc->help_text);
1859 else if (!strcmp(params, "full"))
1861 IpcPrintf(_("Commands currently available:\n"));
1862 IpcPrintf(_(" <command> : <description>\n"));
1864 for (i = 0; i < num; i++)
1866 IpcPrintf("----------------------------------------\n");
1868 nick = (ipc->nick) ? ipc->nick : "";
1869 IpcPrintf("%18s %4s: %s\n", ipc->name, nick, ipc->help_text);
1870 if (ipc->extended_help_text)
1871 IpcPrintf("%s", ipc->extended_help_text);
1876 for (i = 0; i < num; i++)
1879 if (strcmp(params, ipc->name) &&
1880 (ipc->nick == NULL || strcmp(params, ipc->nick)))
1883 nick = (ipc->nick) ? ipc->nick : "";
1884 IpcPrintf("----------------------------------------\n");
1885 IpcPrintf("%18s %4s: %s\n", ipc->name, nick, ipc->help_text);
1886 IpcPrintf("----------------------------------------\n");
1887 if (ipc->extended_help_text)
1888 IpcPrintf("%s", ipc->extended_help_text);