Update local copy of GPLv2 and FSF address in copyrights
[wmaker-crm.git] / src / winspector.c
blobd01646ac9081b1d65b1392ff8dce04cc521ccd9c
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>
31 #include "WindowMaker.h"
32 #include "screen.h"
33 #include "wcore.h"
34 #include "framewin.h"
35 #include "window.h"
36 #include "workspace.h"
37 #include "funcs.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 "xinerama.h"
51 #include <WINGs/WUtil.h>
53 typedef struct InspectorPanel {
54 struct InspectorPanel *nextPtr;
56 WWindow *frame;
58 WWindow *inspected; /* the window that's being inspected */
60 WMWindow *win;
62 Window parent;
64 /* common stuff */
65 WMButton *revertBtn;
66 WMButton *applyBtn;
67 WMButton *saveBtn;
69 WMPopUpButton *pagePopUp;
71 /* first page. general stuff */
73 WMFrame *specFrm;
74 WMButton *instRb;
75 WMButton *clsRb;
76 WMButton *bothRb;
77 WMButton *defaultRb;
79 WMButton *selWinB;
81 WMLabel *specLbl;
83 /* second page. attributes */
85 WMFrame *attrFrm;
86 WMButton *attrChk[11];
88 /* 3rd page. more attributes */
89 WMFrame *moreFrm;
90 #ifdef XKB_BUTTON_HINT
91 WMButton *moreChk[10];
92 #else
93 WMButton *moreChk[9];
94 #endif
96 /* 4th page. icon and workspace */
97 WMFrame *iconFrm;
98 WMLabel *iconLbl;
99 WMLabel *fileLbl;
100 WMTextField *fileText;
101 WMButton *alwChk;
103 WMButton *updateIconBtn;
105 WMButton *browseIconBtn;
107 WMFrame *wsFrm;
108 WMPopUpButton *wsP;
110 /* 5th page. application wide attributes */
111 WMFrame *appFrm;
112 WMButton *appChk[3];
114 unsigned int done:1;
115 unsigned int destroyed:1;
116 unsigned int choosingIcon:1;
117 } InspectorPanel;
119 extern Cursor wCursor[WCUR_LAST];
120 extern WDDomain *WDWindowAttributes;
121 extern WPreferences wPreferences;
123 static InspectorPanel *panelList = NULL;
124 static WMPropList *ANoTitlebar = NULL;
125 static WMPropList *ANoResizebar;
126 static WMPropList *ANoMiniaturizeButton;
127 static WMPropList *ANoCloseButton;
128 static WMPropList *ANoBorder;
129 static WMPropList *ANoHideOthers;
130 static WMPropList *ANoMouseBindings;
131 static WMPropList *ANoKeyBindings;
132 static WMPropList *ANoAppIcon;
133 static WMPropList *AKeepOnTop;
134 static WMPropList *AKeepOnBottom;
135 static WMPropList *AOmnipresent;
136 static WMPropList *ASkipWindowList;
137 static WMPropList *AKeepInsideScreen;
138 static WMPropList *AUnfocusable;
139 static WMPropList *ADontFocusAcrossWorkspace;
140 static WMPropList *AAlwaysUserIcon;
141 static WMPropList *AStartMiniaturized;
142 static WMPropList *AStartMaximized;
143 static WMPropList *ADontSaveSession;
144 static WMPropList *AEmulateAppIcon;
145 static WMPropList *AFullMaximize;
146 static WMPropList *ASharedAppIcon;
147 #ifdef XKB_BUTTON_HINT
148 static WMPropList *ANoLanguageButton;
149 #endif
150 static WMPropList *AStartWorkspace;
151 static WMPropList *AIcon;
153 /* application wide options */
154 static WMPropList *AStartHidden;
155 static WMPropList *AnyWindow;
156 static WMPropList *EmptyString;
157 static WMPropList *Yes, *No;
159 #define PWIDTH 270
160 #define PHEIGHT 350
162 static char *spec_text;
163 static void applySettings(WMButton * button, InspectorPanel * panel);
165 #define UNDEFINED_POS 0xffffff
167 static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel);
169 static void make_keys(void)
171 if (ANoTitlebar != NULL)
172 return;
174 AIcon = WMCreatePLString("Icon");
175 ANoTitlebar = WMCreatePLString("NoTitlebar");
176 ANoResizebar = WMCreatePLString("NoResizebar");
177 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
178 ANoCloseButton = WMCreatePLString("NoCloseButton");
179 ANoBorder = WMCreatePLString("NoBorder");
180 ANoHideOthers = WMCreatePLString("NoHideOthers");
181 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
182 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
183 ANoAppIcon = WMCreatePLString("NoAppIcon");
184 AKeepOnTop = WMCreatePLString("KeepOnTop");
185 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
186 AOmnipresent = WMCreatePLString("Omnipresent");
187 ASkipWindowList = WMCreatePLString("SkipWindowList");
188 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
189 AUnfocusable = WMCreatePLString("Unfocusable");
190 ADontFocusAcrossWorkspace = WMCreatePLString("DontFocusAcrossWorkspace");
191 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
192 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
193 AStartMaximized = WMCreatePLString("StartMaximized");
194 AStartHidden = WMCreatePLString("StartHidden");
195 ADontSaveSession = WMCreatePLString("DontSaveSession");
196 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
197 AFullMaximize = WMCreatePLString("FullMaximize");
198 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
199 #ifdef XKB_BUTTON_HINT
200 ANoLanguageButton = WMCreatePLString("NoLanguageButton");
201 #endif
203 AStartWorkspace = WMCreatePLString("StartWorkspace");
205 AnyWindow = WMCreatePLString("*");
206 EmptyString = WMCreatePLString("");
207 Yes = WMCreatePLString("Yes");
208 No = WMCreatePLString("No");
211 static void freeInspector(InspectorPanel * panel)
213 panel->destroyed = 1;
214 if (panel->choosingIcon)
215 return;
217 WMDestroyWidget(panel->win);
219 XDestroyWindow(dpy, panel->parent);
221 wfree(panel);
224 static void destroyInspector(WCoreWindow * foo, void *data, XEvent * event)
226 InspectorPanel *panel;
227 InspectorPanel *tmp;
229 panel = panelList;
230 while (panel->frame != data)
231 panel = panel->nextPtr;
233 if (panelList == panel)
234 panelList = panel->nextPtr;
235 else {
236 tmp = panelList;
237 while (tmp->nextPtr != panel) {
238 tmp = tmp->nextPtr;
240 tmp->nextPtr = panel->nextPtr;
242 panel->inspected->flags.inspector_open = 0;
243 panel->inspected->inspector = NULL;
245 WMRemoveNotificationObserver(panel);
247 wWindowUnmap(panel->frame);
248 wUnmanageWindow(panel->frame, True, False);
250 freeInspector(panel);
253 void wDestroyInspectorPanels(void)
255 InspectorPanel *panel;
257 while (panelList != NULL) {
258 panel = panelList;
259 panelList = panelList->nextPtr;
260 wUnmanageWindow(panel->frame, False, False);
261 WMDestroyWidget(panel->win);
263 panel->inspected->flags.inspector_open = 0;
264 panel->inspected->inspector = NULL;
266 wfree(panel);
270 static void changePage(WMPopUpButton * bPtr, InspectorPanel * panel)
272 int page;
274 page = WMGetPopUpButtonSelectedItem(bPtr);
276 if (page == 0) {
277 WMMapWidget(panel->specFrm);
278 WMMapWidget(panel->specLbl);
279 } else if (page == 1) {
280 WMMapWidget(panel->attrFrm);
281 } else if (page == 2) {
282 WMMapWidget(panel->moreFrm);
283 } else if (page == 3) {
284 WMMapWidget(panel->iconFrm);
285 WMMapWidget(panel->wsFrm);
286 } else {
287 WMMapWidget(panel->appFrm);
290 if (page != 0) {
291 WMUnmapWidget(panel->specFrm);
292 WMUnmapWidget(panel->specLbl);
294 if (page != 1)
295 WMUnmapWidget(panel->attrFrm);
296 if (page != 2)
297 WMUnmapWidget(panel->moreFrm);
298 if (page != 3) {
299 WMUnmapWidget(panel->iconFrm);
300 WMUnmapWidget(panel->wsFrm);
302 if (page != 4 && panel->appFrm)
303 WMUnmapWidget(panel->appFrm);
306 #define USE_TEXT_FIELD 1
307 #define UPDATE_TEXT_FIELD 2
308 #define REVERT_TO_DEFAULT 4
310 static int showIconFor(WMScreen * scrPtr, InspectorPanel * panel, char *wm_instance, char *wm_class, int flags)
312 WMPixmap *pixmap = (WMPixmap *) NULL;
313 char *file = NULL, *path = NULL;
314 char *db_icon = NULL;
316 if ((flags & USE_TEXT_FIELD) != 0) {
317 file = WMGetTextFieldText(panel->fileText);
318 if (file && file[0] == 0) {
319 wfree(file);
320 file = NULL;
322 } else {
323 db_icon = wDefaultGetIconFile(panel->inspected->screen_ptr, wm_instance, wm_class, False);
324 if (db_icon != NULL)
325 file = wstrdup(db_icon);
327 if (db_icon != NULL && (flags & REVERT_TO_DEFAULT) != 0) {
328 if (file)
329 file = wstrdup(db_icon);
330 flags |= UPDATE_TEXT_FIELD;
333 if ((flags & UPDATE_TEXT_FIELD) != 0) {
334 WMSetTextFieldText(panel->fileText, file);
337 if (file) {
338 path = FindImage(wPreferences.icon_path, file);
340 if (!path) {
341 char *buf;
342 int len = strlen(file) + 80;
344 buf = wmalloc(len);
345 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"), file);
346 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
347 wfree(buf);
348 wfree(file);
349 return -1;
352 pixmap = WMCreatePixmapFromFile(scrPtr, path);
353 wfree(path);
355 if (!pixmap) {
356 char *buf;
357 int len = strlen(file) + 80;
359 buf = wmalloc(len);
360 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
361 file, RMessageForError(RErrorCode));
362 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
363 wfree(buf);
364 wfree(file);
365 return -1;
367 wfree(file);
370 WMSetLabelImage(panel->iconLbl, pixmap);
371 if (pixmap)
372 WMReleasePixmap(pixmap);
374 return 0;
377 #if 0
378 static void updateIcon(WMButton * button, InspectorPanel * panel)
380 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
382 #endif
384 static int getBool(WMPropList * value)
386 char *val;
388 if (!WMIsPLString(value)) {
389 return 0;
391 if (!(val = WMGetFromPLString(value))) {
392 return 0;
395 if ((val[1] == '\0' && (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' || val[0] == 't' || val[0] == '1'))
396 || (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
398 return 1;
399 } else if ((val[1] == '\0'
400 && (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' || val[0] == 'f' || val[0] == '0'))
401 || (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
403 return 0;
404 } else {
405 wwarning(_("can't convert \"%s\" to boolean"), val);
406 return 0;
410 #define UPDATE_DEFAULTS 1
411 #define IS_BOOLEAN 2
414 * Will insert the attribute = value; pair in window's list,
415 * if it's different from the defaults.
416 * Defaults means either defaults database, or attributes saved
417 * for the default window "*". This is to let one revert options that are
418 * global because they were saved for all windows ("*").
422 static int
423 insertAttribute(WMPropList * dict, WMPropList * window, WMPropList * attr, WMPropList * value, int flags)
425 WMPropList *def_win, *def_value = NULL;
426 int update = 0;
427 int modified = 0;
429 if (!(flags & UPDATE_DEFAULTS) && dict) {
430 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL) {
431 def_value = WMGetFromPLDictionary(def_win, attr);
435 /* If we could not find defaults in database, fall to hardcoded values.
436 * Also this is true if we save defaults for all windows
438 if (!def_value)
439 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
441 if ((flags & IS_BOOLEAN))
442 update = (getBool(value) != getBool(def_value));
443 else {
444 update = !WMIsPropListEqualTo(value, def_value);
447 if (update) {
448 WMPutInPLDictionary(window, attr, value);
449 modified = 1;
452 return modified;
455 static void saveSettings(WMButton * button, InspectorPanel * panel)
457 WWindow *wwin = panel->inspected;
458 WDDomain *db = WDWindowAttributes;
459 WMPropList *dict = db->dictionary;
460 WMPropList *winDic, *appDic, *value, *key, *key2;
461 char *icon_file;
462 int flags = 0;
463 int different = 0, different2 = 0;
465 /* Save will apply the changes and save them */
466 applySettings(panel->applyBtn, panel);
468 if (WMGetButtonSelected(panel->instRb) != 0)
469 key = WMCreatePLString(wwin->wm_instance);
470 else if (WMGetButtonSelected(panel->clsRb) != 0)
471 key = WMCreatePLString(wwin->wm_class);
472 else if (WMGetButtonSelected(panel->bothRb) != 0) {
473 char *buffer;
475 buffer = StrConcatDot(wwin->wm_instance, wwin->wm_class);
476 key = WMCreatePLString(buffer);
477 wfree(buffer);
478 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
479 key = WMRetainPropList(AnyWindow);
480 flags = UPDATE_DEFAULTS;
481 } else
482 key = NULL;
484 if (!key)
485 return;
487 if (!dict) {
488 dict = WMCreatePLDictionary(NULL, NULL);
489 if (dict) {
490 db->dictionary = dict;
491 } else {
492 WMReleasePropList(key);
493 return;
497 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD) < 0)
498 return;
500 WMPLSetCaseSensitive(True);
502 winDic = WMCreatePLDictionary(NULL, NULL);
503 appDic = WMCreatePLDictionary(NULL, NULL);
505 /* Update icon for window */
506 icon_file = WMGetTextFieldText(panel->fileText);
507 if (icon_file) {
508 if (icon_file[0] != 0) {
509 value = WMCreatePLString(icon_file);
510 different |= insertAttribute(dict, winDic, AIcon, value, flags);
511 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
512 WMReleasePropList(value);
514 wfree(icon_file);
518 int i = WMGetPopUpButtonSelectedItem(panel->wsP);
520 i--;
522 if (i >= 0 && i < panel->frame->screen_ptr->workspace_count) {
523 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
524 different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
525 WMReleasePropList(value);
529 flags |= IS_BOOLEAN;
531 value = (WMGetButtonSelected(panel->alwChk) != 0) ? Yes : No;
532 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
534 value = (WMGetButtonSelected(panel->attrChk[0]) != 0) ? Yes : No;
535 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
537 value = (WMGetButtonSelected(panel->attrChk[1]) != 0) ? Yes : No;
538 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
540 value = (WMGetButtonSelected(panel->attrChk[2]) != 0) ? Yes : No;
541 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
543 value = (WMGetButtonSelected(panel->attrChk[3]) != 0) ? Yes : No;
544 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
546 value = (WMGetButtonSelected(panel->attrChk[4]) != 0) ? Yes : No;
547 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
549 value = (WMGetButtonSelected(panel->attrChk[5]) != 0) ? Yes : No;
550 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
552 value = (WMGetButtonSelected(panel->attrChk[6]) != 0) ? Yes : No;
553 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
555 value = (WMGetButtonSelected(panel->attrChk[7]) != 0) ? Yes : No;
556 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
558 value = (WMGetButtonSelected(panel->attrChk[8]) != 0) ? Yes : No;
559 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
561 value = (WMGetButtonSelected(panel->attrChk[9]) != 0) ? Yes : No;
562 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
564 value = (WMGetButtonSelected(panel->attrChk[10]) != 0) ? Yes : No;
565 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
567 value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No;
568 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
570 value = (WMGetButtonSelected(panel->moreChk[1]) != 0) ? Yes : No;
571 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
573 value = (WMGetButtonSelected(panel->moreChk[2]) != 0) ? Yes : No;
574 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
576 value = (WMGetButtonSelected(panel->moreChk[3]) != 0) ? Yes : No;
577 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
579 value = (WMGetButtonSelected(panel->moreChk[4]) != 0) ? Yes : No;
580 different |= insertAttribute(dict, winDic, AKeepInsideScreen, value, flags);
582 value = (WMGetButtonSelected(panel->moreChk[5]) != 0) ? Yes : No;
583 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
585 value = (WMGetButtonSelected(panel->moreChk[6]) != 0) ? Yes : No;
586 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
588 value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No;
589 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
591 value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No;
592 different |= insertAttribute(dict, winDic, ADontFocusAcrossWorkspace, value, flags);
594 #ifdef XKB_BUTTON_HINT
595 value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No;
596 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
597 #endif
599 if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
600 value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No;
601 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
603 value = (WMGetButtonSelected(panel->appChk[1]) != 0) ? Yes : No;
604 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
606 value = (WMGetButtonSelected(panel->appChk[2]) != 0) ? Yes : No;
607 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
610 if (wwin->fake_group) {
611 key2 = WMCreatePLString(wwin->fake_group->identifier);
612 if (WMIsPropListEqualTo(key, key2)) {
613 WMMergePLDictionaries(winDic, appDic, True);
614 different |= different2;
615 } else {
616 WMRemoveFromPLDictionary(dict, key2);
617 if (different2) {
618 WMPutInPLDictionary(dict, key2, appDic);
621 WMReleasePropList(key2);
622 WMReleasePropList(appDic);
623 } else if (wwin->main_window != wwin->client_win) {
624 WApplication *wapp = wApplicationOf(wwin->main_window);
626 if (wapp) {
627 char *instance = wapp->main_window_desc->wm_instance;
628 char *class = wapp->main_window_desc->wm_class;
629 char *buffer;
631 buffer = StrConcatDot(instance, class);
632 key2 = WMCreatePLString(buffer);
633 wfree(buffer);
635 if (WMIsPropListEqualTo(key, key2)) {
636 WMMergePLDictionaries(winDic, appDic, True);
637 different |= different2;
638 } else {
639 WMRemoveFromPLDictionary(dict, key2);
640 if (different2) {
641 WMPutInPLDictionary(dict, key2, appDic);
644 WMReleasePropList(key2);
645 WMReleasePropList(appDic);
647 } else {
648 WMMergePLDictionaries(winDic, appDic, True);
649 different |= different2;
650 WMReleasePropList(appDic);
653 WMRemoveFromPLDictionary(dict, key);
654 if (different) {
655 WMPutInPLDictionary(dict, key, winDic);
658 WMReleasePropList(key);
659 WMReleasePropList(winDic);
661 UpdateDomainFile(db);
663 /* clean up */
664 WMPLSetCaseSensitive(False);
667 static void makeAppIconFor(WApplication * wapp)
669 WScreen *scr = wapp->main_window_desc->screen_ptr;
671 if (wapp->app_icon)
672 return;
674 if (!WFLAGP(wapp->main_window_desc, no_appicon))
675 wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
676 else
677 wapp->app_icon = NULL;
679 if (wapp->app_icon) {
680 WIcon *icon = wapp->app_icon->icon;
681 WDock *clip = scr->workspaces[scr->current_workspace]->clip;
682 int x = 0, y = 0;
684 wapp->app_icon->main_window = wapp->main_window;
686 if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
687 wapp->app_icon->attracted = 1;
688 if (!wapp->app_icon->icon->shadowed) {
689 wapp->app_icon->icon->shadowed = 1;
690 wapp->app_icon->icon->force_paint = 1;
692 wDockAttachIcon(clip, wapp->app_icon, x, y);
693 } else {
694 PlaceIcon(scr, &x, &y, wGetHeadForWindow(wapp->main_window_desc));
695 wAppIconMove(wapp->app_icon, x, y);
697 if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
698 XMapWindow(dpy, icon->core->window);
700 if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
701 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
705 static void removeAppIconFor(WApplication * wapp)
707 if (!wapp->app_icon)
708 return;
710 if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
711 wapp->app_icon->running = 0;
712 /* since we keep it, we don't care if it was attracted or not */
713 wapp->app_icon->attracted = 0;
714 wapp->app_icon->icon->shadowed = 0;
715 wapp->app_icon->main_window = None;
716 wapp->app_icon->pid = 0;
717 wapp->app_icon->icon->owner = NULL;
718 wapp->app_icon->icon->icon_win = None;
719 wapp->app_icon->icon->force_paint = 1;
720 wAppIconPaint(wapp->app_icon);
721 } else if (wapp->app_icon->docked) {
722 wapp->app_icon->running = 0;
723 wDockDetach(wapp->app_icon->dock, wapp->app_icon);
724 } else {
725 wAppIconDestroy(wapp->app_icon);
727 wapp->app_icon = NULL;
728 if (wPreferences.auto_arrange_icons)
729 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
732 static void applySettings(WMButton * button, InspectorPanel * panel)
734 WWindow *wwin = panel->inspected;
735 WApplication *wapp = wApplicationOf(wwin->main_window);
736 int floating, sunken, skip_window_list;
737 int old_omnipresent;
738 int old_no_bind_keys;
739 int old_no_bind_mouse;
741 old_omnipresent = WFLAGP(wwin, omnipresent);
742 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
743 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
745 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
747 /* Attributes... --> Window Attributes */
748 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
749 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
750 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
751 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
752 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
753 floating = WMGetButtonSelected(panel->attrChk[5]);
754 sunken = WMGetButtonSelected(panel->attrChk[6]);
755 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
756 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
757 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
758 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
760 /* Attributes... --> Advanced Options */
761 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
762 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
763 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
764 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[3]));
765 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[4]));
766 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[5]));
767 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[6]));
768 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[7]));
769 WSETUFLAG(wwin, dont_focus_across_wksp, WMGetButtonSelected(panel->moreChk[8]));
770 #ifdef XKB_BUTTON_HINT
771 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[9]));
772 #endif
773 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
775 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
776 wUnshadeWindow(wwin);
778 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
780 if (floating) {
781 if (!WFLAGP(wwin, floating))
782 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
783 } else if (sunken) {
784 if (!WFLAGP(wwin, sunken))
785 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
786 } else {
787 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
788 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
791 WSETUFLAG(wwin, sunken, sunken);
792 WSETUFLAG(wwin, floating, floating);
793 wwin->flags.omnipresent = 0;
795 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
796 WSETUFLAG(wwin, skip_window_list, skip_window_list);
797 UpdateSwitchMenu(wwin->screen_ptr, wwin, skip_window_list ? ACTION_REMOVE : ACTION_ADD);
798 } else {
799 if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
800 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
804 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
805 if (WFLAGP(wwin, no_bind_keys)) {
806 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
807 } else {
808 wWindowSetKeyGrabs(wwin);
812 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
813 wWindowResetMouseGrabs(wwin);
816 wwin->frame->flags.need_texture_change = 1;
817 wWindowConfigureBorders(wwin);
818 wFrameWindowPaint(wwin->frame);
819 wNETWMUpdateActions(wwin, False);
822 * Can't apply emulate_appicon because it will probably cause problems.
824 if (wapp) {
825 /* do application wide stuff */
826 WSETUFLAG(wapp->main_window_desc, start_hidden, WMGetButtonSelected(panel->appChk[0]));
828 WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1]));
830 WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2]));
832 if (WFLAGP(wapp->main_window_desc, no_appicon))
833 removeAppIconFor(wapp);
834 else
835 makeAppIconFor(wapp);
837 if (wapp->app_icon && wapp->main_window == wwin->client_win) {
838 char *file = WMGetTextFieldText(panel->fileText);
840 if (file[0] == 0) {
841 wfree(file);
842 file = NULL;
844 wIconChangeImageFile(wapp->app_icon->icon, file);
845 if (file)
846 wfree(file);
847 wAppIconPaint(wapp->app_icon);
852 static void revertSettings(WMButton * button, InspectorPanel * panel)
854 WWindow *wwin = panel->inspected;
855 WApplication *wapp = wApplicationOf(wwin->main_window);
856 int i, n;
857 char *wm_instance = NULL;
858 char *wm_class = NULL;
859 int workspace, level;
861 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
862 wm_instance = wwin->wm_instance;
863 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
864 wm_class = wwin->wm_class;
865 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
866 wm_instance = wwin->wm_instance;
867 wm_class = wwin->wm_class;
869 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
870 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
871 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
873 wWindowSetupInitialAttributes(wwin, &level, &workspace);
875 for (i = 0; i < 11; i++) {
876 int flag = 0;
878 switch (i) {
879 case 0:
880 flag = WFLAGP(wwin, no_titlebar);
881 break;
882 case 1:
883 flag = WFLAGP(wwin, no_resizebar);
884 break;
885 case 2:
886 flag = WFLAGP(wwin, no_close_button);
887 break;
888 case 3:
889 flag = WFLAGP(wwin, no_miniaturize_button);
890 break;
891 case 4:
892 flag = WFLAGP(wwin, no_border);
893 break;
894 case 5:
895 flag = WFLAGP(wwin, floating);
896 break;
897 case 6:
898 flag = WFLAGP(wwin, sunken);
899 break;
900 case 7:
901 flag = WFLAGP(wwin, omnipresent);
902 break;
903 case 8:
904 flag = WFLAGP(wwin, start_miniaturized);
905 break;
906 case 9:
907 flag = WFLAGP(wwin, start_maximized != 0);
908 break;
909 case 10:
910 flag = WFLAGP(wwin, full_maximize);
911 break;
913 WMSetButtonSelected(panel->attrChk[i], flag);
915 for (i = 0; i < 9; i++) {
916 int flag = 0;
918 switch (i) {
919 case 0:
920 flag = WFLAGP(wwin, no_bind_keys);
921 break;
922 case 1:
923 flag = WFLAGP(wwin, no_bind_mouse);
924 break;
925 case 2:
926 flag = WFLAGP(wwin, skip_window_list);
927 break;
928 case 3:
929 flag = WFLAGP(wwin, no_focusable);
930 break;
931 case 4:
932 flag = WFLAGP(wwin, dont_move_off);
933 break;
934 case 5:
935 flag = WFLAGP(wwin, no_hide_others);
936 break;
937 case 6:
938 flag = WFLAGP(wwin, dont_save_session);
939 break;
940 case 7:
941 flag = WFLAGP(wwin, emulate_appicon);
942 break;
943 case 8:
944 flag = WFLAGP(wwin, dont_focus_across_wksp);
945 break;
946 #ifdef XKB_BUTTON_HINT
947 case 9:
948 flag = WFLAGP(wwin, no_language_button);
949 break;
950 #endif
952 WMSetButtonSelected(panel->moreChk[i], flag);
954 if (panel->appFrm && wapp) {
955 for (i = 0; i < 2; i++) {
956 int flag = 0;
958 switch (i) {
959 case 0:
960 flag = WFLAGP(wapp->main_window_desc, start_hidden);
961 break;
962 case 1:
963 flag = WFLAGP(wapp->main_window_desc, no_appicon);
964 break;
965 case 2:
966 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
967 break;
969 WMSetButtonSelected(panel->appChk[i], flag);
972 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
974 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
976 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
978 if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
979 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
980 } else {
981 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
984 /* must auto apply, so that there wno't be internal
985 * inconsistencies between the state in the flags and
986 * the actual state of the window */
987 applySettings(panel->applyBtn, panel);
990 static void chooseIconCallback(WMWidget * self, void *clientData)
992 char *file;
993 InspectorPanel *panel = (InspectorPanel *) clientData;
994 int result;
996 panel->choosingIcon = 1;
998 WMSetButtonEnabled(panel->browseIconBtn, False);
1000 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
1001 panel->inspected->wm_instance, panel->inspected->wm_class);
1003 panel->choosingIcon = 0;
1005 if (!panel->destroyed) { /* kluge */
1006 if (result) {
1007 WMSetTextFieldText(panel->fileText, file);
1008 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
1009 wfree(file);
1011 WMSetButtonEnabled(panel->browseIconBtn, True);
1012 } else {
1013 freeInspector(panel);
1017 static void textEditedObserver(void *observerData, WMNotification * notification)
1019 InspectorPanel *panel = (InspectorPanel *) observerData;
1021 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
1022 return;
1024 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
1026 WMPerformButtonClick(panel->updateIconBtn);
1030 static void selectSpecification(WMWidget * bPtr, void *data)
1032 InspectorPanel *panel = (InspectorPanel *) data;
1033 char *str;
1034 WWindow *wwin = panel->inspected;
1035 int len;
1037 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class)) {
1038 WMSetButtonEnabled(panel->applyBtn, False);
1039 } else {
1040 WMSetButtonEnabled(panel->applyBtn, True);
1043 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
1044 + strlen(wwin->wm_class ? wwin->wm_class : "?");
1046 str = wmalloc(len);
1048 snprintf(str, len, _("Inspecting %s.%s"),
1049 wwin->wm_instance ? wwin->wm_instance : "?", wwin->wm_class ? wwin->wm_class : "?");
1051 wFrameWindowChangeTitle(panel->frame->frame, str);
1053 wfree(str);
1056 static void selectWindow(WMWidget * bPtr, void *data)
1058 InspectorPanel *panel = (InspectorPanel *) data;
1059 WWindow *wwin = panel->inspected;
1060 WScreen *scr = wwin->screen_ptr;
1061 XEvent event;
1062 WWindow *iwin;
1064 if (XGrabPointer(dpy, scr->root_win, True,
1065 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1066 wCursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
1067 wwarning("could not grab mouse pointer");
1068 return;
1071 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1073 WMMaskEvent(dpy, ButtonPressMask, &event);
1075 XUngrabPointer(dpy, CurrentTime);
1077 iwin = wWindowFor(event.xbutton.subwindow);
1079 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
1081 iwin->flags.inspector_open = 1;
1082 iwin->inspector = createInspectorForWindow(iwin,
1083 panel->frame->frame_x, panel->frame->frame_y, True);
1084 wCloseInspectorForWindow(wwin);
1085 } else {
1086 WMSetLabelText(panel->specLbl, spec_text);
1090 static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel)
1092 WScreen *scr = wwin->screen_ptr;
1093 InspectorPanel *panel;
1094 Window parent;
1095 int i;
1096 int x, y;
1097 int btn_width, frame_width;
1098 WMButton *selectedBtn = NULL;
1099 #ifdef wrong_behaviour
1100 WMPixmap *pixmap;
1101 #endif
1103 spec_text = _("The configuration will apply to all\n"
1104 "windows that have their WM_CLASS\n"
1105 "property set to the above selected\n" "name, when saved.");
1107 panel = wmalloc(sizeof(InspectorPanel));
1108 memset(panel, 0, sizeof(InspectorPanel));
1110 panel->destroyed = 0;
1112 panel->inspected = wwin;
1114 panel->nextPtr = panelList;
1115 panelList = panel;
1117 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1118 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1120 /**** create common stuff ****/
1122 /* command buttons */
1123 /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
1124 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1125 panel->saveBtn = WMCreateCommandButton(panel->win);
1126 WMSetButtonAction(panel->saveBtn, (WMAction *) saveSettings, panel);
1127 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, 310);
1128 WMSetButtonText(panel->saveBtn, _("Save"));
1129 WMResizeWidget(panel->saveBtn, btn_width, 28);
1130 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1131 WMSetButtonEnabled(panel->saveBtn, False);
1133 panel->applyBtn = WMCreateCommandButton(panel->win);
1134 WMSetButtonAction(panel->applyBtn, (WMAction *) applySettings, panel);
1135 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, 310);
1136 WMSetButtonText(panel->applyBtn, _("Apply"));
1137 WMResizeWidget(panel->applyBtn, btn_width, 28);
1139 panel->revertBtn = WMCreateCommandButton(panel->win);
1140 WMSetButtonAction(panel->revertBtn, (WMAction *) revertSettings, panel);
1141 WMMoveWidget(panel->revertBtn, 15, 310);
1142 WMSetButtonText(panel->revertBtn, _("Reload"));
1143 WMResizeWidget(panel->revertBtn, btn_width, 28);
1145 /* page selection popup button */
1146 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1147 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction *) changePage, panel);
1148 WMMoveWidget(panel->pagePopUp, 25, 15);
1149 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1151 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1152 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1153 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1154 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1155 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1157 /**** window spec ****/
1158 frame_width = PWIDTH - (2 * 15);
1160 panel->specFrm = WMCreateFrame(panel->win);
1161 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1162 WMMoveWidget(panel->specFrm, 15, 65);
1163 WMResizeWidget(panel->specFrm, frame_width, 145);
1165 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1166 WMMoveWidget(panel->defaultRb, 10, 78);
1167 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1168 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1169 WMSetButtonSelected(panel->defaultRb, False);
1170 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1172 if (wwin->wm_class && wwin->wm_instance) {
1173 char *str, *tmp;
1175 tmp = wstrconcat(wwin->wm_instance, ".");
1176 str = wstrconcat(tmp, wwin->wm_class);
1178 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1179 WMMoveWidget(panel->bothRb, 10, 18);
1180 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1181 WMSetButtonText(panel->bothRb, str);
1182 wfree(tmp);
1183 wfree(str);
1184 WMGroupButtons(panel->defaultRb, panel->bothRb);
1186 if (!selectedBtn)
1187 selectedBtn = panel->bothRb;
1189 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1192 if (wwin->wm_instance) {
1193 panel->instRb = WMCreateRadioButton(panel->specFrm);
1194 WMMoveWidget(panel->instRb, 10, 38);
1195 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1196 WMSetButtonText(panel->instRb, wwin->wm_instance);
1197 WMGroupButtons(panel->defaultRb, panel->instRb);
1199 if (!selectedBtn)
1200 selectedBtn = panel->instRb;
1202 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1205 if (wwin->wm_class) {
1206 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1207 WMMoveWidget(panel->clsRb, 10, 58);
1208 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1209 WMSetButtonText(panel->clsRb, wwin->wm_class);
1210 WMGroupButtons(panel->defaultRb, panel->clsRb);
1212 if (!selectedBtn)
1213 selectedBtn = panel->clsRb;
1215 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1218 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1219 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1220 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1221 WMSetButtonText(panel->selWinB, _("Select window"));
1222 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1224 panel->specLbl = WMCreateLabel(panel->win);
1225 WMMoveWidget(panel->specLbl, 15, 210);
1226 WMResizeWidget(panel->specLbl, frame_width, 100);
1227 WMSetLabelText(panel->specLbl, spec_text);
1228 WMSetLabelWraps(panel->specLbl, True);
1230 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1232 /**** attributes ****/
1233 panel->attrFrm = WMCreateFrame(panel->win);
1234 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1235 WMMoveWidget(panel->attrFrm, 15, 45);
1236 WMResizeWidget(panel->attrFrm, frame_width, 250);
1238 for (i = 0; i < 11; i++) {
1239 char *caption = NULL;
1240 int flag = 0;
1241 char *descr = NULL;
1243 switch (i) {
1244 case 0:
1245 caption = _("Disable titlebar");
1246 flag = WFLAGP(wwin, no_titlebar);
1247 descr = _("Remove the titlebar of this window.\n"
1248 "To access the window commands menu of a window\n"
1249 "without it's titlebar, press Control+Esc (or the\n"
1250 "equivalent shortcut, if you changed the default\n" "settings).");
1251 break;
1252 case 1:
1253 caption = _("Disable resizebar");
1254 flag = WFLAGP(wwin, no_resizebar);
1255 descr = _("Remove the resizebar of this window.");
1256 break;
1257 case 2:
1258 caption = _("Disable close button");
1259 flag = WFLAGP(wwin, no_close_button);
1260 descr = _("Remove the `close window' button of this window.");
1261 break;
1262 case 3:
1263 caption = _("Disable miniaturize button");
1264 flag = WFLAGP(wwin, no_miniaturize_button);
1265 descr = _("Remove the `miniaturize window' button of the window.");
1266 break;
1267 case 4:
1268 caption = _("Disable border");
1269 flag = WFLAGP(wwin, no_border);
1270 descr = _("Remove the 1 pixel black border around the window.");
1271 break;
1272 case 5:
1273 caption = _("Keep on top (floating)");
1274 flag = WFLAGP(wwin, floating);
1275 descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
1276 break;
1277 case 6:
1278 caption = _("Keep at bottom (sunken)");
1279 flag = WFLAGP(wwin, sunken);
1280 descr = _("Keep the window under all other windows.");
1281 break;
1282 case 7:
1283 caption = _("Omnipresent");
1284 flag = WFLAGP(wwin, omnipresent);
1285 descr = _("Make window present in all workspaces.");
1286 break;
1287 case 8:
1288 caption = _("Start miniaturized");
1289 flag = WFLAGP(wwin, start_miniaturized);
1290 descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
1291 break;
1292 case 9:
1293 caption = _("Start maximized");
1294 flag = WFLAGP(wwin, start_maximized != 0);
1295 descr = _("Make the window be automatically maximized when it's\n" "first shown.");
1296 break;
1297 case 10:
1298 caption = _("Full screen maximization");
1299 flag = WFLAGP(wwin, full_maximize);
1300 descr = _("Make the window use the whole screen space when it's\n"
1301 "maximized. The titlebar and resizebar will be moved\n"
1302 "to outside the screen.");
1303 break;
1305 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1306 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1307 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1308 WMSetButtonSelected(panel->attrChk[i], flag);
1309 WMSetButtonText(panel->attrChk[i], caption);
1311 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1314 /**** more attributes ****/
1315 panel->moreFrm = WMCreateFrame(panel->win);
1316 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1317 WMMoveWidget(panel->moreFrm, 15, 45);
1318 WMResizeWidget(panel->moreFrm, frame_width, 250);
1320 for (i = 0;
1321 #ifdef XKB_BUTTON_HINT
1322 i < 10;
1323 #else
1324 i < 9;
1325 #endif
1326 i++) {
1327 char *caption = NULL;
1328 int flag = 0;
1329 char *descr = NULL;
1331 switch (i) {
1332 case 0:
1333 caption = _("Do not bind keyboard shortcuts");
1334 flag = WFLAGP(wwin, no_bind_keys);
1335 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1336 "when this window is focused. This will allow the\n"
1337 "window to receive all key combinations regardless\n"
1338 "of your shortcut configuration.");
1339 break;
1340 case 1:
1341 caption = _("Do not bind mouse clicks");
1342 flag = WFLAGP(wwin, no_bind_mouse);
1343 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1344 "in the window (when alt is the modifier you have\n" "configured).");
1345 break;
1346 case 2:
1347 caption = _("Do not show in the window list");
1348 flag = WFLAGP(wwin, skip_window_list);
1349 descr = _("Do not list the window in the window list menu.");
1350 break;
1351 case 3:
1352 caption = _("Do not let it take focus");
1353 flag = WFLAGP(wwin, no_focusable);
1354 descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
1355 break;
1356 case 4:
1357 caption = _("Keep inside screen");
1358 flag = WFLAGP(wwin, dont_move_off);
1359 descr = _("Do not allow the window to move itself completely\n"
1360 "outside the screen. For bug compatibility.\n");
1361 break;
1362 case 5:
1363 caption = _("Ignore 'Hide Others'");
1364 flag = WFLAGP(wwin, no_hide_others);
1365 descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
1366 break;
1367 case 6:
1368 caption = _("Ignore 'Save Session'");
1369 flag = WFLAGP(wwin, dont_save_session);
1370 descr = _("Do not save the associated application in the\n"
1371 "session's state, so that it won't be restarted\n"
1372 "together with other applications when Window Maker\n" "starts.");
1373 break;
1374 case 7:
1375 caption = _("Emulate application icon");
1376 flag = WFLAGP(wwin, emulate_appicon);
1377 descr = _("Make this window act as an application that provides\n"
1378 "enough information to Window Maker for a dockable\n"
1379 "application icon to be created.");
1380 break;
1381 case 8:
1382 caption = _("Don't focus across workspaces");
1383 flag = WFLAGP(wwin, dont_focus_across_wksp);
1384 descr = _("Do not allow Window Maker to switch workspace to satisfy\n"
1385 "a focus request (useful e.g. in the case of a multiple-tab\n"
1386 "firefox opening in a different workspace).");
1387 break;
1388 #ifdef XKB_BUTTON_HINT
1389 case 9:
1390 caption = _("Disable language button");
1391 flag = WFLAGP(wwin, no_language_button);
1392 descr = _("Remove the `toggle language' button of the window.");
1393 break;
1394 #endif
1396 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1397 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
1398 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1399 WMSetButtonSelected(panel->moreChk[i], flag);
1400 WMSetButtonText(panel->moreChk[i], caption);
1402 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1405 /* miniwindow/workspace */
1406 panel->iconFrm = WMCreateFrame(panel->win);
1407 WMMoveWidget(panel->iconFrm, 15, 50);
1408 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1409 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1411 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1412 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1413 WMResizeWidget(panel->iconLbl, 64, 64);
1414 WMSetLabelRelief(panel->iconLbl, WRGroove);
1415 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1417 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1418 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1419 WMMoveWidget(panel->browseIconBtn, 22, 32);
1420 WMResizeWidget(panel->browseIconBtn, 120, 26);
1421 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1423 #ifdef wrong_behaviour
1424 WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
1425 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
1426 WMSetButtonImage(panel->updateIconBtn, pixmap);
1427 WMReleasePixmap(pixmap);
1428 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
1429 WMSetButtonAltImage(panel->updateIconBtn, pixmap);
1430 WMReleasePixmap(pixmap);
1431 #endif
1433 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1434 WMMoveWidget(panel->fileLbl, 20, 85);
1435 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1436 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1438 panel->fileText = WMCreateTextField(panel->iconFrm);
1439 WMMoveWidget(panel->fileText, 20, 105);
1440 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1441 WMSetTextFieldText(panel->fileText, NULL);
1442 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1444 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1445 WMMoveWidget(panel->alwChk, 20, 130);
1446 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1447 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1448 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1450 panel->wsFrm = WMCreateFrame(panel->win);
1451 WMMoveWidget(panel->wsFrm, 15, 225);
1452 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1453 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1455 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1456 "first shown."), WMWidgetView(panel->wsFrm));
1458 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1459 WMMoveWidget(panel->wsP, 20, 30);
1460 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1461 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1462 for (i = 0; i < wwin->screen_ptr->workspace_count; i++) {
1463 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1466 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1467 if (i >= 0 && i <= wwin->screen_ptr->workspace_count) {
1468 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1469 } else {
1470 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1473 /* application wide attributes */
1474 if (wwin->main_window != None) {
1475 WApplication *wapp = wApplicationOf(wwin->main_window);
1477 panel->appFrm = WMCreateFrame(panel->win);
1478 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1479 WMMoveWidget(panel->appFrm, 15, 50);
1480 WMResizeWidget(panel->appFrm, frame_width, 240);
1482 for (i = 0; i < 3; i++) {
1483 char *caption = NULL;
1484 int flag = 0;
1485 char *descr = NULL;
1487 switch (i) {
1488 case 0:
1489 caption = _("Start hidden");
1490 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1491 descr = _("Automatically hide application when it's started.");
1492 break;
1493 case 1:
1494 caption = _("No application icon");
1495 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1496 descr = _("Disable the application icon for the application.\n"
1497 "Note that you won't be able to dock it anymore,\n"
1498 "and any icons that are already docked will stop\n"
1499 "working correctly.");
1500 break;
1501 case 2:
1502 caption = _("Shared application icon");
1503 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1504 descr = _("Use a single shared application icon for all of\n"
1505 "the instances of this application.\n");
1506 break;
1508 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1509 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1510 WMResizeWidget(panel->appChk[i], 205, 20);
1511 WMSetButtonSelected(panel->appChk[i], flag);
1512 WMSetButtonText(panel->appChk[i], caption);
1514 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1517 if (WFLAGP(wwin, emulate_appicon)) {
1518 WMSetButtonEnabled(panel->appChk[1], False);
1519 WMSetButtonEnabled(panel->moreChk[7], True);
1520 } else {
1521 WMSetButtonEnabled(panel->appChk[1], True);
1522 WMSetButtonEnabled(panel->moreChk[7], False);
1524 } else {
1525 int tmp;
1527 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1528 || !wwin->wm_class || !wwin->wm_instance)
1529 tmp = False;
1530 else
1531 tmp = True;
1532 WMSetButtonEnabled(panel->moreChk[7], tmp);
1534 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1535 panel->appFrm = NULL;
1538 /* if the window is a transient, don't let it have a miniaturize
1539 * button */
1540 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1541 WMSetButtonEnabled(panel->attrChk[3], False);
1542 else
1543 WMSetButtonEnabled(panel->attrChk[3], True);
1545 if (!wwin->wm_class && !wwin->wm_instance) {
1546 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1549 WMRealizeWidget(panel->win);
1551 WMMapSubwidgets(panel->win);
1552 WMMapSubwidgets(panel->specFrm);
1553 WMMapSubwidgets(panel->attrFrm);
1554 WMMapSubwidgets(panel->moreFrm);
1555 WMMapSubwidgets(panel->iconFrm);
1556 WMMapSubwidgets(panel->wsFrm);
1557 if (panel->appFrm)
1558 WMMapSubwidgets(panel->appFrm);
1560 if (showSelectPanel) {
1561 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1562 changePage(panel->pagePopUp, panel);
1563 } else {
1564 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1565 changePage(panel->pagePopUp, panel);
1568 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1569 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1570 panel->parent = parent;
1571 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1573 WMMapWidget(panel->win);
1575 XSetTransientForHint(dpy, parent, wwin->client_win);
1577 if (xpos == UNDEFINED_POS) {
1578 x = wwin->frame_x + wwin->frame->core->width / 2;
1579 y = wwin->frame_y + wwin->frame->top_width * 2;
1580 if (y + PHEIGHT > scr->scr_height)
1581 y = scr->scr_height - PHEIGHT - 30;
1582 if (x + PWIDTH > scr->scr_width)
1583 x = scr->scr_width - PWIDTH;
1584 } else {
1585 x = xpos;
1586 y = ypos;
1589 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1591 if (!selectedBtn)
1592 selectedBtn = panel->defaultRb;
1594 WMSetButtonSelected(selectedBtn, True);
1596 selectSpecification(selectedBtn, panel);
1598 /* kluge to know who should get the key events */
1599 panel->frame->client_leader = WMWidgetXID(panel->win);
1601 WSETUFLAG(panel->frame, no_closable, 0);
1602 WSETUFLAG(panel->frame, no_close_button, 0);
1603 wWindowUpdateButtonImages(panel->frame);
1604 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1605 panel->frame->frame->on_click_right = destroyInspector;
1607 wWindowMap(panel->frame);
1609 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1611 return panel;
1614 void wShowInspectorForWindow(WWindow * wwin)
1616 if (wwin->flags.inspector_open)
1617 return;
1619 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1621 make_keys();
1622 wwin->flags.inspector_open = 1;
1623 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1626 void wHideInspectorForWindow(WWindow * wwin)
1628 WWindow *pwin = wwin->inspector->frame;
1630 wWindowUnmap(pwin);
1631 pwin->flags.hidden = 1;
1633 wClientSetState(pwin, IconicState, None);
1636 void wUnhideInspectorForWindow(WWindow * wwin)
1638 WWindow *pwin = wwin->inspector->frame;
1640 pwin->flags.hidden = 0;
1641 pwin->flags.mapped = 1;
1642 XMapWindow(dpy, pwin->client_win);
1643 XMapWindow(dpy, pwin->frame->core->window);
1644 wClientSetState(pwin, NormalState, None);
1647 WWindow *wGetWindowOfInspectorForWindow(WWindow * wwin)
1649 if (wwin->inspector) {
1650 assert(wwin->flags.inspector_open != 0);
1652 return wwin->inspector->frame;
1653 } else
1654 return NULL;
1657 void wCloseInspectorForWindow(WWindow * wwin)
1659 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1661 (*pwin->frame->on_click_right) (NULL, pwin, NULL);