PageRenderTime 153ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 0ms

/WindowMaker-0.95.3/src/winspector.c

#
C | 1689 lines | 1343 code | 276 blank | 70 comment | 304 complexity | 77ea94e8fe28943350de5e9a7b424c11 MD5 | raw file
Possible License(s): GPL-2.0, WTFPL, LGPL-2.0
  1. /* winspector.c - window attribute inspector
  2. *
  3. * Window Maker window manager
  4. *
  5. * Copyright (c) 1997-2003 Alfredo K. Kojima
  6. * Copyright (c) 1998-2003 Dan Pascu
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. */
  22. #include "wconfig.h"
  23. #include <X11/Xlib.h>
  24. #include <X11/Xutil.h>
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <strings.h>
  29. #include "WindowMaker.h"
  30. #include "screen.h"
  31. #include "wcore.h"
  32. #include "framewin.h"
  33. #include "window.h"
  34. #include "workspace.h"
  35. #include "funcs.h"
  36. #include "defaults.h"
  37. #include "dialog.h"
  38. #include "icon.h"
  39. #include "stacking.h"
  40. #include "application.h"
  41. #include "appicon.h"
  42. #include "actions.h"
  43. #include "winspector.h"
  44. #include "dock.h"
  45. #include "client.h"
  46. #include "wmspec.h"
  47. #include "xinerama.h"
  48. #include <WINGs/WUtil.h>
  49. typedef struct InspectorPanel {
  50. struct InspectorPanel *nextPtr;
  51. WWindow *frame;
  52. WWindow *inspected; /* the window that's being inspected */
  53. WMWindow *win;
  54. Window parent;
  55. /* common stuff */
  56. WMButton *revertBtn;
  57. WMButton *applyBtn;
  58. WMButton *saveBtn;
  59. WMPopUpButton *pagePopUp;
  60. /* first page. general stuff */
  61. WMFrame *specFrm;
  62. WMButton *instRb;
  63. WMButton *clsRb;
  64. WMButton *bothRb;
  65. WMButton *defaultRb;
  66. WMButton *selWinB;
  67. WMLabel *specLbl;
  68. /* second page. attributes */
  69. WMFrame *attrFrm;
  70. WMButton *attrChk[11];
  71. /* 3rd page. more attributes */
  72. WMFrame *moreFrm;
  73. #ifdef XKB_BUTTON_HINT
  74. WMButton *moreChk[12];
  75. #else
  76. WMButton *moreChk[11];
  77. #endif
  78. /* 4th page. icon and workspace */
  79. WMFrame *iconFrm;
  80. WMLabel *iconLbl;
  81. WMLabel *fileLbl;
  82. WMTextField *fileText;
  83. WMButton *alwChk;
  84. /*
  85. WMButton *updateIconBtn;
  86. */
  87. WMButton *browseIconBtn;
  88. WMFrame *wsFrm;
  89. WMPopUpButton *wsP;
  90. /* 5th page. application wide attributes */
  91. WMFrame *appFrm;
  92. WMButton *appChk[3];
  93. unsigned int done:1;
  94. unsigned int destroyed:1;
  95. unsigned int choosingIcon:1;
  96. } InspectorPanel;
  97. extern Cursor wCursor[WCUR_LAST];
  98. extern WDDomain *WDWindowAttributes;
  99. extern WPreferences wPreferences;
  100. static InspectorPanel *panelList = NULL;
  101. static WMPropList *ANoTitlebar = NULL;
  102. static WMPropList *ANoResizebar;
  103. static WMPropList *ANoMiniaturizeButton;
  104. static WMPropList *ANoCloseButton;
  105. static WMPropList *ANoBorder;
  106. static WMPropList *ANoHideOthers;
  107. static WMPropList *ANoMouseBindings;
  108. static WMPropList *ANoKeyBindings;
  109. static WMPropList *ANoAppIcon;
  110. static WMPropList *AKeepOnTop;
  111. static WMPropList *AKeepOnBottom;
  112. static WMPropList *AOmnipresent;
  113. static WMPropList *ASkipWindowList;
  114. static WMPropList *ASkipSwitchPanel;
  115. static WMPropList *AKeepInsideScreen;
  116. static WMPropList *AUnfocusable;
  117. static WMPropList *AFocusAcrossWorkspace;
  118. static WMPropList *AAlwaysUserIcon;
  119. static WMPropList *AStartMiniaturized;
  120. static WMPropList *AStartMaximized;
  121. static WMPropList *ADontSaveSession;
  122. static WMPropList *AEmulateAppIcon;
  123. static WMPropList *AFullMaximize;
  124. static WMPropList *ASharedAppIcon;
  125. static WMPropList *ANoMiniaturizable;
  126. #ifdef XKB_BUTTON_HINT
  127. static WMPropList *ANoLanguageButton;
  128. #endif
  129. static WMPropList *AStartWorkspace;
  130. static WMPropList *AIcon;
  131. /* application wide options */
  132. static WMPropList *AStartHidden;
  133. static WMPropList *AnyWindow;
  134. static WMPropList *EmptyString;
  135. static WMPropList *Yes, *No;
  136. #define PWIDTH 290
  137. #define PHEIGHT 360
  138. static char *spec_text;
  139. static void applySettings(WMButton * button, InspectorPanel * panel);
  140. #define UNDEFINED_POS 0xffffff
  141. static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel);
  142. static void make_keys(void)
  143. {
  144. if (ANoTitlebar != NULL)
  145. return;
  146. AIcon = WMCreatePLString("Icon");
  147. ANoTitlebar = WMCreatePLString("NoTitlebar");
  148. ANoResizebar = WMCreatePLString("NoResizebar");
  149. ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
  150. ANoCloseButton = WMCreatePLString("NoCloseButton");
  151. ANoBorder = WMCreatePLString("NoBorder");
  152. ANoHideOthers = WMCreatePLString("NoHideOthers");
  153. ANoMouseBindings = WMCreatePLString("NoMouseBindings");
  154. ANoKeyBindings = WMCreatePLString("NoKeyBindings");
  155. ANoAppIcon = WMCreatePLString("NoAppIcon");
  156. AKeepOnTop = WMCreatePLString("KeepOnTop");
  157. AKeepOnBottom = WMCreatePLString("KeepOnBottom");
  158. AOmnipresent = WMCreatePLString("Omnipresent");
  159. ASkipWindowList = WMCreatePLString("SkipWindowList");
  160. ASkipSwitchPanel = WMCreatePLString("SkipSwitchPanel");
  161. AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
  162. AUnfocusable = WMCreatePLString("Unfocusable");
  163. AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace");
  164. AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
  165. AStartMiniaturized = WMCreatePLString("StartMiniaturized");
  166. AStartMaximized = WMCreatePLString("StartMaximized");
  167. AStartHidden = WMCreatePLString("StartHidden");
  168. ADontSaveSession = WMCreatePLString("DontSaveSession");
  169. AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
  170. AFullMaximize = WMCreatePLString("FullMaximize");
  171. ASharedAppIcon = WMCreatePLString("SharedAppIcon");
  172. ANoMiniaturizable = WMCreatePLString("NoMiniaturizable");
  173. #ifdef XKB_BUTTON_HINT
  174. ANoLanguageButton = WMCreatePLString("NoLanguageButton");
  175. #endif
  176. AStartWorkspace = WMCreatePLString("StartWorkspace");
  177. AnyWindow = WMCreatePLString("*");
  178. EmptyString = WMCreatePLString("");
  179. Yes = WMCreatePLString("Yes");
  180. No = WMCreatePLString("No");
  181. }
  182. static void freeInspector(InspectorPanel * panel)
  183. {
  184. panel->destroyed = 1;
  185. if (panel->choosingIcon)
  186. return;
  187. WMDestroyWidget(panel->win);
  188. XDestroyWindow(dpy, panel->parent);
  189. wfree(panel);
  190. }
  191. static void destroyInspector(WCoreWindow * foo, void *data, XEvent * event)
  192. {
  193. InspectorPanel *panel;
  194. InspectorPanel *tmp;
  195. panel = panelList;
  196. while (panel->frame != data)
  197. panel = panel->nextPtr;
  198. if (panelList == panel)
  199. panelList = panel->nextPtr;
  200. else {
  201. tmp = panelList;
  202. while (tmp->nextPtr != panel) {
  203. tmp = tmp->nextPtr;
  204. }
  205. tmp->nextPtr = panel->nextPtr;
  206. }
  207. panel->inspected->flags.inspector_open = 0;
  208. panel->inspected->inspector = NULL;
  209. WMRemoveNotificationObserver(panel);
  210. wWindowUnmap(panel->frame);
  211. wUnmanageWindow(panel->frame, True, False);
  212. freeInspector(panel);
  213. }
  214. void wDestroyInspectorPanels(void)
  215. {
  216. InspectorPanel *panel;
  217. while (panelList != NULL) {
  218. panel = panelList;
  219. panelList = panelList->nextPtr;
  220. wUnmanageWindow(panel->frame, False, False);
  221. WMDestroyWidget(panel->win);
  222. panel->inspected->flags.inspector_open = 0;
  223. panel->inspected->inspector = NULL;
  224. wfree(panel);
  225. }
  226. }
  227. static void changePage(WMPopUpButton * bPtr, InspectorPanel * panel)
  228. {
  229. int page;
  230. page = WMGetPopUpButtonSelectedItem(bPtr);
  231. if (page == 0) {
  232. WMMapWidget(panel->specFrm);
  233. WMMapWidget(panel->specLbl);
  234. } else if (page == 1) {
  235. WMMapWidget(panel->attrFrm);
  236. } else if (page == 2) {
  237. WMMapWidget(panel->moreFrm);
  238. } else if (page == 3) {
  239. WMMapWidget(panel->iconFrm);
  240. WMMapWidget(panel->wsFrm);
  241. } else {
  242. WMMapWidget(panel->appFrm);
  243. }
  244. if (page != 0) {
  245. WMUnmapWidget(panel->specFrm);
  246. WMUnmapWidget(panel->specLbl);
  247. }
  248. if (page != 1)
  249. WMUnmapWidget(panel->attrFrm);
  250. if (page != 2)
  251. WMUnmapWidget(panel->moreFrm);
  252. if (page != 3) {
  253. WMUnmapWidget(panel->iconFrm);
  254. WMUnmapWidget(panel->wsFrm);
  255. }
  256. if (page != 4 && panel->appFrm)
  257. WMUnmapWidget(panel->appFrm);
  258. }
  259. #define USE_TEXT_FIELD 1
  260. #define UPDATE_TEXT_FIELD 2
  261. #define REVERT_TO_DEFAULT 4
  262. static int showIconFor(WMScreen * scrPtr, InspectorPanel * panel, char *wm_instance, char *wm_class, int flags)
  263. {
  264. WMPixmap *pixmap = (WMPixmap *) NULL;
  265. char *file = NULL, *path = NULL;
  266. char *db_icon = NULL;
  267. if ((flags & USE_TEXT_FIELD) != 0) {
  268. file = WMGetTextFieldText(panel->fileText);
  269. if (file && file[0] == 0) {
  270. wfree(file);
  271. file = NULL;
  272. }
  273. } else {
  274. db_icon = wDefaultGetIconFile(panel->inspected->screen_ptr, wm_instance, wm_class, False);
  275. if (db_icon != NULL)
  276. file = wstrdup(db_icon);
  277. }
  278. if (db_icon != NULL && (flags & REVERT_TO_DEFAULT) != 0) {
  279. if (file)
  280. file = wstrdup(db_icon);
  281. flags |= UPDATE_TEXT_FIELD;
  282. }
  283. if ((flags & UPDATE_TEXT_FIELD) != 0) {
  284. WMSetTextFieldText(panel->fileText, file);
  285. }
  286. if (file) {
  287. path = FindImage(wPreferences.icon_path, file);
  288. if (!path) {
  289. char *buf;
  290. int len = strlen(file) + 80;
  291. buf = wmalloc(len);
  292. snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"), file);
  293. wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
  294. wfree(buf);
  295. wfree(file);
  296. return -1;
  297. }
  298. pixmap = WMCreatePixmapFromFile(scrPtr, path);
  299. wfree(path);
  300. if (!pixmap) {
  301. char *buf;
  302. int len = strlen(file) + 80;
  303. buf = wmalloc(len);
  304. snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
  305. file, RMessageForError(RErrorCode));
  306. wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
  307. wfree(buf);
  308. wfree(file);
  309. return -1;
  310. }
  311. wfree(file);
  312. }
  313. WMSetLabelImage(panel->iconLbl, pixmap);
  314. if (pixmap)
  315. WMReleasePixmap(pixmap);
  316. return 0;
  317. }
  318. #if 0
  319. static void updateIcon(WMButton * button, InspectorPanel * panel)
  320. {
  321. showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
  322. }
  323. #endif
  324. static int getBool(WMPropList * value)
  325. {
  326. char *val;
  327. if (!WMIsPLString(value)) {
  328. return 0;
  329. }
  330. if (!(val = WMGetFromPLString(value))) {
  331. return 0;
  332. }
  333. if ((val[1] == '\0' && (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' || val[0] == 't' || val[0] == '1'))
  334. || (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
  335. return 1;
  336. } else if ((val[1] == '\0'
  337. && (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' || val[0] == 'f' || val[0] == '0'))
  338. || (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
  339. return 0;
  340. } else {
  341. wwarning(_("can't convert \"%s\" to boolean"), val);
  342. return 0;
  343. }
  344. }
  345. #define UPDATE_DEFAULTS 1
  346. #define IS_BOOLEAN 2
  347. /*
  348. * Will insert the attribute = value; pair in window's list,
  349. * if it's different from the defaults.
  350. * Defaults means either defaults database, or attributes saved
  351. * for the default window "*". This is to let one revert options that are
  352. * global because they were saved for all windows ("*").
  353. *
  354. */
  355. static int
  356. insertAttribute(WMPropList * dict, WMPropList * window, WMPropList * attr, WMPropList * value, int flags)
  357. {
  358. WMPropList *def_win, *def_value = NULL;
  359. int update = 0;
  360. int modified = 0;
  361. if (!(flags & UPDATE_DEFAULTS) && dict) {
  362. if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL) {
  363. def_value = WMGetFromPLDictionary(def_win, attr);
  364. }
  365. }
  366. /* If we could not find defaults in database, fall to hardcoded values.
  367. * Also this is true if we save defaults for all windows
  368. */
  369. if (!def_value)
  370. def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
  371. if ((flags & IS_BOOLEAN))
  372. update = (getBool(value) != getBool(def_value));
  373. else {
  374. update = !WMIsPropListEqualTo(value, def_value);
  375. }
  376. if (update) {
  377. WMPutInPLDictionary(window, attr, value);
  378. modified = 1;
  379. }
  380. return modified;
  381. }
  382. static void saveSettings(WMButton * button, InspectorPanel * panel)
  383. {
  384. WWindow *wwin = panel->inspected;
  385. WDDomain *db = WDWindowAttributes;
  386. WMPropList *dict = db->dictionary;
  387. WMPropList *winDic, *appDic, *value, *key, *key2;
  388. char *icon_file;
  389. int flags = 0;
  390. int different = 0, different2 = 0;
  391. /* Save will apply the changes and save them */
  392. applySettings(panel->applyBtn, panel);
  393. if (WMGetButtonSelected(panel->instRb) != 0)
  394. key = WMCreatePLString(wwin->wm_instance);
  395. else if (WMGetButtonSelected(panel->clsRb) != 0)
  396. key = WMCreatePLString(wwin->wm_class);
  397. else if (WMGetButtonSelected(panel->bothRb) != 0) {
  398. char *buffer;
  399. buffer = StrConcatDot(wwin->wm_instance, wwin->wm_class);
  400. key = WMCreatePLString(buffer);
  401. wfree(buffer);
  402. } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
  403. key = WMRetainPropList(AnyWindow);
  404. flags = UPDATE_DEFAULTS;
  405. } else
  406. key = NULL;
  407. if (!key)
  408. return;
  409. if (!dict) {
  410. dict = WMCreatePLDictionary(NULL, NULL);
  411. if (dict) {
  412. db->dictionary = dict;
  413. } else {
  414. WMReleasePropList(key);
  415. return;
  416. }
  417. }
  418. if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD) < 0)
  419. return;
  420. WMPLSetCaseSensitive(True);
  421. winDic = WMCreatePLDictionary(NULL, NULL);
  422. appDic = WMCreatePLDictionary(NULL, NULL);
  423. /* Update icon for window */
  424. icon_file = WMGetTextFieldText(panel->fileText);
  425. if (icon_file) {
  426. if (icon_file[0] != 0) {
  427. value = WMCreatePLString(icon_file);
  428. different |= insertAttribute(dict, winDic, AIcon, value, flags);
  429. different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
  430. WMReleasePropList(value);
  431. }
  432. wfree(icon_file);
  433. }
  434. {
  435. int i = WMGetPopUpButtonSelectedItem(panel->wsP);
  436. i--;
  437. if (i >= 0 && i < panel->frame->screen_ptr->workspace_count) {
  438. value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
  439. different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
  440. WMReleasePropList(value);
  441. }
  442. }
  443. flags |= IS_BOOLEAN;
  444. value = (WMGetButtonSelected(panel->alwChk) != 0) ? Yes : No;
  445. different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
  446. value = (WMGetButtonSelected(panel->attrChk[0]) != 0) ? Yes : No;
  447. different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
  448. value = (WMGetButtonSelected(panel->attrChk[1]) != 0) ? Yes : No;
  449. different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
  450. value = (WMGetButtonSelected(panel->attrChk[2]) != 0) ? Yes : No;
  451. different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
  452. value = (WMGetButtonSelected(panel->attrChk[3]) != 0) ? Yes : No;
  453. different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
  454. value = (WMGetButtonSelected(panel->attrChk[4]) != 0) ? Yes : No;
  455. different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
  456. value = (WMGetButtonSelected(panel->attrChk[5]) != 0) ? Yes : No;
  457. different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
  458. value = (WMGetButtonSelected(panel->attrChk[6]) != 0) ? Yes : No;
  459. different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
  460. value = (WMGetButtonSelected(panel->attrChk[7]) != 0) ? Yes : No;
  461. different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
  462. value = (WMGetButtonSelected(panel->attrChk[8]) != 0) ? Yes : No;
  463. different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
  464. value = (WMGetButtonSelected(panel->attrChk[9]) != 0) ? Yes : No;
  465. different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
  466. value = (WMGetButtonSelected(panel->attrChk[10]) != 0) ? Yes : No;
  467. different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
  468. value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No;
  469. different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
  470. value = (WMGetButtonSelected(panel->moreChk[1]) != 0) ? Yes : No;
  471. different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
  472. value = (WMGetButtonSelected(panel->moreChk[2]) != 0) ? Yes : No;
  473. different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
  474. value = (WMGetButtonSelected(panel->moreChk[3]) != 0) ? Yes : No;
  475. different |= insertAttribute(dict, winDic, ASkipSwitchPanel, value, flags);
  476. value = (WMGetButtonSelected(panel->moreChk[4]) != 0) ? Yes : No;
  477. different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
  478. value = (WMGetButtonSelected(panel->moreChk[5]) != 0) ? Yes : No;
  479. different |= insertAttribute(dict, winDic, AKeepInsideScreen, value, flags);
  480. value = (WMGetButtonSelected(panel->moreChk[6]) != 0) ? Yes : No;
  481. different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
  482. value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No;
  483. different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
  484. value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No;
  485. different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
  486. value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No;
  487. different |= insertAttribute(dict, winDic, AFocusAcrossWorkspace, value, flags);
  488. value = (WMGetButtonSelected(panel->moreChk[10]) != 0) ? Yes : No;
  489. different |= insertAttribute(dict, winDic, ANoMiniaturizable, value, flags);
  490. #ifdef XKB_BUTTON_HINT
  491. value = (WMGetButtonSelected(panel->moreChk[11]) != 0) ? Yes : No;
  492. different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
  493. #endif
  494. if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
  495. value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No;
  496. different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
  497. value = (WMGetButtonSelected(panel->appChk[1]) != 0) ? Yes : No;
  498. different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
  499. value = (WMGetButtonSelected(panel->appChk[2]) != 0) ? Yes : No;
  500. different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
  501. }
  502. if (wwin->fake_group) {
  503. key2 = WMCreatePLString(wwin->fake_group->identifier);
  504. if (WMIsPropListEqualTo(key, key2)) {
  505. WMMergePLDictionaries(winDic, appDic, True);
  506. different |= different2;
  507. } else {
  508. WMRemoveFromPLDictionary(dict, key2);
  509. if (different2) {
  510. WMPutInPLDictionary(dict, key2, appDic);
  511. }
  512. }
  513. WMReleasePropList(key2);
  514. WMReleasePropList(appDic);
  515. } else if (wwin->main_window != wwin->client_win) {
  516. WApplication *wapp = wApplicationOf(wwin->main_window);
  517. if (wapp) {
  518. char *instance = wapp->main_window_desc->wm_instance;
  519. char *class = wapp->main_window_desc->wm_class;
  520. char *buffer;
  521. buffer = StrConcatDot(instance, class);
  522. key2 = WMCreatePLString(buffer);
  523. wfree(buffer);
  524. if (WMIsPropListEqualTo(key, key2)) {
  525. WMMergePLDictionaries(winDic, appDic, True);
  526. different |= different2;
  527. } else {
  528. WMRemoveFromPLDictionary(dict, key2);
  529. if (different2)
  530. WMPutInPLDictionary(dict, key2, appDic);
  531. }
  532. WMReleasePropList(key2);
  533. WMReleasePropList(appDic);
  534. }
  535. } else {
  536. WMMergePLDictionaries(winDic, appDic, True);
  537. different |= different2;
  538. WMReleasePropList(appDic);
  539. }
  540. WMRemoveFromPLDictionary(dict, key);
  541. if (different) {
  542. WMPutInPLDictionary(dict, key, winDic);
  543. }
  544. WMReleasePropList(key);
  545. WMReleasePropList(winDic);
  546. UpdateDomainFile(db);
  547. /* clean up */
  548. WMPLSetCaseSensitive(False);
  549. }
  550. static void makeAppIconFor(WApplication * wapp)
  551. {
  552. WScreen *scr = wapp->main_window_desc->screen_ptr;
  553. if (wapp->app_icon)
  554. return;
  555. if (!WFLAGP(wapp->main_window_desc, no_appicon))
  556. wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
  557. else
  558. wapp->app_icon = NULL;
  559. if (wapp->app_icon) {
  560. WIcon *icon = wapp->app_icon->icon;
  561. WDock *clip = scr->workspaces[scr->current_workspace]->clip;
  562. int x = 0, y = 0;
  563. wapp->app_icon->main_window = wapp->main_window;
  564. if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
  565. wapp->app_icon->attracted = 1;
  566. if (!wapp->app_icon->icon->shadowed) {
  567. wapp->app_icon->icon->shadowed = 1;
  568. wapp->app_icon->icon->force_paint = 1;
  569. }
  570. wDockAttachIcon(clip, wapp->app_icon, x, y);
  571. } else {
  572. PlaceIcon(scr, &x, &y, wGetHeadForWindow(wapp->main_window_desc));
  573. wAppIconMove(wapp->app_icon, x, y);
  574. }
  575. if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
  576. XMapWindow(dpy, icon->core->window);
  577. if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
  578. wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
  579. }
  580. }
  581. static void removeAppIconFor(WApplication * wapp)
  582. {
  583. if (!wapp->app_icon)
  584. return;
  585. if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
  586. wapp->app_icon->running = 0;
  587. /* since we keep it, we don't care if it was attracted or not */
  588. wapp->app_icon->attracted = 0;
  589. wapp->app_icon->icon->shadowed = 0;
  590. wapp->app_icon->main_window = None;
  591. wapp->app_icon->pid = 0;
  592. wapp->app_icon->icon->owner = NULL;
  593. wapp->app_icon->icon->icon_win = None;
  594. wapp->app_icon->icon->force_paint = 1;
  595. wAppIconPaint(wapp->app_icon);
  596. } else if (wapp->app_icon->docked) {
  597. wapp->app_icon->running = 0;
  598. wDockDetach(wapp->app_icon->dock, wapp->app_icon);
  599. } else {
  600. wAppIconDestroy(wapp->app_icon);
  601. }
  602. wapp->app_icon = NULL;
  603. if (wPreferences.auto_arrange_icons)
  604. wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
  605. }
  606. static void applySettings(WMButton * button, InspectorPanel * panel)
  607. {
  608. WWindow *wwin = panel->inspected;
  609. WApplication *wapp = wApplicationOf(wwin->main_window);
  610. int floating, sunken, skip_window_list;
  611. int old_omnipresent;
  612. int old_no_bind_keys;
  613. int old_no_bind_mouse;
  614. old_omnipresent = WFLAGP(wwin, omnipresent);
  615. old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
  616. old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
  617. showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
  618. /* Attributes... --> Window Attributes */
  619. WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
  620. WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
  621. WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
  622. WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
  623. WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
  624. floating = WMGetButtonSelected(panel->attrChk[5]);
  625. sunken = WMGetButtonSelected(panel->attrChk[6]);
  626. WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
  627. WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
  628. WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
  629. WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
  630. /* Attributes... --> Advanced Options */
  631. WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
  632. WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
  633. skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
  634. WSETUFLAG(wwin, skip_switchpanel, WMGetButtonSelected(panel->moreChk[3]));
  635. WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[4]));
  636. WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[5]));
  637. WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[6]));
  638. WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[7]));
  639. WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[8]));
  640. WSETUFLAG(wwin, focus_across_wksp, WMGetButtonSelected(panel->moreChk[9]));
  641. WSETUFLAG(wwin, no_miniaturizable, WMGetButtonSelected(panel->moreChk[10]));
  642. #ifdef XKB_BUTTON_HINT
  643. WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[11]));
  644. #endif
  645. WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
  646. if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
  647. wUnshadeWindow(wwin);
  648. WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
  649. if (floating) {
  650. if (!WFLAGP(wwin, floating))
  651. ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
  652. } else if (sunken) {
  653. if (!WFLAGP(wwin, sunken))
  654. ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
  655. } else {
  656. if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
  657. ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
  658. }
  659. WSETUFLAG(wwin, sunken, sunken);
  660. WSETUFLAG(wwin, floating, floating);
  661. wwin->flags.omnipresent = 0;
  662. if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
  663. WSETUFLAG(wwin, skip_window_list, skip_window_list);
  664. UpdateSwitchMenu(wwin->screen_ptr, wwin, skip_window_list ? ACTION_REMOVE : ACTION_ADD);
  665. } else {
  666. if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
  667. WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
  668. }
  669. }
  670. if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
  671. if (WFLAGP(wwin, no_bind_keys)) {
  672. XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
  673. } else {
  674. wWindowSetKeyGrabs(wwin);
  675. }
  676. }
  677. if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
  678. wWindowResetMouseGrabs(wwin);
  679. }
  680. wwin->frame->flags.need_texture_change = 1;
  681. wWindowConfigureBorders(wwin);
  682. wFrameWindowPaint(wwin->frame);
  683. wNETWMUpdateActions(wwin, False);
  684. /*
  685. * Can't apply emulate_appicon because it will probably cause problems.
  686. */
  687. if (wapp) {
  688. /* do application wide stuff */
  689. WSETUFLAG(wapp->main_window_desc, start_hidden, WMGetButtonSelected(panel->appChk[0]));
  690. WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1]));
  691. WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2]));
  692. if (WFLAGP(wapp->main_window_desc, no_appicon))
  693. removeAppIconFor(wapp);
  694. else
  695. makeAppIconFor(wapp);
  696. if (wapp->app_icon && wapp->main_window == wwin->client_win) {
  697. char *file = WMGetTextFieldText(panel->fileText);
  698. if (file[0] == 0) {
  699. wfree(file);
  700. file = NULL;
  701. }
  702. wIconChangeImageFile(wapp->app_icon->icon, file);
  703. if (file)
  704. wfree(file);
  705. wAppIconPaint(wapp->app_icon);
  706. }
  707. }
  708. }
  709. static void revertSettings(WMButton * button, InspectorPanel * panel)
  710. {
  711. WWindow *wwin = panel->inspected;
  712. WApplication *wapp = wApplicationOf(wwin->main_window);
  713. int i, n;
  714. char *wm_instance = NULL;
  715. char *wm_class = NULL;
  716. int workspace, level;
  717. if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
  718. wm_instance = wwin->wm_instance;
  719. else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
  720. wm_class = wwin->wm_class;
  721. else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
  722. wm_instance = wwin->wm_instance;
  723. wm_class = wwin->wm_class;
  724. }
  725. memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
  726. memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
  727. memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
  728. wWindowSetupInitialAttributes(wwin, &level, &workspace);
  729. for (i = 0; i < 11; i++) {
  730. int flag = 0;
  731. switch (i) {
  732. case 0:
  733. flag = WFLAGP(wwin, no_titlebar);
  734. break;
  735. case 1:
  736. flag = WFLAGP(wwin, no_resizebar);
  737. break;
  738. case 2:
  739. flag = WFLAGP(wwin, no_close_button);
  740. break;
  741. case 3:
  742. flag = WFLAGP(wwin, no_miniaturize_button);
  743. break;
  744. case 4:
  745. flag = WFLAGP(wwin, no_border);
  746. break;
  747. case 5:
  748. flag = WFLAGP(wwin, floating);
  749. break;
  750. case 6:
  751. flag = WFLAGP(wwin, sunken);
  752. break;
  753. case 7:
  754. flag = WFLAGP(wwin, omnipresent);
  755. break;
  756. case 8:
  757. flag = WFLAGP(wwin, start_miniaturized);
  758. break;
  759. case 9:
  760. flag = WFLAGP(wwin, start_maximized != 0);
  761. break;
  762. case 10:
  763. flag = WFLAGP(wwin, full_maximize);
  764. break;
  765. }
  766. WMSetButtonSelected(panel->attrChk[i], flag);
  767. }
  768. for (i = 0; i < 12; i++) {
  769. int flag = 0;
  770. switch (i) {
  771. case 0:
  772. flag = WFLAGP(wwin, no_bind_keys);
  773. break;
  774. case 1:
  775. flag = WFLAGP(wwin, no_bind_mouse);
  776. break;
  777. case 2:
  778. flag = WFLAGP(wwin, skip_window_list);
  779. break;
  780. case 3:
  781. flag = WFLAGP(wwin, skip_switchpanel);
  782. break;
  783. case 4:
  784. flag = WFLAGP(wwin, no_focusable);
  785. break;
  786. case 5:
  787. flag = WFLAGP(wwin, dont_move_off);
  788. break;
  789. case 6:
  790. flag = WFLAGP(wwin, no_hide_others);
  791. break;
  792. case 7:
  793. flag = WFLAGP(wwin, dont_save_session);
  794. break;
  795. case 8:
  796. flag = WFLAGP(wwin, emulate_appicon);
  797. break;
  798. case 9:
  799. flag = WFLAGP(wwin, focus_across_wksp);
  800. break;
  801. case 10:
  802. flag = WFLAGP(wwin, no_miniaturizable);
  803. break;
  804. #ifdef XKB_BUTTON_HINT
  805. case 11:
  806. flag = WFLAGP(wwin, no_language_button);
  807. break;
  808. #endif
  809. }
  810. WMSetButtonSelected(panel->moreChk[i], flag);
  811. }
  812. if (panel->appFrm && wapp) {
  813. for (i = 0; i < 3; i++) {
  814. int flag = 0;
  815. switch (i) {
  816. case 0:
  817. flag = WFLAGP(wapp->main_window_desc, start_hidden);
  818. break;
  819. case 1:
  820. flag = WFLAGP(wapp->main_window_desc, no_appicon);
  821. break;
  822. case 2:
  823. flag = WFLAGP(wapp->main_window_desc, shared_appicon);
  824. break;
  825. }
  826. WMSetButtonSelected(panel->appChk[i], flag);
  827. }
  828. }
  829. WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
  830. showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
  831. n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
  832. if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
  833. WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
  834. } else {
  835. WMSetPopUpButtonSelectedItem(panel->wsP, 0);
  836. }
  837. /* must auto apply, so that there wno't be internal
  838. * inconsistencies between the state in the flags and
  839. * the actual state of the window */
  840. applySettings(panel->applyBtn, panel);
  841. }
  842. static void chooseIconCallback(WMWidget * self, void *clientData)
  843. {
  844. char *file;
  845. InspectorPanel *panel = (InspectorPanel *) clientData;
  846. int result;
  847. panel->choosingIcon = 1;
  848. WMSetButtonEnabled(panel->browseIconBtn, False);
  849. result = wIconChooserDialog(panel->frame->screen_ptr, &file,
  850. panel->inspected->wm_instance, panel->inspected->wm_class);
  851. panel->choosingIcon = 0;
  852. if (!panel->destroyed) { /* kluge */
  853. if (result) {
  854. WMSetTextFieldText(panel->fileText, file);
  855. showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
  856. wfree(file);
  857. }
  858. WMSetButtonEnabled(panel->browseIconBtn, True);
  859. } else {
  860. freeInspector(panel);
  861. }
  862. }
  863. static void textEditedObserver(void *observerData, WMNotification * notification)
  864. {
  865. InspectorPanel *panel = (InspectorPanel *) observerData;
  866. if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
  867. return;
  868. showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
  869. /*
  870. WMPerformButtonClick(panel->updateIconBtn);
  871. */
  872. }
  873. static void selectSpecification(WMWidget * bPtr, void *data)
  874. {
  875. InspectorPanel *panel = (InspectorPanel *) data;
  876. char *str;
  877. WWindow *wwin = panel->inspected;
  878. int len;
  879. if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class))
  880. WMSetButtonEnabled(panel->applyBtn, False);
  881. else
  882. WMSetButtonEnabled(panel->applyBtn, True);
  883. len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
  884. + strlen(wwin->wm_class ? wwin->wm_class : "?");
  885. str = wmalloc(len);
  886. snprintf(str, len, _("Inspecting %s.%s"),
  887. wwin->wm_instance ? wwin->wm_instance : "?", wwin->wm_class ? wwin->wm_class : "?");
  888. wFrameWindowChangeTitle(panel->frame->frame, str);
  889. wfree(str);
  890. }
  891. static void selectWindow(WMWidget * bPtr, void *data)
  892. {
  893. InspectorPanel *panel = (InspectorPanel *) data;
  894. WWindow *wwin = panel->inspected;
  895. WScreen *scr = wwin->screen_ptr;
  896. XEvent event;
  897. WWindow *iwin;
  898. if (XGrabPointer(dpy, scr->root_win, True,
  899. ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
  900. wCursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
  901. wwarning("could not grab mouse pointer");
  902. return;
  903. }
  904. WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
  905. WMMaskEvent(dpy, ButtonPressMask, &event);
  906. XUngrabPointer(dpy, CurrentTime);
  907. iwin = wWindowFor(event.xbutton.subwindow);
  908. if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
  909. iwin->flags.inspector_open = 1;
  910. iwin->inspector = createInspectorForWindow(iwin,
  911. panel->frame->frame_x, panel->frame->frame_y, True);
  912. wCloseInspectorForWindow(wwin);
  913. } else {
  914. WMSetLabelText(panel->specLbl, spec_text);
  915. }
  916. }
  917. static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel)
  918. {
  919. WScreen *scr = wwin->screen_ptr;
  920. InspectorPanel *panel;
  921. Window parent;
  922. int i;
  923. int x, y;
  924. int btn_width, frame_width;
  925. WMButton *selectedBtn = NULL;
  926. #ifdef wrong_behaviour
  927. WMPixmap *pixmap;
  928. #endif
  929. spec_text = _("The configuration will apply to all\n"
  930. "windows that have their WM_CLASS\n"
  931. "property set to the above selected\n" "name, when saved.");
  932. panel = wmalloc(sizeof(InspectorPanel));
  933. memset(panel, 0, sizeof(InspectorPanel));
  934. panel->destroyed = 0;
  935. panel->inspected = wwin;
  936. panel->nextPtr = panelList;
  937. panelList = panel;
  938. panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
  939. WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
  940. /**** create common stuff ****/
  941. /* command buttons */
  942. /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
  943. btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
  944. panel->saveBtn = WMCreateCommandButton(panel->win);
  945. WMSetButtonAction(panel->saveBtn, (WMAction *) saveSettings, panel);
  946. WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, PHEIGHT - 40);
  947. WMSetButtonText(panel->saveBtn, _("Save"));
  948. WMResizeWidget(panel->saveBtn, btn_width, 28);
  949. if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
  950. WMSetButtonEnabled(panel->saveBtn, False);
  951. panel->applyBtn = WMCreateCommandButton(panel->win);
  952. WMSetButtonAction(panel->applyBtn, (WMAction *) applySettings, panel);
  953. WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, PHEIGHT - 40);
  954. WMSetButtonText(panel->applyBtn, _("Apply"));
  955. WMResizeWidget(panel->applyBtn, btn_width, 28);
  956. panel->revertBtn = WMCreateCommandButton(panel->win);
  957. WMSetButtonAction(panel->revertBtn, (WMAction *) revertSettings, panel);
  958. WMMoveWidget(panel->revertBtn, 15, PHEIGHT - 40);
  959. WMSetButtonText(panel->revertBtn, _("Reload"));
  960. WMResizeWidget(panel->revertBtn, btn_width, 28);
  961. /* page selection popup button */
  962. panel->pagePopUp = WMCreatePopUpButton(panel->win);
  963. WMSetPopUpButtonAction(panel->pagePopUp, (WMAction *) changePage, panel);
  964. WMMoveWidget(panel->pagePopUp, 25, 15);
  965. WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
  966. WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
  967. WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
  968. WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
  969. WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
  970. WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
  971. /**** window spec ****/
  972. frame_width = PWIDTH - (2 * 15);
  973. panel->specFrm = WMCreateFrame(panel->win);
  974. WMSetFrameTitle(panel->specFrm, _("Window Specification"));
  975. WMMoveWidget(panel->specFrm, 15, 65);
  976. WMResizeWidget(panel->specFrm, frame_width, 145);
  977. panel->defaultRb = WMCreateRadioButton(panel->specFrm);
  978. WMMoveWidget(panel->defaultRb, 10, 78);
  979. WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
  980. WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
  981. WMSetButtonSelected(panel->defaultRb, False);
  982. WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
  983. if (wwin->wm_class && wwin->wm_instance) {
  984. char *str, *tmp;
  985. tmp = wstrconcat(wwin->wm_instance, ".");
  986. str = wstrconcat(tmp, wwin->wm_class);
  987. panel->bothRb = WMCreateRadioButton(panel->specFrm);
  988. WMMoveWidget(panel->bothRb, 10, 18);
  989. WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
  990. WMSetButtonText(panel->bothRb, str);
  991. wfree(tmp);
  992. wfree(str);
  993. WMGroupButtons(panel->defaultRb, panel->bothRb);
  994. if (!selectedBtn)
  995. selectedBtn = panel->bothRb;
  996. WMSetButtonAction(panel->bothRb, selectSpecification, panel);
  997. }
  998. if (wwin->wm_instance) {
  999. panel->instRb = WMCreateRadioButton(panel->specFrm);
  1000. WMMoveWidget(panel->instRb, 10, 38);
  1001. WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
  1002. WMSetButtonText(panel->instRb, wwin->wm_instance);
  1003. WMGroupButtons(panel->defaultRb, panel->instRb);
  1004. if (!selectedBtn)
  1005. selectedBtn = panel->instRb;
  1006. WMSetButtonAction(panel->instRb, selectSpecification, panel);
  1007. }
  1008. if (wwin->wm_class) {
  1009. panel->clsRb = WMCreateRadioButton(panel->specFrm);
  1010. WMMoveWidget(panel->clsRb, 10, 58);
  1011. WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
  1012. WMSetButtonText(panel->clsRb, wwin->wm_class);
  1013. WMGroupButtons(panel->defaultRb, panel->clsRb);
  1014. if (!selectedBtn)
  1015. selectedBtn = panel->clsRb;
  1016. WMSetButtonAction(panel->clsRb, selectSpecification, panel);
  1017. }
  1018. panel->selWinB = WMCreateCommandButton(panel->specFrm);
  1019. WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
  1020. WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
  1021. WMSetButtonText(panel->selWinB, _("Select window"));
  1022. WMSetButtonAction(panel->selWinB, selectWindow, panel);
  1023. panel->specLbl = WMCreateLabel(panel->win);
  1024. WMMoveWidget(panel->specLbl, 15, 210);
  1025. WMResizeWidget(panel->specLbl, frame_width, 100);
  1026. WMSetLabelText(panel->specLbl, spec_text);
  1027. WMSetLabelWraps(panel->specLbl, True);
  1028. WMSetLabelTextAlignment(panel->specLbl, WALeft);
  1029. /**** attributes ****/
  1030. panel->attrFrm = WMCreateFrame(panel->win);
  1031. WMSetFrameTitle(panel->attrFrm, _("Attributes"));
  1032. WMMoveWidget(panel->attrFrm, 15, 45);
  1033. WMResizeWidget(panel->attrFrm, frame_width, 250);
  1034. for (i = 0; i < 11; i++) {
  1035. char *caption = NULL;
  1036. int flag = 0;
  1037. char *descr = NULL;
  1038. switch (i) {
  1039. case 0:
  1040. caption = _("Disable titlebar");
  1041. flag = WFLAGP(wwin, no_titlebar);
  1042. descr = _("Remove the titlebar of this window.\n"
  1043. "To access the window commands menu of a window\n"
  1044. "without it's titlebar, press Control+Esc (or the\n"
  1045. "equivalent shortcut, if you changed the default\n" "settings).");
  1046. break;
  1047. case 1:
  1048. caption = _("Disable resizebar");
  1049. flag = WFLAGP(wwin, no_resizebar);
  1050. descr = _("Remove the resizebar of this window.");
  1051. break;
  1052. case 2:
  1053. caption = _("Disable close button");
  1054. flag = WFLAGP(wwin, no_close_button);
  1055. descr = _("Remove the `close window' button of this window.");
  1056. break;
  1057. case 3:
  1058. caption = _("Disable miniaturize button");
  1059. flag = WFLAGP(wwin, no_miniaturize_button);
  1060. descr = _("Remove the `miniaturize window' button of the window.");
  1061. break;
  1062. case 4:
  1063. caption = _("Disable border");
  1064. flag = WFLAGP(wwin, no_border);
  1065. descr = _("Remove the 1 pixel black border around the window.");
  1066. break;
  1067. case 5:
  1068. caption = _("Keep on top (floating)");
  1069. flag = WFLAGP(wwin, floating);
  1070. descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
  1071. break;
  1072. case 6:
  1073. caption = _("Keep at bottom (sunken)");
  1074. flag = WFLAGP(wwin, sunken);
  1075. descr = _("Keep the window under all other windows.");
  1076. break;
  1077. case 7:
  1078. caption = _("Omnipresent");
  1079. flag = WFLAGP(wwin, omnipresent);
  1080. descr = _("Make window present in all workspaces.");
  1081. break;
  1082. case 8:
  1083. caption = _("Start miniaturized");
  1084. flag = WFLAGP(wwin, start_miniaturized);
  1085. descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
  1086. break;
  1087. case 9:
  1088. caption = _("Start maximized");
  1089. flag = WFLAGP(wwin, start_maximized != 0);
  1090. descr = _("Make the window be automatically maximized when it's\n" "first shown.");
  1091. break;
  1092. case 10:
  1093. caption = _("Full screen maximization");
  1094. flag = WFLAGP(wwin, full_maximize);
  1095. descr = _("Make the window use the whole screen space when it's\n"
  1096. "maximized. The titlebar and resizebar will be moved\n"
  1097. "to outside the screen.");
  1098. break;
  1099. }
  1100. panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
  1101. WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
  1102. WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
  1103. WMSetButtonSelected(panel->attrChk[i], flag);
  1104. WMSetButtonText(panel->attrChk[i], caption);
  1105. WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
  1106. }
  1107. /**** more attributes ****/
  1108. panel->moreFrm = WMCreateFrame(panel->win);
  1109. WMSetFrameTitle(panel->moreFrm, _("Advanced"));
  1110. WMMoveWidget(panel->moreFrm, 15, 45);
  1111. WMResizeWidget(panel->moreFrm, frame_width, 265);
  1112. for (i = 0;
  1113. #ifdef XKB_BUTTON_HINT
  1114. i < 12;
  1115. #else
  1116. i < 11;
  1117. #endif
  1118. i++) {
  1119. char *caption = NULL;
  1120. int flag = 0;
  1121. char *descr = NULL;
  1122. switch (i) {
  1123. case 0:
  1124. caption = _("Do not bind keyboard shortcuts");
  1125. flag = WFLAGP(wwin, no_bind_keys);
  1126. descr = _("Do not bind keyboard shortcuts from Window Maker\n"
  1127. "when this window is focused. This will allow the\n"
  1128. "window to receive all key combinations regardless\n"
  1129. "of your shortcut configuration.");
  1130. break;
  1131. case 1:
  1132. caption = _("Do not bind mouse clicks");
  1133. flag = WFLAGP(wwin, no_bind_mouse);
  1134. descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
  1135. "in the window (when alt is the modifier you have\n" "configured).");
  1136. break;
  1137. case 2:
  1138. caption = _("Do not show in the window list");
  1139. flag = WFLAGP(wwin, skip_window_list);
  1140. descr = _("Do not list the window in the window list menu.");
  1141. break;
  1142. case 3:
  1143. caption = _("Do not show in the switch panel");
  1144. flag = WFLAGP(wwin, skip_switchpanel);
  1145. descr = _("Do not include in switchpanel while alternating windows.");
  1146. break;
  1147. case 4:
  1148. caption = _("Do not let it take focus");
  1149. flag = WFLAGP(wwin, no_focusable);
  1150. descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
  1151. break;
  1152. case 5:
  1153. caption = _("Keep inside screen");
  1154. flag = WFLAGP(wwin, dont_move_off);
  1155. descr = _("Do not allow the window to move itself completely\n"
  1156. "outside the screen. For bug compatibility.\n");
  1157. break;
  1158. case 6:
  1159. caption = _("Ignore 'Hide Others'");
  1160. flag = WFLAGP(wwin, no_hide_others);
  1161. descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
  1162. break;
  1163. case 7:
  1164. caption = _("Ignore 'Save Session'");
  1165. flag = WFLAGP(wwin, dont_save_session);
  1166. descr = _("Do not save the associated application in the\n"
  1167. "session's state, so that it won't be restarted\n"
  1168. "together with other applications when Window Maker\n" "starts.");
  1169. break;
  1170. case 8:
  1171. caption = _("Emulate application icon");
  1172. flag = WFLAGP(wwin, emulate_appicon);
  1173. descr = _("Make this window act as an application that provides\n"
  1174. "enough information to Window Maker for a dockable\n"
  1175. "application icon to be created.");
  1176. break;
  1177. case 9:
  1178. caption = _("Focus across workspaces");
  1179. flag = WFLAGP(wwin, focus_across_wksp);
  1180. descr = _("Allow Window Maker to switch workspace to satisfy\n"
  1181. "a focus request (annoying).");
  1182. break;
  1183. case 10:
  1184. caption = _("Do not let it be minimized");
  1185. flag = WFLAGP(wwin, no_miniaturizable);
  1186. descr = _("Do not let the window of this application be\n"
  1187. "minimized.\n");
  1188. break;
  1189. #ifdef XKB_BUTTON_HINT
  1190. case 11:
  1191. caption = _("Disable language button");
  1192. flag = WFLAGP(wwin, no_language_button);
  1193. descr = _("Remove the `toggle language' button of the window.");
  1194. break;
  1195. #endif
  1196. }
  1197. panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
  1198. WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
  1199. WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
  1200. WMSetButtonSelected(panel->moreChk[i], flag);
  1201. WMSetButtonText(panel->moreChk[i], caption);
  1202. WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
  1203. }
  1204. /* miniwindow/workspace */
  1205. panel->iconFrm = WMCreateFrame(panel->win);
  1206. WMMoveWidget(panel->iconFrm, 15, 50);
  1207. WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
  1208. WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
  1209. panel->iconLbl = WMCreateLabel(panel->iconFrm);
  1210. WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
  1211. WMResizeWidget(panel->iconLbl, 64, 64);
  1212. WMSetLabelRelief(panel->iconLbl, WRGroove);
  1213. WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
  1214. panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
  1215. WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
  1216. WMMoveWidget(panel->browseIconBtn, 22, 32);
  1217. WMResizeWidget(panel->browseIconBtn, 120, 26);
  1218. WMSetButtonText(panel->browseIconBtn, _("Browse..."));
  1219. #ifdef wrong_behaviour
  1220. WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
  1221. pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
  1222. WMSetButtonImage(panel->updateIconBtn, pixmap);
  1223. WMReleasePixmap(pixmap);
  1224. pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
  1225. WMSetButtonAltImage(panel->updateIconBtn, pixmap);
  1226. WMReleasePixmap(pixmap);
  1227. #endif
  1228. panel->fileLbl = WMCreateLabel(panel->iconFrm);
  1229. WMMoveWidget(panel->fileLbl, 20, 85);
  1230. WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
  1231. WMSetLabelText(panel->fileLbl, _("Icon filename:"));
  1232. panel->fileText = WMCreateTextField(panel->iconFrm);
  1233. WMMoveWidget(panel->fileText, 20, 105);
  1234. WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
  1235. WMSetTextFieldText(panel->fileText, NULL);
  1236. WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
  1237. panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
  1238. WMMoveWidget(panel->alwChk, 20, 130);
  1239. WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
  1240. WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
  1241. WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
  1242. panel->wsFrm = WMCreateFrame(panel->win);
  1243. WMMoveWidget(panel->wsFrm, 15, 225);
  1244. WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
  1245. WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
  1246. WMSetBalloonTextForView(_("The workspace to place the window when it's"
  1247. "first shown."), WMWidgetView(panel->wsFrm));
  1248. panel->wsP = WMCreatePopUpButton(panel->wsFrm);
  1249. WMMoveWidget(panel->wsP, 20, 30);
  1250. WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
  1251. WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
  1252. for (i = 0; i < wwin->screen_ptr->workspace_count; i++) {
  1253. WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
  1254. }
  1255. i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
  1256. if (i >= 0 && i <= wwin->screen_ptr->workspace_count) {
  1257. WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
  1258. } else {
  1259. WMSetPopUpButtonSelectedItem(panel->wsP, 0);
  1260. }
  1261. /* application wide attributes */
  1262. if (wwin->main_window != None) {
  1263. WApplication *wapp = wApplicationOf(wwin->main_window);
  1264. panel->appFrm = WMCreateFrame(panel->win);
  1265. WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
  1266. WMMoveWidget(panel->appFrm, 15, 50);
  1267. WMResizeWidget(panel->appFrm, frame_width, 240);
  1268. for (i = 0; i < 3; i++) {
  1269. char *caption = NULL;
  1270. int flag = 0;
  1271. char *descr = NULL;
  1272. switch (i) {
  1273. case 0:
  1274. caption = _("Start hidden");
  1275. flag = WFLAGP(wapp->main_window_desc, start_hidden);
  1276. descr = _("Automatically hide application when it's started.");
  1277. break;
  1278. case 1:
  1279. caption = _("No application icon");
  1280. flag = WFLAGP(wapp->main_window_desc, no_appicon);
  1281. descr = _("Disable the application icon for the application.\n"
  1282. "Note that you won't be able to dock it anymore,\n"
  1283. "and any icons that are already docked will stop\n"
  1284. "working correctly.");
  1285. break;
  1286. case 2:
  1287. caption = _("Shared application icon");
  1288. flag = WFLAGP(wapp->main_window_desc, shared_appicon);
  1289. descr = _("Use a single shared application icon for all of\n"
  1290. "the instances of this application.\n");
  1291. break;
  1292. }
  1293. panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
  1294. WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
  1295. WMResizeWidget(panel->appChk[i], 205, 20);
  1296. WMSetButtonSelected(panel->appChk[i], flag);
  1297. WMSetButtonText(panel->appChk[i], caption);
  1298. WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
  1299. }
  1300. if (WFLAGP(wwin, emulate_appicon)) {
  1301. WMSetButtonEnabled(panel->appChk[1], False);
  1302. WMSetButtonEnabled(panel->moreChk[7], True);
  1303. } else {
  1304. WMSetButtonEnabled(panel->appChk[1], True);
  1305. WMSetButtonEnabled(panel->moreChk[7], False);
  1306. }
  1307. } else {
  1308. int tmp;
  1309. if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
  1310. || !wwin->wm_class || !wwin->wm_instance)
  1311. tmp = False;
  1312. else
  1313. tmp = True;
  1314. WMSetButtonEnabled(panel->moreChk[7], tmp);
  1315. WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
  1316. panel->appFrm = NULL;
  1317. }
  1318. /* if the window is a transient, don't let it have a miniaturize
  1319. * button */
  1320. if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
  1321. WMSetButtonEnabled(panel->attrChk[3], False);
  1322. else
  1323. WMSetButtonEnabled(panel->attrChk[3], True);
  1324. if (!wwin->wm_class && !wwin->wm_instance) {
  1325. WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
  1326. }
  1327. WMRealizeWidget(panel->win);
  1328. WMMapSubwidgets(panel->win);
  1329. WMMapSubwidgets(panel->specFrm);
  1330. WMMapSubwidgets(panel->attrFrm);
  1331. WMMapSubwidgets(panel->moreFrm);
  1332. WMMapSubwidgets(panel->iconFrm);
  1333. WMMapSubwidgets(panel->wsFrm);
  1334. if (panel->appFrm)
  1335. WMMapSubwidgets(panel->appFrm);
  1336. if (showSelectPanel) {
  1337. WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
  1338. changePage(panel->pagePopUp, panel);
  1339. } else {
  1340. WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
  1341. changePage(panel->pagePopUp, panel);
  1342. }
  1343. parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
  1344. XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
  1345. panel->parent = parent;
  1346. XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
  1347. WMMapWidget(panel->win);
  1348. XSetTransientForHint(dpy, parent, wwin->client_win);
  1349. if (xpos == UNDEFINED_POS) {
  1350. x = wwin->frame_x + wwin->frame->core->width / 2;
  1351. y = wwin->frame_y + wwin->frame->top_width * 2;
  1352. if (y + PHEIGHT > scr->scr_height)
  1353. y = scr->scr_height - PHEIGHT - 30;
  1354. if (x + PWIDTH > scr->scr_width)
  1355. x = scr->scr_width - PWIDTH;
  1356. } else {
  1357. x = xpos;
  1358. y = ypos;
  1359. }
  1360. panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
  1361. if (!selectedBtn)
  1362. selectedBtn = panel->defaultRb;
  1363. WMSetButtonSelected(selectedBtn, True);
  1364. selectSpecification(selectedBtn, panel);
  1365. /* kluge to know who should get the key events */
  1366. panel->frame->client_leader = WMWidgetXID(panel->win);
  1367. WSETUFLAG(panel->frame, no_closable, 0);
  1368. WSETUFLAG(panel->frame, no_close_button, 0);
  1369. wWindowUpdateButtonImages(panel->frame);
  1370. wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
  1371. panel->frame->frame->on_click_right = destroyInspector;
  1372. wWindowMap(panel->frame);
  1373. showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
  1374. return panel;
  1375. }
  1376. void wShowInspectorForWindow(WWindow * wwin)
  1377. {
  1378. if (wwin->flags.inspector_open)
  1379. return;
  1380. WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
  1381. make_keys();
  1382. wwin->flags.inspector_open = 1;
  1383. wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
  1384. }
  1385. void wHideInspectorForWindow(WWindow * wwin)
  1386. {
  1387. WWindow *pwin = wwin->inspector->frame;
  1388. wWindowUnmap(pwin);
  1389. pwin->flags.hidden = 1;
  1390. wClientSetState(pwin, IconicState, None);
  1391. }
  1392. void wUnhideInspectorForWindow(WWindow * wwin)
  1393. {
  1394. WWindow *pwin = wwin->inspector->frame;
  1395. pwin->flags.hidden = 0;
  1396. pwin->flags.mapped = 1;
  1397. XMapWindow(dpy, pwin->client_win);
  1398. XMapWindow(dpy, pwin->frame->core->window);
  1399. wClientSetState(pwin, NormalState, None);
  1400. }
  1401. WWindow *wGetWindowOfInspectorForWindow(WWindow * wwin)
  1402. {
  1403. if (wwin->inspector) {
  1404. assert(wwin->flags.inspector_open != 0);
  1405. return wwin->inspector->frame;
  1406. } else
  1407. return NULL;
  1408. }
  1409. void wCloseInspectorForWindow(WWindow * wwin)
  1410. {
  1411. WWindow *pwin = wwin->inspector->frame; /* the inspector window */
  1412. (*pwin->frame->on_click_right) (NULL, pwin, NULL);
  1413. }