wmaker: Fix typos (used codespell).
[wmaker-crm.git] / src / winspector.c
blobe3d8f7f1a379f23fe143b07df06823d90196fa62
1 /* winspector.c - window attribute inspector
3 * Window Maker window manager
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * Copyright (c) 1998-2003 Dan Pascu
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.
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.
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.
23 #include "wconfig.h"
25 #include <X11/Xlib.h>
26 #include <X11/Xutil.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <strings.h>
32 #include "WindowMaker.h"
33 #include "screen.h"
34 #include "wcore.h"
35 #include "framewin.h"
36 #include "window.h"
37 #include "workspace.h"
38 #include "defaults.h"
39 #include "dialog.h"
40 #include "icon.h"
41 #include "stacking.h"
42 #include "application.h"
43 #include "appicon.h"
44 #include "actions.h"
45 #include "winspector.h"
46 #include "dock.h"
47 #include "client.h"
48 #include "wmspec.h"
49 #include "misc.h"
50 #include "switchmenu.h"
52 #include <WINGs/WUtil.h>
54 #define USE_TEXT_FIELD 1
55 #define UPDATE_TEXT_FIELD 2
56 #define REVERT_TO_DEFAULT 4
57 #define PWIDTH 290
58 #define PHEIGHT 360
59 #define UNDEFINED_POS 0xffffff
60 #define UPDATE_DEFAULTS 1
61 #define IS_BOOLEAN 2
64 static const struct {
65 const char *key_name;
66 WWindowAttributes flag;
67 const char *caption;
68 const char *description;
69 } window_attribute[] = {
70 { "NoTitlebar", { .no_titlebar = 1 }, N_("Disable titlebar"),
71 N_("Remove the titlebar of this window.\n"
72 "To access the window commands menu of a window\n"
73 "without it's titlebar, press Control+Esc (or the\n"
74 "equivalent shortcut, if you changed the default\n"
75 "settings).") },
77 { "NoResizebar", { .no_resizebar = 1 }, N_("Disable resizebar"),
78 N_("Remove the resizebar of this window.") },
80 { "NoCloseButton", { .no_close_button = 1 }, N_("Disable close button"),
81 N_("Remove the `close window' button of this window.") },
83 { "NoMiniaturizeButton", { .no_miniaturize_button = 1 }, N_("Disable miniaturize button"),
84 N_("Remove the `miniaturize window' button of the window.") },
86 { "NoBorder", { .no_border = 1 }, N_("Disable border"),
87 N_("Remove the 1 pixel black border around the window.") },
89 { "KeepOnTop", { .floating = 1 }, N_("Keep on top (floating)"),
90 N_("Keep the window over other windows, not allowing\n"
91 "them to cover it.") },
93 { "KeepOnBottom", { .sunken = 1 }, N_("Keep at bottom (sunken)"),
94 N_("Keep the window under all other windows.") },
96 { "Omnipresent", { .omnipresent = 1 }, N_("Omnipresent"),
97 N_("Make window present in all workspaces.") },
99 { "StartMiniaturized", { .start_miniaturized = 1 }, N_("Start miniaturized"),
100 N_("Make the window be automatically miniaturized when it's\n"
101 "first shown.") },
103 { "StartMaximized", { .start_maximized = 1 }, N_("Start maximized"),
104 N_("Make the window be automatically maximized when it's\n"
105 "first shown.") },
107 { "FullMaximize", { .full_maximize = 1 }, N_("Full screen maximization"),
108 N_("Make the window use the whole screen space when it's\n"
109 "maximized. The titlebar and resizebar will be moved\n"
110 "to outside the screen.") }
112 }, advanced_option[] = {
113 { "NoKeyBindings", { .no_bind_keys = 1 }, N_("Do not bind keyboard shortcuts"),
114 N_("Do not bind keyboard shortcuts from Window Maker\n"
115 "when this window is focused. This will allow the\n"
116 "window to receive all key combinations regardless\n"
117 "of your shortcut configuration.") },
119 { "NoMouseBindings", { .no_bind_mouse = 1 }, N_("Do not bind mouse clicks"),
120 N_("Do not bind mouse actions, such as `Alt'+drag\n"
121 "in the window (when Alt is the modifier you have\n"
122 "configured).") },
124 { "SkipWindowList", { .skip_window_list = 1 }, N_("Do not show in the window list"),
125 N_("Do not list the window in the window list menu.") },
127 { "SkipSwitchPanel", { .skip_switchpanel = 1 }, N_("Do not show in the switch panel"),
128 N_("Do not include in switch panel while cycling windows.") },
130 { "Unfocusable", { .no_focusable = 1 }, N_("Do not let it take focus"),
131 N_("Do not let the window take keyboard focus when you\n"
132 "click on it.") },
134 { "KeepInsideScreen", { .dont_move_off = 1 }, N_("Keep inside screen"),
135 N_("Do not allow the window to move itself completely\n"
136 "outside the screen. For bug compatibility.\n") },
138 { "NoHideOthers", { .no_hide_others = 1 }, N_("Ignore 'Hide Others'"),
139 N_("Do not hide the window when issuing the\n"
140 "`HideOthers' command.") },
142 { "DontSaveSession", { .dont_save_session = 1 }, N_("Ignore 'Save Session'"),
143 N_("Do not save the associated application in the\n"
144 "session's state, so that it won't be restarted\n"
145 "together with other applications when Window Maker\n"
146 "starts.") },
148 { "EmulateAppIcon", { .emulate_appicon = 1 }, N_("Emulate application icon"),
149 N_("Make this window act as an application that provides\n"
150 "enough information to Window Maker for a dockable\n"
151 "application icon to be created.") },
153 { "FocusAcrossWorkspace", { .focus_across_wksp = 1 }, N_("Focus across workspaces"),
154 N_("Allow Window Maker to switch workspace to satisfy\n"
155 "a focus request (annoying).") },
157 { "NoMiniaturizable", { .no_miniaturizable = 1 }, N_("Do not let it be minimized"),
158 N_("Do not let the window of this application be\n"
159 "minimized.\n") }
161 #ifdef XKB_BUTTON_HINT
162 ,{ "NoLanguageButton", { .no_language_button = 1 }, N_("Disable language button"),
163 N_("Remove the `toggle language' button of the window.") }
164 #endif
166 }, application_attr[] = {
167 { "StartHidden", { .start_hidden = 1 }, N_("Start hidden"),
168 N_("Automatically hide application when it's started.") },
170 { "NoAppIcon", { .no_appicon = 1 }, N_("No application icon"),
171 N_("Disable the application icon for the application.\n"
172 "Note that you won't be able to dock it anymore,\n"
173 "and any icons that are already docked will stop\n"
174 "working correctly.") },
176 { "SharedAppIcon", { .shared_appicon = 1 }, N_("Shared application icon"),
177 N_("Use a single shared application icon for all of\n"
178 "the instances of this application.\n") }
181 typedef struct InspectorPanel {
182 struct InspectorPanel *nextPtr;
184 WWindow *frame;
185 WWindow *inspected; /* the window that's being inspected */
186 WMWindow *win;
187 Window parent;
189 /* common stuff */
190 WMButton *revertBtn;
191 WMButton *applyBtn;
192 WMButton *saveBtn;
193 WMPopUpButton *pagePopUp;
195 /* first page. general stuff */
196 WMFrame *specFrm;
197 WMButton *instRb;
198 WMButton *clsRb;
199 WMButton *bothRb;
200 WMButton *defaultRb;
201 WMButton *selWinB;
202 WMLabel *specLbl;
204 /* second page. attributes */
205 WMFrame *attrFrm;
206 WMButton *attrChk[sizeof(window_attribute) / sizeof(window_attribute[0])];
208 /* 3rd page. more attributes */
209 WMFrame *moreFrm;
210 WMButton *moreChk[sizeof(advanced_option) / sizeof(advanced_option[0])];
212 /* 4th page. icon and workspace */
213 WMFrame *iconFrm;
214 WMLabel *iconLbl;
215 WMLabel *fileLbl;
216 WMTextField *fileText;
217 WMButton *alwChk;
218 WMButton *browseIconBtn;
219 WMFrame *wsFrm;
220 WMPopUpButton *wsP;
222 /* 5th page. application wide attributes */
223 WMFrame *appFrm;
224 WMButton *appChk[sizeof(application_attr) / sizeof(application_attr[0])];
226 unsigned int done:1;
227 unsigned int destroyed:1;
228 unsigned int choosingIcon:1;
229 } InspectorPanel;
231 static InspectorPanel *panelList = NULL;
234 * We are supposed to use the 'key_name' from the the 'window_attribute' structure when we want to
235 * save the user choice to the database, but as we will need to convert that name into a Property
236 * List, we use here a Cache of Property Lists, generated only once, which can be reused. It will
237 * also save on memory because of the re-use of the same storage space instead of allocating a new
238 * one every time.
240 static WMPropList *pl_attribute[sizeof(window_attribute) / sizeof(window_attribute[0])] = { [0] = NULL };
241 static WMPropList *pl_advoptions[sizeof(advanced_option) / sizeof(advanced_option[0])];
242 static WMPropList *pl_appattrib[sizeof(application_attr) / sizeof(application_attr[0])];
244 static WMPropList *AAlwaysUserIcon;
245 static WMPropList *AStartWorkspace;
246 static WMPropList *AIcon;
248 /* application wide options */
249 static WMPropList *AnyWindow;
250 static WMPropList *EmptyString;
251 static WMPropList *Yes, *No;
253 static char *spec_text;
254 static void applySettings(WMWidget *button, void *panel);
256 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel);
258 static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width);
259 static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width);
260 static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel);
261 static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width);
264 * These 3 functions sets/clear/read a bit inside a bit-field in a generic manner;
265 * they uses binary operators to be as effiscient as possible, also counting on compiler's
266 * optimisations because the bit-field structure will fit in only 1 or 2 int but it is
267 * depending on the processor architecture.
269 static inline void set_attr_flag(WWindowAttributes *target, const WWindowAttributes *flag)
271 int i;
272 const unsigned char *src;
273 unsigned char *dst;
275 src = (const unsigned char *) flag;
276 dst = (unsigned char *) target;
278 for (i = 0; i < sizeof(*flag); i++)
279 dst[i] |= src[i];
282 static inline void clear_attr_flag(WWindowAttributes *target, const WWindowAttributes *flag)
284 int i;
285 const unsigned char *src;
286 unsigned char *dst;
288 src = (const unsigned char *) flag;
289 dst = (unsigned char *) target;
291 for (i = 0; i < sizeof(*flag); i++)
292 dst[i] &= ~src[i];
295 static inline int get_attr_flag(const WWindowAttributes *from, const WWindowAttributes *flag)
297 int i;
298 const unsigned char *xpect, *field;
300 field = (const unsigned char *) from;
301 xpect = (const unsigned char *) flag;
303 for (i = 0; i < sizeof(*flag); i++)
304 if (field[i] & xpect[i])
305 return 1;
307 return 0;
311 * This function is creating the Property List for the cache mentionned above
313 static void make_keys(void)
315 int i;
317 if (pl_attribute[0] != NULL)
318 return;
320 for (i = 0; i < wlengthof(window_attribute); i++)
321 pl_attribute[i] = WMCreatePLString(window_attribute[i].key_name);
323 for (i = 0; i < wlengthof(advanced_option); i++)
324 pl_advoptions[i] = WMCreatePLString(advanced_option[i].key_name);
326 for (i = 0; i < wlengthof(application_attr); i++)
327 pl_appattrib[i] = WMCreatePLString(application_attr[i].key_name);
329 AIcon = WMCreatePLString("Icon");
330 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
332 AStartWorkspace = WMCreatePLString("StartWorkspace");
334 AnyWindow = WMCreatePLString("*");
335 EmptyString = WMCreatePLString("");
336 Yes = WMCreatePLString("Yes");
337 No = WMCreatePLString("No");
340 static void freeInspector(InspectorPanel *panel)
342 panel->destroyed = 1;
344 if (panel->choosingIcon)
345 return;
347 WMDestroyWidget(panel->win);
348 XDestroyWindow(dpy, panel->parent);
349 wfree(panel);
352 static void destroyInspector(WCoreWindow *foo, void *data, XEvent *event)
354 InspectorPanel *panel, *tmp;
356 /* Parameter not used, but tell the compiler that it is ok */
357 (void) foo;
358 (void) event;
360 panel = panelList;
361 while (panel->frame != data)
362 panel = panel->nextPtr;
364 if (panelList == panel) {
365 panelList = panel->nextPtr;
366 } else {
367 tmp = panelList;
368 while (tmp->nextPtr != panel)
369 tmp = tmp->nextPtr;
371 tmp->nextPtr = panel->nextPtr;
373 panel->inspected->flags.inspector_open = 0;
374 panel->inspected->inspector = NULL;
376 WMRemoveNotificationObserver(panel);
378 wWindowUnmap(panel->frame);
379 wUnmanageWindow(panel->frame, True, False);
381 freeInspector(panel);
384 void wDestroyInspectorPanels(void)
386 InspectorPanel *panel;
388 while (panelList != NULL) {
389 panel = panelList;
390 panelList = panelList->nextPtr;
391 wUnmanageWindow(panel->frame, False, False);
392 WMDestroyWidget(panel->win);
394 panel->inspected->flags.inspector_open = 0;
395 panel->inspected->inspector = NULL;
397 wfree(panel);
401 static void changePage(WMWidget *bPtr, void *client_data)
403 InspectorPanel *panel = (InspectorPanel *) client_data;
404 int page;
406 page = WMGetPopUpButtonSelectedItem(bPtr);
408 if (page == 0) {
409 WMMapWidget(panel->specFrm);
410 WMMapWidget(panel->specLbl);
411 } else if (page == 1) {
412 WMMapWidget(panel->attrFrm);
413 } else if (page == 2) {
414 WMMapWidget(panel->moreFrm);
415 } else if (page == 3) {
416 WMMapWidget(panel->iconFrm);
417 WMMapWidget(panel->wsFrm);
418 } else {
419 WMMapWidget(panel->appFrm);
422 if (page != 0) {
423 WMUnmapWidget(panel->specFrm);
424 WMUnmapWidget(panel->specLbl);
426 if (page != 1)
427 WMUnmapWidget(panel->attrFrm);
428 if (page != 2)
429 WMUnmapWidget(panel->moreFrm);
430 if (page != 3) {
431 WMUnmapWidget(panel->iconFrm);
432 WMUnmapWidget(panel->wsFrm);
434 if (page != 4 && panel->appFrm)
435 WMUnmapWidget(panel->appFrm);
438 static int showIconFor(WMScreen *scrPtr, InspectorPanel *panel, const char *wm_instance, const char *wm_class, int flags)
440 WMPixmap *pixmap = (WMPixmap *) NULL;
441 char *file = NULL, *path = NULL;
443 if ((flags & USE_TEXT_FIELD) != 0) {
444 file = WMGetTextFieldText(panel->fileText);
445 if (file && file[0] == 0) {
446 wfree(file);
447 file = NULL;
449 } else if (flags & REVERT_TO_DEFAULT) {
450 const char *db_icon;
452 /* Get the application icon, default NOT included */
453 db_icon = wDefaultGetIconFile(wm_instance, wm_class, False);
454 if (db_icon != NULL) {
455 file = wstrdup(db_icon);
456 flags |= UPDATE_TEXT_FIELD;
460 if ((flags & UPDATE_TEXT_FIELD) != 0)
461 WMSetTextFieldText(panel->fileText, file);
463 if (file) {
464 path = FindImage(wPreferences.icon_path, file);
466 if (!path) {
467 char *buf;
468 int len = strlen(file) + 80;
470 buf = wmalloc(len);
471 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"), file);
472 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
473 wfree(buf);
474 wfree(file);
475 return -1;
478 pixmap = WMCreatePixmapFromFile(scrPtr, path);
479 wfree(path);
481 if (!pixmap) {
482 char *buf;
483 int len = strlen(file) + 80;
485 buf = wmalloc(len);
486 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
487 file, RMessageForError(RErrorCode));
488 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
489 wfree(buf);
490 wfree(file);
491 return -1;
493 wfree(file);
496 WMSetLabelImage(panel->iconLbl, pixmap);
497 if (pixmap)
498 WMReleasePixmap(pixmap);
500 return 0;
503 static int getBool(WMPropList *value)
505 char *val;
507 if (!WMIsPLString(value))
508 return 0;
510 val = WMGetFromPLString(value);
511 if (val == NULL)
512 return 0;
514 if ((val[1] == '\0' &&
515 (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' ||
516 val[0] == 't' || val[0] == '1')) ||
517 (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
518 return 1;
519 } else if ((val[1] == '\0' &&
520 (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' ||
521 val[0] == 'f' || val[0] == '0')) ||
522 (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
523 return 0;
524 } else {
525 wwarning(_("can't convert \"%s\" to boolean"), val);
526 return 0;
530 /* Will insert the attribute = value; pair in window's list,
531 * if it's different from the defaults.
532 * Defaults means either defaults database, or attributes saved
533 * for the default window "*". This is to let one revert options that are
534 * global because they were saved for all windows ("*"). */
535 static int
536 insertAttribute(WMPropList *dict, WMPropList *window, WMPropList *attr, WMPropList *value, int flags)
538 WMPropList *def_win, *def_value = NULL;
539 int update = 0, modified = 0;
541 if (!(flags & UPDATE_DEFAULTS) && dict) {
542 def_win = WMGetFromPLDictionary(dict, AnyWindow);
543 if (def_win != NULL)
544 def_value = WMGetFromPLDictionary(def_win, attr);
547 /* If we could not find defaults in database, fall to hardcoded values.
548 * Also this is true if we save defaults for all windows */
549 if (!def_value)
550 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
552 if (flags & IS_BOOLEAN)
553 update = (getBool(value) != getBool(def_value));
554 else
555 update = !WMIsPropListEqualTo(value, def_value);
557 if (update) {
558 WMPutInPLDictionary(window, attr, value);
559 modified = 1;
562 return modified;
565 static void saveSettings(WMWidget *button, void *client_data)
567 InspectorPanel *panel = (InspectorPanel *) client_data;
568 WWindow *wwin = panel->inspected;
569 WDDomain *db = w_global.domain.window_attr;
570 WMPropList *dict = NULL;
571 WMPropList *winDic, *appDic, *value, *value1, *key = NULL, *key2;
572 char *icon_file, *buf1, *buf2;
573 int flags = 0, i = 0, different = 0, different2 = 0;
575 /* Save will apply the changes and save them */
576 applySettings(panel->applyBtn, panel);
578 if (WMGetButtonSelected(panel->instRb) != 0) {
579 key = WMCreatePLString(wwin->wm_instance);
580 } else if (WMGetButtonSelected(panel->clsRb) != 0) {
581 key = WMCreatePLString(wwin->wm_class);
582 } else if (WMGetButtonSelected(panel->bothRb) != 0) {
583 buf1 = StrConcatDot(wwin->wm_instance, wwin->wm_class);
584 key = WMCreatePLString(buf1);
585 wfree(buf1);
586 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
587 key = WMRetainPropList(AnyWindow);
588 flags = UPDATE_DEFAULTS;
591 if (!key)
592 return;
594 dict = db->dictionary;
595 if (!dict) {
596 dict = WMCreatePLDictionary(NULL, NULL);
597 if (dict) {
598 db->dictionary = dict;
599 } else {
600 WMReleasePropList(key);
601 return;
605 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD) < 0)
606 return;
608 WMPLSetCaseSensitive(True);
610 winDic = WMCreatePLDictionary(NULL, NULL);
611 appDic = WMCreatePLDictionary(NULL, NULL);
613 /* Save the icon info */
614 /* The flag "Ignore client suplied icon is not selected" */
615 buf1 = wmalloc(4);
616 snprintf(buf1, 4, "%s", (WMGetButtonSelected(panel->alwChk) != 0) ? "Yes" : "No");
617 value1 = WMCreatePLString(buf1);
618 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value1, flags);
619 WMReleasePropList(value1);
620 wfree(buf1);
622 /* The icon filename (if exists) */
623 icon_file = WMGetTextFieldText(panel->fileText);
624 if (icon_file != NULL) {
625 if (icon_file[0] != '\0') {
626 value = WMCreatePLString(icon_file);
627 different |= insertAttribute(dict, winDic, AIcon, value, flags);
628 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
629 WMReleasePropList(value);
631 wfree(icon_file);
634 i = WMGetPopUpButtonSelectedItem(panel->wsP) - 1;
635 if (i >= 0 && i < panel->frame->screen_ptr->workspace_count) {
636 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
637 different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
638 WMReleasePropList(value);
641 flags |= IS_BOOLEAN;
643 /* Attributes... --> Window Attributes */
644 for (i = 0; i < wlengthof(window_attribute); i++) {
645 value = (WMGetButtonSelected(panel->attrChk[i]) != 0) ? Yes : No;
646 different |= insertAttribute(dict, winDic, pl_attribute[i], value, flags);
649 /* Attributes... --> Advanced Options */
650 for (i = 0; i < wlengthof(advanced_option); i++) {
651 value = (WMGetButtonSelected(panel->moreChk[i]) != 0) ? Yes : No;
652 different |= insertAttribute(dict, winDic, pl_advoptions[i], value, flags);
655 /* Attributes... --> Application Specific */
656 if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
657 for (i = 0; i < wlengthof(application_attr); i++) {
658 value = (WMGetButtonSelected(panel->appChk[i]) != 0) ? Yes : No;
659 different2 |= insertAttribute(dict, appDic, pl_appattrib[i], value, flags);
663 if (wwin->fake_group) {
664 key2 = WMCreatePLString(wwin->fake_group->identifier);
665 if (WMIsPropListEqualTo(key, key2)) {
666 WMMergePLDictionaries(winDic, appDic, True);
667 different |= different2;
668 } else {
669 WMRemoveFromPLDictionary(dict, key2);
670 if (different2)
671 WMPutInPLDictionary(dict, key2, appDic);
673 WMReleasePropList(key2);
674 } else if (wwin->main_window != wwin->client_win) {
675 WApplication *wapp = wApplicationOf(wwin->main_window);
677 if (wapp) {
678 buf2 = StrConcatDot(wapp->main_window_desc->wm_instance,
679 wapp->main_window_desc->wm_class);
680 key2 = WMCreatePLString(buf2);
681 wfree(buf2);
683 if (WMIsPropListEqualTo(key, key2)) {
684 WMMergePLDictionaries(winDic, appDic, True);
685 different |= different2;
686 } else {
687 WMRemoveFromPLDictionary(dict, key2);
688 if (different2)
689 WMPutInPLDictionary(dict, key2, appDic);
691 WMReleasePropList(key2);
693 } else {
694 WMMergePLDictionaries(winDic, appDic, True);
695 different |= different2;
697 WMReleasePropList(appDic);
699 WMRemoveFromPLDictionary(dict, key);
700 if (different)
701 WMPutInPLDictionary(dict, key, winDic);
703 WMReleasePropList(key);
704 WMReleasePropList(winDic);
706 UpdateDomainFile(db);
708 /* clean up */
709 WMPLSetCaseSensitive(False);
712 static void applySettings(WMWidget *button, void *client_data)
714 InspectorPanel *panel = (InspectorPanel *) client_data;
715 WWindow *wwin = panel->inspected;
716 WApplication *wapp = wApplicationOf(wwin->main_window);
717 int old_skip_window_list, old_omnipresent, old_no_bind_keys, old_no_bind_mouse;
718 int i;
720 old_skip_window_list = WFLAGP(wwin, skip_window_list);
721 old_omnipresent = WFLAGP(wwin, omnipresent);
722 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
723 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
725 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
727 /* Attributes... --> Window Attributes */
728 for (i = 0; i < wlengthof(window_attribute); i++) {
729 if (WMGetButtonSelected(panel->attrChk[i]))
730 set_attr_flag(&wwin->user_flags, &window_attribute[i].flag);
731 else
732 clear_attr_flag(&wwin->user_flags, &window_attribute[i].flag);
734 set_attr_flag(&wwin->defined_user_flags, &window_attribute[i].flag);
737 /* Attributes... --> Advanced Options */
738 for (i = 0; i < wlengthof(advanced_option); i++) {
739 if (WMGetButtonSelected(panel->moreChk[i]))
740 set_attr_flag(&wwin->user_flags, &advanced_option[i].flag);
741 else
742 clear_attr_flag(&wwin->user_flags, &advanced_option[i].flag);
744 set_attr_flag(&wwin->defined_user_flags, &advanced_option[i].flag);
747 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
749 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
750 wUnshadeWindow(wwin);
752 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
755 * Update the window level according to AlwaysOnTop/AlwaysOnBotton
756 * if the level did not change, ChangeStackingLevel will do nothing anyway
758 if (WFLAGP(wwin, floating))
759 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
760 else if (WFLAGP(wwin, sunken))
761 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
762 else
763 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
765 wwin->flags.omnipresent = 0;
767 if (WFLAGP(wwin, skip_window_list) != old_skip_window_list) {
768 UpdateSwitchMenu(wwin->screen_ptr, wwin, WFLAGP(wwin, skip_window_list)?ACTION_REMOVE:ACTION_ADD);
769 } else {
770 if (WFLAGP(wwin, omnipresent) != old_omnipresent)
771 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
774 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
775 if (WFLAGP(wwin, no_bind_keys))
776 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
777 else
778 wWindowSetKeyGrabs(wwin);
781 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse)
782 wWindowResetMouseGrabs(wwin);
784 wwin->frame->flags.need_texture_change = 1;
785 wWindowConfigureBorders(wwin);
786 wFrameWindowPaint(wwin->frame);
787 wNETWMUpdateActions(wwin, False);
789 /* Can't apply emulate_appicon because it will probably cause problems. */
790 if (wapp) {
791 /* do application wide stuff */
792 for (i = 0; i < wlengthof(application_attr); i++) {
793 if (WMGetButtonSelected(panel->appChk[i]))
794 set_attr_flag(&wapp->main_window_desc->user_flags, &application_attr[i].flag);
795 else
796 clear_attr_flag(&wapp->main_window_desc->user_flags, &application_attr[i].flag);
798 set_attr_flag(&wapp->main_window_desc->defined_user_flags, &application_attr[i].flag);
801 if (WFLAGP(wapp->main_window_desc, no_appicon))
802 unpaint_app_icon(wapp);
803 else
804 paint_app_icon(wapp);
806 char *file = WMGetTextFieldText(panel->fileText);
807 if (file[0] == 0) {
808 wfree(file);
809 file = NULL;
812 /* If always_user_icon flag is set, but the user icon is not set
813 * we use client supplied icon and we unset the flag */
814 if ((WFLAGP(wwin, always_user_icon) && (!file))) {
815 /* Show the warning */
816 char *buf;
817 int len = 100;
819 buf = wmalloc(len);
820 snprintf(buf, len, _("Ignore client supplied icon is set, but icon filename textbox is empty. Using client supplied icon"));
821 wMessageDialog(panel->frame->screen_ptr, _("Warning"), buf, _("OK"), NULL, NULL);
822 wfree(buf);
823 wfree(file);
825 /* Change the flags */
826 WSETUFLAG(wwin, always_user_icon, 0);
827 WMSetButtonSelected(panel->alwChk, 0);
830 /* After test the always_user_icon flag value before,
831 * the "else" block is used only if the flag is set and
832 * the icon text box has an icon path */
833 if (!WFLAGP(wwin, always_user_icon)) {
834 /* Change App Icon image, using the icon provided by the client */
835 if (wapp->app_icon) {
836 RImage *image = get_rimage_icon_from_wm_hints(wapp->app_icon->icon);
837 if (image) {
838 set_icon_image_from_image(wapp->app_icon->icon, image);
839 update_icon_pixmap(wapp->app_icon->icon);
840 } else {
841 wIconUpdate(wapp->app_icon->icon);
845 /* Change icon image if the app is minimized,
846 * using the icon provided by the client */
847 if (wwin->icon) {
848 RImage *image = get_rimage_icon_from_wm_hints(wwin->icon);
849 if (image) {
850 set_icon_image_from_image(wwin->icon, image);
851 update_icon_pixmap(wwin->icon);
852 } else {
853 wIconUpdate(wwin->icon);
856 } else {
857 /* Change App Icon image */
858 if (wapp->app_icon)
859 wIconChangeImageFile(wapp->app_icon->icon, file);
861 /* Change icon image if the app is minimized */
862 if (wwin->icon)
863 wIconChangeImageFile(wwin->icon, file);
866 if (file)
867 wfree(file);
870 wNETFrameExtents(wwin);
873 static void revertSettings(WMWidget *button, void *client_data)
875 InspectorPanel *panel = (InspectorPanel *) client_data;
876 WWindow *wwin = panel->inspected;
877 WApplication *wapp = wApplicationOf(wwin->main_window);
878 int i, n, workspace, level;
879 char *wm_instance = NULL, *wm_class = NULL;
881 /* Parameter not used, but tell the compiler that it is ok */
882 (void) button;
884 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
885 wm_instance = wwin->wm_instance;
886 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
887 wm_class = wwin->wm_class;
888 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
889 wm_instance = wwin->wm_instance;
890 wm_class = wwin->wm_class;
893 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
894 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
895 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
897 wWindowSetupInitialAttributes(wwin, &level, &workspace);
899 /* Attributes... --> Window Attributes */
900 for (i = 0; i < wlengthof(window_attribute); i++) {
901 int is_userdef, flag;
903 is_userdef = get_attr_flag(&wwin->defined_user_flags, &window_attribute[i].flag);
904 if (is_userdef)
905 flag = get_attr_flag(&wwin->user_flags, &window_attribute[i].flag);
906 else
907 flag = get_attr_flag(&wwin->client_flags, &window_attribute[i].flag);
909 WMSetButtonSelected(panel->attrChk[i], flag);
912 /* Attributes... --> Advanced Options */
913 for (i = 0; i < wlengthof(advanced_option); i++) {
914 int is_userdef, flag;
916 is_userdef = get_attr_flag(&wwin->defined_user_flags, &advanced_option[i].flag);
917 if (is_userdef)
918 flag = get_attr_flag(&wwin->user_flags, &advanced_option[i].flag);
919 else
920 flag = get_attr_flag(&wwin->client_flags, &advanced_option[i].flag);
922 WMSetButtonSelected(panel->moreChk[i], flag);
925 /* Attributes... --> Application Specific */
926 if (panel->appFrm && wapp) {
927 for (i = 0; i < wlengthof(application_attr); i++) {
928 int is_userdef, flag = 0;
930 is_userdef = get_attr_flag(&wapp->main_window_desc->defined_user_flags, &application_attr[i].flag);
931 if (is_userdef)
932 flag = get_attr_flag(&wapp->main_window_desc->user_flags, &application_attr[i].flag);
933 else
934 flag = get_attr_flag(&wapp->main_window_desc->client_flags, &application_attr[i].flag);
936 WMSetButtonSelected(panel->appChk[i], flag);
939 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
941 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
943 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
945 if (n >= 0 && n < wwin->screen_ptr->workspace_count)
946 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
947 else
948 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
950 /* must auto apply, so that there wno't be internal
951 * inconsistencies between the state in the flags and
952 * the actual state of the window */
953 applySettings(panel->applyBtn, panel);
956 static void chooseIconCallback(WMWidget *self, void *clientData)
958 char *file;
959 InspectorPanel *panel = (InspectorPanel *) clientData;
960 int result;
962 panel->choosingIcon = 1;
964 WMSetButtonEnabled(panel->browseIconBtn, False);
966 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
967 panel->inspected->wm_instance,
968 panel->inspected->wm_class);
970 panel->choosingIcon = 0;
972 if (!panel->destroyed) { /* kluge */
973 if (result) {
974 WMSetTextFieldText(panel->fileText, file);
975 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
977 WMSetButtonEnabled(panel->browseIconBtn, True);
978 } else {
979 freeInspector(panel);
981 if (result)
982 wfree(file);
985 static void textEditedObserver(void *observerData, WMNotification *notification)
987 InspectorPanel *panel = (InspectorPanel *) observerData;
989 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
990 return;
992 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
995 static void selectSpecification(WMWidget *bPtr, void *data)
997 InspectorPanel *panel = (InspectorPanel *) data;
998 char str[256];
999 WWindow *wwin = panel->inspected;
1001 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class))
1002 WMSetButtonEnabled(panel->applyBtn, False);
1003 else
1004 WMSetButtonEnabled(panel->applyBtn, True);
1006 snprintf(str, sizeof(str),
1007 _("Inspecting %s.%s"),
1008 wwin->wm_instance ? wwin->wm_instance : "?",
1009 wwin->wm_class ? wwin->wm_class : "?");
1011 wFrameWindowChangeTitle(panel->frame->frame, str);
1014 static void selectWindow(WMWidget *bPtr, void *data)
1016 InspectorPanel *panel = (InspectorPanel *) data;
1017 WWindow *wwin = panel->inspected;
1018 WScreen *scr = wwin->screen_ptr;
1019 XEvent event;
1020 WWindow *iwin;
1022 /* Parameter not used, but tell the compiler that it is ok */
1023 (void) bPtr;
1025 if (XGrabPointer(dpy, scr->root_win, True,
1026 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1027 wPreferences.cursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
1028 wwarning("could not grab mouse pointer");
1029 return;
1032 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1033 WMMaskEvent(dpy, ButtonPressMask, &event);
1034 XUngrabPointer(dpy, CurrentTime);
1036 iwin = wWindowFor(event.xbutton.subwindow);
1037 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
1038 iwin->flags.inspector_open = 1;
1039 iwin->inspector = createInspectorForWindow(iwin,
1040 panel->frame->frame_x, panel->frame->frame_y, True);
1041 wCloseInspectorForWindow(wwin);
1042 } else {
1043 WMSetLabelText(panel->specLbl, spec_text);
1047 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel)
1049 WScreen *scr = wwin->screen_ptr;
1050 InspectorPanel *panel;
1051 Window parent;
1052 char *str = NULL, *tmp = NULL;
1053 int x, y, btn_width, frame_width;
1054 WMButton *selectedBtn = NULL;
1056 spec_text = _("The configuration will apply to all\n"
1057 "windows that have their WM_CLASS\n"
1058 "property set to the above selected\n" "name, when saved.");
1060 panel = wmalloc(sizeof(InspectorPanel));
1061 memset(panel, 0, sizeof(InspectorPanel));
1063 panel->destroyed = 0;
1064 panel->inspected = wwin;
1065 panel->nextPtr = panelList;
1066 panelList = panel;
1067 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1068 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1070 /**** create common stuff ****/
1071 /* command buttons */
1072 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1073 panel->saveBtn = WMCreateCommandButton(panel->win);
1074 WMSetButtonAction(panel->saveBtn, saveSettings, panel);
1075 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, PHEIGHT - 40);
1076 WMSetButtonText(panel->saveBtn, _("Save"));
1077 WMResizeWidget(panel->saveBtn, btn_width, 28);
1078 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1079 WMSetButtonEnabled(panel->saveBtn, False);
1081 panel->applyBtn = WMCreateCommandButton(panel->win);
1082 WMSetButtonAction(panel->applyBtn, applySettings, panel);
1083 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, PHEIGHT - 40);
1084 WMSetButtonText(panel->applyBtn, _("Apply"));
1085 WMResizeWidget(panel->applyBtn, btn_width, 28);
1087 panel->revertBtn = WMCreateCommandButton(panel->win);
1088 WMSetButtonAction(panel->revertBtn, revertSettings, panel);
1089 WMMoveWidget(panel->revertBtn, 15, PHEIGHT - 40);
1090 WMSetButtonText(panel->revertBtn, _("Reload"));
1091 WMResizeWidget(panel->revertBtn, btn_width, 28);
1093 /* page selection popup button */
1094 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1095 WMSetPopUpButtonAction(panel->pagePopUp, changePage, panel);
1096 WMMoveWidget(panel->pagePopUp, 25, 15);
1097 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1099 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1100 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1101 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1102 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1103 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1105 /**** window spec ****/
1106 frame_width = PWIDTH - (2 * 15);
1108 panel->specFrm = WMCreateFrame(panel->win);
1109 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1110 WMMoveWidget(panel->specFrm, 15, 65);
1111 WMResizeWidget(panel->specFrm, frame_width, 145);
1113 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1114 WMMoveWidget(panel->defaultRb, 10, 78);
1115 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1116 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1117 WMSetButtonSelected(panel->defaultRb, False);
1118 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1120 if (wwin->wm_class && wwin->wm_instance) {
1121 tmp = wstrconcat(wwin->wm_instance, ".");
1122 str = wstrconcat(tmp, wwin->wm_class);
1124 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1125 WMMoveWidget(panel->bothRb, 10, 18);
1126 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1127 WMSetButtonText(panel->bothRb, str);
1128 wfree(tmp);
1129 wfree(str);
1130 WMGroupButtons(panel->defaultRb, panel->bothRb);
1132 if (!selectedBtn)
1133 selectedBtn = panel->bothRb;
1135 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1138 if (wwin->wm_instance) {
1139 panel->instRb = WMCreateRadioButton(panel->specFrm);
1140 WMMoveWidget(panel->instRb, 10, 38);
1141 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1142 WMSetButtonText(panel->instRb, wwin->wm_instance);
1143 WMGroupButtons(panel->defaultRb, panel->instRb);
1145 if (!selectedBtn)
1146 selectedBtn = panel->instRb;
1148 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1151 if (wwin->wm_class) {
1152 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1153 WMMoveWidget(panel->clsRb, 10, 58);
1154 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1155 WMSetButtonText(panel->clsRb, wwin->wm_class);
1156 WMGroupButtons(panel->defaultRb, panel->clsRb);
1158 if (!selectedBtn)
1159 selectedBtn = panel->clsRb;
1161 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1164 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1165 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1166 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1167 WMSetButtonText(panel->selWinB, _("Select window"));
1168 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1170 panel->specLbl = WMCreateLabel(panel->win);
1171 WMMoveWidget(panel->specLbl, 15, 210);
1172 WMResizeWidget(panel->specLbl, frame_width, 100);
1173 WMSetLabelText(panel->specLbl, spec_text);
1174 WMSetLabelWraps(panel->specLbl, True);
1176 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1178 /**** attributes ****/
1179 create_tab_window_attributes(wwin, panel, frame_width);
1180 create_tab_window_advanced(wwin, panel, frame_width);
1181 create_tab_icon_workspace(wwin, panel);
1182 create_tab_app_specific(wwin, panel, frame_width);
1184 /* if the window is a transient, don't let it have a miniaturize button */
1185 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1186 WMSetButtonEnabled(panel->attrChk[3], False);
1187 else
1188 WMSetButtonEnabled(panel->attrChk[3], True);
1190 if (!wwin->wm_class && !wwin->wm_instance)
1191 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1193 WMRealizeWidget(panel->win);
1195 WMMapSubwidgets(panel->win);
1196 WMMapSubwidgets(panel->specFrm);
1197 WMMapSubwidgets(panel->attrFrm);
1198 WMMapSubwidgets(panel->moreFrm);
1199 WMMapSubwidgets(panel->iconFrm);
1200 WMMapSubwidgets(panel->wsFrm);
1201 if (panel->appFrm)
1202 WMMapSubwidgets(panel->appFrm);
1204 if (showSelectPanel) {
1205 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1206 changePage(panel->pagePopUp, panel);
1207 } else {
1208 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1209 changePage(panel->pagePopUp, panel);
1212 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1213 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1214 panel->parent = parent;
1215 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1217 WMMapWidget(panel->win);
1219 XSetTransientForHint(dpy, parent, wwin->client_win);
1221 if (xpos == UNDEFINED_POS) {
1222 x = wwin->frame_x + wwin->frame->core->width / 2;
1223 y = wwin->frame_y + wwin->frame->top_width * 2;
1224 if (y + PHEIGHT > scr->scr_height)
1225 y = scr->scr_height - PHEIGHT - 30;
1226 if (x + PWIDTH > scr->scr_width)
1227 x = scr->scr_width - PWIDTH;
1228 } else {
1229 x = xpos;
1230 y = ypos;
1233 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1235 if (!selectedBtn)
1236 selectedBtn = panel->defaultRb;
1238 WMSetButtonSelected(selectedBtn, True);
1239 selectSpecification(selectedBtn, panel);
1241 /* kluge to know who should get the key events */
1242 panel->frame->client_leader = WMWidgetXID(panel->win);
1244 panel->frame->client_flags.no_closable = 0;
1245 panel->frame->client_flags.no_close_button = 0;
1246 wWindowUpdateButtonImages(panel->frame);
1247 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1248 panel->frame->frame->on_click_right = destroyInspector;
1250 wWindowMap(panel->frame);
1252 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1254 return panel;
1257 void wShowInspectorForWindow(WWindow *wwin)
1259 if (wwin->flags.inspector_open)
1260 return;
1262 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1264 make_keys();
1265 wwin->flags.inspector_open = 1;
1266 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1269 void wHideInspectorForWindow(WWindow *wwin)
1271 WWindow *pwin = wwin->inspector->frame;
1273 wWindowUnmap(pwin);
1274 pwin->flags.hidden = 1;
1276 wClientSetState(pwin, IconicState, None);
1279 void wUnhideInspectorForWindow(WWindow *wwin)
1281 WWindow *pwin = wwin->inspector->frame;
1283 pwin->flags.hidden = 0;
1284 pwin->flags.mapped = 1;
1285 XMapWindow(dpy, pwin->client_win);
1286 XMapWindow(dpy, pwin->frame->core->window);
1287 wClientSetState(pwin, NormalState, None);
1290 WWindow *wGetWindowOfInspectorForWindow(WWindow *wwin)
1292 if (!wwin->inspector)
1293 return NULL;
1295 assert(wwin->flags.inspector_open != 0);
1296 return wwin->inspector->frame;
1299 void wCloseInspectorForWindow(WWindow *wwin)
1301 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1303 (*pwin->frame->on_click_right) (NULL, pwin, NULL);
1306 static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width)
1308 int i = 0;
1310 panel->attrFrm = WMCreateFrame(panel->win);
1311 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1312 WMMoveWidget(panel->attrFrm, 15, 45);
1313 WMResizeWidget(panel->attrFrm, frame_width, 250);
1315 for (i = 0; i < wlengthof(window_attribute); i++) {
1316 int is_userdef, flag;
1318 is_userdef = get_attr_flag(&wwin->defined_user_flags, &window_attribute[i].flag);
1319 if (is_userdef)
1320 flag = get_attr_flag(&wwin->user_flags, &window_attribute[i].flag);
1321 else
1322 flag = get_attr_flag(&wwin->client_flags, &window_attribute[i].flag);
1324 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1325 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1326 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1327 WMSetButtonSelected(panel->attrChk[i], flag);
1328 WMSetButtonText(panel->attrChk[i], _(window_attribute[i].caption));
1330 WMSetBalloonTextForView(_(window_attribute[i].description), WMWidgetView(panel->attrChk[i]));
1334 static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width)
1336 int i = 0;
1338 panel->moreFrm = WMCreateFrame(panel->win);
1339 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1340 WMMoveWidget(panel->moreFrm, 15, 45);
1341 WMResizeWidget(panel->moreFrm, frame_width, 265);
1343 for (i = 0; i < wlengthof(advanced_option); i++) {
1344 int is_userdef, flag;
1346 is_userdef = get_attr_flag(&wwin->defined_user_flags, &advanced_option[i].flag);
1347 if (is_userdef)
1348 flag = get_attr_flag(&wwin->user_flags, &advanced_option[i].flag);
1349 else
1350 flag = get_attr_flag(&wwin->client_flags, &advanced_option[i].flag);
1352 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1353 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1) - 4);
1354 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1355 WMSetButtonSelected(panel->moreChk[i], flag);
1356 WMSetButtonText(panel->moreChk[i], _(advanced_option[i].caption));
1358 WMSetBalloonTextForView(_(advanced_option[i].description), WMWidgetView(panel->moreChk[i]));
1362 static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel)
1364 WScreen *scr = wwin->screen_ptr;
1365 int i = 0;
1367 /* miniwindow/workspace */
1368 panel->iconFrm = WMCreateFrame(panel->win);
1369 WMMoveWidget(panel->iconFrm, 15, 50);
1370 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1371 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1373 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1374 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1375 WMResizeWidget(panel->iconLbl, 64, 64);
1376 WMSetLabelRelief(panel->iconLbl, WRGroove);
1377 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1379 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1380 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1381 WMMoveWidget(panel->browseIconBtn, 22, 32);
1382 WMResizeWidget(panel->browseIconBtn, 120, 26);
1383 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1385 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1386 WMMoveWidget(panel->fileLbl, 20, 85);
1387 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1388 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1390 panel->fileText = WMCreateTextField(panel->iconFrm);
1391 WMMoveWidget(panel->fileText, 20, 105);
1392 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1393 WMSetTextFieldText(panel->fileText, NULL);
1394 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1396 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1397 WMMoveWidget(panel->alwChk, 20, 130);
1398 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1399 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1400 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1402 panel->wsFrm = WMCreateFrame(panel->win);
1403 WMMoveWidget(panel->wsFrm, 15, 225);
1404 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1405 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1407 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1408 " first shown."), WMWidgetView(panel->wsFrm));
1410 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1411 WMMoveWidget(panel->wsP, 20, 30);
1412 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1413 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1415 for (i = 0; i < wwin->screen_ptr->workspace_count; i++)
1416 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1418 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1419 if (i >= 0 && i <= wwin->screen_ptr->workspace_count)
1420 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1421 else
1422 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1425 static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width)
1427 WScreen *scr = wwin->screen_ptr;
1428 int i = 0, tmp;
1430 if (wwin->main_window != None) {
1431 WApplication *wapp = wApplicationOf(wwin->main_window);
1433 panel->appFrm = WMCreateFrame(panel->win);
1434 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1435 WMMoveWidget(panel->appFrm, 15, 50);
1436 WMResizeWidget(panel->appFrm, frame_width, 240);
1438 for (i = 0; i < wlengthof(application_attr); i++) {
1439 int is_userdef, flag;
1441 is_userdef = get_attr_flag(&wapp->main_window_desc->defined_user_flags, &application_attr[i].flag);
1442 if (is_userdef)
1443 flag = get_attr_flag(&wapp->main_window_desc->user_flags, &application_attr[i].flag);
1444 else
1445 flag = get_attr_flag(&wapp->main_window_desc->client_flags, &application_attr[i].flag);
1447 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1448 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1449 WMResizeWidget(panel->appChk[i], 205, 20);
1450 WMSetButtonSelected(panel->appChk[i], flag);
1451 WMSetButtonText(panel->appChk[i], _(application_attr[i].caption));
1453 WMSetBalloonTextForView(_(application_attr[i].description),
1454 WMWidgetView(panel->appChk[i]));
1457 if (WFLAGP(wwin, emulate_appicon)) {
1458 WMSetButtonEnabled(panel->appChk[1], False);
1459 WMSetButtonEnabled(panel->moreChk[7], True);
1460 } else {
1461 WMSetButtonEnabled(panel->appChk[1], True);
1462 WMSetButtonEnabled(panel->moreChk[7], False);
1464 } else {
1465 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1466 || !wwin->wm_class || !wwin->wm_instance)
1467 tmp = False;
1468 else
1469 tmp = True;
1471 WMSetButtonEnabled(panel->moreChk[7], tmp);
1473 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1474 panel->appFrm = NULL;