Get rid of cropline(), use wtrimspace() instead
[wmaker-crm.git] / src / winspector.c
blobadaf8b73e1f52ff9906e319309c4e8fb12684728
1 /* winspector.c - window attribute inspector
3 * Window Maker window manager
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * Copyright (c) 1998-2003 Dan Pascu
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "wconfig.h"
25 #include <X11/Xlib.h>
26 #include <X11/Xutil.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <strings.h>
32 #include "WindowMaker.h"
33 #include "screen.h"
34 #include "wcore.h"
35 #include "framewin.h"
36 #include "window.h"
37 #include "workspace.h"
38 #include "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"
49 #include "wmspec.h"
50 #include "xinerama.h"
52 #include <WINGs/WUtil.h>
54 typedef struct InspectorPanel {
55 struct InspectorPanel *nextPtr;
57 WWindow *frame;
59 WWindow *inspected; /* the window that's being inspected */
61 WMWindow *win;
63 Window parent;
65 /* common stuff */
66 WMButton *revertBtn;
67 WMButton *applyBtn;
68 WMButton *saveBtn;
70 WMPopUpButton *pagePopUp;
72 /* first page. general stuff */
74 WMFrame *specFrm;
75 WMButton *instRb;
76 WMButton *clsRb;
77 WMButton *bothRb;
78 WMButton *defaultRb;
80 WMButton *selWinB;
82 WMLabel *specLbl;
84 /* second page. attributes */
86 WMFrame *attrFrm;
87 WMButton *attrChk[11];
89 /* 3rd page. more attributes */
90 WMFrame *moreFrm;
91 #ifdef XKB_BUTTON_HINT
92 WMButton *moreChk[12];
93 #else
94 WMButton *moreChk[11];
95 #endif
97 /* 4th page. icon and workspace */
98 WMFrame *iconFrm;
99 WMLabel *iconLbl;
100 WMLabel *fileLbl;
101 WMTextField *fileText;
102 WMButton *alwChk;
104 WMButton *updateIconBtn;
106 WMButton *browseIconBtn;
108 WMFrame *wsFrm;
109 WMPopUpButton *wsP;
111 /* 5th page. application wide attributes */
112 WMFrame *appFrm;
113 WMButton *appChk[3];
115 unsigned int done:1;
116 unsigned int destroyed:1;
117 unsigned int choosingIcon:1;
118 } InspectorPanel;
120 extern Cursor wCursor[WCUR_LAST];
121 extern WDDomain *WDWindowAttributes;
122 extern WPreferences wPreferences;
124 static InspectorPanel *panelList = NULL;
125 static WMPropList *ANoTitlebar = NULL;
126 static WMPropList *ANoResizebar;
127 static WMPropList *ANoMiniaturizeButton;
128 static WMPropList *ANoCloseButton;
129 static WMPropList *ANoBorder;
130 static WMPropList *ANoHideOthers;
131 static WMPropList *ANoMouseBindings;
132 static WMPropList *ANoKeyBindings;
133 static WMPropList *ANoAppIcon;
134 static WMPropList *AKeepOnTop;
135 static WMPropList *AKeepOnBottom;
136 static WMPropList *AOmnipresent;
137 static WMPropList *ASkipWindowList;
138 static WMPropList *ASkipSwitchPanel;
139 static WMPropList *AKeepInsideScreen;
140 static WMPropList *AUnfocusable;
141 static WMPropList *AFocusAcrossWorkspace;
142 static WMPropList *AAlwaysUserIcon;
143 static WMPropList *AStartMiniaturized;
144 static WMPropList *AStartMaximized;
145 static WMPropList *ADontSaveSession;
146 static WMPropList *AEmulateAppIcon;
147 static WMPropList *AFullMaximize;
148 static WMPropList *ASharedAppIcon;
149 static WMPropList *ANoMiniaturizable;
150 #ifdef XKB_BUTTON_HINT
151 static WMPropList *ANoLanguageButton;
152 #endif
153 static WMPropList *AStartWorkspace;
154 static WMPropList *AIcon;
156 /* application wide options */
157 static WMPropList *AStartHidden;
158 static WMPropList *AnyWindow;
159 static WMPropList *EmptyString;
160 static WMPropList *Yes, *No;
162 #define PWIDTH 290
163 #define PHEIGHT 360
165 static char *spec_text;
166 static void applySettings(WMButton * button, InspectorPanel * panel);
168 #define UNDEFINED_POS 0xffffff
170 static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel);
172 static void make_keys(void)
174 if (ANoTitlebar != NULL)
175 return;
177 AIcon = WMCreatePLString("Icon");
178 ANoTitlebar = WMCreatePLString("NoTitlebar");
179 ANoResizebar = WMCreatePLString("NoResizebar");
180 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
181 ANoCloseButton = WMCreatePLString("NoCloseButton");
182 ANoBorder = WMCreatePLString("NoBorder");
183 ANoHideOthers = WMCreatePLString("NoHideOthers");
184 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
185 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
186 ANoAppIcon = WMCreatePLString("NoAppIcon");
187 AKeepOnTop = WMCreatePLString("KeepOnTop");
188 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
189 AOmnipresent = WMCreatePLString("Omnipresent");
190 ASkipWindowList = WMCreatePLString("SkipWindowList");
191 ASkipSwitchPanel = WMCreatePLString("SkipSwitchPanel");
192 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
193 AUnfocusable = WMCreatePLString("Unfocusable");
194 AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace");
195 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
196 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
197 AStartMaximized = WMCreatePLString("StartMaximized");
198 AStartHidden = WMCreatePLString("StartHidden");
199 ADontSaveSession = WMCreatePLString("DontSaveSession");
200 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
201 AFullMaximize = WMCreatePLString("FullMaximize");
202 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
203 ANoMiniaturizable = WMCreatePLString("NoMiniaturizable");
204 #ifdef XKB_BUTTON_HINT
205 ANoLanguageButton = WMCreatePLString("NoLanguageButton");
206 #endif
208 AStartWorkspace = WMCreatePLString("StartWorkspace");
210 AnyWindow = WMCreatePLString("*");
211 EmptyString = WMCreatePLString("");
212 Yes = WMCreatePLString("Yes");
213 No = WMCreatePLString("No");
216 static void freeInspector(InspectorPanel * panel)
218 panel->destroyed = 1;
219 if (panel->choosingIcon)
220 return;
222 WMDestroyWidget(panel->win);
224 XDestroyWindow(dpy, panel->parent);
226 wfree(panel);
229 static void destroyInspector(WCoreWindow * foo, void *data, XEvent * event)
231 InspectorPanel *panel;
232 InspectorPanel *tmp;
234 panel = panelList;
235 while (panel->frame != data)
236 panel = panel->nextPtr;
238 if (panelList == panel)
239 panelList = panel->nextPtr;
240 else {
241 tmp = panelList;
242 while (tmp->nextPtr != panel) {
243 tmp = tmp->nextPtr;
245 tmp->nextPtr = panel->nextPtr;
247 panel->inspected->flags.inspector_open = 0;
248 panel->inspected->inspector = NULL;
250 WMRemoveNotificationObserver(panel);
252 wWindowUnmap(panel->frame);
253 wUnmanageWindow(panel->frame, True, False);
255 freeInspector(panel);
258 void wDestroyInspectorPanels(void)
260 InspectorPanel *panel;
262 while (panelList != NULL) {
263 panel = panelList;
264 panelList = panelList->nextPtr;
265 wUnmanageWindow(panel->frame, False, False);
266 WMDestroyWidget(panel->win);
268 panel->inspected->flags.inspector_open = 0;
269 panel->inspected->inspector = NULL;
271 wfree(panel);
275 static void changePage(WMPopUpButton * bPtr, InspectorPanel * panel)
277 int page;
279 page = WMGetPopUpButtonSelectedItem(bPtr);
281 if (page == 0) {
282 WMMapWidget(panel->specFrm);
283 WMMapWidget(panel->specLbl);
284 } else if (page == 1) {
285 WMMapWidget(panel->attrFrm);
286 } else if (page == 2) {
287 WMMapWidget(panel->moreFrm);
288 } else if (page == 3) {
289 WMMapWidget(panel->iconFrm);
290 WMMapWidget(panel->wsFrm);
291 } else {
292 WMMapWidget(panel->appFrm);
295 if (page != 0) {
296 WMUnmapWidget(panel->specFrm);
297 WMUnmapWidget(panel->specLbl);
299 if (page != 1)
300 WMUnmapWidget(panel->attrFrm);
301 if (page != 2)
302 WMUnmapWidget(panel->moreFrm);
303 if (page != 3) {
304 WMUnmapWidget(panel->iconFrm);
305 WMUnmapWidget(panel->wsFrm);
307 if (page != 4 && panel->appFrm)
308 WMUnmapWidget(panel->appFrm);
311 #define USE_TEXT_FIELD 1
312 #define UPDATE_TEXT_FIELD 2
313 #define REVERT_TO_DEFAULT 4
315 static int showIconFor(WMScreen * scrPtr, InspectorPanel * panel, char *wm_instance, char *wm_class, int flags)
317 WMPixmap *pixmap = (WMPixmap *) NULL;
318 char *file = NULL, *path = NULL;
319 char *db_icon = NULL;
321 if ((flags & USE_TEXT_FIELD) != 0) {
322 file = WMGetTextFieldText(panel->fileText);
323 if (file && file[0] == 0) {
324 wfree(file);
325 file = NULL;
327 } else {
328 db_icon = wDefaultGetIconFile(panel->inspected->screen_ptr, wm_instance, wm_class, False);
329 if (db_icon != NULL)
330 file = wstrdup(db_icon);
332 if (db_icon != NULL && (flags & REVERT_TO_DEFAULT) != 0) {
333 if (file)
334 file = wstrdup(db_icon);
335 flags |= UPDATE_TEXT_FIELD;
338 if ((flags & UPDATE_TEXT_FIELD) != 0) {
339 WMSetTextFieldText(panel->fileText, file);
342 if (file) {
343 path = FindImage(wPreferences.icon_path, file);
345 if (!path) {
346 char *buf;
347 int len = strlen(file) + 80;
349 buf = wmalloc(len);
350 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"), file);
351 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
352 wfree(buf);
353 wfree(file);
354 return -1;
357 pixmap = WMCreatePixmapFromFile(scrPtr, path);
358 wfree(path);
360 if (!pixmap) {
361 char *buf;
362 int len = strlen(file) + 80;
364 buf = wmalloc(len);
365 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
366 file, RMessageForError(RErrorCode));
367 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
368 wfree(buf);
369 wfree(file);
370 return -1;
372 wfree(file);
375 WMSetLabelImage(panel->iconLbl, pixmap);
376 if (pixmap)
377 WMReleasePixmap(pixmap);
379 return 0;
382 #if 0
383 static void updateIcon(WMButton * button, InspectorPanel * panel)
385 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
387 #endif
389 static int getBool(WMPropList * value)
391 char *val;
393 if (!WMIsPLString(value)) {
394 return 0;
396 if (!(val = WMGetFromPLString(value))) {
397 return 0;
400 if ((val[1] == '\0' && (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' || val[0] == 't' || val[0] == '1'))
401 || (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
403 return 1;
404 } else if ((val[1] == '\0'
405 && (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' || val[0] == 'f' || val[0] == '0'))
406 || (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
408 return 0;
409 } else {
410 wwarning(_("can't convert \"%s\" to boolean"), val);
411 return 0;
415 #define UPDATE_DEFAULTS 1
416 #define IS_BOOLEAN 2
419 * Will insert the attribute = value; pair in window's list,
420 * if it's different from the defaults.
421 * Defaults means either defaults database, or attributes saved
422 * for the default window "*". This is to let one revert options that are
423 * global because they were saved for all windows ("*").
427 static int
428 insertAttribute(WMPropList * dict, WMPropList * window, WMPropList * attr, WMPropList * value, int flags)
430 WMPropList *def_win, *def_value = NULL;
431 int update = 0;
432 int modified = 0;
434 if (!(flags & UPDATE_DEFAULTS) && dict) {
435 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL) {
436 def_value = WMGetFromPLDictionary(def_win, attr);
440 /* If we could not find defaults in database, fall to hardcoded values.
441 * Also this is true if we save defaults for all windows
443 if (!def_value)
444 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
446 if ((flags & IS_BOOLEAN))
447 update = (getBool(value) != getBool(def_value));
448 else {
449 update = !WMIsPropListEqualTo(value, def_value);
452 if (update) {
453 WMPutInPLDictionary(window, attr, value);
454 modified = 1;
457 return modified;
460 static void saveSettings(WMButton * button, InspectorPanel * panel)
462 WWindow *wwin = panel->inspected;
463 WDDomain *db = WDWindowAttributes;
464 WMPropList *dict = db->dictionary;
465 WMPropList *winDic, *appDic, *value, *key, *key2;
466 char *icon_file;
467 int flags = 0;
468 int different = 0, different2 = 0;
470 /* Save will apply the changes and save them */
471 applySettings(panel->applyBtn, panel);
473 if (WMGetButtonSelected(panel->instRb) != 0)
474 key = WMCreatePLString(wwin->wm_instance);
475 else if (WMGetButtonSelected(panel->clsRb) != 0)
476 key = WMCreatePLString(wwin->wm_class);
477 else if (WMGetButtonSelected(panel->bothRb) != 0) {
478 char *buffer;
480 buffer = StrConcatDot(wwin->wm_instance, wwin->wm_class);
481 key = WMCreatePLString(buffer);
482 wfree(buffer);
483 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
484 key = WMRetainPropList(AnyWindow);
485 flags = UPDATE_DEFAULTS;
486 } else
487 key = NULL;
489 if (!key)
490 return;
492 if (!dict) {
493 dict = WMCreatePLDictionary(NULL, NULL);
494 if (dict) {
495 db->dictionary = dict;
496 } else {
497 WMReleasePropList(key);
498 return;
502 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD) < 0)
503 return;
505 WMPLSetCaseSensitive(True);
507 winDic = WMCreatePLDictionary(NULL, NULL);
508 appDic = WMCreatePLDictionary(NULL, NULL);
510 /* Update icon for window */
511 icon_file = WMGetTextFieldText(panel->fileText);
512 if (icon_file) {
513 if (icon_file[0] != 0) {
514 value = WMCreatePLString(icon_file);
515 different |= insertAttribute(dict, winDic, AIcon, value, flags);
516 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
517 WMReleasePropList(value);
519 wfree(icon_file);
523 int i = WMGetPopUpButtonSelectedItem(panel->wsP);
525 i--;
527 if (i >= 0 && i < panel->frame->screen_ptr->workspace_count) {
528 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
529 different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
530 WMReleasePropList(value);
534 flags |= IS_BOOLEAN;
536 value = (WMGetButtonSelected(panel->alwChk) != 0) ? Yes : No;
537 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
539 value = (WMGetButtonSelected(panel->attrChk[0]) != 0) ? Yes : No;
540 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
542 value = (WMGetButtonSelected(panel->attrChk[1]) != 0) ? Yes : No;
543 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
545 value = (WMGetButtonSelected(panel->attrChk[2]) != 0) ? Yes : No;
546 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
548 value = (WMGetButtonSelected(panel->attrChk[3]) != 0) ? Yes : No;
549 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
551 value = (WMGetButtonSelected(panel->attrChk[4]) != 0) ? Yes : No;
552 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
554 value = (WMGetButtonSelected(panel->attrChk[5]) != 0) ? Yes : No;
555 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
557 value = (WMGetButtonSelected(panel->attrChk[6]) != 0) ? Yes : No;
558 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
560 value = (WMGetButtonSelected(panel->attrChk[7]) != 0) ? Yes : No;
561 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
563 value = (WMGetButtonSelected(panel->attrChk[8]) != 0) ? Yes : No;
564 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
566 value = (WMGetButtonSelected(panel->attrChk[9]) != 0) ? Yes : No;
567 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
569 value = (WMGetButtonSelected(panel->attrChk[10]) != 0) ? Yes : No;
570 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
572 value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No;
573 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
575 value = (WMGetButtonSelected(panel->moreChk[1]) != 0) ? Yes : No;
576 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
578 value = (WMGetButtonSelected(panel->moreChk[2]) != 0) ? Yes : No;
579 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
581 value = (WMGetButtonSelected(panel->moreChk[3]) != 0) ? Yes : No;
582 different |= insertAttribute(dict, winDic, ASkipSwitchPanel, value, flags);
584 value = (WMGetButtonSelected(panel->moreChk[4]) != 0) ? Yes : No;
585 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
587 value = (WMGetButtonSelected(panel->moreChk[5]) != 0) ? Yes : No;
588 different |= insertAttribute(dict, winDic, AKeepInsideScreen, value, flags);
590 value = (WMGetButtonSelected(panel->moreChk[6]) != 0) ? Yes : No;
591 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
593 value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No;
594 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
596 value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No;
597 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
599 value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No;
600 different |= insertAttribute(dict, winDic, AFocusAcrossWorkspace, value, flags);
602 value = (WMGetButtonSelected(panel->moreChk[10]) != 0) ? Yes : No;
603 different |= insertAttribute(dict, winDic, ANoMiniaturizable, value, flags);
605 #ifdef XKB_BUTTON_HINT
606 value = (WMGetButtonSelected(panel->moreChk[11]) != 0) ? Yes : No;
607 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
608 #endif
610 if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
611 value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No;
612 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
614 value = (WMGetButtonSelected(panel->appChk[1]) != 0) ? Yes : No;
615 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
617 value = (WMGetButtonSelected(panel->appChk[2]) != 0) ? Yes : No;
618 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
621 if (wwin->fake_group) {
622 key2 = WMCreatePLString(wwin->fake_group->identifier);
623 if (WMIsPropListEqualTo(key, key2)) {
624 WMMergePLDictionaries(winDic, appDic, True);
625 different |= different2;
626 } else {
627 WMRemoveFromPLDictionary(dict, key2);
628 if (different2) {
629 WMPutInPLDictionary(dict, key2, appDic);
632 WMReleasePropList(key2);
633 WMReleasePropList(appDic);
634 } else if (wwin->main_window != wwin->client_win) {
635 WApplication *wapp = wApplicationOf(wwin->main_window);
637 if (wapp) {
638 char *instance = wapp->main_window_desc->wm_instance;
639 char *class = wapp->main_window_desc->wm_class;
640 char *buffer;
642 buffer = StrConcatDot(instance, class);
643 key2 = WMCreatePLString(buffer);
644 wfree(buffer);
646 if (WMIsPropListEqualTo(key, key2)) {
647 WMMergePLDictionaries(winDic, appDic, True);
648 different |= different2;
649 } else {
650 WMRemoveFromPLDictionary(dict, key2);
651 if (different2) {
652 WMPutInPLDictionary(dict, key2, appDic);
655 WMReleasePropList(key2);
656 WMReleasePropList(appDic);
658 } else {
659 WMMergePLDictionaries(winDic, appDic, True);
660 different |= different2;
661 WMReleasePropList(appDic);
664 WMRemoveFromPLDictionary(dict, key);
665 if (different) {
666 WMPutInPLDictionary(dict, key, winDic);
669 WMReleasePropList(key);
670 WMReleasePropList(winDic);
672 UpdateDomainFile(db);
674 /* clean up */
675 WMPLSetCaseSensitive(False);
678 static void makeAppIconFor(WApplication * wapp)
680 WScreen *scr = wapp->main_window_desc->screen_ptr;
682 if (wapp->app_icon)
683 return;
685 if (!WFLAGP(wapp->main_window_desc, no_appicon))
686 wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
687 else
688 wapp->app_icon = NULL;
690 if (wapp->app_icon) {
691 WIcon *icon = wapp->app_icon->icon;
692 WDock *clip = scr->workspaces[scr->current_workspace]->clip;
693 int x = 0, y = 0;
695 wapp->app_icon->main_window = wapp->main_window;
697 if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
698 wapp->app_icon->attracted = 1;
699 if (!wapp->app_icon->icon->shadowed) {
700 wapp->app_icon->icon->shadowed = 1;
701 wapp->app_icon->icon->force_paint = 1;
703 wDockAttachIcon(clip, wapp->app_icon, x, y);
704 } else {
705 PlaceIcon(scr, &x, &y, wGetHeadForWindow(wapp->main_window_desc));
706 wAppIconMove(wapp->app_icon, x, y);
708 if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
709 XMapWindow(dpy, icon->core->window);
711 if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
712 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
716 static void removeAppIconFor(WApplication * wapp)
718 if (!wapp->app_icon)
719 return;
721 if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
722 wapp->app_icon->running = 0;
723 /* since we keep it, we don't care if it was attracted or not */
724 wapp->app_icon->attracted = 0;
725 wapp->app_icon->icon->shadowed = 0;
726 wapp->app_icon->main_window = None;
727 wapp->app_icon->pid = 0;
728 wapp->app_icon->icon->owner = NULL;
729 wapp->app_icon->icon->icon_win = None;
730 wapp->app_icon->icon->force_paint = 1;
731 wAppIconPaint(wapp->app_icon);
732 } else if (wapp->app_icon->docked) {
733 wapp->app_icon->running = 0;
734 wDockDetach(wapp->app_icon->dock, wapp->app_icon);
735 } else {
736 wAppIconDestroy(wapp->app_icon);
738 wapp->app_icon = NULL;
739 if (wPreferences.auto_arrange_icons)
740 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
743 static void applySettings(WMButton * button, InspectorPanel * panel)
745 WWindow *wwin = panel->inspected;
746 WApplication *wapp = wApplicationOf(wwin->main_window);
747 int floating, sunken, skip_window_list;
748 int old_omnipresent;
749 int old_no_bind_keys;
750 int old_no_bind_mouse;
752 old_omnipresent = WFLAGP(wwin, omnipresent);
753 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
754 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
756 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
758 /* Attributes... --> Window Attributes */
759 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
760 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
761 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
762 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
763 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
764 floating = WMGetButtonSelected(panel->attrChk[5]);
765 sunken = WMGetButtonSelected(panel->attrChk[6]);
766 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
767 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
768 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
769 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
771 /* Attributes... --> Advanced Options */
772 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
773 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
774 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
775 WSETUFLAG(wwin, skip_switchpanel, WMGetButtonSelected(panel->moreChk[3]));
776 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[4]));
777 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[5]));
778 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[6]));
779 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[7]));
780 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[8]));
781 WSETUFLAG(wwin, focus_across_wksp, WMGetButtonSelected(panel->moreChk[9]));
782 WSETUFLAG(wwin, no_miniaturizable, WMGetButtonSelected(panel->moreChk[10]));
783 #ifdef XKB_BUTTON_HINT
784 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[11]));
785 #endif
786 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
788 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
789 wUnshadeWindow(wwin);
791 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
793 if (floating) {
794 if (!WFLAGP(wwin, floating))
795 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
796 } else if (sunken) {
797 if (!WFLAGP(wwin, sunken))
798 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
799 } else {
800 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
801 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
804 WSETUFLAG(wwin, sunken, sunken);
805 WSETUFLAG(wwin, floating, floating);
806 wwin->flags.omnipresent = 0;
808 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
809 WSETUFLAG(wwin, skip_window_list, skip_window_list);
810 UpdateSwitchMenu(wwin->screen_ptr, wwin, skip_window_list ? ACTION_REMOVE : ACTION_ADD);
811 } else {
812 if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
813 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
817 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
818 if (WFLAGP(wwin, no_bind_keys)) {
819 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
820 } else {
821 wWindowSetKeyGrabs(wwin);
825 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
826 wWindowResetMouseGrabs(wwin);
829 wwin->frame->flags.need_texture_change = 1;
830 wWindowConfigureBorders(wwin);
831 wFrameWindowPaint(wwin->frame);
832 wNETWMUpdateActions(wwin, False);
835 * Can't apply emulate_appicon because it will probably cause problems.
837 if (wapp) {
838 /* do application wide stuff */
839 WSETUFLAG(wapp->main_window_desc, start_hidden, WMGetButtonSelected(panel->appChk[0]));
841 WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1]));
843 WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2]));
845 if (WFLAGP(wapp->main_window_desc, no_appicon))
846 removeAppIconFor(wapp);
847 else
848 makeAppIconFor(wapp);
850 if (wapp->app_icon && wapp->main_window == wwin->client_win) {
851 char *file = WMGetTextFieldText(panel->fileText);
853 if (file[0] == 0) {
854 wfree(file);
855 file = NULL;
857 wIconChangeImageFile(wapp->app_icon->icon, file);
858 if (file)
859 wfree(file);
860 wAppIconPaint(wapp->app_icon);
865 static void revertSettings(WMButton * button, InspectorPanel * panel)
867 WWindow *wwin = panel->inspected;
868 WApplication *wapp = wApplicationOf(wwin->main_window);
869 int i, n;
870 char *wm_instance = NULL;
871 char *wm_class = NULL;
872 int workspace, level;
874 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
875 wm_instance = wwin->wm_instance;
876 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
877 wm_class = wwin->wm_class;
878 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
879 wm_instance = wwin->wm_instance;
880 wm_class = wwin->wm_class;
882 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
883 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
884 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
886 wWindowSetupInitialAttributes(wwin, &level, &workspace);
888 for (i = 0; i < 11; i++) {
889 int flag = 0;
891 switch (i) {
892 case 0:
893 flag = WFLAGP(wwin, no_titlebar);
894 break;
895 case 1:
896 flag = WFLAGP(wwin, no_resizebar);
897 break;
898 case 2:
899 flag = WFLAGP(wwin, no_close_button);
900 break;
901 case 3:
902 flag = WFLAGP(wwin, no_miniaturize_button);
903 break;
904 case 4:
905 flag = WFLAGP(wwin, no_border);
906 break;
907 case 5:
908 flag = WFLAGP(wwin, floating);
909 break;
910 case 6:
911 flag = WFLAGP(wwin, sunken);
912 break;
913 case 7:
914 flag = WFLAGP(wwin, omnipresent);
915 break;
916 case 8:
917 flag = WFLAGP(wwin, start_miniaturized);
918 break;
919 case 9:
920 flag = WFLAGP(wwin, start_maximized != 0);
921 break;
922 case 10:
923 flag = WFLAGP(wwin, full_maximize);
924 break;
926 WMSetButtonSelected(panel->attrChk[i], flag);
928 for (i = 0; i < 12; i++) {
929 int flag = 0;
931 switch (i) {
932 case 0:
933 flag = WFLAGP(wwin, no_bind_keys);
934 break;
935 case 1:
936 flag = WFLAGP(wwin, no_bind_mouse);
937 break;
938 case 2:
939 flag = WFLAGP(wwin, skip_window_list);
940 break;
941 case 3:
942 flag = WFLAGP(wwin, skip_switchpanel);
943 break;
944 case 4:
945 flag = WFLAGP(wwin, no_focusable);
946 break;
947 case 5:
948 flag = WFLAGP(wwin, dont_move_off);
949 break;
950 case 6:
951 flag = WFLAGP(wwin, no_hide_others);
952 break;
953 case 7:
954 flag = WFLAGP(wwin, dont_save_session);
955 break;
956 case 8:
957 flag = WFLAGP(wwin, emulate_appicon);
958 break;
959 case 9:
960 flag = WFLAGP(wwin, focus_across_wksp);
961 break;
962 case 10:
963 flag = WFLAGP(wwin, no_miniaturizable);
964 break;
965 #ifdef XKB_BUTTON_HINT
966 case 11:
967 flag = WFLAGP(wwin, no_language_button);
968 break;
969 #endif
971 WMSetButtonSelected(panel->moreChk[i], flag);
973 if (panel->appFrm && wapp) {
974 for (i = 0; i < 3; i++) {
975 int flag = 0;
977 switch (i) {
978 case 0:
979 flag = WFLAGP(wapp->main_window_desc, start_hidden);
980 break;
981 case 1:
982 flag = WFLAGP(wapp->main_window_desc, no_appicon);
983 break;
984 case 2:
985 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
986 break;
988 WMSetButtonSelected(panel->appChk[i], flag);
991 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
993 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
995 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
997 if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
998 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
999 } else {
1000 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1003 /* must auto apply, so that there wno't be internal
1004 * inconsistencies between the state in the flags and
1005 * the actual state of the window */
1006 applySettings(panel->applyBtn, panel);
1009 static void chooseIconCallback(WMWidget * self, void *clientData)
1011 char *file;
1012 InspectorPanel *panel = (InspectorPanel *) clientData;
1013 int result;
1015 panel->choosingIcon = 1;
1017 WMSetButtonEnabled(panel->browseIconBtn, False);
1019 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
1020 panel->inspected->wm_instance, panel->inspected->wm_class);
1022 panel->choosingIcon = 0;
1024 if (!panel->destroyed) { /* kluge */
1025 if (result) {
1026 WMSetTextFieldText(panel->fileText, file);
1027 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
1028 wfree(file);
1030 WMSetButtonEnabled(panel->browseIconBtn, True);
1031 } else {
1032 freeInspector(panel);
1036 static void textEditedObserver(void *observerData, WMNotification * notification)
1038 InspectorPanel *panel = (InspectorPanel *) observerData;
1040 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
1041 return;
1043 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
1045 WMPerformButtonClick(panel->updateIconBtn);
1049 static void selectSpecification(WMWidget * bPtr, void *data)
1051 InspectorPanel *panel = (InspectorPanel *) data;
1052 char *str;
1053 WWindow *wwin = panel->inspected;
1054 int len;
1056 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class)) {
1057 WMSetButtonEnabled(panel->applyBtn, False);
1058 } else {
1059 WMSetButtonEnabled(panel->applyBtn, True);
1062 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
1063 + strlen(wwin->wm_class ? wwin->wm_class : "?");
1065 str = wmalloc(len);
1067 snprintf(str, len, _("Inspecting %s.%s"),
1068 wwin->wm_instance ? wwin->wm_instance : "?", wwin->wm_class ? wwin->wm_class : "?");
1070 wFrameWindowChangeTitle(panel->frame->frame, str);
1072 wfree(str);
1075 static void selectWindow(WMWidget * bPtr, void *data)
1077 InspectorPanel *panel = (InspectorPanel *) data;
1078 WWindow *wwin = panel->inspected;
1079 WScreen *scr = wwin->screen_ptr;
1080 XEvent event;
1081 WWindow *iwin;
1083 if (XGrabPointer(dpy, scr->root_win, True,
1084 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1085 wCursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
1086 wwarning("could not grab mouse pointer");
1087 return;
1090 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1092 WMMaskEvent(dpy, ButtonPressMask, &event);
1094 XUngrabPointer(dpy, CurrentTime);
1096 iwin = wWindowFor(event.xbutton.subwindow);
1098 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
1100 iwin->flags.inspector_open = 1;
1101 iwin->inspector = createInspectorForWindow(iwin,
1102 panel->frame->frame_x, panel->frame->frame_y, True);
1103 wCloseInspectorForWindow(wwin);
1104 } else {
1105 WMSetLabelText(panel->specLbl, spec_text);
1109 static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel)
1111 WScreen *scr = wwin->screen_ptr;
1112 InspectorPanel *panel;
1113 Window parent;
1114 int i;
1115 int x, y;
1116 int btn_width, frame_width;
1117 WMButton *selectedBtn = NULL;
1118 #ifdef wrong_behaviour
1119 WMPixmap *pixmap;
1120 #endif
1122 spec_text = _("The configuration will apply to all\n"
1123 "windows that have their WM_CLASS\n"
1124 "property set to the above selected\n" "name, when saved.");
1126 panel = wmalloc(sizeof(InspectorPanel));
1127 memset(panel, 0, sizeof(InspectorPanel));
1129 panel->destroyed = 0;
1131 panel->inspected = wwin;
1133 panel->nextPtr = panelList;
1134 panelList = panel;
1136 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1137 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1139 /**** create common stuff ****/
1141 /* command buttons */
1142 /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
1143 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1144 panel->saveBtn = WMCreateCommandButton(panel->win);
1145 WMSetButtonAction(panel->saveBtn, (WMAction *) saveSettings, panel);
1146 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, PHEIGHT - 40);
1147 WMSetButtonText(panel->saveBtn, _("Save"));
1148 WMResizeWidget(panel->saveBtn, btn_width, 28);
1149 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1150 WMSetButtonEnabled(panel->saveBtn, False);
1152 panel->applyBtn = WMCreateCommandButton(panel->win);
1153 WMSetButtonAction(panel->applyBtn, (WMAction *) applySettings, panel);
1154 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, PHEIGHT - 40);
1155 WMSetButtonText(panel->applyBtn, _("Apply"));
1156 WMResizeWidget(panel->applyBtn, btn_width, 28);
1158 panel->revertBtn = WMCreateCommandButton(panel->win);
1159 WMSetButtonAction(panel->revertBtn, (WMAction *) revertSettings, panel);
1160 WMMoveWidget(panel->revertBtn, 15, PHEIGHT - 40);
1161 WMSetButtonText(panel->revertBtn, _("Reload"));
1162 WMResizeWidget(panel->revertBtn, btn_width, 28);
1164 /* page selection popup button */
1165 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1166 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction *) changePage, panel);
1167 WMMoveWidget(panel->pagePopUp, 25, 15);
1168 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1170 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1171 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1172 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1173 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1174 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1176 /**** window spec ****/
1177 frame_width = PWIDTH - (2 * 15);
1179 panel->specFrm = WMCreateFrame(panel->win);
1180 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1181 WMMoveWidget(panel->specFrm, 15, 65);
1182 WMResizeWidget(panel->specFrm, frame_width, 145);
1184 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1185 WMMoveWidget(panel->defaultRb, 10, 78);
1186 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1187 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1188 WMSetButtonSelected(panel->defaultRb, False);
1189 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1191 if (wwin->wm_class && wwin->wm_instance) {
1192 char *str, *tmp;
1194 tmp = wstrconcat(wwin->wm_instance, ".");
1195 str = wstrconcat(tmp, wwin->wm_class);
1197 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1198 WMMoveWidget(panel->bothRb, 10, 18);
1199 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1200 WMSetButtonText(panel->bothRb, str);
1201 wfree(tmp);
1202 wfree(str);
1203 WMGroupButtons(panel->defaultRb, panel->bothRb);
1205 if (!selectedBtn)
1206 selectedBtn = panel->bothRb;
1208 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1211 if (wwin->wm_instance) {
1212 panel->instRb = WMCreateRadioButton(panel->specFrm);
1213 WMMoveWidget(panel->instRb, 10, 38);
1214 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1215 WMSetButtonText(panel->instRb, wwin->wm_instance);
1216 WMGroupButtons(panel->defaultRb, panel->instRb);
1218 if (!selectedBtn)
1219 selectedBtn = panel->instRb;
1221 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1224 if (wwin->wm_class) {
1225 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1226 WMMoveWidget(panel->clsRb, 10, 58);
1227 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1228 WMSetButtonText(panel->clsRb, wwin->wm_class);
1229 WMGroupButtons(panel->defaultRb, panel->clsRb);
1231 if (!selectedBtn)
1232 selectedBtn = panel->clsRb;
1234 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1237 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1238 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1239 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1240 WMSetButtonText(panel->selWinB, _("Select window"));
1241 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1243 panel->specLbl = WMCreateLabel(panel->win);
1244 WMMoveWidget(panel->specLbl, 15, 210);
1245 WMResizeWidget(panel->specLbl, frame_width, 100);
1246 WMSetLabelText(panel->specLbl, spec_text);
1247 WMSetLabelWraps(panel->specLbl, True);
1249 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1251 /**** attributes ****/
1252 panel->attrFrm = WMCreateFrame(panel->win);
1253 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1254 WMMoveWidget(panel->attrFrm, 15, 45);
1255 WMResizeWidget(panel->attrFrm, frame_width, 250);
1257 for (i = 0; i < 11; i++) {
1258 char *caption = NULL;
1259 int flag = 0;
1260 char *descr = NULL;
1262 switch (i) {
1263 case 0:
1264 caption = _("Disable titlebar");
1265 flag = WFLAGP(wwin, no_titlebar);
1266 descr = _("Remove the titlebar of this window.\n"
1267 "To access the window commands menu of a window\n"
1268 "without it's titlebar, press Control+Esc (or the\n"
1269 "equivalent shortcut, if you changed the default\n" "settings).");
1270 break;
1271 case 1:
1272 caption = _("Disable resizebar");
1273 flag = WFLAGP(wwin, no_resizebar);
1274 descr = _("Remove the resizebar of this window.");
1275 break;
1276 case 2:
1277 caption = _("Disable close button");
1278 flag = WFLAGP(wwin, no_close_button);
1279 descr = _("Remove the `close window' button of this window.");
1280 break;
1281 case 3:
1282 caption = _("Disable miniaturize button");
1283 flag = WFLAGP(wwin, no_miniaturize_button);
1284 descr = _("Remove the `miniaturize window' button of the window.");
1285 break;
1286 case 4:
1287 caption = _("Disable border");
1288 flag = WFLAGP(wwin, no_border);
1289 descr = _("Remove the 1 pixel black border around the window.");
1290 break;
1291 case 5:
1292 caption = _("Keep on top (floating)");
1293 flag = WFLAGP(wwin, floating);
1294 descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
1295 break;
1296 case 6:
1297 caption = _("Keep at bottom (sunken)");
1298 flag = WFLAGP(wwin, sunken);
1299 descr = _("Keep the window under all other windows.");
1300 break;
1301 case 7:
1302 caption = _("Omnipresent");
1303 flag = WFLAGP(wwin, omnipresent);
1304 descr = _("Make window present in all workspaces.");
1305 break;
1306 case 8:
1307 caption = _("Start miniaturized");
1308 flag = WFLAGP(wwin, start_miniaturized);
1309 descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
1310 break;
1311 case 9:
1312 caption = _("Start maximized");
1313 flag = WFLAGP(wwin, start_maximized != 0);
1314 descr = _("Make the window be automatically maximized when it's\n" "first shown.");
1315 break;
1316 case 10:
1317 caption = _("Full screen maximization");
1318 flag = WFLAGP(wwin, full_maximize);
1319 descr = _("Make the window use the whole screen space when it's\n"
1320 "maximized. The titlebar and resizebar will be moved\n"
1321 "to outside the screen.");
1322 break;
1324 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1325 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1326 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1327 WMSetButtonSelected(panel->attrChk[i], flag);
1328 WMSetButtonText(panel->attrChk[i], caption);
1330 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1333 /**** more attributes ****/
1334 panel->moreFrm = WMCreateFrame(panel->win);
1335 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1336 WMMoveWidget(panel->moreFrm, 15, 45);
1337 WMResizeWidget(panel->moreFrm, frame_width, 265);
1339 for (i = 0;
1340 #ifdef XKB_BUTTON_HINT
1341 i < 12;
1342 #else
1343 i < 11;
1344 #endif
1345 i++) {
1346 char *caption = NULL;
1347 int flag = 0;
1348 char *descr = NULL;
1350 switch (i) {
1351 case 0:
1352 caption = _("Do not bind keyboard shortcuts");
1353 flag = WFLAGP(wwin, no_bind_keys);
1354 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1355 "when this window is focused. This will allow the\n"
1356 "window to receive all key combinations regardless\n"
1357 "of your shortcut configuration.");
1358 break;
1359 case 1:
1360 caption = _("Do not bind mouse clicks");
1361 flag = WFLAGP(wwin, no_bind_mouse);
1362 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1363 "in the window (when alt is the modifier you have\n" "configured).");
1364 break;
1365 case 2:
1366 caption = _("Do not show in the window list");
1367 flag = WFLAGP(wwin, skip_window_list);
1368 descr = _("Do not list the window in the window list menu.");
1369 break;
1370 case 3:
1371 caption = _("Do not show in the switch panel");
1372 flag = WFLAGP(wwin, skip_switchpanel);
1373 descr = _("Do not include in switchpanel while alternating windows.");
1374 break;
1375 case 4:
1376 caption = _("Do not let it take focus");
1377 flag = WFLAGP(wwin, no_focusable);
1378 descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
1379 break;
1380 case 5:
1381 caption = _("Keep inside screen");
1382 flag = WFLAGP(wwin, dont_move_off);
1383 descr = _("Do not allow the window to move itself completely\n"
1384 "outside the screen. For bug compatibility.\n");
1385 break;
1386 case 6:
1387 caption = _("Ignore 'Hide Others'");
1388 flag = WFLAGP(wwin, no_hide_others);
1389 descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
1390 break;
1391 case 7:
1392 caption = _("Ignore 'Save Session'");
1393 flag = WFLAGP(wwin, dont_save_session);
1394 descr = _("Do not save the associated application in the\n"
1395 "session's state, so that it won't be restarted\n"
1396 "together with other applications when Window Maker\n" "starts.");
1397 break;
1398 case 8:
1399 caption = _("Emulate application icon");
1400 flag = WFLAGP(wwin, emulate_appicon);
1401 descr = _("Make this window act as an application that provides\n"
1402 "enough information to Window Maker for a dockable\n"
1403 "application icon to be created.");
1404 break;
1405 case 9:
1406 caption = _("Focus across workspaces");
1407 flag = WFLAGP(wwin, focus_across_wksp);
1408 descr = _("Allow Window Maker to switch workspace to satisfy\n"
1409 "a focus request (annoying).");
1410 break;
1411 case 10:
1412 caption = _("Do not let it be minimized");
1413 flag = WFLAGP(wwin, no_miniaturizable);
1414 descr = _("Do not let the window of this application be\n"
1415 "minimized.\n");
1416 break;
1417 #ifdef XKB_BUTTON_HINT
1418 case 11:
1419 caption = _("Disable language button");
1420 flag = WFLAGP(wwin, no_language_button);
1421 descr = _("Remove the `toggle language' button of the window.");
1422 break;
1423 #endif
1425 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1426 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
1427 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1428 WMSetButtonSelected(panel->moreChk[i], flag);
1429 WMSetButtonText(panel->moreChk[i], caption);
1431 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1434 /* miniwindow/workspace */
1435 panel->iconFrm = WMCreateFrame(panel->win);
1436 WMMoveWidget(panel->iconFrm, 15, 50);
1437 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1438 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1440 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1441 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1442 WMResizeWidget(panel->iconLbl, 64, 64);
1443 WMSetLabelRelief(panel->iconLbl, WRGroove);
1444 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1446 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1447 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1448 WMMoveWidget(panel->browseIconBtn, 22, 32);
1449 WMResizeWidget(panel->browseIconBtn, 120, 26);
1450 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1452 #ifdef wrong_behaviour
1453 WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
1454 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
1455 WMSetButtonImage(panel->updateIconBtn, pixmap);
1456 WMReleasePixmap(pixmap);
1457 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
1458 WMSetButtonAltImage(panel->updateIconBtn, pixmap);
1459 WMReleasePixmap(pixmap);
1460 #endif
1462 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1463 WMMoveWidget(panel->fileLbl, 20, 85);
1464 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1465 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1467 panel->fileText = WMCreateTextField(panel->iconFrm);
1468 WMMoveWidget(panel->fileText, 20, 105);
1469 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1470 WMSetTextFieldText(panel->fileText, NULL);
1471 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1473 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1474 WMMoveWidget(panel->alwChk, 20, 130);
1475 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1476 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1477 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1479 panel->wsFrm = WMCreateFrame(panel->win);
1480 WMMoveWidget(panel->wsFrm, 15, 225);
1481 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1482 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1484 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1485 "first shown."), WMWidgetView(panel->wsFrm));
1487 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1488 WMMoveWidget(panel->wsP, 20, 30);
1489 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1490 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1491 for (i = 0; i < wwin->screen_ptr->workspace_count; i++) {
1492 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1495 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1496 if (i >= 0 && i <= wwin->screen_ptr->workspace_count) {
1497 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1498 } else {
1499 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1502 /* application wide attributes */
1503 if (wwin->main_window != None) {
1504 WApplication *wapp = wApplicationOf(wwin->main_window);
1506 panel->appFrm = WMCreateFrame(panel->win);
1507 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1508 WMMoveWidget(panel->appFrm, 15, 50);
1509 WMResizeWidget(panel->appFrm, frame_width, 240);
1511 for (i = 0; i < 3; i++) {
1512 char *caption = NULL;
1513 int flag = 0;
1514 char *descr = NULL;
1516 switch (i) {
1517 case 0:
1518 caption = _("Start hidden");
1519 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1520 descr = _("Automatically hide application when it's started.");
1521 break;
1522 case 1:
1523 caption = _("No application icon");
1524 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1525 descr = _("Disable the application icon for the application.\n"
1526 "Note that you won't be able to dock it anymore,\n"
1527 "and any icons that are already docked will stop\n"
1528 "working correctly.");
1529 break;
1530 case 2:
1531 caption = _("Shared application icon");
1532 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1533 descr = _("Use a single shared application icon for all of\n"
1534 "the instances of this application.\n");
1535 break;
1537 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1538 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1539 WMResizeWidget(panel->appChk[i], 205, 20);
1540 WMSetButtonSelected(panel->appChk[i], flag);
1541 WMSetButtonText(panel->appChk[i], caption);
1543 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1546 if (WFLAGP(wwin, emulate_appicon)) {
1547 WMSetButtonEnabled(panel->appChk[1], False);
1548 WMSetButtonEnabled(panel->moreChk[7], True);
1549 } else {
1550 WMSetButtonEnabled(panel->appChk[1], True);
1551 WMSetButtonEnabled(panel->moreChk[7], False);
1553 } else {
1554 int tmp;
1556 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1557 || !wwin->wm_class || !wwin->wm_instance)
1558 tmp = False;
1559 else
1560 tmp = True;
1561 WMSetButtonEnabled(panel->moreChk[7], tmp);
1563 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1564 panel->appFrm = NULL;
1567 /* if the window is a transient, don't let it have a miniaturize
1568 * button */
1569 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1570 WMSetButtonEnabled(panel->attrChk[3], False);
1571 else
1572 WMSetButtonEnabled(panel->attrChk[3], True);
1574 if (!wwin->wm_class && !wwin->wm_instance) {
1575 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1578 WMRealizeWidget(panel->win);
1580 WMMapSubwidgets(panel->win);
1581 WMMapSubwidgets(panel->specFrm);
1582 WMMapSubwidgets(panel->attrFrm);
1583 WMMapSubwidgets(panel->moreFrm);
1584 WMMapSubwidgets(panel->iconFrm);
1585 WMMapSubwidgets(panel->wsFrm);
1586 if (panel->appFrm)
1587 WMMapSubwidgets(panel->appFrm);
1589 if (showSelectPanel) {
1590 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1591 changePage(panel->pagePopUp, panel);
1592 } else {
1593 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1594 changePage(panel->pagePopUp, panel);
1597 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1598 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1599 panel->parent = parent;
1600 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1602 WMMapWidget(panel->win);
1604 XSetTransientForHint(dpy, parent, wwin->client_win);
1606 if (xpos == UNDEFINED_POS) {
1607 x = wwin->frame_x + wwin->frame->core->width / 2;
1608 y = wwin->frame_y + wwin->frame->top_width * 2;
1609 if (y + PHEIGHT > scr->scr_height)
1610 y = scr->scr_height - PHEIGHT - 30;
1611 if (x + PWIDTH > scr->scr_width)
1612 x = scr->scr_width - PWIDTH;
1613 } else {
1614 x = xpos;
1615 y = ypos;
1618 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1620 if (!selectedBtn)
1621 selectedBtn = panel->defaultRb;
1623 WMSetButtonSelected(selectedBtn, True);
1625 selectSpecification(selectedBtn, panel);
1627 /* kluge to know who should get the key events */
1628 panel->frame->client_leader = WMWidgetXID(panel->win);
1630 WSETUFLAG(panel->frame, no_closable, 0);
1631 WSETUFLAG(panel->frame, no_close_button, 0);
1632 wWindowUpdateButtonImages(panel->frame);
1633 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1634 panel->frame->frame->on_click_right = destroyInspector;
1636 wWindowMap(panel->frame);
1638 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1640 return panel;
1643 void wShowInspectorForWindow(WWindow * wwin)
1645 if (wwin->flags.inspector_open)
1646 return;
1648 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1650 make_keys();
1651 wwin->flags.inspector_open = 1;
1652 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1655 void wHideInspectorForWindow(WWindow * wwin)
1657 WWindow *pwin = wwin->inspector->frame;
1659 wWindowUnmap(pwin);
1660 pwin->flags.hidden = 1;
1662 wClientSetState(pwin, IconicState, None);
1665 void wUnhideInspectorForWindow(WWindow * wwin)
1667 WWindow *pwin = wwin->inspector->frame;
1669 pwin->flags.hidden = 0;
1670 pwin->flags.mapped = 1;
1671 XMapWindow(dpy, pwin->client_win);
1672 XMapWindow(dpy, pwin->frame->core->window);
1673 wClientSetState(pwin, NormalState, None);
1676 WWindow *wGetWindowOfInspectorForWindow(WWindow * wwin)
1678 if (wwin->inspector) {
1679 assert(wwin->flags.inspector_open != 0);
1681 return wwin->inspector->frame;
1682 } else
1683 return NULL;
1686 void wCloseInspectorForWindow(WWindow * wwin)
1688 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1690 (*pwin->frame->on_click_right) (NULL, pwin, NULL);