- s/sprintf/snprintf
[wmaker-crm.git] / src / winspector.c
blobfc2c30f836ec1e8438523df2a3cc0f9485d3d188
1 /* winspector.c - window attribute inspector
2 *
3 * Window Maker window manager
4 *
5 * Copyright (c) 1997, 1998 Alfredo K. Kojima
6 * Copyright (c) 1998 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"
50 #include <proplist.h>
58 typedef struct InspectorPanel {
59 struct InspectorPanel *nextPtr;
61 WWindow *frame;
63 WWindow *inspected; /* the window that's being inspected */
65 WMWindow *win;
67 Window parent;
69 /* common stuff */
70 WMButton *revertBtn;
71 WMButton *applyBtn;
72 WMButton *saveBtn;
74 WMPopUpButton *pagePopUp;
76 /* first page. general stuff */
78 WMFrame *specFrm;
79 WMButton *instRb;
80 WMButton *clsRb;
81 WMButton *bothRb;
82 WMButton *defaultRb;
84 WMButton *selWinB;
86 WMLabel *specLbl;
88 /* second page. attributes */
90 WMFrame *attrFrm;
91 WMButton *attrChk[11];
93 /* 3rd page. more attributes */
94 WMFrame *moreFrm;
95 #ifdef XKB_BUTTON_HINT
96 WMButton *moreChk[9];
97 #else
98 WMButton *moreChk[8];
99 #endif
101 /* 4th page. icon and workspace */
102 WMFrame *iconFrm;
103 WMLabel *iconLbl;
104 WMLabel *fileLbl;
105 WMTextField *fileText;
106 WMButton *alwChk;
108 WMButton *updateIconBtn;
110 WMButton *browseIconBtn;
112 WMFrame *wsFrm;
113 WMPopUpButton *wsP;
115 /* 5th page. application wide attributes */
116 WMFrame *appFrm;
117 WMButton *appChk[3];
119 unsigned int done:1;
120 unsigned int destroyed:1;
121 unsigned int choosingIcon:1;
122 } InspectorPanel;
127 extern Cursor wCursor[WCUR_LAST];
129 extern WDDomain *WDWindowAttributes;
131 static InspectorPanel *panelList=NULL;
133 extern WPreferences wPreferences;
135 static proplist_t ANoTitlebar = NULL;
136 static proplist_t ANoResizebar;
137 static proplist_t ANoMiniaturizeButton;
138 static proplist_t ANoCloseButton;
139 static proplist_t ANoBorder;
140 static proplist_t ANoHideOthers;
141 static proplist_t ANoMouseBindings;
142 static proplist_t ANoKeyBindings;
143 static proplist_t ANoAppIcon;
144 static proplist_t AKeepOnTop;
145 static proplist_t AKeepOnBottom;
146 static proplist_t AOmnipresent;
147 static proplist_t ASkipWindowList;
148 static proplist_t AKeepInsideScreen;
149 static proplist_t AUnfocusable;
150 static proplist_t AAlwaysUserIcon;
151 static proplist_t AStartMiniaturized;
152 static proplist_t AStartMaximized;
153 static proplist_t ADontSaveSession;
154 static proplist_t AEmulateAppIcon;
155 static proplist_t AFullMaximize;
156 static proplist_t ACollapseAppIcons;
157 #ifdef XKB_BUTTON_HINT
158 static proplist_t ANoLanguageButton;
159 #endif
161 static proplist_t AStartWorkspace;
163 static proplist_t AIcon;
165 /* application wide options */
166 static proplist_t AStartHidden;
169 static proplist_t AnyWindow;
170 static proplist_t EmptyString;
171 static proplist_t Yes, No;
174 #define PWIDTH 270
175 #define PHEIGHT 350
179 static char *spec_text;
182 static void applySettings(WMButton *button, InspectorPanel *panel);
187 #define UNDEFINED_POS 0xffffff
189 static InspectorPanel *createInspectorForWindow(WWindow *wwin,
190 int xpos, int ypos,
191 Bool showSelectPanel);
195 static void
196 make_keys()
198 if (ANoTitlebar!=NULL)
199 return;
201 AIcon = PLMakeString("Icon");
202 ANoTitlebar = PLMakeString("NoTitlebar");
203 ANoResizebar = PLMakeString("NoResizebar");
204 ANoMiniaturizeButton = PLMakeString("NoMiniaturizeButton");
205 ANoCloseButton = PLMakeString("NoCloseButton");
206 ANoBorder = PLMakeString("NoBorder");
207 ANoHideOthers = PLMakeString("NoHideOthers");
208 ANoMouseBindings = PLMakeString("NoMouseBindings");
209 ANoKeyBindings = PLMakeString("NoKeyBindings");
210 ANoAppIcon = PLMakeString("NoAppIcon");
211 AKeepOnTop = PLMakeString("KeepOnTop");
212 AKeepOnBottom = PLMakeString("KeepOnBottom");
213 AOmnipresent = PLMakeString("Omnipresent");
214 ASkipWindowList = PLMakeString("SkipWindowList");
215 AKeepInsideScreen = PLMakeString("KeepInsideScreen");
216 AUnfocusable = PLMakeString("Unfocusable");
217 AAlwaysUserIcon = PLMakeString("AlwaysUserIcon");
218 AStartMiniaturized = PLMakeString("StartMiniaturized");
219 AStartMaximized = PLMakeString("StartMaximized");
220 AStartHidden = PLMakeString("StartHidden");
221 ADontSaveSession = PLMakeString("DontSaveSession");
222 AEmulateAppIcon = PLMakeString("EmulateAppIcon");
223 AFullMaximize = PLMakeString("FullMaximize");
224 ACollapseAppIcons = PLMakeString("CollapseAppIcons");
225 #ifdef XKB_BUTTON_HINT
226 ANoLanguageButton = PLMakeString("NoLanguageButton");
227 #endif
229 AStartWorkspace = PLMakeString("StartWorkspace");
231 AnyWindow = PLMakeString("*");
232 EmptyString = PLMakeString("");
233 Yes = PLMakeString("Yes");
234 No = PLMakeString("No");
239 static void
240 freeInspector(InspectorPanel *panel)
242 panel->destroyed = 1;
243 if (panel->choosingIcon)
244 return;
246 WMDestroyWidget(panel->win);
248 XDestroyWindow(dpy, panel->parent);
250 wfree(panel);
254 static void
255 destroyInspector(WCoreWindow *foo, void *data, XEvent *event)
257 InspectorPanel *panel;
258 InspectorPanel *tmp;
260 panel = panelList;
261 while (panel->frame!=data)
262 panel = panel->nextPtr;
264 if (panelList == panel)
265 panelList = panel->nextPtr;
266 else {
267 tmp = panelList;
268 while (tmp->nextPtr!=panel) {
269 tmp = tmp->nextPtr;
271 tmp->nextPtr = panel->nextPtr;
273 panel->inspected->flags.inspector_open = 0;
274 panel->inspected->inspector = NULL;
276 WMRemoveNotificationObserver(panel);
278 wWindowUnmap(panel->frame);
279 wUnmanageWindow(panel->frame, True, False);
281 freeInspector(panel);
286 void
287 wDestroyInspectorPanels()
289 InspectorPanel *panel;
291 while (panelList != NULL) {
292 panel = panelList;
293 panelList = panelList->nextPtr;
294 wUnmanageWindow(panel->frame, False, False);
295 WMDestroyWidget(panel->win);
297 panel->inspected->flags.inspector_open = 0;
298 panel->inspected->inspector = NULL;
300 wfree(panel);
305 static void
306 changePage(WMPopUpButton *bPtr, InspectorPanel *panel)
308 int page;
310 page = WMGetPopUpButtonSelectedItem(bPtr);
312 if (page == 0) {
313 WMMapWidget(panel->specFrm);
314 WMMapWidget(panel->specLbl);
315 } else if (page == 1) {
316 WMMapWidget(panel->attrFrm);
317 } else if (page == 2) {
318 WMMapWidget(panel->moreFrm);
319 } else if (page == 3) {
320 WMMapWidget(panel->iconFrm);
321 WMMapWidget(panel->wsFrm);
322 } else {
323 WMMapWidget(panel->appFrm);
326 if (page != 0) {
327 WMUnmapWidget(panel->specFrm);
328 WMUnmapWidget(panel->specLbl);
330 if (page != 1)
331 WMUnmapWidget(panel->attrFrm);
332 if (page != 2)
333 WMUnmapWidget(panel->moreFrm);
334 if (page != 3) {
335 WMUnmapWidget(panel->iconFrm);
336 WMUnmapWidget(panel->wsFrm);
338 if (page != 4 && panel->appFrm)
339 WMUnmapWidget(panel->appFrm);
343 #define USE_TEXT_FIELD 1
344 #define UPDATE_TEXT_FIELD 2
345 #define REVERT_TO_DEFAULT 4
348 static int
349 showIconFor(WMScreen *scrPtr, InspectorPanel *panel,
350 char *wm_instance, char *wm_class, int flags)
352 WMPixmap *pixmap = (WMPixmap*) NULL;
353 char *file=NULL, *path=NULL;
354 char *db_icon=NULL;
356 if ((flags & USE_TEXT_FIELD) != 0) {
357 file = WMGetTextFieldText(panel->fileText);
358 if (file && file[0] == 0) {
359 wfree(file);
360 file = NULL;
362 } else {
363 db_icon = wDefaultGetIconFile(panel->inspected->screen_ptr,
364 wm_instance, wm_class, False);
365 if(db_icon != NULL)
366 file = wstrdup(db_icon);
368 if (db_icon!=NULL && (flags & REVERT_TO_DEFAULT)!=0) {
369 if (file)
370 file = wstrdup(db_icon);
371 flags |= UPDATE_TEXT_FIELD;
374 if ((flags & UPDATE_TEXT_FIELD) != 0) {
375 WMSetTextFieldText(panel->fileText, file);
378 if (file) {
379 path = FindImage(wPreferences.icon_path, file);
381 if (!path) {
382 char *buf;
383 int len = strlen(file)+80;
385 buf = wmalloc(len);
386 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"),
387 file);
388 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf,
389 _("OK"), NULL, NULL);
390 wfree(buf);
391 wfree(file);
392 return -1;
395 pixmap = WMCreatePixmapFromFile(scrPtr, path);
396 wfree(path);
398 if (!pixmap) {
399 char *buf;
400 int len = strlen(file)+80;
402 buf = wmalloc(len);
403 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
404 file, RMessageForError(RErrorCode));
405 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf,
406 _("OK"), NULL, NULL);
407 wfree(buf);
408 wfree(file);
409 return -1;
411 wfree(file);
414 WMSetLabelImage(panel->iconLbl, pixmap);
415 if (pixmap)
416 WMReleasePixmap(pixmap);
418 return 0;
421 #if 0
422 static void
423 updateIcon(WMButton *button, InspectorPanel *panel)
425 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
427 #endif
429 static int
430 getBool(proplist_t value)
432 char *val;
434 if (!PLIsString(value)) {
435 return 0;
437 if (!(val = PLGetString(value))) {
438 return 0;
441 if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y' || val[0]=='T'
442 || val[0]=='t' || val[0]=='1'))
443 || (strcasecmp(val, "YES")==0 || strcasecmp(val, "TRUE")==0)) {
445 return 1;
446 } else if ((val[1]=='\0'
447 && (val[0]=='n' || val[0]=='N' || val[0]=='F'
448 || val[0]=='f' || val[0]=='0'))
449 || (strcasecmp(val, "NO")==0 || strcasecmp(val, "FALSE")==0)) {
451 return 0;
452 } else {
453 wwarning(_("can't convert \"%s\" to boolean"), val);
454 return 0;
459 #define UPDATE_DEFAULTS 1
460 #define IS_BOOLEAN 2
464 * Will insert the attribute = value; pair in window's list,
465 * if it's different from the defaults.
466 * Defaults means either defaults database, or attributes saved
467 * for the default window "*". This is to let one revert options that are
468 * global because they were saved for all windows ("*").
473 static int
474 insertAttribute(proplist_t dict, proplist_t window, proplist_t attr,
475 proplist_t value, int flags)
477 proplist_t def_win, def_value=NULL;
478 int update = 0;
479 int modified = 0;
481 if (!(flags & UPDATE_DEFAULTS) && dict) {
482 if ((def_win = PLGetDictionaryEntry(dict, AnyWindow)) != NULL) {
483 def_value = PLGetDictionaryEntry(def_win, attr);
487 /* If we could not find defaults in database, fall to hardcoded values.
488 * Also this is true if we save defaults for all windows
490 if (!def_value)
491 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
493 if ((flags & IS_BOOLEAN))
494 update = (getBool(value) != getBool(def_value));
495 else {
496 update = !PLIsEqual(value, def_value);
499 if (update) {
500 PLInsertDictionaryEntry(window, attr, value);
501 modified = 1;
504 return modified;
508 static void
509 saveSettings(WMButton *button, InspectorPanel *panel)
511 WWindow *wwin = panel->inspected;
512 WDDomain *db = WDWindowAttributes;
513 proplist_t dict = db->dictionary;
514 proplist_t winDic, value, key;
515 char *icon_file;
516 int flags = 0;
517 int different = 0;
519 /* Save will apply the changes and save them */
520 applySettings(panel->applyBtn, panel);
522 if (WMGetButtonSelected(panel->instRb) != 0)
523 key = PLMakeString(wwin->wm_instance);
524 else if (WMGetButtonSelected(panel->clsRb) != 0)
525 key = PLMakeString(wwin->wm_class);
526 else if (WMGetButtonSelected(panel->bothRb) != 0) {
527 char *buffer;
529 buffer = wmalloc(strlen(wwin->wm_instance)+strlen(wwin->wm_class)+4);
530 strcat(strcat(strcpy(buffer, wwin->wm_instance), "."), wwin->wm_class);
531 key = PLMakeString(buffer);
532 wfree(buffer);
533 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
534 key = PLRetain(AnyWindow);
535 flags = UPDATE_DEFAULTS;
536 } else
537 key = NULL;
539 if (!key)
540 return;
542 if (!dict) {
543 dict = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
544 if (dict) {
545 db->dictionary = dict;
546 value = PLMakeString(db->path);
547 PLSetFilename(dict, value);
548 PLRelease(value);
550 else {
551 PLRelease(key);
552 return;
556 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL,
557 USE_TEXT_FIELD) < 0)
558 return;
560 PLSetStringCmpHook(NULL);
562 winDic = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
564 /* Update icon for window */
565 icon_file = WMGetTextFieldText(panel->fileText);
566 if (icon_file) {
567 if (icon_file[0] != 0) {
568 value = PLMakeString(icon_file);
569 different |= insertAttribute(dict, winDic, AIcon, value, flags);
570 PLRelease(value);
572 wfree(icon_file);
576 int i = WMGetPopUpButtonSelectedItem(panel->wsP);
578 i--;
580 if (i>=0 && i < panel->frame->screen_ptr->workspace_count) {
581 value = PLMakeString(panel->frame->screen_ptr->workspaces[i]->name);
582 different |= insertAttribute(dict, winDic, AStartWorkspace, value,
583 flags);
584 PLRelease(value);
588 flags |= IS_BOOLEAN;
590 value = (WMGetButtonSelected(panel->alwChk)!=0) ? Yes : No;
591 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
593 value = (WMGetButtonSelected(panel->attrChk[0])!=0) ? Yes : No;
594 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
596 value = (WMGetButtonSelected(panel->attrChk[1])!=0) ? Yes : No;
597 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
599 value = (WMGetButtonSelected(panel->attrChk[2])!=0) ? Yes : No;
600 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
602 value = (WMGetButtonSelected(panel->attrChk[3])!=0) ? Yes : No;
603 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
605 value = (WMGetButtonSelected(panel->attrChk[4])!=0) ? Yes : No;
606 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
608 value = (WMGetButtonSelected(panel->attrChk[5])!=0) ? Yes : No;
609 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
611 value = (WMGetButtonSelected(panel->attrChk[6])!=0) ? Yes : No;
612 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
614 value = (WMGetButtonSelected(panel->attrChk[7])!=0) ? Yes : No;
615 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
617 value = (WMGetButtonSelected(panel->attrChk[8])!=0) ? Yes : No;
618 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
620 value = (WMGetButtonSelected(panel->attrChk[9])!=0) ? Yes : No;
621 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
623 value = (WMGetButtonSelected(panel->attrChk[10])!=0) ? Yes : No;
624 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
627 value = (WMGetButtonSelected(panel->moreChk[0])!=0) ? Yes : No;
628 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
630 value = (WMGetButtonSelected(panel->moreChk[1])!=0) ? Yes : No;
631 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
633 value = (WMGetButtonSelected(panel->moreChk[2])!=0) ? Yes : No;
634 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
636 value = (WMGetButtonSelected(panel->moreChk[3])!=0) ? Yes : No;
637 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
639 value = (WMGetButtonSelected(panel->moreChk[4])!=0) ? Yes : No;
640 different |= insertAttribute(dict, winDic, AKeepInsideScreen,value, flags);
642 value = (WMGetButtonSelected(panel->moreChk[5])!=0) ? Yes : No;
643 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
645 value = (WMGetButtonSelected(panel->moreChk[6])!=0) ? Yes : No;
646 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
648 value = (WMGetButtonSelected(panel->moreChk[7])!=0) ? Yes : No;
649 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
651 #ifdef XKB_BUTTON_HINT
652 value = (WMGetButtonSelected(panel->moreChk[8])!=0) ? Yes : No;
653 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
654 #endif
656 /* application wide settings for when */
657 /* the window is the leader, save the attribute with the others */
658 if (panel->inspected->main_window == panel->inspected->client_win) {
660 value = (WMGetButtonSelected(panel->appChk[0])!=0) ? Yes : No;
661 different |= insertAttribute(dict, winDic, AStartHidden, value, flags);
663 value = (WMGetButtonSelected(panel->appChk[1])!=0) ? Yes : No;
664 different |= insertAttribute(dict, winDic, ANoAppIcon, value, flags);
666 value = (WMGetButtonSelected(panel->appChk[2])!=0) ? Yes : No;
667 different |= insertAttribute(dict, winDic, ACollapseAppIcons, value, flags);
670 PLRemoveDictionaryEntry(dict, key);
671 if (different) {
672 PLInsertDictionaryEntry(dict, key, winDic);
675 PLRelease(key);
676 PLRelease(winDic);
678 different = 0;
680 /* application wide settings */
681 if (panel->inspected->main_window != panel->inspected->client_win
682 && !(flags & UPDATE_DEFAULTS)) {
683 WApplication *wapp;
684 proplist_t appDic;
686 wapp = wApplicationOf(panel->inspected->main_window);
687 if (wapp) {
688 char *iconFile;
689 char *buffer;
691 appDic = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
693 assert(wapp->main_window_desc->wm_instance!=NULL);
694 assert(wapp->main_window_desc->wm_class!=NULL);
696 buffer = wmalloc(strlen(wapp->main_window_desc->wm_instance)
697 +strlen(wapp->main_window_desc->wm_class)+4);
698 strcat(strcpy(buffer, wapp->main_window_desc->wm_instance), ".");
699 strcat(buffer, wapp->main_window_desc->wm_class);
700 key = PLMakeString(buffer);
701 wfree(buffer);
703 iconFile = wDefaultGetIconFile(wwin->screen_ptr,
704 wapp->main_window_desc->wm_instance,
705 wapp->main_window_desc->wm_class,
706 False);
708 if (iconFile && iconFile[0]!=0) {
709 value = PLMakeString(iconFile);
710 different |= insertAttribute(dict, appDic, AIcon, value,
711 flags&~IS_BOOLEAN);
712 PLRelease(value);
715 value = (WMGetButtonSelected(panel->appChk[0])!=0) ? Yes : No;
716 different |= insertAttribute(dict, appDic, AStartHidden, value,
717 flags);
719 value = (WMGetButtonSelected(panel->appChk[1])!=0) ? Yes : No;
720 different |= insertAttribute(dict, appDic, ANoAppIcon, value,
721 flags);
723 value = (WMGetButtonSelected(panel->appChk[2])!=0) ? Yes : No;
724 different |= insertAttribute(dict, appDic, ACollapseAppIcons, value,
725 flags);
727 PLRemoveDictionaryEntry(dict, key);
728 if (different) {
729 PLInsertDictionaryEntry(dict, key, appDic);
731 PLRelease(key);
732 PLRelease(appDic);
736 PLSave(dict, YES);
738 /* clean up */
739 PLSetStringCmpHook(StringCompareHook);
743 static void
744 makeAppIconFor(WApplication *wapp)
746 WScreen *scr = wapp->main_window_desc->screen_ptr;
748 if (wapp->app_icon)
749 return;
751 if (!WFLAGP(wapp->main_window_desc, no_appicon))
752 wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
753 else
754 wapp->app_icon = NULL;
756 if (wapp->app_icon) {
757 WIcon *icon = wapp->app_icon->icon;
758 WDock *clip = scr->workspaces[scr->current_workspace]->clip;
759 int x=0, y=0;
761 wapp->app_icon->main_window = wapp->main_window;
763 if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
764 wapp->app_icon->attracted = 1;
765 if (!wapp->app_icon->icon->shadowed) {
766 wapp->app_icon->icon->shadowed = 1;
767 wapp->app_icon->icon->force_paint = 1;
769 wDockAttachIcon(clip, wapp->app_icon, x, y);
770 } else {
771 PlaceIcon(scr, &x, &y);
772 wAppIconMove(wapp->app_icon, x, y);
774 if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
775 XMapWindow(dpy, icon->core->window);
777 if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
778 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
783 static void
784 removeAppIconFor(WApplication *wapp)
786 if (!wapp->app_icon)
787 return;
789 if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
790 wapp->app_icon->running = 0;
791 /* since we keep it, we don't care if it was attracted or not */
792 wapp->app_icon->attracted = 0;
793 wapp->app_icon->icon->shadowed = 0;
794 wapp->app_icon->main_window = None;
795 wapp->app_icon->pid = 0;
796 wapp->app_icon->icon->owner = NULL;
797 wapp->app_icon->icon->icon_win = None;
798 wapp->app_icon->icon->force_paint = 1;
799 wAppIconPaint(wapp->app_icon);
800 } else if (wapp->app_icon->docked) {
801 wapp->app_icon->running = 0;
802 wDockDetach(wapp->app_icon->dock, wapp->app_icon);
803 } else {
804 wAppIconDestroy(wapp->app_icon);
806 wapp->app_icon = NULL;
807 if (wPreferences.auto_arrange_icons)
808 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
812 static void
813 applySettings(WMButton *button, InspectorPanel *panel)
815 WWindow *wwin = panel->inspected;
816 WApplication *wapp = wApplicationOf(wwin->main_window);
817 int floating, sunken, skip_window_list;
818 int old_omnipresent;
819 int old_no_bind_keys;
820 int old_no_bind_mouse;
822 old_omnipresent = WFLAGP(wwin, omnipresent);
823 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
824 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
826 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
828 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
829 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
830 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
831 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
832 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
833 floating = WMGetButtonSelected(panel->attrChk[5]);
834 sunken = WMGetButtonSelected(panel->attrChk[6]);
835 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
836 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
837 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
838 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
840 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
841 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
842 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
843 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[3]));
844 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[4]));
845 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[5]));
846 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[6]));
847 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[7]));
848 #ifdef XKB_BUTTON_HINT
849 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[8]));
850 #endif
851 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
853 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
854 wUnshadeWindow(wwin);
856 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
858 if (floating) {
859 if (!WFLAGP(wwin, floating))
860 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
861 } else if (sunken) {
862 if (!WFLAGP(wwin, sunken))
863 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
864 } else {
865 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
866 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
869 WSETUFLAG(wwin, sunken, sunken);
870 WSETUFLAG(wwin, floating, floating);
871 wwin->flags.omnipresent = 0;
873 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
874 WSETUFLAG(wwin, skip_window_list, skip_window_list);
875 UpdateSwitchMenu(wwin->screen_ptr, wwin,
876 skip_window_list ? ACTION_REMOVE : ACTION_ADD);
877 } else {
878 if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
879 UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE_WORKSPACE);
883 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
884 if (WFLAGP(wwin, no_bind_keys)) {
885 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
886 } else {
887 wWindowSetKeyGrabs(wwin);
891 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
892 wWindowResetMouseGrabs(wwin);
895 wwin->frame->flags.need_texture_change = 1;
896 wWindowConfigureBorders(wwin);
897 wFrameWindowPaint(wwin->frame);
900 * Can't apply emulate_appicon because it will probably cause problems.
903 if (wapp) {
904 /* do application wide stuff */
905 WSETUFLAG(wapp->main_window_desc, start_hidden,
906 WMGetButtonSelected(panel->appChk[0]));
908 WSETUFLAG(wapp->main_window_desc, no_appicon,
909 WMGetButtonSelected(panel->appChk[1]));
911 WSETUFLAG(wapp->main_window_desc, collapse_appicons,
912 WMGetButtonSelected(panel->appChk[2]));
914 if (WFLAGP(wapp->main_window_desc, no_appicon))
915 removeAppIconFor(wapp);
916 else
917 makeAppIconFor(wapp);
919 if (wapp->app_icon && wapp->main_window == wwin->client_win) {
920 char *file = WMGetTextFieldText(panel->fileText);
922 if (file[0] == 0) {
923 wfree(file);
924 file = NULL;
926 wIconChangeImageFile(wapp->app_icon->icon, file);
927 if (file)
928 wfree(file);
929 wAppIconPaint(wapp->app_icon);
937 static void
938 revertSettings(WMButton *button, InspectorPanel *panel)
940 WWindow *wwin = panel->inspected;
941 WApplication *wapp = wApplicationOf(wwin->main_window);
942 int i, n;
943 char *wm_instance = NULL;
944 char *wm_class = NULL;
945 int workspace, level;
947 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
948 wm_instance = wwin->wm_instance;
949 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
950 wm_class = wwin->wm_class;
951 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
952 wm_instance = wwin->wm_instance;
953 wm_class = wwin->wm_class;
955 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
956 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
957 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
959 wWindowSetupInitialAttributes(wwin, &level, &workspace);
961 for (i=0; i < 11; i++) {
962 int flag = 0;
964 switch (i) {
965 case 0:
966 flag = WFLAGP(wwin, no_titlebar);
967 break;
968 case 1:
969 flag = WFLAGP(wwin, no_resizebar);
970 break;
971 case 2:
972 flag = WFLAGP(wwin, no_close_button);
973 break;
974 case 3:
975 flag = WFLAGP(wwin, no_miniaturize_button);
976 break;
977 case 4:
978 flag = WFLAGP(wwin, no_border);
979 break;
980 case 5:
981 flag = WFLAGP(wwin, floating);
982 break;
983 case 6:
984 flag = WFLAGP(wwin, sunken);
985 break;
986 case 7:
987 flag = WFLAGP(wwin, omnipresent);
988 break;
989 case 8:
990 flag = WFLAGP(wwin, start_miniaturized);
991 break;
992 case 9:
993 flag = WFLAGP(wwin, start_maximized!=0);
994 break;
995 case 10:
996 flag = WFLAGP(wwin, full_maximize);
997 break;
999 WMSetButtonSelected(panel->attrChk[i], flag);
1001 for (i=0; i < 8; i++) {
1002 int flag = 0;
1004 switch (i) {
1005 case 0:
1006 flag = WFLAGP(wwin, no_bind_keys);
1007 break;
1008 case 1:
1009 flag = WFLAGP(wwin, no_bind_mouse);
1010 break;
1011 case 2:
1012 flag = WFLAGP(wwin, skip_window_list);
1013 break;
1014 case 3:
1015 flag = WFLAGP(wwin, no_focusable);
1016 break;
1017 case 4:
1018 flag = WFLAGP(wwin, dont_move_off);
1019 break;
1020 case 5:
1021 flag = WFLAGP(wwin, no_hide_others);
1022 break;
1023 case 6:
1024 flag = WFLAGP(wwin, dont_save_session);
1025 break;
1026 case 7:
1027 flag = WFLAGP(wwin, emulate_appicon);
1028 break;
1029 #ifdef XKB_BUTTON_HINT
1030 case 8:
1031 flag = WFLAGP(wwin, no_language_button);
1032 break;
1033 #endif
1035 WMSetButtonSelected(panel->moreChk[i], flag);
1037 if (panel->appFrm && wapp) {
1038 for (i=0; i < 2; i++) {
1039 int flag = 0;
1041 switch (i) {
1042 case 0:
1043 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1044 break;
1045 case 1:
1046 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1047 break;
1048 case 2:
1049 flag = WFLAGP(wapp->main_window_desc, collapse_appicons);
1050 break;
1052 WMSetButtonSelected(panel->appChk[i], flag);
1055 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1057 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class,
1058 REVERT_TO_DEFAULT);
1060 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
1062 if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
1063 WMSetPopUpButtonSelectedItem(panel->wsP, n+1);
1064 } else {
1065 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1068 /* must auto apply, so that there wno't be internal
1069 * inconsistencies between the state in the flags and
1070 * the actual state of the window */
1071 applySettings(panel->applyBtn, panel);
1075 static void
1076 chooseIconCallback(WMWidget *self, void *clientData)
1078 char *file;
1079 InspectorPanel *panel = (InspectorPanel*)clientData;
1080 int result;
1082 panel->choosingIcon = 1;
1084 WMSetButtonEnabled(panel->browseIconBtn, False);
1086 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
1087 panel->inspected->wm_instance,
1088 panel->inspected->wm_class);
1090 panel->choosingIcon = 0;
1092 if (!panel->destroyed) { /* kluge */
1093 if (result) {
1094 WMSetTextFieldText(panel->fileText, file);
1095 showIconFor(WMWidgetScreen(self), panel, NULL, NULL,
1096 USE_TEXT_FIELD);
1097 wfree(file);
1099 WMSetButtonEnabled(panel->browseIconBtn, True);
1100 } else {
1101 freeInspector(panel);
1106 static void
1107 textEditedObserver(void *observerData, WMNotification *notification)
1109 InspectorPanel *panel = (InspectorPanel*)observerData;
1111 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
1112 return;
1114 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL,
1115 USE_TEXT_FIELD);
1117 WMPerformButtonClick(panel->updateIconBtn);
1122 static void
1123 selectSpecification(WMWidget *bPtr, void *data)
1125 InspectorPanel *panel = (InspectorPanel*)data;
1126 char *str;
1127 WWindow *wwin = panel->inspected;
1128 int len;
1130 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class)) {
1131 WMSetButtonEnabled(panel->applyBtn, False);
1132 } else {
1133 WMSetButtonEnabled(panel->applyBtn, True);
1136 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
1137 + strlen(wwin->wm_class ? wwin->wm_class : "?");
1139 str = wmalloc(len);
1141 snprintf(str, len, _("Inspecting %s.%s"),
1142 wwin->wm_instance ? wwin->wm_instance : "?",
1143 wwin->wm_class ? wwin->wm_class : "?");
1145 wFrameWindowChangeTitle(panel->frame->frame, str);
1147 wfree(str);
1151 static void
1152 selectWindow(WMWidget *bPtr, void *data)
1154 InspectorPanel *panel = (InspectorPanel*)data;
1155 WWindow *wwin = panel->inspected;
1156 WScreen *scr = wwin->screen_ptr;
1157 XEvent event;
1158 WWindow *iwin;
1160 if (XGrabPointer(dpy, scr->root_win, True,
1161 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1162 wCursor[WCUR_SELECT], CurrentTime)!=GrabSuccess) {
1163 wwarning("could not grab mouse pointer");
1164 return;
1167 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1169 WMMaskEvent(dpy, ButtonPressMask, &event);
1171 XUngrabPointer(dpy, CurrentTime);
1173 iwin = wWindowFor(event.xbutton.subwindow);
1175 if (iwin && !iwin->flags.internal_window && iwin != wwin
1176 && !iwin->flags.inspector_open) {
1178 iwin->flags.inspector_open = 1;
1179 iwin->inspector = createInspectorForWindow(iwin,
1180 panel->frame->frame_x,
1181 panel->frame->frame_y,
1182 True);
1183 wCloseInspectorForWindow(wwin);
1184 } else {
1185 WMSetLabelText(panel->specLbl, spec_text);
1191 static InspectorPanel*
1192 createInspectorForWindow(WWindow *wwin, int xpos, int ypos,
1193 Bool showSelectPanel)
1195 WScreen *scr = wwin->screen_ptr;
1196 InspectorPanel *panel;
1197 Window parent;
1198 int i;
1199 int x, y;
1200 int btn_width, frame_width;
1201 WMButton *selectedBtn = NULL;
1202 #ifdef wrong_behaviour
1203 WMPixmap *pixmap;
1204 #endif
1206 spec_text = _("The configuration will apply to all\n"
1207 "windows that have their WM_CLASS\n"
1208 "property set to the above selected\n"
1209 "name, when saved.");
1211 panel = wmalloc(sizeof(InspectorPanel));
1212 memset(panel, 0, sizeof(InspectorPanel));
1214 panel->destroyed = 0;
1217 panel->inspected = wwin;
1219 panel->nextPtr = panelList;
1220 panelList = panel;
1223 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1224 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1227 /**** create common stuff ****/
1229 /* command buttons */
1230 /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
1231 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1232 panel->saveBtn = WMCreateCommandButton(panel->win);
1233 WMSetButtonAction(panel->saveBtn, (WMAction*)saveSettings, panel);
1234 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, 310);
1235 WMSetButtonText(panel->saveBtn, _("Save"));
1236 WMResizeWidget(panel->saveBtn, btn_width, 28);
1237 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1238 WMSetButtonEnabled(panel->saveBtn, False);
1240 panel->applyBtn = WMCreateCommandButton(panel->win);
1241 WMSetButtonAction(panel->applyBtn, (WMAction*)applySettings, panel);
1242 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, 310);
1243 WMSetButtonText(panel->applyBtn, _("Apply"));
1244 WMResizeWidget(panel->applyBtn, btn_width, 28);
1246 panel->revertBtn = WMCreateCommandButton(panel->win);
1247 WMSetButtonAction(panel->revertBtn, (WMAction*)revertSettings, panel);
1248 WMMoveWidget(panel->revertBtn, 15, 310);
1249 WMSetButtonText(panel->revertBtn, _("Reload"));
1250 WMResizeWidget(panel->revertBtn, btn_width, 28);
1252 /* page selection popup button */
1253 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1254 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction*)changePage, panel);
1255 WMMoveWidget(panel->pagePopUp, 25, 15);
1256 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1258 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1259 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1260 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1261 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1262 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1264 /**** window spec ****/
1265 frame_width = PWIDTH - (2 * 15);
1267 panel->specFrm = WMCreateFrame(panel->win);
1268 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1269 WMMoveWidget(panel->specFrm, 15, 65);
1270 WMResizeWidget(panel->specFrm, frame_width, 145);
1273 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1274 WMMoveWidget(panel->defaultRb, 10, 78);
1275 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1276 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1277 WMSetButtonSelected(panel->defaultRb, False);
1278 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1280 if (wwin->wm_class && wwin->wm_instance) {
1281 char *str, *tmp;
1283 tmp = wstrconcat(wwin->wm_instance, ".");
1284 str = wstrconcat(tmp, wwin->wm_class);
1286 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1287 WMMoveWidget(panel->bothRb, 10, 18);
1288 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1289 WMSetButtonText(panel->bothRb, str);
1290 wfree(tmp);
1291 wfree(str);
1292 WMGroupButtons(panel->defaultRb, panel->bothRb);
1294 if (!selectedBtn)
1295 selectedBtn = panel->bothRb;
1297 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1300 if (wwin->wm_instance) {
1301 panel->instRb = WMCreateRadioButton(panel->specFrm);
1302 WMMoveWidget(panel->instRb, 10, 38);
1303 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1304 WMSetButtonText(panel->instRb, wwin->wm_instance);
1305 WMGroupButtons(panel->defaultRb, panel->instRb);
1307 if (!selectedBtn)
1308 selectedBtn = panel->instRb;
1310 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1313 if (wwin->wm_class) {
1314 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1315 WMMoveWidget(panel->clsRb, 10, 58);
1316 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1317 WMSetButtonText(panel->clsRb, wwin->wm_class);
1318 WMGroupButtons(panel->defaultRb, panel->clsRb);
1320 if (!selectedBtn)
1321 selectedBtn = panel->clsRb;
1323 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1327 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1328 WMMoveWidget(panel->selWinB, 20, 145-24 - 10);
1329 WMResizeWidget(panel->selWinB, frame_width - 2*10 - 20, 24);
1330 WMSetButtonText(panel->selWinB, _("Select window"));
1331 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1334 panel->specLbl = WMCreateLabel(panel->win);
1335 WMMoveWidget(panel->specLbl, 15, 210);
1336 WMResizeWidget(panel->specLbl, frame_width, 100);
1337 WMSetLabelText(panel->specLbl, spec_text);
1338 WMSetLabelWraps(panel->specLbl, True);
1340 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1342 /**** attributes ****/
1343 panel->attrFrm = WMCreateFrame(panel->win);
1344 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1345 WMMoveWidget(panel->attrFrm, 15, 45);
1346 WMResizeWidget(panel->attrFrm, frame_width, 250);
1348 for (i=0; i < 11; i++) {
1349 char *caption = NULL;
1350 int flag = 0;
1351 char *descr = NULL;
1353 switch (i) {
1354 case 0:
1355 caption = _("Disable titlebar");
1356 flag = WFLAGP(wwin, no_titlebar);
1357 descr = _("Remove the titlebar of this window.\n"
1358 "To access the window commands menu of a window\n"
1359 "without it's titlebar, press Control+Esc (or the\n"
1360 "equivalent shortcut, if you changed the default\n"
1361 "settings).");
1362 break;
1363 case 1:
1364 caption = _("Disable resizebar");
1365 flag = WFLAGP(wwin, no_resizebar);
1366 descr = _("Remove the resizebar of this window.");
1367 break;
1368 case 2:
1369 caption = _("Disable close button");
1370 flag = WFLAGP(wwin, no_close_button);
1371 descr = _("Remove the `close window' button of this window.");
1372 break;
1373 case 3:
1374 caption = _("Disable miniaturize button");
1375 flag = WFLAGP(wwin, no_miniaturize_button);
1376 descr = _("Remove the `miniaturize window' button of the window.");
1377 break;
1378 case 4:
1379 caption = _("Disable border");
1380 flag = WFLAGP(wwin, no_border);
1381 descr = _("Remove the 1 pixel black border around the window.");
1382 break;
1383 case 5:
1384 caption = _("Keep on top (floating)");
1385 flag = WFLAGP(wwin, floating);
1386 descr = _("Keep the window over other windows, not allowing\n"
1387 "them to cover it.");
1388 break;
1389 case 6:
1390 caption = _("Keep at bottom (sunken)");
1391 flag = WFLAGP(wwin, sunken);
1392 descr = _("Keep the window under all other windows.");
1393 break;
1394 case 7:
1395 caption = _("Omnipresent");
1396 flag = WFLAGP(wwin, omnipresent);
1397 descr = _("Make window present in all workspaces.");
1398 break;
1399 case 8:
1400 caption = _("Start miniaturized");
1401 flag = WFLAGP(wwin, start_miniaturized);
1402 descr = _("Make the window be automatically miniaturized when it's\n"
1403 "first shown.");
1404 break;
1405 case 9:
1406 caption = _("Start maximized");
1407 flag = WFLAGP(wwin, start_maximized!=0);
1408 descr = _("Make the window be automatically maximized when it's\n"
1409 "first shown.");
1410 break;
1411 case 10:
1412 caption = _("Full screen maximization");
1413 flag = WFLAGP(wwin, full_maximize);
1414 descr = _("Make the window use the whole screen space when it's\n"
1415 "maximized. The titlebar and resizebar will be moved\n"
1416 "to outside the screen.");
1417 break;
1419 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1420 WMMoveWidget(panel->attrChk[i], 10, 20*(i+1));
1421 WMResizeWidget(panel->attrChk[i], frame_width-15, 20);
1422 WMSetButtonSelected(panel->attrChk[i], flag);
1423 WMSetButtonText(panel->attrChk[i], caption);
1425 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1429 /**** more attributes ****/
1430 panel->moreFrm = WMCreateFrame(panel->win);
1431 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1432 WMMoveWidget(panel->moreFrm, 15, 45);
1433 WMResizeWidget(panel->moreFrm, frame_width, 250);
1435 for (i=0;
1436 #ifdef XKB_BUTTON_HINT
1437 i < 9;
1438 #else
1439 i < 8;
1440 #endif
1441 i++) {
1442 char *caption = NULL;
1443 int flag = 0;
1444 char *descr = NULL;
1446 switch (i) {
1447 case 0:
1448 caption = _("Do not bind keyboard shortcuts");
1449 flag = WFLAGP(wwin, no_bind_keys);
1450 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1451 "when this window is focused. This will allow the\n"
1452 "window to receive all key combinations regardless\n"
1453 "of your shortcut configuration.");
1454 break;
1455 case 1:
1456 caption = _("Do not bind mouse clicks");
1457 flag = WFLAGP(wwin, no_bind_mouse);
1458 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1459 "in the window (when alt is the modifier you have"
1460 "configured).");
1461 break;
1462 case 2:
1463 caption = _("Do not show in the window list");
1464 flag = WFLAGP(wwin, skip_window_list);
1465 descr = _("Do not list the window in the window list menu.");
1466 break;
1467 case 3:
1468 caption = _("Do not let it take focus");
1469 flag = WFLAGP(wwin, no_focusable);
1470 descr = _("Do not let the window take keyboard focus when you\n"
1471 "click on it.");
1472 break;
1473 case 4:
1474 caption = _("Keep inside screen");
1475 flag = WFLAGP(wwin, dont_move_off);
1476 descr = _("Do not allow the window to move itself completely\n"
1477 "outside the screen. For bug compatibility.\n");
1478 break;
1479 case 5:
1480 caption = _("Ignore 'Hide Others'");
1481 flag = WFLAGP(wwin, no_hide_others);
1482 descr = _("Do not hide the window when issuing the\n"
1483 "`HideOthers' command.");
1484 break;
1485 case 6:
1486 caption = _("Ignore 'Save Session'");
1487 flag = WFLAGP(wwin, dont_save_session);
1488 descr = _("Do not save the associated application in the\n"
1489 "session's state, so that it won't be restarted\n"
1490 "together with other applications when Window Maker\n"
1491 "starts.");
1492 break;
1493 case 7:
1494 caption = _("Emulate application icon");
1495 flag = WFLAGP(wwin, emulate_appicon);
1496 descr = _("Make this window act as an application that provides\n"
1497 "enough information to Window Maker for a dockable\n"
1498 "application icon to be created.");
1499 break;
1500 #ifdef XKB_BUTTON_HINT
1501 case 8:
1502 caption = _("Disable language button");
1503 flag = WFLAGP(wwin, no_language_button);
1504 descr = _("Remove the `toggle language' button of the window.");
1505 break;
1506 #endif
1508 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1509 WMMoveWidget(panel->moreChk[i], 10, 20*(i+1));
1510 WMResizeWidget(panel->moreChk[i], frame_width-15, 20);
1511 WMSetButtonSelected(panel->moreChk[i], flag);
1512 WMSetButtonText(panel->moreChk[i], caption);
1514 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1517 /* miniwindow/workspace */
1518 panel->iconFrm = WMCreateFrame(panel->win);
1519 WMMoveWidget(panel->iconFrm, 15, 50);
1520 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1521 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1523 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1524 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1525 WMResizeWidget(panel->iconLbl, 64, 64);
1526 WMSetLabelRelief(panel->iconLbl, WRGroove);
1527 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1529 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1530 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1531 WMMoveWidget(panel->browseIconBtn, 22, 32);
1532 WMResizeWidget(panel->browseIconBtn, 120, 26);
1533 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1535 #ifdef wrong_behaviour
1536 WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
1537 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
1538 WMSetButtonImage(panel->updateIconBtn, pixmap);
1539 WMReleasePixmap(pixmap);
1540 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
1541 WMSetButtonAltImage(panel->updateIconBtn, pixmap);
1542 WMReleasePixmap(pixmap);
1543 #endif
1545 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1546 WMMoveWidget(panel->fileLbl, 20, 85);
1547 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1548 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1550 panel->fileText = WMCreateTextField(panel->iconFrm);
1551 WMMoveWidget(panel->fileText, 20, 105);
1552 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1553 WMSetTextFieldText(panel->fileText, NULL);
1554 WMAddNotificationObserver(textEditedObserver, panel,
1555 WMTextDidEndEditingNotification,
1556 panel->fileText);
1558 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1559 WMMoveWidget(panel->alwChk, 20, 130);
1560 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1561 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1562 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1565 panel->wsFrm = WMCreateFrame(panel->win);
1566 WMMoveWidget(panel->wsFrm, 15, 225);
1567 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1568 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1570 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1571 "first shown."), WMWidgetView(panel->wsFrm));
1573 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1574 WMMoveWidget(panel->wsP, 20, 30);
1575 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1576 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1577 for (i = 0; i < wwin->screen_ptr->workspace_count; i++) {
1578 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1581 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance,
1582 wwin->wm_class);
1583 if (i >= 0 && i <= wwin->screen_ptr->workspace_count) {
1584 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1585 } else {
1586 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1589 /* application wide attributes */
1590 if (wwin->main_window != None) {
1591 WApplication *wapp = wApplicationOf(wwin->main_window);
1593 panel->appFrm = WMCreateFrame(panel->win);
1594 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1595 WMMoveWidget(panel->appFrm, 15, 50);
1596 WMResizeWidget(panel->appFrm, frame_width, 240);
1598 for (i=0; i < 3; i++) {
1599 char *caption = NULL;
1600 int flag = 0;
1601 char *descr = NULL;
1603 switch (i) {
1604 case 0:
1605 caption = _("Start hidden");
1606 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1607 descr = _("Automatically hide application when it's started.");
1608 break;
1609 case 1:
1610 caption = _("No application icon");
1611 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1612 descr = _("Disable the application icon for the application.\n"
1613 "Note that you won't be able to dock it anymore,\n"
1614 "and any icons that are already docked will stop\n"
1615 "working correctly.");
1616 break;
1617 case 2:
1618 caption = _("Collapse application icons");
1619 flag = WFLAGP(wapp->main_window_desc, collapse_appicons);
1620 descr = _("Collapse application icons from other instances\n"
1621 "of this application into one.\n");
1622 break;
1624 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1625 WMMoveWidget(panel->appChk[i], 10, 20*(i+1));
1626 WMResizeWidget(panel->appChk[i], 205, 20);
1627 WMSetButtonSelected(panel->appChk[i], flag);
1628 WMSetButtonText(panel->appChk[i], caption);
1630 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1633 if (WFLAGP(wwin, emulate_appicon)) {
1634 WMSetButtonEnabled(panel->appChk[1], False);
1635 WMSetButtonEnabled(panel->moreChk[7], True);
1636 } else {
1637 WMSetButtonEnabled(panel->appChk[1], True);
1638 WMSetButtonEnabled(panel->moreChk[7], False);
1640 } else {
1641 int tmp;
1643 if ((wwin->transient_for!=None && wwin->transient_for!=scr->root_win)
1644 || !wwin->wm_class || !wwin->wm_instance)
1645 tmp = False;
1646 else
1647 tmp = True;
1648 WMSetButtonEnabled(panel->moreChk[7], tmp);
1650 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1651 panel->appFrm = NULL;
1654 /* if the window is a transient, don't let it have a miniaturize
1655 * button */
1656 if (wWindowFor(wwin->transient_for)!=NULL)
1657 WMSetButtonEnabled(panel->attrChk[3], False);
1658 else
1659 WMSetButtonEnabled(panel->attrChk[3], True);
1662 if (!wwin->wm_class && !wwin->wm_instance) {
1663 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1667 WMRealizeWidget(panel->win);
1669 WMMapSubwidgets(panel->win);
1670 WMMapSubwidgets(panel->specFrm);
1671 WMMapSubwidgets(panel->attrFrm);
1672 WMMapSubwidgets(panel->moreFrm);
1673 WMMapSubwidgets(panel->iconFrm);
1674 WMMapSubwidgets(panel->wsFrm);
1675 if (panel->appFrm)
1676 WMMapSubwidgets(panel->appFrm);
1678 if (showSelectPanel) {
1679 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1680 changePage(panel->pagePopUp, panel);
1681 } else {
1682 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1683 changePage(panel->pagePopUp, panel);
1687 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT,
1688 0, 0, 0);
1689 XSelectInput(dpy, parent, KeyPressMask|KeyReleaseMask);
1690 panel->parent = parent;
1691 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1693 WMMapWidget(panel->win);
1695 XSetTransientForHint(dpy, parent, wwin->client_win);
1697 if (xpos == UNDEFINED_POS) {
1698 x = wwin->frame_x+wwin->frame->core->width/2;
1699 y = wwin->frame_y+wwin->frame->top_width*2;
1700 if (y + PHEIGHT > scr->scr_height)
1701 y = scr->scr_height - PHEIGHT - 30;
1702 if (x + PWIDTH > scr->scr_width)
1703 x = scr->scr_width - PWIDTH;
1704 } else {
1705 x = xpos;
1706 y = ypos;
1709 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win,
1710 "Inspector", x, y, PWIDTH, PHEIGHT);
1712 if (!selectedBtn)
1713 selectedBtn = panel->defaultRb;
1715 WMSetButtonSelected(selectedBtn, True);
1717 selectSpecification(selectedBtn, panel);
1719 /* kluge to know who should get the key events */
1720 panel->frame->client_leader = WMWidgetXID(panel->win);
1722 WSETUFLAG(panel->frame, no_closable, 0);
1723 WSETUFLAG(panel->frame, no_close_button, 0);
1724 wWindowUpdateButtonImages(panel->frame);
1725 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1726 panel->frame->frame->on_click_right = destroyInspector;
1728 wWindowMap(panel->frame);
1730 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance,
1731 wwin->wm_class, UPDATE_TEXT_FIELD);
1733 return panel;
1737 void
1738 wShowInspectorForWindow(WWindow *wwin)
1740 if (wwin->flags.inspector_open)
1741 return;
1743 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1745 make_keys();
1746 wwin->flags.inspector_open = 1;
1747 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS,
1748 UNDEFINED_POS, False);
1754 void
1755 wHideInspectorForWindow(WWindow *wwin)
1757 WWindow *pwin = wwin->inspector->frame;
1759 wWindowUnmap(pwin);
1760 pwin->flags.hidden = 1;
1762 wClientSetState(pwin, IconicState, None);
1767 void
1768 wUnhideInspectorForWindow(WWindow *wwin)
1770 WWindow *pwin = wwin->inspector->frame;
1772 pwin->flags.hidden = 0;
1773 pwin->flags.mapped = 1;
1774 XMapWindow(dpy, pwin->client_win);
1775 XMapWindow(dpy, pwin->frame->core->window);
1776 wClientSetState(pwin, NormalState, None);
1781 WWindow*
1782 wGetWindowOfInspectorForWindow(WWindow *wwin)
1784 if (wwin->inspector) {
1785 assert(wwin->flags.inspector_open != 0);
1787 return wwin->inspector->frame;
1788 } else
1789 return NULL;
1793 void
1794 wCloseInspectorForWindow(WWindow *wwin)
1796 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1798 (*pwin->frame->on_click_right)(NULL, pwin, NULL);