- Fixed crashing bug in menu.c
[wmaker-crm.git] / src / winspector.c
blob717e39e49e98276b2790d5ffd8e3f2ee0a951016
1 /* winspector.c - window attribute inspector
2 *
3 * Window Maker window manager
4 *
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * Copyright (c) 1998-2003 Dan Pascu
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
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
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 * USA.
24 #include "wconfig.h"
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.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 "funcs.h"
39 #include "defaults.h"
40 #include "dialog.h"
41 #include "icon.h"
42 #include "stacking.h"
43 #include "application.h"
44 #include "appicon.h"
45 #include "actions.h"
46 #include "winspector.h"
47 #include "dock.h"
48 #include "client.h"
51 #include <WINGs/WUtil.h>
59 typedef struct InspectorPanel {
60 struct InspectorPanel *nextPtr;
62 WWindow *frame;
64 WWindow *inspected; /* the window that's being inspected */
66 WMWindow *win;
68 Window parent;
70 /* common stuff */
71 WMButton *revertBtn;
72 WMButton *applyBtn;
73 WMButton *saveBtn;
75 WMPopUpButton *pagePopUp;
77 /* first page. general stuff */
79 WMFrame *specFrm;
80 WMButton *instRb;
81 WMButton *clsRb;
82 WMButton *bothRb;
83 WMButton *defaultRb;
85 WMButton *selWinB;
87 WMLabel *specLbl;
89 /* second page. attributes */
91 WMFrame *attrFrm;
92 WMButton *attrChk[11];
94 /* 3rd page. more attributes */
95 WMFrame *moreFrm;
96 #ifdef XKB_BUTTON_HINT
97 WMButton *moreChk[9];
98 #else
99 WMButton *moreChk[8];
100 #endif
102 /* 4th page. icon and workspace */
103 WMFrame *iconFrm;
104 WMLabel *iconLbl;
105 WMLabel *fileLbl;
106 WMTextField *fileText;
107 WMButton *alwChk;
109 WMButton *updateIconBtn;
111 WMButton *browseIconBtn;
113 WMFrame *wsFrm;
114 WMPopUpButton *wsP;
116 /* 5th page. application wide attributes */
117 WMFrame *appFrm;
118 WMButton *appChk[3];
120 unsigned int done:1;
121 unsigned int destroyed:1;
122 unsigned int choosingIcon:1;
123 } InspectorPanel;
128 extern Cursor wCursor[WCUR_LAST];
130 extern WDDomain *WDWindowAttributes;
132 static InspectorPanel *panelList=NULL;
134 extern WPreferences wPreferences;
136 static WMPropList *ANoTitlebar = NULL;
137 static WMPropList *ANoResizebar;
138 static WMPropList *ANoMiniaturizeButton;
139 static WMPropList *ANoCloseButton;
140 static WMPropList *ANoBorder;
141 static WMPropList *ANoHideOthers;
142 static WMPropList *ANoMouseBindings;
143 static WMPropList *ANoKeyBindings;
144 static WMPropList *ANoAppIcon;
145 static WMPropList *AKeepOnTop;
146 static WMPropList *AKeepOnBottom;
147 static WMPropList *AOmnipresent;
148 static WMPropList *ASkipWindowList;
149 static WMPropList *AKeepInsideScreen;
150 static WMPropList *AUnfocusable;
151 static WMPropList *AAlwaysUserIcon;
152 static WMPropList *AStartMiniaturized;
153 static WMPropList *AStartMaximized;
154 static WMPropList *ADontSaveSession;
155 static WMPropList *AEmulateAppIcon;
156 static WMPropList *AFullMaximize;
157 static WMPropList *ASharedAppIcon;
158 #ifdef XKB_BUTTON_HINT
159 static WMPropList *ANoLanguageButton;
160 #endif
162 static WMPropList *AStartWorkspace;
164 static WMPropList *AIcon;
166 /* application wide options */
167 static WMPropList *AStartHidden;
170 static WMPropList *AnyWindow;
171 static WMPropList *EmptyString;
172 static WMPropList *Yes, *No;
175 #define PWIDTH 270
176 #define PHEIGHT 350
180 static char *spec_text;
183 static void applySettings(WMButton *button, InspectorPanel *panel);
188 #define UNDEFINED_POS 0xffffff
190 static InspectorPanel *createInspectorForWindow(WWindow *wwin,
191 int xpos, int ypos,
192 Bool showSelectPanel);
196 static void
197 make_keys()
199 if (ANoTitlebar!=NULL)
200 return;
202 AIcon = WMCreatePLString("Icon");
203 ANoTitlebar = WMCreatePLString("NoTitlebar");
204 ANoResizebar = WMCreatePLString("NoResizebar");
205 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
206 ANoCloseButton = WMCreatePLString("NoCloseButton");
207 ANoBorder = WMCreatePLString("NoBorder");
208 ANoHideOthers = WMCreatePLString("NoHideOthers");
209 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
210 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
211 ANoAppIcon = WMCreatePLString("NoAppIcon");
212 AKeepOnTop = WMCreatePLString("KeepOnTop");
213 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
214 AOmnipresent = WMCreatePLString("Omnipresent");
215 ASkipWindowList = WMCreatePLString("SkipWindowList");
216 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
217 AUnfocusable = WMCreatePLString("Unfocusable");
218 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
219 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
220 AStartMaximized = WMCreatePLString("StartMaximized");
221 AStartHidden = WMCreatePLString("StartHidden");
222 ADontSaveSession = WMCreatePLString("DontSaveSession");
223 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
224 AFullMaximize = WMCreatePLString("FullMaximize");
225 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
226 #ifdef XKB_BUTTON_HINT
227 ANoLanguageButton = WMCreatePLString("NoLanguageButton");
228 #endif
230 AStartWorkspace = WMCreatePLString("StartWorkspace");
232 AnyWindow = WMCreatePLString("*");
233 EmptyString = WMCreatePLString("");
234 Yes = WMCreatePLString("Yes");
235 No = WMCreatePLString("No");
240 static void
241 freeInspector(InspectorPanel *panel)
243 panel->destroyed = 1;
244 if (panel->choosingIcon)
245 return;
247 WMDestroyWidget(panel->win);
249 XDestroyWindow(dpy, panel->parent);
251 wfree(panel);
255 static void
256 destroyInspector(WCoreWindow *foo, void *data, XEvent *event)
258 InspectorPanel *panel;
259 InspectorPanel *tmp;
261 panel = panelList;
262 while (panel->frame!=data)
263 panel = panel->nextPtr;
265 if (panelList == panel)
266 panelList = panel->nextPtr;
267 else {
268 tmp = panelList;
269 while (tmp->nextPtr!=panel) {
270 tmp = tmp->nextPtr;
272 tmp->nextPtr = panel->nextPtr;
274 panel->inspected->flags.inspector_open = 0;
275 panel->inspected->inspector = NULL;
277 WMRemoveNotificationObserver(panel);
279 wWindowUnmap(panel->frame);
280 wUnmanageWindow(panel->frame, True, False);
282 freeInspector(panel);
287 void
288 wDestroyInspectorPanels()
290 InspectorPanel *panel;
292 while (panelList != NULL) {
293 panel = panelList;
294 panelList = panelList->nextPtr;
295 wUnmanageWindow(panel->frame, False, False);
296 WMDestroyWidget(panel->win);
298 panel->inspected->flags.inspector_open = 0;
299 panel->inspected->inspector = NULL;
301 wfree(panel);
306 static void
307 changePage(WMPopUpButton *bPtr, InspectorPanel *panel)
309 int page;
311 page = WMGetPopUpButtonSelectedItem(bPtr);
313 if (page == 0) {
314 WMMapWidget(panel->specFrm);
315 WMMapWidget(panel->specLbl);
316 } else if (page == 1) {
317 WMMapWidget(panel->attrFrm);
318 } else if (page == 2) {
319 WMMapWidget(panel->moreFrm);
320 } else if (page == 3) {
321 WMMapWidget(panel->iconFrm);
322 WMMapWidget(panel->wsFrm);
323 } else {
324 WMMapWidget(panel->appFrm);
327 if (page != 0) {
328 WMUnmapWidget(panel->specFrm);
329 WMUnmapWidget(panel->specLbl);
331 if (page != 1)
332 WMUnmapWidget(panel->attrFrm);
333 if (page != 2)
334 WMUnmapWidget(panel->moreFrm);
335 if (page != 3) {
336 WMUnmapWidget(panel->iconFrm);
337 WMUnmapWidget(panel->wsFrm);
339 if (page != 4 && panel->appFrm)
340 WMUnmapWidget(panel->appFrm);
344 #define USE_TEXT_FIELD 1
345 #define UPDATE_TEXT_FIELD 2
346 #define REVERT_TO_DEFAULT 4
349 static int
350 showIconFor(WMScreen *scrPtr, InspectorPanel *panel,
351 char *wm_instance, char *wm_class, int flags)
353 WMPixmap *pixmap = (WMPixmap*) NULL;
354 char *file=NULL, *path=NULL;
355 char *db_icon=NULL;
357 if ((flags & USE_TEXT_FIELD) != 0) {
358 file = WMGetTextFieldText(panel->fileText);
359 if (file && file[0] == 0) {
360 wfree(file);
361 file = NULL;
363 } else {
364 db_icon = wDefaultGetIconFile(panel->inspected->screen_ptr,
365 wm_instance, wm_class, False);
366 if(db_icon != NULL)
367 file = wstrdup(db_icon);
369 if (db_icon!=NULL && (flags & REVERT_TO_DEFAULT)!=0) {
370 if (file)
371 file = wstrdup(db_icon);
372 flags |= UPDATE_TEXT_FIELD;
375 if ((flags & UPDATE_TEXT_FIELD) != 0) {
376 WMSetTextFieldText(panel->fileText, file);
379 if (file) {
380 path = FindImage(wPreferences.icon_path, file);
382 if (!path) {
383 char *buf;
384 int len = strlen(file)+80;
386 buf = wmalloc(len);
387 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"),
388 file);
389 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf,
390 _("OK"), NULL, NULL);
391 wfree(buf);
392 wfree(file);
393 return -1;
396 pixmap = WMCreatePixmapFromFile(scrPtr, path);
397 wfree(path);
399 if (!pixmap) {
400 char *buf;
401 int len = strlen(file)+80;
403 buf = wmalloc(len);
404 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
405 file, RMessageForError(RErrorCode));
406 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf,
407 _("OK"), NULL, NULL);
408 wfree(buf);
409 wfree(file);
410 return -1;
412 wfree(file);
415 WMSetLabelImage(panel->iconLbl, pixmap);
416 if (pixmap)
417 WMReleasePixmap(pixmap);
419 return 0;
422 #if 0
423 static void
424 updateIcon(WMButton *button, InspectorPanel *panel)
426 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
428 #endif
430 static int
431 getBool(WMPropList *value)
433 char *val;
435 if (!WMIsPLString(value)) {
436 return 0;
438 if (!(val = WMGetFromPLString(value))) {
439 return 0;
442 if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y' || val[0]=='T'
443 || val[0]=='t' || val[0]=='1'))
444 || (strcasecmp(val, "YES")==0 || strcasecmp(val, "TRUE")==0)) {
446 return 1;
447 } else if ((val[1]=='\0'
448 && (val[0]=='n' || val[0]=='N' || val[0]=='F'
449 || val[0]=='f' || val[0]=='0'))
450 || (strcasecmp(val, "NO")==0 || strcasecmp(val, "FALSE")==0)) {
452 return 0;
453 } else {
454 wwarning(_("can't convert \"%s\" to boolean"), val);
455 return 0;
460 #define UPDATE_DEFAULTS 1
461 #define IS_BOOLEAN 2
465 * Will insert the attribute = value; pair in window's list,
466 * if it's different from the defaults.
467 * Defaults means either defaults database, or attributes saved
468 * for the default window "*". This is to let one revert options that are
469 * global because they were saved for all windows ("*").
474 static int
475 insertAttribute(WMPropList *dict, WMPropList *window, WMPropList *attr,
476 WMPropList *value, int flags)
478 WMPropList *def_win, *def_value=NULL;
479 int update = 0;
480 int modified = 0;
482 if (!(flags & UPDATE_DEFAULTS) && dict) {
483 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL) {
484 def_value = WMGetFromPLDictionary(def_win, attr);
488 /* If we could not find defaults in database, fall to hardcoded values.
489 * Also this is true if we save defaults for all windows
491 if (!def_value)
492 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
494 if ((flags & IS_BOOLEAN))
495 update = (getBool(value) != getBool(def_value));
496 else {
497 update = !WMIsPropListEqualTo(value, def_value);
500 if (update) {
501 WMPutInPLDictionary(window, attr, value);
502 modified = 1;
505 return modified;
509 static void
510 saveSettings(WMButton *button, InspectorPanel *panel)
512 WWindow *wwin = panel->inspected;
513 WDDomain *db = WDWindowAttributes;
514 WMPropList *dict = db->dictionary;
515 WMPropList *winDic, *appDic, *value, *key, *key2;
516 char *icon_file;
517 int flags = 0;
518 int different = 0, different2 = 0;
520 /* Save will apply the changes and save them */
521 applySettings(panel->applyBtn, panel);
523 if (WMGetButtonSelected(panel->instRb) != 0)
524 key = WMCreatePLString(wwin->wm_instance);
525 else if (WMGetButtonSelected(panel->clsRb) != 0)
526 key = WMCreatePLString(wwin->wm_class);
527 else if (WMGetButtonSelected(panel->bothRb) != 0) {
528 char *buffer;
530 buffer = StrConcatDot(wwin->wm_instance, wwin->wm_class);
531 key = WMCreatePLString(buffer);
532 wfree(buffer);
533 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
534 key = WMRetainPropList(AnyWindow);
535 flags = UPDATE_DEFAULTS;
536 } else
537 key = NULL;
539 if (!key)
540 return;
542 if (!dict) {
543 dict = WMCreatePLDictionary(NULL, NULL, NULL);
544 if (dict) {
545 db->dictionary = dict;
546 } else {
547 WMReleasePropList(key);
548 return;
552 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL,
553 USE_TEXT_FIELD) < 0)
554 return;
556 WMPLSetCaseSensitive(True);
558 winDic = WMCreatePLDictionary(NULL, NULL, NULL);
559 appDic = WMCreatePLDictionary(NULL, NULL, NULL);
561 /* Update icon for window */
562 icon_file = WMGetTextFieldText(panel->fileText);
563 if (icon_file) {
564 if (icon_file[0] != 0) {
565 value = WMCreatePLString(icon_file);
566 different |= insertAttribute(dict, winDic, AIcon, value, flags);
567 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
568 WMReleasePropList(value);
570 wfree(icon_file);
574 int i = WMGetPopUpButtonSelectedItem(panel->wsP);
576 i--;
578 if (i>=0 && i < panel->frame->screen_ptr->workspace_count) {
579 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
580 different |= insertAttribute(dict, winDic, AStartWorkspace, value,
581 flags);
582 WMReleasePropList(value);
586 flags |= IS_BOOLEAN;
588 value = (WMGetButtonSelected(panel->alwChk)!=0) ? Yes : No;
589 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
591 value = (WMGetButtonSelected(panel->attrChk[0])!=0) ? Yes : No;
592 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
594 value = (WMGetButtonSelected(panel->attrChk[1])!=0) ? Yes : No;
595 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
597 value = (WMGetButtonSelected(panel->attrChk[2])!=0) ? Yes : No;
598 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
600 value = (WMGetButtonSelected(panel->attrChk[3])!=0) ? Yes : No;
601 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
603 value = (WMGetButtonSelected(panel->attrChk[4])!=0) ? Yes : No;
604 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
606 value = (WMGetButtonSelected(panel->attrChk[5])!=0) ? Yes : No;
607 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
609 value = (WMGetButtonSelected(panel->attrChk[6])!=0) ? Yes : No;
610 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
612 value = (WMGetButtonSelected(panel->attrChk[7])!=0) ? Yes : No;
613 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
615 value = (WMGetButtonSelected(panel->attrChk[8])!=0) ? Yes : No;
616 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
618 value = (WMGetButtonSelected(panel->attrChk[9])!=0) ? Yes : No;
619 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
621 value = (WMGetButtonSelected(panel->attrChk[10])!=0) ? Yes : No;
622 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
625 value = (WMGetButtonSelected(panel->moreChk[0])!=0) ? Yes : No;
626 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
628 value = (WMGetButtonSelected(panel->moreChk[1])!=0) ? Yes : No;
629 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
631 value = (WMGetButtonSelected(panel->moreChk[2])!=0) ? Yes : No;
632 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
634 value = (WMGetButtonSelected(panel->moreChk[3])!=0) ? Yes : No;
635 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
637 value = (WMGetButtonSelected(panel->moreChk[4])!=0) ? Yes : No;
638 different |= insertAttribute(dict, winDic, AKeepInsideScreen,value, flags);
640 value = (WMGetButtonSelected(panel->moreChk[5])!=0) ? Yes : No;
641 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
643 value = (WMGetButtonSelected(panel->moreChk[6])!=0) ? Yes : No;
644 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
646 value = (WMGetButtonSelected(panel->moreChk[7])!=0) ? Yes : No;
647 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
649 #ifdef XKB_BUTTON_HINT
650 value = (WMGetButtonSelected(panel->moreChk[8])!=0) ? Yes : No;
651 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
652 #endif
654 if (wwin->main_window!=None && wApplicationOf(wwin->main_window)!=NULL) {
655 value = (WMGetButtonSelected(panel->appChk[0])!=0) ? Yes : No;
656 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
658 value = (WMGetButtonSelected(panel->appChk[1])!=0) ? Yes : No;
659 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
661 value = (WMGetButtonSelected(panel->appChk[2])!=0) ? Yes : No;
662 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
665 if (wwin->fake_group) {
666 key2 = WMCreatePLString(wwin->fake_group->identifier);
667 if (WMIsPropListEqualTo(key, key2)) {
668 WMMergePLDictionaries(winDic, appDic, True);
669 different |= different2;
670 } else {
671 WMRemoveFromPLDictionary(dict, key2);
672 if (different2) {
673 WMPutInPLDictionary(dict, key2, appDic);
676 WMReleasePropList(key2);
677 WMReleasePropList(appDic);
678 } else if (wwin->main_window != wwin->client_win) {
679 WApplication *wapp = wApplicationOf(wwin->main_window);
681 if (wapp) {
682 char *instance = wapp->main_window_desc->wm_instance;
683 char *class = wapp->main_window_desc->wm_class;
684 char *buffer;
686 buffer = StrConcatDot(instance, class);
687 key2 = WMCreatePLString(buffer);
688 wfree(buffer);
690 if (WMIsPropListEqualTo(key, key2)) {
691 WMMergePLDictionaries(winDic, appDic, True);
692 different |= different2;
693 } else {
694 WMRemoveFromPLDictionary(dict, key2);
695 if (different2) {
696 WMPutInPLDictionary(dict, key2, appDic);
699 WMReleasePropList(key2);
700 WMReleasePropList(appDic);
702 } else {
703 WMMergePLDictionaries(winDic, appDic, True);
704 different |= different2;
705 WMReleasePropList(appDic);
708 WMRemoveFromPLDictionary(dict, key);
709 if (different) {
710 WMPutInPLDictionary(dict, key, winDic);
713 WMReleasePropList(key);
714 WMReleasePropList(winDic);
716 UpdateDomainFile(db);
718 /* clean up */
719 WMPLSetCaseSensitive(False);
723 static void
724 makeAppIconFor(WApplication *wapp)
726 WScreen *scr = wapp->main_window_desc->screen_ptr;
728 if (wapp->app_icon)
729 return;
731 if (!WFLAGP(wapp->main_window_desc, no_appicon))
732 wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
733 else
734 wapp->app_icon = NULL;
736 if (wapp->app_icon) {
737 WIcon *icon = wapp->app_icon->icon;
738 WDock *clip = scr->workspaces[scr->current_workspace]->clip;
739 int x=0, y=0;
741 wapp->app_icon->main_window = wapp->main_window;
743 if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
744 wapp->app_icon->attracted = 1;
745 if (!wapp->app_icon->icon->shadowed) {
746 wapp->app_icon->icon->shadowed = 1;
747 wapp->app_icon->icon->force_paint = 1;
749 wDockAttachIcon(clip, wapp->app_icon, x, y);
750 } else {
751 PlaceIcon(scr, &x, &y);
752 wAppIconMove(wapp->app_icon, x, y);
754 if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
755 XMapWindow(dpy, icon->core->window);
757 if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
758 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
763 static void
764 removeAppIconFor(WApplication *wapp)
766 if (!wapp->app_icon)
767 return;
769 if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
770 wapp->app_icon->running = 0;
771 /* since we keep it, we don't care if it was attracted or not */
772 wapp->app_icon->attracted = 0;
773 wapp->app_icon->icon->shadowed = 0;
774 wapp->app_icon->main_window = None;
775 wapp->app_icon->pid = 0;
776 wapp->app_icon->icon->owner = NULL;
777 wapp->app_icon->icon->icon_win = None;
778 wapp->app_icon->icon->force_paint = 1;
779 wAppIconPaint(wapp->app_icon);
780 } else if (wapp->app_icon->docked) {
781 wapp->app_icon->running = 0;
782 wDockDetach(wapp->app_icon->dock, wapp->app_icon);
783 } else {
784 wAppIconDestroy(wapp->app_icon);
786 wapp->app_icon = NULL;
787 if (wPreferences.auto_arrange_icons)
788 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
792 static void
793 applySettings(WMButton *button, InspectorPanel *panel)
795 WWindow *wwin = panel->inspected;
796 WApplication *wapp = wApplicationOf(wwin->main_window);
797 int floating, sunken, skip_window_list;
798 int old_omnipresent;
799 int old_no_bind_keys;
800 int old_no_bind_mouse;
802 old_omnipresent = WFLAGP(wwin, omnipresent);
803 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
804 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
806 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
808 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
809 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
810 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
811 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
812 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
813 floating = WMGetButtonSelected(panel->attrChk[5]);
814 sunken = WMGetButtonSelected(panel->attrChk[6]);
815 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
816 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
817 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
818 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
820 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
821 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
822 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
823 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[3]));
824 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[4]));
825 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[5]));
826 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[6]));
827 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[7]));
828 #ifdef XKB_BUTTON_HINT
829 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[8]));
830 #endif
831 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
833 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
834 wUnshadeWindow(wwin);
836 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
838 if (floating) {
839 if (!WFLAGP(wwin, floating))
840 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
841 } else if (sunken) {
842 if (!WFLAGP(wwin, sunken))
843 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
844 } else {
845 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
846 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
849 WSETUFLAG(wwin, sunken, sunken);
850 WSETUFLAG(wwin, floating, floating);
851 wwin->flags.omnipresent = 0;
853 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
854 WSETUFLAG(wwin, skip_window_list, skip_window_list);
855 UpdateSwitchMenu(wwin->screen_ptr, wwin,
856 skip_window_list ? ACTION_REMOVE : ACTION_ADD);
857 } else {
858 if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
859 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
863 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
864 if (WFLAGP(wwin, no_bind_keys)) {
865 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
866 } else {
867 wWindowSetKeyGrabs(wwin);
871 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
872 wWindowResetMouseGrabs(wwin);
875 wwin->frame->flags.need_texture_change = 1;
876 wWindowConfigureBorders(wwin);
877 wFrameWindowPaint(wwin->frame);
880 * Can't apply emulate_appicon because it will probably cause problems.
883 if (wapp) {
884 /* do application wide stuff */
885 WSETUFLAG(wapp->main_window_desc, start_hidden,
886 WMGetButtonSelected(panel->appChk[0]));
888 WSETUFLAG(wapp->main_window_desc, no_appicon,
889 WMGetButtonSelected(panel->appChk[1]));
891 WSETUFLAG(wapp->main_window_desc, shared_appicon,
892 WMGetButtonSelected(panel->appChk[2]));
894 if (WFLAGP(wapp->main_window_desc, no_appicon))
895 removeAppIconFor(wapp);
896 else
897 makeAppIconFor(wapp);
899 if (wapp->app_icon && wapp->main_window == wwin->client_win) {
900 char *file = WMGetTextFieldText(panel->fileText);
902 if (file[0] == 0) {
903 wfree(file);
904 file = NULL;
906 wIconChangeImageFile(wapp->app_icon->icon, file);
907 if (file)
908 wfree(file);
909 wAppIconPaint(wapp->app_icon);
917 static void
918 revertSettings(WMButton *button, InspectorPanel *panel)
920 WWindow *wwin = panel->inspected;
921 WApplication *wapp = wApplicationOf(wwin->main_window);
922 int i, n;
923 char *wm_instance = NULL;
924 char *wm_class = NULL;
925 int workspace, level;
927 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
928 wm_instance = wwin->wm_instance;
929 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
930 wm_class = wwin->wm_class;
931 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
932 wm_instance = wwin->wm_instance;
933 wm_class = wwin->wm_class;
935 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
936 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
937 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
939 wWindowSetupInitialAttributes(wwin, &level, &workspace);
941 for (i=0; i < 11; i++) {
942 int flag = 0;
944 switch (i) {
945 case 0:
946 flag = WFLAGP(wwin, no_titlebar);
947 break;
948 case 1:
949 flag = WFLAGP(wwin, no_resizebar);
950 break;
951 case 2:
952 flag = WFLAGP(wwin, no_close_button);
953 break;
954 case 3:
955 flag = WFLAGP(wwin, no_miniaturize_button);
956 break;
957 case 4:
958 flag = WFLAGP(wwin, no_border);
959 break;
960 case 5:
961 flag = WFLAGP(wwin, floating);
962 break;
963 case 6:
964 flag = WFLAGP(wwin, sunken);
965 break;
966 case 7:
967 flag = WFLAGP(wwin, omnipresent);
968 break;
969 case 8:
970 flag = WFLAGP(wwin, start_miniaturized);
971 break;
972 case 9:
973 flag = WFLAGP(wwin, start_maximized!=0);
974 break;
975 case 10:
976 flag = WFLAGP(wwin, full_maximize);
977 break;
979 WMSetButtonSelected(panel->attrChk[i], flag);
981 for (i=0; i < 8; i++) {
982 int flag = 0;
984 switch (i) {
985 case 0:
986 flag = WFLAGP(wwin, no_bind_keys);
987 break;
988 case 1:
989 flag = WFLAGP(wwin, no_bind_mouse);
990 break;
991 case 2:
992 flag = WFLAGP(wwin, skip_window_list);
993 break;
994 case 3:
995 flag = WFLAGP(wwin, no_focusable);
996 break;
997 case 4:
998 flag = WFLAGP(wwin, dont_move_off);
999 break;
1000 case 5:
1001 flag = WFLAGP(wwin, no_hide_others);
1002 break;
1003 case 6:
1004 flag = WFLAGP(wwin, dont_save_session);
1005 break;
1006 case 7:
1007 flag = WFLAGP(wwin, emulate_appicon);
1008 break;
1009 #ifdef XKB_BUTTON_HINT
1010 case 8:
1011 flag = WFLAGP(wwin, no_language_button);
1012 break;
1013 #endif
1015 WMSetButtonSelected(panel->moreChk[i], flag);
1017 if (panel->appFrm && wapp) {
1018 for (i=0; i < 2; i++) {
1019 int flag = 0;
1021 switch (i) {
1022 case 0:
1023 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1024 break;
1025 case 1:
1026 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1027 break;
1028 case 2:
1029 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1030 break;
1032 WMSetButtonSelected(panel->appChk[i], flag);
1035 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1037 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class,
1038 REVERT_TO_DEFAULT);
1040 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
1042 if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
1043 WMSetPopUpButtonSelectedItem(panel->wsP, n+1);
1044 } else {
1045 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1048 /* must auto apply, so that there wno't be internal
1049 * inconsistencies between the state in the flags and
1050 * the actual state of the window */
1051 applySettings(panel->applyBtn, panel);
1055 static void
1056 chooseIconCallback(WMWidget *self, void *clientData)
1058 char *file;
1059 InspectorPanel *panel = (InspectorPanel*)clientData;
1060 int result;
1062 panel->choosingIcon = 1;
1064 WMSetButtonEnabled(panel->browseIconBtn, False);
1066 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
1067 panel->inspected->wm_instance,
1068 panel->inspected->wm_class);
1070 panel->choosingIcon = 0;
1072 if (!panel->destroyed) { /* kluge */
1073 if (result) {
1074 WMSetTextFieldText(panel->fileText, file);
1075 showIconFor(WMWidgetScreen(self), panel, NULL, NULL,
1076 USE_TEXT_FIELD);
1077 wfree(file);
1079 WMSetButtonEnabled(panel->browseIconBtn, True);
1080 } else {
1081 freeInspector(panel);
1086 static void
1087 textEditedObserver(void *observerData, WMNotification *notification)
1089 InspectorPanel *panel = (InspectorPanel*)observerData;
1091 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
1092 return;
1094 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL,
1095 USE_TEXT_FIELD);
1097 WMPerformButtonClick(panel->updateIconBtn);
1102 static void
1103 selectSpecification(WMWidget *bPtr, void *data)
1105 InspectorPanel *panel = (InspectorPanel*)data;
1106 char *str;
1107 WWindow *wwin = panel->inspected;
1108 int len;
1110 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class)) {
1111 WMSetButtonEnabled(panel->applyBtn, False);
1112 } else {
1113 WMSetButtonEnabled(panel->applyBtn, True);
1116 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
1117 + strlen(wwin->wm_class ? wwin->wm_class : "?");
1119 str = wmalloc(len);
1121 snprintf(str, len, _("Inspecting %s.%s"),
1122 wwin->wm_instance ? wwin->wm_instance : "?",
1123 wwin->wm_class ? wwin->wm_class : "?");
1125 wFrameWindowChangeTitle(panel->frame->frame, str);
1127 wfree(str);
1131 static void
1132 selectWindow(WMWidget *bPtr, void *data)
1134 InspectorPanel *panel = (InspectorPanel*)data;
1135 WWindow *wwin = panel->inspected;
1136 WScreen *scr = wwin->screen_ptr;
1137 XEvent event;
1138 WWindow *iwin;
1140 if (XGrabPointer(dpy, scr->root_win, True,
1141 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1142 wCursor[WCUR_SELECT], CurrentTime)!=GrabSuccess) {
1143 wwarning("could not grab mouse pointer");
1144 return;
1147 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1149 WMMaskEvent(dpy, ButtonPressMask, &event);
1151 XUngrabPointer(dpy, CurrentTime);
1153 iwin = wWindowFor(event.xbutton.subwindow);
1155 if (iwin && !iwin->flags.internal_window && iwin != wwin
1156 && !iwin->flags.inspector_open) {
1158 iwin->flags.inspector_open = 1;
1159 iwin->inspector = createInspectorForWindow(iwin,
1160 panel->frame->frame_x,
1161 panel->frame->frame_y,
1162 True);
1163 wCloseInspectorForWindow(wwin);
1164 } else {
1165 WMSetLabelText(panel->specLbl, spec_text);
1171 static InspectorPanel*
1172 createInspectorForWindow(WWindow *wwin, int xpos, int ypos,
1173 Bool showSelectPanel)
1175 WScreen *scr = wwin->screen_ptr;
1176 InspectorPanel *panel;
1177 Window parent;
1178 int i;
1179 int x, y;
1180 int btn_width, frame_width;
1181 WMButton *selectedBtn = NULL;
1182 #ifdef wrong_behaviour
1183 WMPixmap *pixmap;
1184 #endif
1186 spec_text = _("The configuration will apply to all\n"
1187 "windows that have their WM_CLASS\n"
1188 "property set to the above selected\n"
1189 "name, when saved.");
1191 panel = wmalloc(sizeof(InspectorPanel));
1192 memset(panel, 0, sizeof(InspectorPanel));
1194 panel->destroyed = 0;
1197 panel->inspected = wwin;
1199 panel->nextPtr = panelList;
1200 panelList = panel;
1203 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1204 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1207 /**** create common stuff ****/
1209 /* command buttons */
1210 /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
1211 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1212 panel->saveBtn = WMCreateCommandButton(panel->win);
1213 WMSetButtonAction(panel->saveBtn, (WMAction*)saveSettings, panel);
1214 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, 310);
1215 WMSetButtonText(panel->saveBtn, _("Save"));
1216 WMResizeWidget(panel->saveBtn, btn_width, 28);
1217 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1218 WMSetButtonEnabled(panel->saveBtn, False);
1220 panel->applyBtn = WMCreateCommandButton(panel->win);
1221 WMSetButtonAction(panel->applyBtn, (WMAction*)applySettings, panel);
1222 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, 310);
1223 WMSetButtonText(panel->applyBtn, _("Apply"));
1224 WMResizeWidget(panel->applyBtn, btn_width, 28);
1226 panel->revertBtn = WMCreateCommandButton(panel->win);
1227 WMSetButtonAction(panel->revertBtn, (WMAction*)revertSettings, panel);
1228 WMMoveWidget(panel->revertBtn, 15, 310);
1229 WMSetButtonText(panel->revertBtn, _("Reload"));
1230 WMResizeWidget(panel->revertBtn, btn_width, 28);
1232 /* page selection popup button */
1233 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1234 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction*)changePage, panel);
1235 WMMoveWidget(panel->pagePopUp, 25, 15);
1236 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1238 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1239 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1240 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1241 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1242 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1244 /**** window spec ****/
1245 frame_width = PWIDTH - (2 * 15);
1247 panel->specFrm = WMCreateFrame(panel->win);
1248 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1249 WMMoveWidget(panel->specFrm, 15, 65);
1250 WMResizeWidget(panel->specFrm, frame_width, 145);
1253 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1254 WMMoveWidget(panel->defaultRb, 10, 78);
1255 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1256 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1257 WMSetButtonSelected(panel->defaultRb, False);
1258 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1260 if (wwin->wm_class && wwin->wm_instance) {
1261 char *str, *tmp;
1263 tmp = wstrconcat(wwin->wm_instance, ".");
1264 str = wstrconcat(tmp, wwin->wm_class);
1266 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1267 WMMoveWidget(panel->bothRb, 10, 18);
1268 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1269 WMSetButtonText(panel->bothRb, str);
1270 wfree(tmp);
1271 wfree(str);
1272 WMGroupButtons(panel->defaultRb, panel->bothRb);
1274 if (!selectedBtn)
1275 selectedBtn = panel->bothRb;
1277 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1280 if (wwin->wm_instance) {
1281 panel->instRb = WMCreateRadioButton(panel->specFrm);
1282 WMMoveWidget(panel->instRb, 10, 38);
1283 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1284 WMSetButtonText(panel->instRb, wwin->wm_instance);
1285 WMGroupButtons(panel->defaultRb, panel->instRb);
1287 if (!selectedBtn)
1288 selectedBtn = panel->instRb;
1290 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1293 if (wwin->wm_class) {
1294 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1295 WMMoveWidget(panel->clsRb, 10, 58);
1296 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1297 WMSetButtonText(panel->clsRb, wwin->wm_class);
1298 WMGroupButtons(panel->defaultRb, panel->clsRb);
1300 if (!selectedBtn)
1301 selectedBtn = panel->clsRb;
1303 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1307 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1308 WMMoveWidget(panel->selWinB, 20, 145-24 - 10);
1309 WMResizeWidget(panel->selWinB, frame_width - 2*10 - 20, 24);
1310 WMSetButtonText(panel->selWinB, _("Select window"));
1311 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1314 panel->specLbl = WMCreateLabel(panel->win);
1315 WMMoveWidget(panel->specLbl, 15, 210);
1316 WMResizeWidget(panel->specLbl, frame_width, 100);
1317 WMSetLabelText(panel->specLbl, spec_text);
1318 WMSetLabelWraps(panel->specLbl, True);
1320 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1322 /**** attributes ****/
1323 panel->attrFrm = WMCreateFrame(panel->win);
1324 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1325 WMMoveWidget(panel->attrFrm, 15, 45);
1326 WMResizeWidget(panel->attrFrm, frame_width, 250);
1328 for (i=0; i < 11; i++) {
1329 char *caption = NULL;
1330 int flag = 0;
1331 char *descr = NULL;
1333 switch (i) {
1334 case 0:
1335 caption = _("Disable titlebar");
1336 flag = WFLAGP(wwin, no_titlebar);
1337 descr = _("Remove the titlebar of this window.\n"
1338 "To access the window commands menu of a window\n"
1339 "without it's titlebar, press Control+Esc (or the\n"
1340 "equivalent shortcut, if you changed the default\n"
1341 "settings).");
1342 break;
1343 case 1:
1344 caption = _("Disable resizebar");
1345 flag = WFLAGP(wwin, no_resizebar);
1346 descr = _("Remove the resizebar of this window.");
1347 break;
1348 case 2:
1349 caption = _("Disable close button");
1350 flag = WFLAGP(wwin, no_close_button);
1351 descr = _("Remove the `close window' button of this window.");
1352 break;
1353 case 3:
1354 caption = _("Disable miniaturize button");
1355 flag = WFLAGP(wwin, no_miniaturize_button);
1356 descr = _("Remove the `miniaturize window' button of the window.");
1357 break;
1358 case 4:
1359 caption = _("Disable border");
1360 flag = WFLAGP(wwin, no_border);
1361 descr = _("Remove the 1 pixel black border around the window.");
1362 break;
1363 case 5:
1364 caption = _("Keep on top (floating)");
1365 flag = WFLAGP(wwin, floating);
1366 descr = _("Keep the window over other windows, not allowing\n"
1367 "them to cover it.");
1368 break;
1369 case 6:
1370 caption = _("Keep at bottom (sunken)");
1371 flag = WFLAGP(wwin, sunken);
1372 descr = _("Keep the window under all other windows.");
1373 break;
1374 case 7:
1375 caption = _("Omnipresent");
1376 flag = WFLAGP(wwin, omnipresent);
1377 descr = _("Make window present in all workspaces.");
1378 break;
1379 case 8:
1380 caption = _("Start miniaturized");
1381 flag = WFLAGP(wwin, start_miniaturized);
1382 descr = _("Make the window be automatically miniaturized when it's\n"
1383 "first shown.");
1384 break;
1385 case 9:
1386 caption = _("Start maximized");
1387 flag = WFLAGP(wwin, start_maximized!=0);
1388 descr = _("Make the window be automatically maximized when it's\n"
1389 "first shown.");
1390 break;
1391 case 10:
1392 caption = _("Full screen maximization");
1393 flag = WFLAGP(wwin, full_maximize);
1394 descr = _("Make the window use the whole screen space when it's\n"
1395 "maximized. The titlebar and resizebar will be moved\n"
1396 "to outside the screen.");
1397 break;
1399 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1400 WMMoveWidget(panel->attrChk[i], 10, 20*(i+1));
1401 WMResizeWidget(panel->attrChk[i], frame_width-15, 20);
1402 WMSetButtonSelected(panel->attrChk[i], flag);
1403 WMSetButtonText(panel->attrChk[i], caption);
1405 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1409 /**** more attributes ****/
1410 panel->moreFrm = WMCreateFrame(panel->win);
1411 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1412 WMMoveWidget(panel->moreFrm, 15, 45);
1413 WMResizeWidget(panel->moreFrm, frame_width, 250);
1415 for (i=0;
1416 #ifdef XKB_BUTTON_HINT
1417 i < 9;
1418 #else
1419 i < 8;
1420 #endif
1421 i++) {
1422 char *caption = NULL;
1423 int flag = 0;
1424 char *descr = NULL;
1426 switch (i) {
1427 case 0:
1428 caption = _("Do not bind keyboard shortcuts");
1429 flag = WFLAGP(wwin, no_bind_keys);
1430 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1431 "when this window is focused. This will allow the\n"
1432 "window to receive all key combinations regardless\n"
1433 "of your shortcut configuration.");
1434 break;
1435 case 1:
1436 caption = _("Do not bind mouse clicks");
1437 flag = WFLAGP(wwin, no_bind_mouse);
1438 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1439 "in the window (when alt is the modifier you have"
1440 "configured).");
1441 break;
1442 case 2:
1443 caption = _("Do not show in the window list");
1444 flag = WFLAGP(wwin, skip_window_list);
1445 descr = _("Do not list the window in the window list menu.");
1446 break;
1447 case 3:
1448 caption = _("Do not let it take focus");
1449 flag = WFLAGP(wwin, no_focusable);
1450 descr = _("Do not let the window take keyboard focus when you\n"
1451 "click on it.");
1452 break;
1453 case 4:
1454 caption = _("Keep inside screen");
1455 flag = WFLAGP(wwin, dont_move_off);
1456 descr = _("Do not allow the window to move itself completely\n"
1457 "outside the screen. For bug compatibility.\n");
1458 break;
1459 case 5:
1460 caption = _("Ignore 'Hide Others'");
1461 flag = WFLAGP(wwin, no_hide_others);
1462 descr = _("Do not hide the window when issuing the\n"
1463 "`HideOthers' command.");
1464 break;
1465 case 6:
1466 caption = _("Ignore 'Save Session'");
1467 flag = WFLAGP(wwin, dont_save_session);
1468 descr = _("Do not save the associated application in the\n"
1469 "session's state, so that it won't be restarted\n"
1470 "together with other applications when Window Maker\n"
1471 "starts.");
1472 break;
1473 case 7:
1474 caption = _("Emulate application icon");
1475 flag = WFLAGP(wwin, emulate_appicon);
1476 descr = _("Make this window act as an application that provides\n"
1477 "enough information to Window Maker for a dockable\n"
1478 "application icon to be created.");
1479 break;
1480 #ifdef XKB_BUTTON_HINT
1481 case 8:
1482 caption = _("Disable language button");
1483 flag = WFLAGP(wwin, no_language_button);
1484 descr = _("Remove the `toggle language' button of the window.");
1485 break;
1486 #endif
1488 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1489 WMMoveWidget(panel->moreChk[i], 10, 20*(i+1));
1490 WMResizeWidget(panel->moreChk[i], frame_width-15, 20);
1491 WMSetButtonSelected(panel->moreChk[i], flag);
1492 WMSetButtonText(panel->moreChk[i], caption);
1494 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1497 /* miniwindow/workspace */
1498 panel->iconFrm = WMCreateFrame(panel->win);
1499 WMMoveWidget(panel->iconFrm, 15, 50);
1500 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1501 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1503 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1504 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1505 WMResizeWidget(panel->iconLbl, 64, 64);
1506 WMSetLabelRelief(panel->iconLbl, WRGroove);
1507 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1509 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1510 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1511 WMMoveWidget(panel->browseIconBtn, 22, 32);
1512 WMResizeWidget(panel->browseIconBtn, 120, 26);
1513 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1515 #ifdef wrong_behaviour
1516 WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
1517 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
1518 WMSetButtonImage(panel->updateIconBtn, pixmap);
1519 WMReleasePixmap(pixmap);
1520 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
1521 WMSetButtonAltImage(panel->updateIconBtn, pixmap);
1522 WMReleasePixmap(pixmap);
1523 #endif
1525 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1526 WMMoveWidget(panel->fileLbl, 20, 85);
1527 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1528 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1530 panel->fileText = WMCreateTextField(panel->iconFrm);
1531 WMMoveWidget(panel->fileText, 20, 105);
1532 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1533 WMSetTextFieldText(panel->fileText, NULL);
1534 WMAddNotificationObserver(textEditedObserver, panel,
1535 WMTextDidEndEditingNotification,
1536 panel->fileText);
1538 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1539 WMMoveWidget(panel->alwChk, 20, 130);
1540 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1541 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1542 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1545 panel->wsFrm = WMCreateFrame(panel->win);
1546 WMMoveWidget(panel->wsFrm, 15, 225);
1547 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1548 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1550 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1551 "first shown."), WMWidgetView(panel->wsFrm));
1553 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1554 WMMoveWidget(panel->wsP, 20, 30);
1555 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1556 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1557 for (i = 0; i < wwin->screen_ptr->workspace_count; i++) {
1558 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1561 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance,
1562 wwin->wm_class);
1563 if (i >= 0 && i <= wwin->screen_ptr->workspace_count) {
1564 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1565 } else {
1566 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1569 /* application wide attributes */
1570 if (wwin->main_window != None) {
1571 WApplication *wapp = wApplicationOf(wwin->main_window);
1573 panel->appFrm = WMCreateFrame(panel->win);
1574 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1575 WMMoveWidget(panel->appFrm, 15, 50);
1576 WMResizeWidget(panel->appFrm, frame_width, 240);
1578 for (i=0; i < 3; i++) {
1579 char *caption = NULL;
1580 int flag = 0;
1581 char *descr = NULL;
1583 switch (i) {
1584 case 0:
1585 caption = _("Start hidden");
1586 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1587 descr = _("Automatically hide application when it's started.");
1588 break;
1589 case 1:
1590 caption = _("No application icon");
1591 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1592 descr = _("Disable the application icon for the application.\n"
1593 "Note that you won't be able to dock it anymore,\n"
1594 "and any icons that are already docked will stop\n"
1595 "working correctly.");
1596 break;
1597 case 2:
1598 caption = _("Shared application icon");
1599 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1600 descr = _("Use a single shared application icon for all of\n"
1601 "the instances of this application.\n");
1602 break;
1604 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1605 WMMoveWidget(panel->appChk[i], 10, 20*(i+1));
1606 WMResizeWidget(panel->appChk[i], 205, 20);
1607 WMSetButtonSelected(panel->appChk[i], flag);
1608 WMSetButtonText(panel->appChk[i], caption);
1610 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1613 if (WFLAGP(wwin, emulate_appicon)) {
1614 WMSetButtonEnabled(panel->appChk[1], False);
1615 WMSetButtonEnabled(panel->moreChk[7], True);
1616 } else {
1617 WMSetButtonEnabled(panel->appChk[1], True);
1618 WMSetButtonEnabled(panel->moreChk[7], False);
1620 } else {
1621 int tmp;
1623 if ((wwin->transient_for!=None && wwin->transient_for!=scr->root_win)
1624 || !wwin->wm_class || !wwin->wm_instance)
1625 tmp = False;
1626 else
1627 tmp = True;
1628 WMSetButtonEnabled(panel->moreChk[7], tmp);
1630 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1631 panel->appFrm = NULL;
1634 /* if the window is a transient, don't let it have a miniaturize
1635 * button */
1636 if (wwin->transient_for!=None && wwin->transient_for!=scr->root_win)
1637 WMSetButtonEnabled(panel->attrChk[3], False);
1638 else
1639 WMSetButtonEnabled(panel->attrChk[3], True);
1642 if (!wwin->wm_class && !wwin->wm_instance) {
1643 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1647 WMRealizeWidget(panel->win);
1649 WMMapSubwidgets(panel->win);
1650 WMMapSubwidgets(panel->specFrm);
1651 WMMapSubwidgets(panel->attrFrm);
1652 WMMapSubwidgets(panel->moreFrm);
1653 WMMapSubwidgets(panel->iconFrm);
1654 WMMapSubwidgets(panel->wsFrm);
1655 if (panel->appFrm)
1656 WMMapSubwidgets(panel->appFrm);
1658 if (showSelectPanel) {
1659 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1660 changePage(panel->pagePopUp, panel);
1661 } else {
1662 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1663 changePage(panel->pagePopUp, panel);
1667 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT,
1668 0, 0, 0);
1669 XSelectInput(dpy, parent, KeyPressMask|KeyReleaseMask);
1670 panel->parent = parent;
1671 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1673 WMMapWidget(panel->win);
1675 XSetTransientForHint(dpy, parent, wwin->client_win);
1677 if (xpos == UNDEFINED_POS) {
1678 x = wwin->frame_x+wwin->frame->core->width/2;
1679 y = wwin->frame_y+wwin->frame->top_width*2;
1680 if (y + PHEIGHT > scr->scr_height)
1681 y = scr->scr_height - PHEIGHT - 30;
1682 if (x + PWIDTH > scr->scr_width)
1683 x = scr->scr_width - PWIDTH;
1684 } else {
1685 x = xpos;
1686 y = ypos;
1689 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win,
1690 "Inspector", x, y, PWIDTH, PHEIGHT);
1692 if (!selectedBtn)
1693 selectedBtn = panel->defaultRb;
1695 WMSetButtonSelected(selectedBtn, True);
1697 selectSpecification(selectedBtn, panel);
1699 /* kluge to know who should get the key events */
1700 panel->frame->client_leader = WMWidgetXID(panel->win);
1702 WSETUFLAG(panel->frame, no_closable, 0);
1703 WSETUFLAG(panel->frame, no_close_button, 0);
1704 wWindowUpdateButtonImages(panel->frame);
1705 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1706 panel->frame->frame->on_click_right = destroyInspector;
1708 wWindowMap(panel->frame);
1710 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance,
1711 wwin->wm_class, UPDATE_TEXT_FIELD);
1713 return panel;
1717 void
1718 wShowInspectorForWindow(WWindow *wwin)
1720 if (wwin->flags.inspector_open)
1721 return;
1723 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1725 make_keys();
1726 wwin->flags.inspector_open = 1;
1727 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS,
1728 UNDEFINED_POS, False);
1734 void
1735 wHideInspectorForWindow(WWindow *wwin)
1737 WWindow *pwin = wwin->inspector->frame;
1739 wWindowUnmap(pwin);
1740 pwin->flags.hidden = 1;
1742 wClientSetState(pwin, IconicState, None);
1747 void
1748 wUnhideInspectorForWindow(WWindow *wwin)
1750 WWindow *pwin = wwin->inspector->frame;
1752 pwin->flags.hidden = 0;
1753 pwin->flags.mapped = 1;
1754 XMapWindow(dpy, pwin->client_win);
1755 XMapWindow(dpy, pwin->frame->core->window);
1756 wClientSetState(pwin, NormalState, None);
1761 WWindow*
1762 wGetWindowOfInspectorForWindow(WWindow *wwin)
1764 if (wwin->inspector) {
1765 assert(wwin->flags.inspector_open != 0);
1767 return wwin->inspector->frame;
1768 } else
1769 return NULL;
1773 void
1774 wCloseInspectorForWindow(WWindow *wwin)
1776 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1778 (*pwin->frame->on_click_right)(NULL, pwin, NULL);