Update Serbian translation from master branch
[wmaker-crm.git] / src / winspector.c
blobe0d0f6e8262f8316e441d25c552971b758b5cfd6
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 its 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 { "IgnoreDecorationChanges", { .ignore_decoration_changes = 1 }, N_("Ignore decoration changes"),
162 N_("Ignore any request from the application to change\n"
163 "window decorations (like hiding the titlebar).\n") }
165 #ifdef XKB_BUTTON_HINT
166 ,{ "NoLanguageButton", { .no_language_button = 1 }, N_("Disable language button"),
167 N_("Remove the `toggle language' button of the window.") }
168 #endif
170 }, application_attr[] = {
171 { "StartHidden", { .start_hidden = 1 }, N_("Start hidden"),
172 N_("Automatically hide application when it's started.") },
174 { "NoAppIcon", { .no_appicon = 1 }, N_("No application icon"),
175 N_("Disable the application icon for the application.\n"
176 "Note that you won't be able to dock it anymore,\n"
177 "and any icons that are already docked will stop\n"
178 "working correctly.") },
180 { "SharedAppIcon", { .shared_appicon = 1 }, N_("Shared application icon"),
181 N_("Use a single shared application icon for all of\n"
182 "the instances of this application.\n") }
185 typedef struct InspectorPanel {
186 struct InspectorPanel *nextPtr;
188 WWindow *frame;
189 WWindow *inspected; /* the window that's being inspected */
190 WMWindow *win;
191 Window parent;
193 /* common stuff */
194 WMButton *revertBtn;
195 WMButton *applyBtn;
196 WMButton *saveBtn;
197 WMPopUpButton *pagePopUp;
199 /* first page. general stuff */
200 WMFrame *specFrm;
201 WMButton *instRb;
202 WMButton *clsRb;
203 WMButton *bothRb;
204 WMButton *defaultRb;
205 WMButton *selWinB;
206 WMLabel *specLbl;
208 /* second page. attributes */
209 WMFrame *attrFrm;
210 WMButton *attrChk[sizeof(window_attribute) / sizeof(window_attribute[0])];
212 /* 3rd page. more attributes */
213 WMFrame *moreFrm;
214 WMButton *moreChk[sizeof(advanced_option) / sizeof(advanced_option[0])];
216 /* 4th page. icon and workspace */
217 WMFrame *iconFrm;
218 WMLabel *iconLbl;
219 WMLabel *fileLbl;
220 WMTextField *fileText;
221 WMButton *alwChk;
222 WMButton *browseIconBtn;
223 WMFrame *wsFrm;
224 WMPopUpButton *wsP;
226 /* 5th page. application wide attributes */
227 WMFrame *appFrm;
228 WMButton *appChk[sizeof(application_attr) / sizeof(application_attr[0])];
230 unsigned int done:1;
231 unsigned int destroyed:1;
232 unsigned int choosingIcon:1;
233 } InspectorPanel;
235 static InspectorPanel *panelList = NULL;
238 * We are supposed to use the 'key_name' from the the 'window_attribute' structure when we want to
239 * save the user choice to the database, but as we will need to convert that name into a Property
240 * List, we use here a Cache of Property Lists, generated only once, which can be reused. It will
241 * also save on memory because of the re-use of the same storage space instead of allocating a new
242 * one every time.
244 static WMPropList *pl_attribute[sizeof(window_attribute) / sizeof(window_attribute[0])] = { [0] = NULL };
245 static WMPropList *pl_advoptions[sizeof(advanced_option) / sizeof(advanced_option[0])];
246 static WMPropList *pl_appattrib[sizeof(application_attr) / sizeof(application_attr[0])];
248 static WMPropList *AAlwaysUserIcon;
249 static WMPropList *AStartWorkspace;
250 static WMPropList *AIcon;
252 /* application wide options */
253 static WMPropList *AnyWindow;
254 static WMPropList *EmptyString;
255 static WMPropList *Yes, *No;
257 static char *spec_text;
258 static void applySettings(WMWidget *button, void *panel);
260 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel);
262 static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width);
263 static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width);
264 static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel);
265 static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width);
268 * These 3 functions sets/clear/read a bit inside a bit-field in a generic manner;
269 * they uses binary operators to be as effiscient as possible, also counting on compiler's
270 * optimisations because the bit-field structure will fit in only 1 or 2 int but it is
271 * depending on the processor architecture.
273 static inline void set_attr_flag(WWindowAttributes *target, const WWindowAttributes *flag)
275 int i;
276 const unsigned char *src;
277 unsigned char *dst;
279 src = (const unsigned char *) flag;
280 dst = (unsigned char *) target;
282 for (i = 0; i < sizeof(*flag); i++)
283 dst[i] |= src[i];
286 static inline void clear_attr_flag(WWindowAttributes *target, const WWindowAttributes *flag)
288 int i;
289 const unsigned char *src;
290 unsigned char *dst;
292 src = (const unsigned char *) flag;
293 dst = (unsigned char *) target;
295 for (i = 0; i < sizeof(*flag); i++)
296 dst[i] &= ~src[i];
299 static inline int get_attr_flag(const WWindowAttributes *from, const WWindowAttributes *flag)
301 int i;
302 const unsigned char *xpect, *field;
304 field = (const unsigned char *) from;
305 xpect = (const unsigned char *) flag;
307 for (i = 0; i < sizeof(*flag); i++)
308 if (field[i] & xpect[i])
309 return 1;
311 return 0;
315 * This function is creating the Property List for the cache mentionned above
317 static void make_keys(void)
319 int i;
321 if (pl_attribute[0] != NULL)
322 return;
324 for (i = 0; i < wlengthof(window_attribute); i++)
325 pl_attribute[i] = WMCreatePLString(window_attribute[i].key_name);
327 for (i = 0; i < wlengthof(advanced_option); i++)
328 pl_advoptions[i] = WMCreatePLString(advanced_option[i].key_name);
330 for (i = 0; i < wlengthof(application_attr); i++)
331 pl_appattrib[i] = WMCreatePLString(application_attr[i].key_name);
333 AIcon = WMCreatePLString("Icon");
334 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
336 AStartWorkspace = WMCreatePLString("StartWorkspace");
338 AnyWindow = WMCreatePLString("*");
339 EmptyString = WMCreatePLString("");
340 Yes = WMCreatePLString("Yes");
341 No = WMCreatePLString("No");
344 static void freeInspector(InspectorPanel *panel)
346 panel->destroyed = 1;
348 if (panel->choosingIcon)
349 return;
351 WMDestroyWidget(panel->win);
352 XDestroyWindow(dpy, panel->parent);
353 wfree(panel);
356 static void destroyInspector(WCoreWindow *foo, void *data, XEvent *event)
358 InspectorPanel *panel, *tmp;
360 /* Parameter not used, but tell the compiler that it is ok */
361 (void) foo;
362 (void) event;
364 panel = panelList;
365 while (panel->frame != data)
366 panel = panel->nextPtr;
368 if (panelList == panel) {
369 panelList = panel->nextPtr;
370 } else {
371 tmp = panelList;
372 while (tmp->nextPtr != panel)
373 tmp = tmp->nextPtr;
375 tmp->nextPtr = panel->nextPtr;
377 panel->inspected->flags.inspector_open = 0;
378 panel->inspected->inspector = NULL;
380 WMRemoveNotificationObserver(panel);
382 wWindowUnmap(panel->frame);
383 wUnmanageWindow(panel->frame, True, False);
385 freeInspector(panel);
388 void wDestroyInspectorPanels(void)
390 InspectorPanel *panel;
392 while (panelList != NULL) {
393 panel = panelList;
394 panelList = panelList->nextPtr;
395 wUnmanageWindow(panel->frame, False, False);
396 WMDestroyWidget(panel->win);
398 panel->inspected->flags.inspector_open = 0;
399 panel->inspected->inspector = NULL;
401 wfree(panel);
405 static void changePage(WMWidget *bPtr, void *client_data)
407 InspectorPanel *panel = (InspectorPanel *) client_data;
408 int page;
410 page = WMGetPopUpButtonSelectedItem(bPtr);
412 if (page == 0) {
413 WMMapWidget(panel->specFrm);
414 WMMapWidget(panel->specLbl);
415 } else if (page == 1) {
416 WMMapWidget(panel->attrFrm);
417 } else if (page == 2) {
418 WMMapWidget(panel->moreFrm);
419 } else if (page == 3) {
420 WMMapWidget(panel->iconFrm);
421 WMMapWidget(panel->wsFrm);
422 } else {
423 WMMapWidget(panel->appFrm);
426 if (page != 0) {
427 WMUnmapWidget(panel->specFrm);
428 WMUnmapWidget(panel->specLbl);
430 if (page != 1)
431 WMUnmapWidget(panel->attrFrm);
432 if (page != 2)
433 WMUnmapWidget(panel->moreFrm);
434 if (page != 3) {
435 WMUnmapWidget(panel->iconFrm);
436 WMUnmapWidget(panel->wsFrm);
438 if (page != 4 && panel->appFrm)
439 WMUnmapWidget(panel->appFrm);
442 static int showIconFor(WMScreen *scrPtr, InspectorPanel *panel, const char *wm_instance, const char *wm_class, int flags)
444 WMPixmap *pixmap = (WMPixmap *) NULL;
445 char *file = NULL, *path = NULL;
447 if ((flags & USE_TEXT_FIELD) != 0) {
448 file = WMGetTextFieldText(panel->fileText);
449 if (file && file[0] == 0) {
450 wfree(file);
451 file = NULL;
453 } else if (flags & REVERT_TO_DEFAULT) {
454 const char *db_icon;
456 /* Get the application icon, default NOT included */
457 db_icon = wDefaultGetIconFile(wm_instance, wm_class, False);
458 if (db_icon != NULL) {
459 file = wstrdup(db_icon);
460 flags |= UPDATE_TEXT_FIELD;
464 if ((flags & UPDATE_TEXT_FIELD) != 0)
465 WMSetTextFieldText(panel->fileText, file);
467 if (file) {
468 path = FindImage(wPreferences.icon_path, file);
470 if (!path) {
471 char *buf;
472 int len = strlen(file) + 80;
474 buf = wmalloc(len);
475 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"), file);
476 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
477 wfree(buf);
478 wfree(file);
479 return -1;
482 pixmap = WMCreatePixmapFromFile(scrPtr, path);
483 wfree(path);
485 if (!pixmap) {
486 char *buf;
487 int len = strlen(file) + 80;
489 buf = wmalloc(len);
490 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
491 file, RMessageForError(RErrorCode));
492 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
493 wfree(buf);
494 wfree(file);
495 return -1;
497 wfree(file);
500 WMSetLabelImage(panel->iconLbl, pixmap);
501 if (pixmap)
502 WMReleasePixmap(pixmap);
504 return 0;
507 static int getBool(WMPropList *value)
509 char *val;
511 if (!WMIsPLString(value))
512 return 0;
514 val = WMGetFromPLString(value);
515 if (val == NULL)
516 return 0;
518 if ((val[1] == '\0' &&
519 (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' ||
520 val[0] == 't' || val[0] == '1')) ||
521 (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
522 return 1;
523 } else if ((val[1] == '\0' &&
524 (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' ||
525 val[0] == 'f' || val[0] == '0')) ||
526 (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
527 return 0;
528 } else {
529 wwarning(_("can't convert \"%s\" to boolean"), val);
530 return 0;
534 /* Will insert the attribute = value; pair in window's list,
535 * if it's different from the defaults.
536 * Defaults means either defaults database, or attributes saved
537 * for the default window "*". This is to let one revert options that are
538 * global because they were saved for all windows ("*"). */
539 static int
540 insertAttribute(WMPropList *dict, WMPropList *window, WMPropList *attr, WMPropList *value, int flags)
542 WMPropList *def_win, *def_value = NULL;
543 int update = 0, modified = 0;
545 if (!(flags & UPDATE_DEFAULTS) && dict) {
546 def_win = WMGetFromPLDictionary(dict, AnyWindow);
547 if (def_win != NULL)
548 def_value = WMGetFromPLDictionary(def_win, attr);
551 /* If we could not find defaults in database, fall to hardcoded values.
552 * Also this is true if we save defaults for all windows */
553 if (!def_value)
554 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
556 if (flags & IS_BOOLEAN)
557 update = (getBool(value) != getBool(def_value));
558 else
559 update = !WMIsPropListEqualTo(value, def_value);
561 if (update) {
562 WMPutInPLDictionary(window, attr, value);
563 modified = 1;
566 return modified;
569 static void saveSettings(WMWidget *button, void *client_data)
571 InspectorPanel *panel = (InspectorPanel *) client_data;
572 WWindow *wwin = panel->inspected;
573 WDDomain *db = w_global.domain.window_attr;
574 WMPropList *dict = NULL;
575 WMPropList *winDic, *appDic, *value, *value1, *key = NULL, *key2;
576 char *icon_file, *buf1, *buf2;
577 int flags = 0, i = 0, different = 0, different2 = 0;
579 /* Save will apply the changes and save them */
580 applySettings(panel->applyBtn, panel);
582 if (WMGetButtonSelected(panel->instRb) != 0) {
583 key = WMCreatePLString(wwin->wm_instance);
584 } else if (WMGetButtonSelected(panel->clsRb) != 0) {
585 key = WMCreatePLString(wwin->wm_class);
586 } else if (WMGetButtonSelected(panel->bothRb) != 0) {
587 buf1 = StrConcatDot(wwin->wm_instance, wwin->wm_class);
588 key = WMCreatePLString(buf1);
589 wfree(buf1);
590 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
591 key = WMRetainPropList(AnyWindow);
592 flags = UPDATE_DEFAULTS;
595 if (!key)
596 return;
598 dict = db->dictionary;
599 if (!dict) {
600 dict = WMCreatePLDictionary(NULL, NULL);
601 if (dict) {
602 db->dictionary = dict;
603 } else {
604 WMReleasePropList(key);
605 return;
609 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD) < 0)
610 return;
612 WMPLSetCaseSensitive(True);
614 winDic = WMCreatePLDictionary(NULL, NULL);
615 appDic = WMCreatePLDictionary(NULL, NULL);
617 /* Save the icon info */
618 /* The flag "Ignore client suplied icon is not selected" */
619 buf1 = wmalloc(4);
620 snprintf(buf1, 4, "%s", (WMGetButtonSelected(panel->alwChk) != 0) ? "Yes" : "No");
621 value1 = WMCreatePLString(buf1);
622 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value1, flags);
623 WMReleasePropList(value1);
624 wfree(buf1);
626 /* The icon filename (if exists) */
627 icon_file = WMGetTextFieldText(panel->fileText);
628 if (icon_file != NULL) {
629 if (icon_file[0] != '\0') {
630 value = WMCreatePLString(icon_file);
631 different |= insertAttribute(dict, winDic, AIcon, value, flags);
632 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
633 WMReleasePropList(value);
635 wfree(icon_file);
638 i = WMGetPopUpButtonSelectedItem(panel->wsP) - 1;
639 if (i >= 0 && i < panel->frame->screen_ptr->workspace_count) {
640 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
641 different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
642 WMReleasePropList(value);
645 flags |= IS_BOOLEAN;
647 /* Attributes... --> Window Attributes */
648 for (i = 0; i < wlengthof(window_attribute); i++) {
649 value = (WMGetButtonSelected(panel->attrChk[i]) != 0) ? Yes : No;
650 different |= insertAttribute(dict, winDic, pl_attribute[i], value, flags);
653 /* Attributes... --> Advanced Options */
654 for (i = 0; i < wlengthof(advanced_option); i++) {
655 value = (WMGetButtonSelected(panel->moreChk[i]) != 0) ? Yes : No;
656 different |= insertAttribute(dict, winDic, pl_advoptions[i], value, flags);
659 /* Attributes... --> Application Specific */
660 if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
661 for (i = 0; i < wlengthof(application_attr); i++) {
662 value = (WMGetButtonSelected(panel->appChk[i]) != 0) ? Yes : No;
663 different2 |= insertAttribute(dict, appDic, pl_appattrib[i], value, flags);
667 if (wwin->fake_group) {
668 key2 = WMCreatePLString(wwin->fake_group->identifier);
669 if (WMIsPropListEqualTo(key, key2)) {
670 WMMergePLDictionaries(winDic, appDic, True);
671 different |= different2;
672 } else {
673 WMRemoveFromPLDictionary(dict, key2);
674 if (different2)
675 WMPutInPLDictionary(dict, key2, appDic);
677 WMReleasePropList(key2);
678 } else if (wwin->main_window != wwin->client_win) {
679 WApplication *wapp = wApplicationOf(wwin->main_window);
681 if (wapp) {
682 buf2 = StrConcatDot(wapp->main_window_desc->wm_instance,
683 wapp->main_window_desc->wm_class);
684 key2 = WMCreatePLString(buf2);
685 wfree(buf2);
687 if (WMIsPropListEqualTo(key, key2)) {
688 WMMergePLDictionaries(winDic, appDic, True);
689 different |= different2;
690 } else {
691 WMRemoveFromPLDictionary(dict, key2);
692 if (different2)
693 WMPutInPLDictionary(dict, key2, appDic);
695 WMReleasePropList(key2);
697 } else {
698 WMMergePLDictionaries(winDic, appDic, True);
699 different |= different2;
701 WMReleasePropList(appDic);
703 WMRemoveFromPLDictionary(dict, key);
704 if (different)
705 WMPutInPLDictionary(dict, key, winDic);
707 WMReleasePropList(key);
708 WMReleasePropList(winDic);
710 UpdateDomainFile(db);
712 /* clean up */
713 WMPLSetCaseSensitive(False);
716 static void applySettings(WMWidget *button, void *client_data)
718 InspectorPanel *panel = (InspectorPanel *) client_data;
719 WWindow *wwin = panel->inspected;
720 WApplication *wapp = wApplicationOf(wwin->main_window);
721 int old_skip_window_list, old_omnipresent, old_no_bind_keys, old_no_bind_mouse;
722 int i;
724 old_skip_window_list = WFLAGP(wwin, skip_window_list);
725 old_omnipresent = WFLAGP(wwin, omnipresent);
726 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
727 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
729 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
731 /* Attributes... --> Window Attributes */
732 for (i = 0; i < wlengthof(window_attribute); i++) {
733 if (WMGetButtonSelected(panel->attrChk[i]))
734 set_attr_flag(&wwin->user_flags, &window_attribute[i].flag);
735 else
736 clear_attr_flag(&wwin->user_flags, &window_attribute[i].flag);
738 set_attr_flag(&wwin->defined_user_flags, &window_attribute[i].flag);
741 /* Attributes... --> Advanced Options */
742 for (i = 0; i < wlengthof(advanced_option); i++) {
743 if (WMGetButtonSelected(panel->moreChk[i]))
744 set_attr_flag(&wwin->user_flags, &advanced_option[i].flag);
745 else
746 clear_attr_flag(&wwin->user_flags, &advanced_option[i].flag);
748 set_attr_flag(&wwin->defined_user_flags, &advanced_option[i].flag);
751 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
753 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
754 wUnshadeWindow(wwin);
756 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
759 * Update the window level according to AlwaysOnTop/AlwaysOnBotton
760 * if the level did not change, ChangeStackingLevel will do nothing anyway
762 if (WFLAGP(wwin, floating))
763 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
764 else if (WFLAGP(wwin, sunken))
765 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
766 else
767 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
769 wwin->flags.omnipresent = 0;
771 if (WFLAGP(wwin, skip_window_list) != old_skip_window_list) {
772 UpdateSwitchMenu(wwin->screen_ptr, wwin, WFLAGP(wwin, skip_window_list)?ACTION_REMOVE:ACTION_ADD);
773 } else {
774 if (WFLAGP(wwin, omnipresent) != old_omnipresent)
775 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
778 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
779 if (WFLAGP(wwin, no_bind_keys))
780 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
781 else
782 wWindowSetKeyGrabs(wwin);
785 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse)
786 wWindowResetMouseGrabs(wwin);
788 wwin->frame->flags.need_texture_change = 1;
789 wWindowConfigureBorders(wwin);
790 wFrameWindowPaint(wwin->frame);
791 wNETWMUpdateActions(wwin, False);
793 /* Can't apply emulate_appicon because it will probably cause problems. */
794 if (wapp) {
795 /* do application wide stuff */
796 for (i = 0; i < wlengthof(application_attr); i++) {
797 if (WMGetButtonSelected(panel->appChk[i]))
798 set_attr_flag(&wapp->main_window_desc->user_flags, &application_attr[i].flag);
799 else
800 clear_attr_flag(&wapp->main_window_desc->user_flags, &application_attr[i].flag);
802 set_attr_flag(&wapp->main_window_desc->defined_user_flags, &application_attr[i].flag);
805 if (WFLAGP(wapp->main_window_desc, no_appicon))
806 unpaint_app_icon(wapp);
807 else
808 paint_app_icon(wapp);
810 char *file = WMGetTextFieldText(panel->fileText);
811 if (file[0] == 0) {
812 wfree(file);
813 file = NULL;
816 /* If always_user_icon flag is set, but the user icon is not set
817 * we use client supplied icon and we unset the flag */
818 if ((WFLAGP(wwin, always_user_icon) && (!file))) {
819 /* Show the warning */
820 char *buf;
821 int len = 100;
823 buf = wmalloc(len);
824 snprintf(buf, len, _("Ignore client supplied icon is set, but icon filename textbox is empty. Using client supplied icon"));
825 wMessageDialog(panel->frame->screen_ptr, _("Warning"), buf, _("OK"), NULL, NULL);
826 wfree(buf);
827 wfree(file);
829 /* Change the flags */
830 WSETUFLAG(wwin, always_user_icon, 0);
831 WMSetButtonSelected(panel->alwChk, 0);
834 /* After test the always_user_icon flag value before,
835 * the "else" block is used only if the flag is set and
836 * the icon text box has an icon path */
837 if (!WFLAGP(wwin, always_user_icon)) {
838 /* Change App Icon image, using the icon provided by the client */
839 if (wapp->app_icon) {
840 RImage *image = get_rimage_icon_from_wm_hints(wapp->app_icon->icon);
841 if (image) {
842 set_icon_image_from_image(wapp->app_icon->icon, image);
843 update_icon_pixmap(wapp->app_icon->icon);
844 } else {
845 wIconUpdate(wapp->app_icon->icon);
849 /* Change icon image if the app is minimized,
850 * using the icon provided by the client */
851 if (wwin->icon) {
852 RImage *image = get_rimage_icon_from_wm_hints(wwin->icon);
853 if (image) {
854 set_icon_image_from_image(wwin->icon, image);
855 update_icon_pixmap(wwin->icon);
856 } else {
857 wIconUpdate(wwin->icon);
860 } else {
861 /* Change App Icon image */
862 if (wapp->app_icon)
863 wIconChangeImageFile(wapp->app_icon->icon, file);
865 /* Change icon image if the app is minimized */
866 if (wwin->icon)
867 wIconChangeImageFile(wwin->icon, file);
870 if (file)
871 wfree(file);
874 wNETFrameExtents(wwin);
877 static void revertSettings(WMWidget *button, void *client_data)
879 InspectorPanel *panel = (InspectorPanel *) client_data;
880 WWindow *wwin = panel->inspected;
881 WApplication *wapp = wApplicationOf(wwin->main_window);
882 int i, n, workspace, level;
883 char *wm_instance = NULL, *wm_class = NULL;
885 /* Parameter not used, but tell the compiler that it is ok */
886 (void) button;
888 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
889 wm_instance = wwin->wm_instance;
890 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
891 wm_class = wwin->wm_class;
892 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
893 wm_instance = wwin->wm_instance;
894 wm_class = wwin->wm_class;
897 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
898 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
899 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
901 wWindowSetupInitialAttributes(wwin, &level, &workspace);
903 /* Attributes... --> Window Attributes */
904 for (i = 0; i < wlengthof(window_attribute); i++) {
905 int is_userdef, flag;
907 is_userdef = get_attr_flag(&wwin->defined_user_flags, &window_attribute[i].flag);
908 if (is_userdef)
909 flag = get_attr_flag(&wwin->user_flags, &window_attribute[i].flag);
910 else
911 flag = get_attr_flag(&wwin->client_flags, &window_attribute[i].flag);
913 WMSetButtonSelected(panel->attrChk[i], flag);
916 /* Attributes... --> Advanced Options */
917 for (i = 0; i < wlengthof(advanced_option); i++) {
918 int is_userdef, flag;
920 is_userdef = get_attr_flag(&wwin->defined_user_flags, &advanced_option[i].flag);
921 if (is_userdef)
922 flag = get_attr_flag(&wwin->user_flags, &advanced_option[i].flag);
923 else
924 flag = get_attr_flag(&wwin->client_flags, &advanced_option[i].flag);
926 WMSetButtonSelected(panel->moreChk[i], flag);
929 /* Attributes... --> Application Specific */
930 if (panel->appFrm && wapp) {
931 for (i = 0; i < wlengthof(application_attr); i++) {
932 int is_userdef, flag = 0;
934 is_userdef = get_attr_flag(&wapp->main_window_desc->defined_user_flags, &application_attr[i].flag);
935 if (is_userdef)
936 flag = get_attr_flag(&wapp->main_window_desc->user_flags, &application_attr[i].flag);
937 else
938 flag = get_attr_flag(&wapp->main_window_desc->client_flags, &application_attr[i].flag);
940 WMSetButtonSelected(panel->appChk[i], flag);
943 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
945 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
947 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
949 if (n >= 0 && n < wwin->screen_ptr->workspace_count)
950 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
951 else
952 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
954 /* must auto apply, so that there wno't be internal
955 * inconsistencies between the state in the flags and
956 * the actual state of the window */
957 applySettings(panel->applyBtn, panel);
960 static void chooseIconCallback(WMWidget *self, void *clientData)
962 char *file;
963 InspectorPanel *panel = (InspectorPanel *) clientData;
964 int result;
966 panel->choosingIcon = 1;
968 WMSetButtonEnabled(panel->browseIconBtn, False);
970 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
971 panel->inspected->wm_instance,
972 panel->inspected->wm_class);
974 panel->choosingIcon = 0;
976 if (!panel->destroyed) { /* kluge */
977 if (result) {
978 WMSetTextFieldText(panel->fileText, file);
979 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
981 WMSetButtonEnabled(panel->browseIconBtn, True);
982 } else {
983 freeInspector(panel);
985 if (result)
986 wfree(file);
989 static void textEditedObserver(void *observerData, WMNotification *notification)
991 InspectorPanel *panel = (InspectorPanel *) observerData;
993 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
994 return;
996 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
999 static void selectSpecification(WMWidget *bPtr, void *data)
1001 InspectorPanel *panel = (InspectorPanel *) data;
1002 char str[256];
1003 WWindow *wwin = panel->inspected;
1005 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class))
1006 WMSetButtonEnabled(panel->applyBtn, False);
1007 else
1008 WMSetButtonEnabled(panel->applyBtn, True);
1010 snprintf(str, sizeof(str),
1011 _("Inspecting %s.%s"),
1012 wwin->wm_instance ? wwin->wm_instance : "?",
1013 wwin->wm_class ? wwin->wm_class : "?");
1015 wFrameWindowChangeTitle(panel->frame->frame, str);
1018 static void selectWindow(WMWidget *bPtr, void *data)
1020 InspectorPanel *panel = (InspectorPanel *) data;
1021 WWindow *wwin = panel->inspected;
1022 WScreen *scr = wwin->screen_ptr;
1023 XEvent event;
1024 WWindow *iwin;
1026 /* Parameter not used, but tell the compiler that it is ok */
1027 (void) bPtr;
1029 if (XGrabPointer(dpy, scr->root_win, True,
1030 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1031 wPreferences.cursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
1032 wwarning("could not grab mouse pointer");
1033 return;
1036 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1037 WMMaskEvent(dpy, ButtonPressMask, &event);
1038 XUngrabPointer(dpy, CurrentTime);
1040 iwin = wWindowFor(event.xbutton.subwindow);
1041 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
1042 iwin->flags.inspector_open = 1;
1043 iwin->inspector = createInspectorForWindow(iwin,
1044 panel->frame->frame_x, panel->frame->frame_y, True);
1045 wCloseInspectorForWindow(wwin);
1046 } else {
1047 WMSetLabelText(panel->specLbl, spec_text);
1051 static InspectorPanel *createInspectorForWindow(WWindow *wwin, int xpos, int ypos, Bool showSelectPanel)
1053 WScreen *scr = wwin->screen_ptr;
1054 InspectorPanel *panel;
1055 Window parent;
1056 char *str = NULL, *tmp = NULL;
1057 int x, y, btn_width, frame_width;
1058 WMButton *selectedBtn = NULL;
1060 spec_text = _("The configuration will apply to all\n"
1061 "windows that have their WM_CLASS\n"
1062 "property set to the above selected\n" "name, when saved.");
1064 panel = wmalloc(sizeof(InspectorPanel));
1065 memset(panel, 0, sizeof(InspectorPanel));
1067 panel->destroyed = 0;
1068 panel->inspected = wwin;
1069 panel->nextPtr = panelList;
1070 panelList = panel;
1071 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1072 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1074 /**** create common stuff ****/
1075 /* command buttons */
1076 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1077 panel->saveBtn = WMCreateCommandButton(panel->win);
1078 WMSetButtonAction(panel->saveBtn, saveSettings, panel);
1079 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, PHEIGHT - 40);
1080 WMSetButtonText(panel->saveBtn, _("Save"));
1081 WMResizeWidget(panel->saveBtn, btn_width, 28);
1082 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1083 WMSetButtonEnabled(panel->saveBtn, False);
1085 panel->applyBtn = WMCreateCommandButton(panel->win);
1086 WMSetButtonAction(panel->applyBtn, applySettings, panel);
1087 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, PHEIGHT - 40);
1088 WMSetButtonText(panel->applyBtn, _("Apply"));
1089 WMResizeWidget(panel->applyBtn, btn_width, 28);
1091 panel->revertBtn = WMCreateCommandButton(panel->win);
1092 WMSetButtonAction(panel->revertBtn, revertSettings, panel);
1093 WMMoveWidget(panel->revertBtn, 15, PHEIGHT - 40);
1094 WMSetButtonText(panel->revertBtn, _("Reload"));
1095 WMResizeWidget(panel->revertBtn, btn_width, 28);
1097 /* page selection popup button */
1098 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1099 WMSetPopUpButtonAction(panel->pagePopUp, changePage, panel);
1100 WMMoveWidget(panel->pagePopUp, 25, 15);
1101 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1103 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1104 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1105 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1106 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1107 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1109 /**** window spec ****/
1110 frame_width = PWIDTH - (2 * 15);
1112 panel->specFrm = WMCreateFrame(panel->win);
1113 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1114 WMMoveWidget(panel->specFrm, 15, 65);
1115 WMResizeWidget(panel->specFrm, frame_width, 145);
1117 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1118 WMMoveWidget(panel->defaultRb, 10, 78);
1119 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1120 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1121 WMSetButtonSelected(panel->defaultRb, False);
1122 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1124 if (wwin->wm_class && wwin->wm_instance) {
1125 tmp = wstrconcat(wwin->wm_instance, ".");
1126 str = wstrconcat(tmp, wwin->wm_class);
1128 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1129 WMMoveWidget(panel->bothRb, 10, 18);
1130 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1131 WMSetButtonText(panel->bothRb, str);
1132 wfree(tmp);
1133 wfree(str);
1134 WMGroupButtons(panel->defaultRb, panel->bothRb);
1136 if (!selectedBtn)
1137 selectedBtn = panel->bothRb;
1139 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1142 if (wwin->wm_instance) {
1143 panel->instRb = WMCreateRadioButton(panel->specFrm);
1144 WMMoveWidget(panel->instRb, 10, 38);
1145 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1146 WMSetButtonText(panel->instRb, wwin->wm_instance);
1147 WMGroupButtons(panel->defaultRb, panel->instRb);
1149 if (!selectedBtn)
1150 selectedBtn = panel->instRb;
1152 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1155 if (wwin->wm_class) {
1156 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1157 WMMoveWidget(panel->clsRb, 10, 58);
1158 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1159 WMSetButtonText(panel->clsRb, wwin->wm_class);
1160 WMGroupButtons(panel->defaultRb, panel->clsRb);
1162 if (!selectedBtn)
1163 selectedBtn = panel->clsRb;
1165 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1168 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1169 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1170 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1171 WMSetButtonText(panel->selWinB, _("Select window"));
1172 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1174 panel->specLbl = WMCreateLabel(panel->win);
1175 WMMoveWidget(panel->specLbl, 15, 210);
1176 WMResizeWidget(panel->specLbl, frame_width, 100);
1177 WMSetLabelText(panel->specLbl, spec_text);
1178 WMSetLabelWraps(panel->specLbl, True);
1180 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1182 /**** attributes ****/
1183 create_tab_window_attributes(wwin, panel, frame_width);
1184 create_tab_window_advanced(wwin, panel, frame_width);
1185 create_tab_icon_workspace(wwin, panel);
1186 create_tab_app_specific(wwin, panel, frame_width);
1188 /* if the window is a transient, don't let it have a miniaturize button */
1189 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1190 WMSetButtonEnabled(panel->attrChk[3], False);
1191 else
1192 WMSetButtonEnabled(panel->attrChk[3], True);
1194 if (!wwin->wm_class && !wwin->wm_instance)
1195 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1197 WMRealizeWidget(panel->win);
1199 WMMapSubwidgets(panel->win);
1200 WMMapSubwidgets(panel->specFrm);
1201 WMMapSubwidgets(panel->attrFrm);
1202 WMMapSubwidgets(panel->moreFrm);
1203 WMMapSubwidgets(panel->iconFrm);
1204 WMMapSubwidgets(panel->wsFrm);
1205 if (panel->appFrm)
1206 WMMapSubwidgets(panel->appFrm);
1208 if (showSelectPanel) {
1209 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1210 changePage(panel->pagePopUp, panel);
1211 } else {
1212 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1213 changePage(panel->pagePopUp, panel);
1216 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1217 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1218 panel->parent = parent;
1219 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1221 WMMapWidget(panel->win);
1223 XSetTransientForHint(dpy, parent, wwin->client_win);
1225 if (xpos == UNDEFINED_POS) {
1226 x = wwin->frame_x + wwin->frame->core->width / 2;
1227 y = wwin->frame_y + wwin->frame->top_width * 2;
1228 if (y + PHEIGHT > scr->scr_height)
1229 y = scr->scr_height - PHEIGHT - 30;
1230 if (x + PWIDTH > scr->scr_width)
1231 x = scr->scr_width - PWIDTH;
1232 } else {
1233 x = xpos;
1234 y = ypos;
1237 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1239 if (!selectedBtn)
1240 selectedBtn = panel->defaultRb;
1242 WMSetButtonSelected(selectedBtn, True);
1243 selectSpecification(selectedBtn, panel);
1245 /* kluge to know who should get the key events */
1246 panel->frame->client_leader = WMWidgetXID(panel->win);
1248 panel->frame->client_flags.no_closable = 0;
1249 panel->frame->client_flags.no_close_button = 0;
1250 wWindowUpdateButtonImages(panel->frame);
1251 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1252 panel->frame->frame->on_click_right = destroyInspector;
1254 wWindowMap(panel->frame);
1256 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, REVERT_TO_DEFAULT);
1258 return panel;
1261 void wShowInspectorForWindow(WWindow *wwin)
1263 if (wwin->flags.inspector_open)
1264 return;
1266 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1268 make_keys();
1269 wwin->flags.inspector_open = 1;
1270 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1273 void wHideInspectorForWindow(WWindow *wwin)
1275 WWindow *pwin = wwin->inspector->frame;
1277 wWindowUnmap(pwin);
1278 pwin->flags.hidden = 1;
1280 wClientSetState(pwin, IconicState, None);
1283 void wUnhideInspectorForWindow(WWindow *wwin)
1285 WWindow *pwin = wwin->inspector->frame;
1287 pwin->flags.hidden = 0;
1288 pwin->flags.mapped = 1;
1289 XMapWindow(dpy, pwin->client_win);
1290 XMapWindow(dpy, pwin->frame->core->window);
1291 wClientSetState(pwin, NormalState, None);
1294 WWindow *wGetWindowOfInspectorForWindow(WWindow *wwin)
1296 if (!wwin->inspector)
1297 return NULL;
1299 assert(wwin->flags.inspector_open != 0);
1300 return wwin->inspector->frame;
1303 void wCloseInspectorForWindow(WWindow *wwin)
1305 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1307 (*pwin->frame->on_click_right) (NULL, pwin, NULL);
1310 static void create_tab_window_attributes(WWindow *wwin, InspectorPanel *panel, int frame_width)
1312 int i = 0;
1314 panel->attrFrm = WMCreateFrame(panel->win);
1315 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1316 WMMoveWidget(panel->attrFrm, 15, 45);
1317 WMResizeWidget(panel->attrFrm, frame_width, 250);
1319 for (i = 0; i < wlengthof(window_attribute); i++) {
1320 int is_userdef, flag;
1322 is_userdef = get_attr_flag(&wwin->defined_user_flags, &window_attribute[i].flag);
1323 if (is_userdef)
1324 flag = get_attr_flag(&wwin->user_flags, &window_attribute[i].flag);
1325 else
1326 flag = get_attr_flag(&wwin->client_flags, &window_attribute[i].flag);
1328 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1329 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1330 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1331 WMSetButtonSelected(panel->attrChk[i], flag);
1332 WMSetButtonText(panel->attrChk[i], _(window_attribute[i].caption));
1334 WMSetBalloonTextForView(_(window_attribute[i].description), WMWidgetView(panel->attrChk[i]));
1338 static void create_tab_window_advanced(WWindow *wwin, InspectorPanel *panel, int frame_width)
1340 int i = 0;
1342 panel->moreFrm = WMCreateFrame(panel->win);
1343 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1344 WMMoveWidget(panel->moreFrm, 15, 45);
1345 WMResizeWidget(panel->moreFrm, frame_width, 265);
1347 for (i = 0; i < wlengthof(advanced_option); i++) {
1348 int is_userdef, flag;
1350 is_userdef = get_attr_flag(&wwin->defined_user_flags, &advanced_option[i].flag);
1351 if (is_userdef)
1352 flag = get_attr_flag(&wwin->user_flags, &advanced_option[i].flag);
1353 else
1354 flag = get_attr_flag(&wwin->client_flags, &advanced_option[i].flag);
1356 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1357 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1) - 4);
1358 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1359 WMSetButtonSelected(panel->moreChk[i], flag);
1360 WMSetButtonText(panel->moreChk[i], _(advanced_option[i].caption));
1362 WMSetBalloonTextForView(_(advanced_option[i].description), WMWidgetView(panel->moreChk[i]));
1366 static void create_tab_icon_workspace(WWindow *wwin, InspectorPanel *panel)
1368 const char *db_icon;
1369 WScreen *scr = wwin->screen_ptr;
1370 int i = 0;
1372 /* miniwindow/workspace */
1373 panel->iconFrm = WMCreateFrame(panel->win);
1374 WMMoveWidget(panel->iconFrm, 15, 50);
1375 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1376 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1378 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1379 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1380 WMResizeWidget(panel->iconLbl, 64, 64);
1381 WMSetLabelRelief(panel->iconLbl, WRGroove);
1382 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1384 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1385 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1386 WMMoveWidget(panel->browseIconBtn, 22, 32);
1387 WMResizeWidget(panel->browseIconBtn, 120, 26);
1388 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1390 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1391 WMMoveWidget(panel->fileLbl, 20, 85);
1392 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1393 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1395 panel->fileText = WMCreateTextField(panel->iconFrm);
1396 WMMoveWidget(panel->fileText, 20, 105);
1397 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1398 db_icon = wDefaultGetIconFile(wwin->wm_instance, wwin->wm_class, False);
1399 WMSetTextFieldText(panel->fileText, db_icon);
1400 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1402 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1403 WMMoveWidget(panel->alwChk, 20, 130);
1404 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1405 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1406 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1408 panel->wsFrm = WMCreateFrame(panel->win);
1409 WMMoveWidget(panel->wsFrm, 15, 225);
1410 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1411 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1413 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1414 " first shown."), WMWidgetView(panel->wsFrm));
1416 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1417 WMMoveWidget(panel->wsP, 20, 30);
1418 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1419 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1421 for (i = 0; i < wwin->screen_ptr->workspace_count; i++)
1422 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1424 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1425 if (i >= 0 && i <= wwin->screen_ptr->workspace_count)
1426 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1427 else
1428 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1431 static void create_tab_app_specific(WWindow *wwin, InspectorPanel *panel, int frame_width)
1433 WScreen *scr = wwin->screen_ptr;
1434 int i = 0, tmp;
1436 if (wwin->main_window != None) {
1437 WApplication *wapp = wApplicationOf(wwin->main_window);
1439 panel->appFrm = WMCreateFrame(panel->win);
1440 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1441 WMMoveWidget(panel->appFrm, 15, 50);
1442 WMResizeWidget(panel->appFrm, frame_width, 240);
1444 for (i = 0; i < wlengthof(application_attr); i++) {
1445 int is_userdef, flag;
1447 is_userdef = get_attr_flag(&wapp->main_window_desc->defined_user_flags, &application_attr[i].flag);
1448 if (is_userdef)
1449 flag = get_attr_flag(&wapp->main_window_desc->user_flags, &application_attr[i].flag);
1450 else
1451 flag = get_attr_flag(&wapp->main_window_desc->client_flags, &application_attr[i].flag);
1453 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1454 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1455 WMResizeWidget(panel->appChk[i], 205, 20);
1456 WMSetButtonSelected(panel->appChk[i], flag);
1457 WMSetButtonText(panel->appChk[i], _(application_attr[i].caption));
1459 WMSetBalloonTextForView(_(application_attr[i].description),
1460 WMWidgetView(panel->appChk[i]));
1463 if (WFLAGP(wwin, emulate_appicon)) {
1464 WMSetButtonEnabled(panel->appChk[1], False);
1465 WMSetButtonEnabled(panel->moreChk[7], True);
1466 } else {
1467 WMSetButtonEnabled(panel->appChk[1], True);
1468 WMSetButtonEnabled(panel->moreChk[7], False);
1470 } else {
1471 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1472 || !wwin->wm_class || !wwin->wm_instance)
1473 tmp = False;
1474 else
1475 tmp = True;
1477 WMSetButtonEnabled(panel->moreChk[7], tmp);
1479 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1480 panel->appFrm = NULL;