Partial fix for focus stealing
[wmaker-crm.git] / src / winspector.c
blob7efe99f1da53097e37d773755ffff9260197372f
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[11];
93 #else
94 WMButton *moreChk[10];
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 #ifdef XKB_BUTTON_HINT
150 static WMPropList *ANoLanguageButton;
151 #endif
152 static WMPropList *AStartWorkspace;
153 static WMPropList *AIcon;
155 /* application wide options */
156 static WMPropList *AStartHidden;
157 static WMPropList *AnyWindow;
158 static WMPropList *EmptyString;
159 static WMPropList *Yes, *No;
161 #define PWIDTH 270
162 #define PHEIGHT 350
164 static char *spec_text;
165 static void applySettings(WMButton * button, InspectorPanel * panel);
167 #define UNDEFINED_POS 0xffffff
169 static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel);
171 static void make_keys(void)
173 if (ANoTitlebar != NULL)
174 return;
176 AIcon = WMCreatePLString("Icon");
177 ANoTitlebar = WMCreatePLString("NoTitlebar");
178 ANoResizebar = WMCreatePLString("NoResizebar");
179 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
180 ANoCloseButton = WMCreatePLString("NoCloseButton");
181 ANoBorder = WMCreatePLString("NoBorder");
182 ANoHideOthers = WMCreatePLString("NoHideOthers");
183 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
184 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
185 ANoAppIcon = WMCreatePLString("NoAppIcon");
186 AKeepOnTop = WMCreatePLString("KeepOnTop");
187 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
188 AOmnipresent = WMCreatePLString("Omnipresent");
189 ASkipWindowList = WMCreatePLString("SkipWindowList");
190 ASkipSwitchPanel = WMCreatePLString("SkipSwitchPanel");
191 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
192 AUnfocusable = WMCreatePLString("Unfocusable");
193 AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace");
194 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
195 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
196 AStartMaximized = WMCreatePLString("StartMaximized");
197 AStartHidden = WMCreatePLString("StartHidden");
198 ADontSaveSession = WMCreatePLString("DontSaveSession");
199 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
200 AFullMaximize = WMCreatePLString("FullMaximize");
201 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
202 #ifdef XKB_BUTTON_HINT
203 ANoLanguageButton = WMCreatePLString("NoLanguageButton");
204 #endif
206 AStartWorkspace = WMCreatePLString("StartWorkspace");
208 AnyWindow = WMCreatePLString("*");
209 EmptyString = WMCreatePLString("");
210 Yes = WMCreatePLString("Yes");
211 No = WMCreatePLString("No");
214 static void freeInspector(InspectorPanel * panel)
216 panel->destroyed = 1;
217 if (panel->choosingIcon)
218 return;
220 WMDestroyWidget(panel->win);
222 XDestroyWindow(dpy, panel->parent);
224 wfree(panel);
227 static void destroyInspector(WCoreWindow * foo, void *data, XEvent * event)
229 InspectorPanel *panel;
230 InspectorPanel *tmp;
232 panel = panelList;
233 while (panel->frame != data)
234 panel = panel->nextPtr;
236 if (panelList == panel)
237 panelList = panel->nextPtr;
238 else {
239 tmp = panelList;
240 while (tmp->nextPtr != panel) {
241 tmp = tmp->nextPtr;
243 tmp->nextPtr = panel->nextPtr;
245 panel->inspected->flags.inspector_open = 0;
246 panel->inspected->inspector = NULL;
248 WMRemoveNotificationObserver(panel);
250 wWindowUnmap(panel->frame);
251 wUnmanageWindow(panel->frame, True, False);
253 freeInspector(panel);
256 void wDestroyInspectorPanels(void)
258 InspectorPanel *panel;
260 while (panelList != NULL) {
261 panel = panelList;
262 panelList = panelList->nextPtr;
263 wUnmanageWindow(panel->frame, False, False);
264 WMDestroyWidget(panel->win);
266 panel->inspected->flags.inspector_open = 0;
267 panel->inspected->inspector = NULL;
269 wfree(panel);
273 static void changePage(WMPopUpButton * bPtr, InspectorPanel * panel)
275 int page;
277 page = WMGetPopUpButtonSelectedItem(bPtr);
279 if (page == 0) {
280 WMMapWidget(panel->specFrm);
281 WMMapWidget(panel->specLbl);
282 } else if (page == 1) {
283 WMMapWidget(panel->attrFrm);
284 } else if (page == 2) {
285 WMMapWidget(panel->moreFrm);
286 } else if (page == 3) {
287 WMMapWidget(panel->iconFrm);
288 WMMapWidget(panel->wsFrm);
289 } else {
290 WMMapWidget(panel->appFrm);
293 if (page != 0) {
294 WMUnmapWidget(panel->specFrm);
295 WMUnmapWidget(panel->specLbl);
297 if (page != 1)
298 WMUnmapWidget(panel->attrFrm);
299 if (page != 2)
300 WMUnmapWidget(panel->moreFrm);
301 if (page != 3) {
302 WMUnmapWidget(panel->iconFrm);
303 WMUnmapWidget(panel->wsFrm);
305 if (page != 4 && panel->appFrm)
306 WMUnmapWidget(panel->appFrm);
309 #define USE_TEXT_FIELD 1
310 #define UPDATE_TEXT_FIELD 2
311 #define REVERT_TO_DEFAULT 4
313 static int showIconFor(WMScreen * scrPtr, InspectorPanel * panel, char *wm_instance, char *wm_class, int flags)
315 WMPixmap *pixmap = (WMPixmap *) NULL;
316 char *file = NULL, *path = NULL;
317 char *db_icon = NULL;
319 if ((flags & USE_TEXT_FIELD) != 0) {
320 file = WMGetTextFieldText(panel->fileText);
321 if (file && file[0] == 0) {
322 wfree(file);
323 file = NULL;
325 } else {
326 db_icon = wDefaultGetIconFile(panel->inspected->screen_ptr, wm_instance, wm_class, False);
327 if (db_icon != NULL)
328 file = wstrdup(db_icon);
330 if (db_icon != NULL && (flags & REVERT_TO_DEFAULT) != 0) {
331 if (file)
332 file = wstrdup(db_icon);
333 flags |= UPDATE_TEXT_FIELD;
336 if ((flags & UPDATE_TEXT_FIELD) != 0) {
337 WMSetTextFieldText(panel->fileText, file);
340 if (file) {
341 path = FindImage(wPreferences.icon_path, file);
343 if (!path) {
344 char *buf;
345 int len = strlen(file) + 80;
347 buf = wmalloc(len);
348 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"), file);
349 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
350 wfree(buf);
351 wfree(file);
352 return -1;
355 pixmap = WMCreatePixmapFromFile(scrPtr, path);
356 wfree(path);
358 if (!pixmap) {
359 char *buf;
360 int len = strlen(file) + 80;
362 buf = wmalloc(len);
363 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
364 file, RMessageForError(RErrorCode));
365 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
366 wfree(buf);
367 wfree(file);
368 return -1;
370 wfree(file);
373 WMSetLabelImage(panel->iconLbl, pixmap);
374 if (pixmap)
375 WMReleasePixmap(pixmap);
377 return 0;
380 #if 0
381 static void updateIcon(WMButton * button, InspectorPanel * panel)
383 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
385 #endif
387 static int getBool(WMPropList * value)
389 char *val;
391 if (!WMIsPLString(value)) {
392 return 0;
394 if (!(val = WMGetFromPLString(value))) {
395 return 0;
398 if ((val[1] == '\0' && (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' || val[0] == 't' || val[0] == '1'))
399 || (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
401 return 1;
402 } else if ((val[1] == '\0'
403 && (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' || val[0] == 'f' || val[0] == '0'))
404 || (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
406 return 0;
407 } else {
408 wwarning(_("can't convert \"%s\" to boolean"), val);
409 return 0;
413 #define UPDATE_DEFAULTS 1
414 #define IS_BOOLEAN 2
417 * Will insert the attribute = value; pair in window's list,
418 * if it's different from the defaults.
419 * Defaults means either defaults database, or attributes saved
420 * for the default window "*". This is to let one revert options that are
421 * global because they were saved for all windows ("*").
425 static int
426 insertAttribute(WMPropList * dict, WMPropList * window, WMPropList * attr, WMPropList * value, int flags)
428 WMPropList *def_win, *def_value = NULL;
429 int update = 0;
430 int modified = 0;
432 if (!(flags & UPDATE_DEFAULTS) && dict) {
433 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL) {
434 def_value = WMGetFromPLDictionary(def_win, attr);
438 /* If we could not find defaults in database, fall to hardcoded values.
439 * Also this is true if we save defaults for all windows
441 if (!def_value)
442 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
444 if ((flags & IS_BOOLEAN))
445 update = (getBool(value) != getBool(def_value));
446 else {
447 update = !WMIsPropListEqualTo(value, def_value);
450 if (update) {
451 WMPutInPLDictionary(window, attr, value);
452 modified = 1;
455 return modified;
458 static void saveSettings(WMButton * button, InspectorPanel * panel)
460 WWindow *wwin = panel->inspected;
461 WDDomain *db = WDWindowAttributes;
462 WMPropList *dict = db->dictionary;
463 WMPropList *winDic, *appDic, *value, *key, *key2;
464 char *icon_file;
465 int flags = 0;
466 int different = 0, different2 = 0;
468 /* Save will apply the changes and save them */
469 applySettings(panel->applyBtn, panel);
471 if (WMGetButtonSelected(panel->instRb) != 0)
472 key = WMCreatePLString(wwin->wm_instance);
473 else if (WMGetButtonSelected(panel->clsRb) != 0)
474 key = WMCreatePLString(wwin->wm_class);
475 else if (WMGetButtonSelected(panel->bothRb) != 0) {
476 char *buffer;
478 buffer = StrConcatDot(wwin->wm_instance, wwin->wm_class);
479 key = WMCreatePLString(buffer);
480 wfree(buffer);
481 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
482 key = WMRetainPropList(AnyWindow);
483 flags = UPDATE_DEFAULTS;
484 } else
485 key = NULL;
487 if (!key)
488 return;
490 if (!dict) {
491 dict = WMCreatePLDictionary(NULL, NULL);
492 if (dict) {
493 db->dictionary = dict;
494 } else {
495 WMReleasePropList(key);
496 return;
500 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD) < 0)
501 return;
503 WMPLSetCaseSensitive(True);
505 winDic = WMCreatePLDictionary(NULL, NULL);
506 appDic = WMCreatePLDictionary(NULL, NULL);
508 /* Update icon for window */
509 icon_file = WMGetTextFieldText(panel->fileText);
510 if (icon_file) {
511 if (icon_file[0] != 0) {
512 value = WMCreatePLString(icon_file);
513 different |= insertAttribute(dict, winDic, AIcon, value, flags);
514 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
515 WMReleasePropList(value);
517 wfree(icon_file);
521 int i = WMGetPopUpButtonSelectedItem(panel->wsP);
523 i--;
525 if (i >= 0 && i < panel->frame->screen_ptr->workspace_count) {
526 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
527 different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
528 WMReleasePropList(value);
532 flags |= IS_BOOLEAN;
534 value = (WMGetButtonSelected(panel->alwChk) != 0) ? Yes : No;
535 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
537 value = (WMGetButtonSelected(panel->attrChk[0]) != 0) ? Yes : No;
538 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
540 value = (WMGetButtonSelected(panel->attrChk[1]) != 0) ? Yes : No;
541 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
543 value = (WMGetButtonSelected(panel->attrChk[2]) != 0) ? Yes : No;
544 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
546 value = (WMGetButtonSelected(panel->attrChk[3]) != 0) ? Yes : No;
547 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
549 value = (WMGetButtonSelected(panel->attrChk[4]) != 0) ? Yes : No;
550 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
552 value = (WMGetButtonSelected(panel->attrChk[5]) != 0) ? Yes : No;
553 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
555 value = (WMGetButtonSelected(panel->attrChk[6]) != 0) ? Yes : No;
556 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
558 value = (WMGetButtonSelected(panel->attrChk[7]) != 0) ? Yes : No;
559 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
561 value = (WMGetButtonSelected(panel->attrChk[8]) != 0) ? Yes : No;
562 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
564 value = (WMGetButtonSelected(panel->attrChk[9]) != 0) ? Yes : No;
565 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
567 value = (WMGetButtonSelected(panel->attrChk[10]) != 0) ? Yes : No;
568 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
570 value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No;
571 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
573 value = (WMGetButtonSelected(panel->moreChk[1]) != 0) ? Yes : No;
574 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
576 value = (WMGetButtonSelected(panel->moreChk[2]) != 0) ? Yes : No;
577 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
579 value = (WMGetButtonSelected(panel->moreChk[3]) != 0) ? Yes : No;
580 different |= insertAttribute(dict, winDic, ASkipSwitchPanel, value, flags);
582 value = (WMGetButtonSelected(panel->moreChk[4]) != 0) ? Yes : No;
583 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
585 value = (WMGetButtonSelected(panel->moreChk[5]) != 0) ? Yes : No;
586 different |= insertAttribute(dict, winDic, AKeepInsideScreen, value, flags);
588 value = (WMGetButtonSelected(panel->moreChk[6]) != 0) ? Yes : No;
589 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
591 value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No;
592 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
594 value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No;
595 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
597 value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No;
598 different |= insertAttribute(dict, winDic, AFocusAcrossWorkspace, value, flags);
600 #ifdef XKB_BUTTON_HINT
601 value = (WMGetButtonSelected(panel->moreChk[10]) != 0) ? Yes : No;
602 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
603 #endif
605 if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
606 value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No;
607 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
609 value = (WMGetButtonSelected(panel->appChk[1]) != 0) ? Yes : No;
610 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
612 value = (WMGetButtonSelected(panel->appChk[2]) != 0) ? Yes : No;
613 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
616 if (wwin->fake_group) {
617 key2 = WMCreatePLString(wwin->fake_group->identifier);
618 if (WMIsPropListEqualTo(key, key2)) {
619 WMMergePLDictionaries(winDic, appDic, True);
620 different |= different2;
621 } else {
622 WMRemoveFromPLDictionary(dict, key2);
623 if (different2) {
624 WMPutInPLDictionary(dict, key2, appDic);
627 WMReleasePropList(key2);
628 WMReleasePropList(appDic);
629 } else if (wwin->main_window != wwin->client_win) {
630 WApplication *wapp = wApplicationOf(wwin->main_window);
632 if (wapp) {
633 char *instance = wapp->main_window_desc->wm_instance;
634 char *class = wapp->main_window_desc->wm_class;
635 char *buffer;
637 buffer = StrConcatDot(instance, class);
638 key2 = WMCreatePLString(buffer);
639 wfree(buffer);
641 if (WMIsPropListEqualTo(key, key2)) {
642 WMMergePLDictionaries(winDic, appDic, True);
643 different |= different2;
644 } else {
645 WMRemoveFromPLDictionary(dict, key2);
646 if (different2) {
647 WMPutInPLDictionary(dict, key2, appDic);
650 WMReleasePropList(key2);
651 WMReleasePropList(appDic);
653 } else {
654 WMMergePLDictionaries(winDic, appDic, True);
655 different |= different2;
656 WMReleasePropList(appDic);
659 WMRemoveFromPLDictionary(dict, key);
660 if (different) {
661 WMPutInPLDictionary(dict, key, winDic);
664 WMReleasePropList(key);
665 WMReleasePropList(winDic);
667 UpdateDomainFile(db);
669 /* clean up */
670 WMPLSetCaseSensitive(False);
673 static void makeAppIconFor(WApplication * wapp)
675 WScreen *scr = wapp->main_window_desc->screen_ptr;
677 if (wapp->app_icon)
678 return;
680 if (!WFLAGP(wapp->main_window_desc, no_appicon))
681 wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
682 else
683 wapp->app_icon = NULL;
685 if (wapp->app_icon) {
686 WIcon *icon = wapp->app_icon->icon;
687 WDock *clip = scr->workspaces[scr->current_workspace]->clip;
688 int x = 0, y = 0;
690 wapp->app_icon->main_window = wapp->main_window;
692 if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
693 wapp->app_icon->attracted = 1;
694 if (!wapp->app_icon->icon->shadowed) {
695 wapp->app_icon->icon->shadowed = 1;
696 wapp->app_icon->icon->force_paint = 1;
698 wDockAttachIcon(clip, wapp->app_icon, x, y);
699 } else {
700 PlaceIcon(scr, &x, &y, wGetHeadForWindow(wapp->main_window_desc));
701 wAppIconMove(wapp->app_icon, x, y);
703 if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
704 XMapWindow(dpy, icon->core->window);
706 if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
707 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
711 static void removeAppIconFor(WApplication * wapp)
713 if (!wapp->app_icon)
714 return;
716 if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
717 wapp->app_icon->running = 0;
718 /* since we keep it, we don't care if it was attracted or not */
719 wapp->app_icon->attracted = 0;
720 wapp->app_icon->icon->shadowed = 0;
721 wapp->app_icon->main_window = None;
722 wapp->app_icon->pid = 0;
723 wapp->app_icon->icon->owner = NULL;
724 wapp->app_icon->icon->icon_win = None;
725 wapp->app_icon->icon->force_paint = 1;
726 wAppIconPaint(wapp->app_icon);
727 } else if (wapp->app_icon->docked) {
728 wapp->app_icon->running = 0;
729 wDockDetach(wapp->app_icon->dock, wapp->app_icon);
730 } else {
731 wAppIconDestroy(wapp->app_icon);
733 wapp->app_icon = NULL;
734 if (wPreferences.auto_arrange_icons)
735 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
738 static void applySettings(WMButton * button, InspectorPanel * panel)
740 WWindow *wwin = panel->inspected;
741 WApplication *wapp = wApplicationOf(wwin->main_window);
742 int floating, sunken, skip_window_list;
743 int old_omnipresent;
744 int old_no_bind_keys;
745 int old_no_bind_mouse;
747 old_omnipresent = WFLAGP(wwin, omnipresent);
748 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
749 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
751 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
753 /* Attributes... --> Window Attributes */
754 WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
755 WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
756 WSETUFLAG(wwin, no_close_button, WMGetButtonSelected(panel->attrChk[2]));
757 WSETUFLAG(wwin, no_miniaturize_button, WMGetButtonSelected(panel->attrChk[3]));
758 WSETUFLAG(wwin, no_border, WMGetButtonSelected(panel->attrChk[4]));
759 floating = WMGetButtonSelected(panel->attrChk[5]);
760 sunken = WMGetButtonSelected(panel->attrChk[6]);
761 WSETUFLAG(wwin, omnipresent, WMGetButtonSelected(panel->attrChk[7]));
762 WSETUFLAG(wwin, start_miniaturized, WMGetButtonSelected(panel->attrChk[8]));
763 WSETUFLAG(wwin, start_maximized, WMGetButtonSelected(panel->attrChk[9]));
764 WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
766 /* Attributes... --> Advanced Options */
767 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
768 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
769 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
770 WSETUFLAG(wwin, skip_switchpanel, WMGetButtonSelected(panel->moreChk[3]));
771 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[4]));
772 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[5]));
773 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[6]));
774 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[7]));
775 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[8]));
776 WSETUFLAG(wwin, focus_across_wksp, WMGetButtonSelected(panel->moreChk[9]));
777 #ifdef XKB_BUTTON_HINT
778 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[10]));
779 #endif
780 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
782 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
783 wUnshadeWindow(wwin);
785 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
787 if (floating) {
788 if (!WFLAGP(wwin, floating))
789 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
790 } else if (sunken) {
791 if (!WFLAGP(wwin, sunken))
792 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
793 } else {
794 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
795 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
798 WSETUFLAG(wwin, sunken, sunken);
799 WSETUFLAG(wwin, floating, floating);
800 wwin->flags.omnipresent = 0;
802 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
803 WSETUFLAG(wwin, skip_window_list, skip_window_list);
804 UpdateSwitchMenu(wwin->screen_ptr, wwin, skip_window_list ? ACTION_REMOVE : ACTION_ADD);
805 } else {
806 if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
807 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
811 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
812 if (WFLAGP(wwin, no_bind_keys)) {
813 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
814 } else {
815 wWindowSetKeyGrabs(wwin);
819 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
820 wWindowResetMouseGrabs(wwin);
823 wwin->frame->flags.need_texture_change = 1;
824 wWindowConfigureBorders(wwin);
825 wFrameWindowPaint(wwin->frame);
826 wNETWMUpdateActions(wwin, False);
829 * Can't apply emulate_appicon because it will probably cause problems.
831 if (wapp) {
832 /* do application wide stuff */
833 WSETUFLAG(wapp->main_window_desc, start_hidden, WMGetButtonSelected(panel->appChk[0]));
835 WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1]));
837 WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2]));
839 if (WFLAGP(wapp->main_window_desc, no_appicon))
840 removeAppIconFor(wapp);
841 else
842 makeAppIconFor(wapp);
844 if (wapp->app_icon && wapp->main_window == wwin->client_win) {
845 char *file = WMGetTextFieldText(panel->fileText);
847 if (file[0] == 0) {
848 wfree(file);
849 file = NULL;
851 wIconChangeImageFile(wapp->app_icon->icon, file);
852 if (file)
853 wfree(file);
854 wAppIconPaint(wapp->app_icon);
859 static void revertSettings(WMButton * button, InspectorPanel * panel)
861 WWindow *wwin = panel->inspected;
862 WApplication *wapp = wApplicationOf(wwin->main_window);
863 int i, n;
864 char *wm_instance = NULL;
865 char *wm_class = NULL;
866 int workspace, level;
868 if (panel->instRb && WMGetButtonSelected(panel->instRb) != 0)
869 wm_instance = wwin->wm_instance;
870 else if (panel->clsRb && WMGetButtonSelected(panel->clsRb) != 0)
871 wm_class = wwin->wm_class;
872 else if (panel->bothRb && WMGetButtonSelected(panel->bothRb) != 0) {
873 wm_instance = wwin->wm_instance;
874 wm_class = wwin->wm_class;
876 memset(&wwin->defined_user_flags, 0, sizeof(WWindowAttributes));
877 memset(&wwin->user_flags, 0, sizeof(WWindowAttributes));
878 memset(&wwin->client_flags, 0, sizeof(WWindowAttributes));
880 wWindowSetupInitialAttributes(wwin, &level, &workspace);
882 for (i = 0; i < 11; i++) {
883 int flag = 0;
885 switch (i) {
886 case 0:
887 flag = WFLAGP(wwin, no_titlebar);
888 break;
889 case 1:
890 flag = WFLAGP(wwin, no_resizebar);
891 break;
892 case 2:
893 flag = WFLAGP(wwin, no_close_button);
894 break;
895 case 3:
896 flag = WFLAGP(wwin, no_miniaturize_button);
897 break;
898 case 4:
899 flag = WFLAGP(wwin, no_border);
900 break;
901 case 5:
902 flag = WFLAGP(wwin, floating);
903 break;
904 case 6:
905 flag = WFLAGP(wwin, sunken);
906 break;
907 case 7:
908 flag = WFLAGP(wwin, omnipresent);
909 break;
910 case 8:
911 flag = WFLAGP(wwin, start_miniaturized);
912 break;
913 case 9:
914 flag = WFLAGP(wwin, start_maximized != 0);
915 break;
916 case 10:
917 flag = WFLAGP(wwin, full_maximize);
918 break;
920 WMSetButtonSelected(panel->attrChk[i], flag);
922 for (i = 0; i < 11; i++) {
923 int flag = 0;
925 switch (i) {
926 case 0:
927 flag = WFLAGP(wwin, no_bind_keys);
928 break;
929 case 1:
930 flag = WFLAGP(wwin, no_bind_mouse);
931 break;
932 case 2:
933 flag = WFLAGP(wwin, skip_window_list);
934 break;
935 case 3:
936 flag = WFLAGP(wwin, skip_switchpanel);
937 break;
938 case 4:
939 flag = WFLAGP(wwin, no_focusable);
940 break;
941 case 5:
942 flag = WFLAGP(wwin, dont_move_off);
943 break;
944 case 6:
945 flag = WFLAGP(wwin, no_hide_others);
946 break;
947 case 7:
948 flag = WFLAGP(wwin, dont_save_session);
949 break;
950 case 8:
951 flag = WFLAGP(wwin, emulate_appicon);
952 break;
953 case 9:
954 flag = WFLAGP(wwin, focus_across_wksp);
955 break;
956 #ifdef XKB_BUTTON_HINT
957 case 10:
958 flag = WFLAGP(wwin, no_language_button);
959 break;
960 #endif
962 WMSetButtonSelected(panel->moreChk[i], flag);
964 if (panel->appFrm && wapp) {
965 for (i = 0; i < 3; i++) {
966 int flag = 0;
968 switch (i) {
969 case 0:
970 flag = WFLAGP(wapp->main_window_desc, start_hidden);
971 break;
972 case 1:
973 flag = WFLAGP(wapp->main_window_desc, no_appicon);
974 break;
975 case 2:
976 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
977 break;
979 WMSetButtonSelected(panel->appChk[i], flag);
982 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
984 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
986 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
988 if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
989 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
990 } else {
991 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
994 /* must auto apply, so that there wno't be internal
995 * inconsistencies between the state in the flags and
996 * the actual state of the window */
997 applySettings(panel->applyBtn, panel);
1000 static void chooseIconCallback(WMWidget * self, void *clientData)
1002 char *file;
1003 InspectorPanel *panel = (InspectorPanel *) clientData;
1004 int result;
1006 panel->choosingIcon = 1;
1008 WMSetButtonEnabled(panel->browseIconBtn, False);
1010 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
1011 panel->inspected->wm_instance, panel->inspected->wm_class);
1013 panel->choosingIcon = 0;
1015 if (!panel->destroyed) { /* kluge */
1016 if (result) {
1017 WMSetTextFieldText(panel->fileText, file);
1018 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
1019 wfree(file);
1021 WMSetButtonEnabled(panel->browseIconBtn, True);
1022 } else {
1023 freeInspector(panel);
1027 static void textEditedObserver(void *observerData, WMNotification * notification)
1029 InspectorPanel *panel = (InspectorPanel *) observerData;
1031 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
1032 return;
1034 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
1036 WMPerformButtonClick(panel->updateIconBtn);
1040 static void selectSpecification(WMWidget * bPtr, void *data)
1042 InspectorPanel *panel = (InspectorPanel *) data;
1043 char *str;
1044 WWindow *wwin = panel->inspected;
1045 int len;
1047 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class)) {
1048 WMSetButtonEnabled(panel->applyBtn, False);
1049 } else {
1050 WMSetButtonEnabled(panel->applyBtn, True);
1053 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
1054 + strlen(wwin->wm_class ? wwin->wm_class : "?");
1056 str = wmalloc(len);
1058 snprintf(str, len, _("Inspecting %s.%s"),
1059 wwin->wm_instance ? wwin->wm_instance : "?", wwin->wm_class ? wwin->wm_class : "?");
1061 wFrameWindowChangeTitle(panel->frame->frame, str);
1063 wfree(str);
1066 static void selectWindow(WMWidget * bPtr, void *data)
1068 InspectorPanel *panel = (InspectorPanel *) data;
1069 WWindow *wwin = panel->inspected;
1070 WScreen *scr = wwin->screen_ptr;
1071 XEvent event;
1072 WWindow *iwin;
1074 if (XGrabPointer(dpy, scr->root_win, True,
1075 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1076 wCursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
1077 wwarning("could not grab mouse pointer");
1078 return;
1081 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1083 WMMaskEvent(dpy, ButtonPressMask, &event);
1085 XUngrabPointer(dpy, CurrentTime);
1087 iwin = wWindowFor(event.xbutton.subwindow);
1089 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
1091 iwin->flags.inspector_open = 1;
1092 iwin->inspector = createInspectorForWindow(iwin,
1093 panel->frame->frame_x, panel->frame->frame_y, True);
1094 wCloseInspectorForWindow(wwin);
1095 } else {
1096 WMSetLabelText(panel->specLbl, spec_text);
1100 static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel)
1102 WScreen *scr = wwin->screen_ptr;
1103 InspectorPanel *panel;
1104 Window parent;
1105 int i;
1106 int x, y;
1107 int btn_width, frame_width;
1108 WMButton *selectedBtn = NULL;
1109 #ifdef wrong_behaviour
1110 WMPixmap *pixmap;
1111 #endif
1113 spec_text = _("The configuration will apply to all\n"
1114 "windows that have their WM_CLASS\n"
1115 "property set to the above selected\n" "name, when saved.");
1117 panel = wmalloc(sizeof(InspectorPanel));
1118 memset(panel, 0, sizeof(InspectorPanel));
1120 panel->destroyed = 0;
1122 panel->inspected = wwin;
1124 panel->nextPtr = panelList;
1125 panelList = panel;
1127 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1128 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1130 /**** create common stuff ****/
1132 /* command buttons */
1133 /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
1134 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1135 panel->saveBtn = WMCreateCommandButton(panel->win);
1136 WMSetButtonAction(panel->saveBtn, (WMAction *) saveSettings, panel);
1137 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, 310);
1138 WMSetButtonText(panel->saveBtn, _("Save"));
1139 WMResizeWidget(panel->saveBtn, btn_width, 28);
1140 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1141 WMSetButtonEnabled(panel->saveBtn, False);
1143 panel->applyBtn = WMCreateCommandButton(panel->win);
1144 WMSetButtonAction(panel->applyBtn, (WMAction *) applySettings, panel);
1145 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, 310);
1146 WMSetButtonText(panel->applyBtn, _("Apply"));
1147 WMResizeWidget(panel->applyBtn, btn_width, 28);
1149 panel->revertBtn = WMCreateCommandButton(panel->win);
1150 WMSetButtonAction(panel->revertBtn, (WMAction *) revertSettings, panel);
1151 WMMoveWidget(panel->revertBtn, 15, 310);
1152 WMSetButtonText(panel->revertBtn, _("Reload"));
1153 WMResizeWidget(panel->revertBtn, btn_width, 28);
1155 /* page selection popup button */
1156 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1157 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction *) changePage, panel);
1158 WMMoveWidget(panel->pagePopUp, 25, 15);
1159 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1161 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1162 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1163 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1164 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1165 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1167 /**** window spec ****/
1168 frame_width = PWIDTH - (2 * 15);
1170 panel->specFrm = WMCreateFrame(panel->win);
1171 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1172 WMMoveWidget(panel->specFrm, 15, 65);
1173 WMResizeWidget(panel->specFrm, frame_width, 145);
1175 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1176 WMMoveWidget(panel->defaultRb, 10, 78);
1177 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1178 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1179 WMSetButtonSelected(panel->defaultRb, False);
1180 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1182 if (wwin->wm_class && wwin->wm_instance) {
1183 char *str, *tmp;
1185 tmp = wstrconcat(wwin->wm_instance, ".");
1186 str = wstrconcat(tmp, wwin->wm_class);
1188 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1189 WMMoveWidget(panel->bothRb, 10, 18);
1190 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1191 WMSetButtonText(panel->bothRb, str);
1192 wfree(tmp);
1193 wfree(str);
1194 WMGroupButtons(panel->defaultRb, panel->bothRb);
1196 if (!selectedBtn)
1197 selectedBtn = panel->bothRb;
1199 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1202 if (wwin->wm_instance) {
1203 panel->instRb = WMCreateRadioButton(panel->specFrm);
1204 WMMoveWidget(panel->instRb, 10, 38);
1205 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1206 WMSetButtonText(panel->instRb, wwin->wm_instance);
1207 WMGroupButtons(panel->defaultRb, panel->instRb);
1209 if (!selectedBtn)
1210 selectedBtn = panel->instRb;
1212 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1215 if (wwin->wm_class) {
1216 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1217 WMMoveWidget(panel->clsRb, 10, 58);
1218 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1219 WMSetButtonText(panel->clsRb, wwin->wm_class);
1220 WMGroupButtons(panel->defaultRb, panel->clsRb);
1222 if (!selectedBtn)
1223 selectedBtn = panel->clsRb;
1225 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1228 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1229 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1230 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1231 WMSetButtonText(panel->selWinB, _("Select window"));
1232 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1234 panel->specLbl = WMCreateLabel(panel->win);
1235 WMMoveWidget(panel->specLbl, 15, 210);
1236 WMResizeWidget(panel->specLbl, frame_width, 100);
1237 WMSetLabelText(panel->specLbl, spec_text);
1238 WMSetLabelWraps(panel->specLbl, True);
1240 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1242 /**** attributes ****/
1243 panel->attrFrm = WMCreateFrame(panel->win);
1244 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1245 WMMoveWidget(panel->attrFrm, 15, 45);
1246 WMResizeWidget(panel->attrFrm, frame_width, 250);
1248 for (i = 0; i < 11; i++) {
1249 char *caption = NULL;
1250 int flag = 0;
1251 char *descr = NULL;
1253 switch (i) {
1254 case 0:
1255 caption = _("Disable titlebar");
1256 flag = WFLAGP(wwin, no_titlebar);
1257 descr = _("Remove the titlebar of this window.\n"
1258 "To access the window commands menu of a window\n"
1259 "without it's titlebar, press Control+Esc (or the\n"
1260 "equivalent shortcut, if you changed the default\n" "settings).");
1261 break;
1262 case 1:
1263 caption = _("Disable resizebar");
1264 flag = WFLAGP(wwin, no_resizebar);
1265 descr = _("Remove the resizebar of this window.");
1266 break;
1267 case 2:
1268 caption = _("Disable close button");
1269 flag = WFLAGP(wwin, no_close_button);
1270 descr = _("Remove the `close window' button of this window.");
1271 break;
1272 case 3:
1273 caption = _("Disable miniaturize button");
1274 flag = WFLAGP(wwin, no_miniaturize_button);
1275 descr = _("Remove the `miniaturize window' button of the window.");
1276 break;
1277 case 4:
1278 caption = _("Disable border");
1279 flag = WFLAGP(wwin, no_border);
1280 descr = _("Remove the 1 pixel black border around the window.");
1281 break;
1282 case 5:
1283 caption = _("Keep on top (floating)");
1284 flag = WFLAGP(wwin, floating);
1285 descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
1286 break;
1287 case 6:
1288 caption = _("Keep at bottom (sunken)");
1289 flag = WFLAGP(wwin, sunken);
1290 descr = _("Keep the window under all other windows.");
1291 break;
1292 case 7:
1293 caption = _("Omnipresent");
1294 flag = WFLAGP(wwin, omnipresent);
1295 descr = _("Make window present in all workspaces.");
1296 break;
1297 case 8:
1298 caption = _("Start miniaturized");
1299 flag = WFLAGP(wwin, start_miniaturized);
1300 descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
1301 break;
1302 case 9:
1303 caption = _("Start maximized");
1304 flag = WFLAGP(wwin, start_maximized != 0);
1305 descr = _("Make the window be automatically maximized when it's\n" "first shown.");
1306 break;
1307 case 10:
1308 caption = _("Full screen maximization");
1309 flag = WFLAGP(wwin, full_maximize);
1310 descr = _("Make the window use the whole screen space when it's\n"
1311 "maximized. The titlebar and resizebar will be moved\n"
1312 "to outside the screen.");
1313 break;
1315 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1316 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1317 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1318 WMSetButtonSelected(panel->attrChk[i], flag);
1319 WMSetButtonText(panel->attrChk[i], caption);
1321 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1324 /**** more attributes ****/
1325 panel->moreFrm = WMCreateFrame(panel->win);
1326 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1327 WMMoveWidget(panel->moreFrm, 15, 45);
1328 WMResizeWidget(panel->moreFrm, frame_width, 250);
1330 for (i = 0;
1331 #ifdef XKB_BUTTON_HINT
1332 i < 11;
1333 #else
1334 i < 10;
1335 #endif
1336 i++) {
1337 char *caption = NULL;
1338 int flag = 0;
1339 char *descr = NULL;
1341 switch (i) {
1342 case 0:
1343 caption = _("Do not bind keyboard shortcuts");
1344 flag = WFLAGP(wwin, no_bind_keys);
1345 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1346 "when this window is focused. This will allow the\n"
1347 "window to receive all key combinations regardless\n"
1348 "of your shortcut configuration.");
1349 break;
1350 case 1:
1351 caption = _("Do not bind mouse clicks");
1352 flag = WFLAGP(wwin, no_bind_mouse);
1353 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1354 "in the window (when alt is the modifier you have\n" "configured).");
1355 break;
1356 case 2:
1357 caption = _("Do not show in the window list");
1358 flag = WFLAGP(wwin, skip_window_list);
1359 descr = _("Do not list the window in the window list menu.");
1360 break;
1361 case 3:
1362 caption = _("Do not show in the switch panel");
1363 flag = WFLAGP(wwin, skip_switchpanel);
1364 descr = _("Do not include in switchpanel while alternating windows.");
1365 break;
1366 case 4:
1367 caption = _("Do not let it take focus");
1368 flag = WFLAGP(wwin, no_focusable);
1369 descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
1370 break;
1371 case 5:
1372 caption = _("Keep inside screen");
1373 flag = WFLAGP(wwin, dont_move_off);
1374 descr = _("Do not allow the window to move itself completely\n"
1375 "outside the screen. For bug compatibility.\n");
1376 break;
1377 case 6:
1378 caption = _("Ignore 'Hide Others'");
1379 flag = WFLAGP(wwin, no_hide_others);
1380 descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
1381 break;
1382 case 7:
1383 caption = _("Ignore 'Save Session'");
1384 flag = WFLAGP(wwin, dont_save_session);
1385 descr = _("Do not save the associated application in the\n"
1386 "session's state, so that it won't be restarted\n"
1387 "together with other applications when Window Maker\n" "starts.");
1388 break;
1389 case 8:
1390 caption = _("Emulate application icon");
1391 flag = WFLAGP(wwin, emulate_appicon);
1392 descr = _("Make this window act as an application that provides\n"
1393 "enough information to Window Maker for a dockable\n"
1394 "application icon to be created.");
1395 break;
1396 case 9:
1397 caption = _("Focus across workspaces");
1398 flag = WFLAGP(wwin, focus_across_wksp);
1399 descr = _("Allow Window Maker to switch workspace to satisfy\n"
1400 "a focus request (annoying).");
1401 break;
1402 #ifdef XKB_BUTTON_HINT
1403 case 10:
1404 caption = _("Disable language button");
1405 flag = WFLAGP(wwin, no_language_button);
1406 descr = _("Remove the `toggle language' button of the window.");
1407 break;
1408 #endif
1410 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1411 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
1412 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1413 WMSetButtonSelected(panel->moreChk[i], flag);
1414 WMSetButtonText(panel->moreChk[i], caption);
1416 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1419 /* miniwindow/workspace */
1420 panel->iconFrm = WMCreateFrame(panel->win);
1421 WMMoveWidget(panel->iconFrm, 15, 50);
1422 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1423 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1425 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1426 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1427 WMResizeWidget(panel->iconLbl, 64, 64);
1428 WMSetLabelRelief(panel->iconLbl, WRGroove);
1429 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1431 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1432 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1433 WMMoveWidget(panel->browseIconBtn, 22, 32);
1434 WMResizeWidget(panel->browseIconBtn, 120, 26);
1435 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1437 #ifdef wrong_behaviour
1438 WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
1439 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
1440 WMSetButtonImage(panel->updateIconBtn, pixmap);
1441 WMReleasePixmap(pixmap);
1442 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
1443 WMSetButtonAltImage(panel->updateIconBtn, pixmap);
1444 WMReleasePixmap(pixmap);
1445 #endif
1447 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1448 WMMoveWidget(panel->fileLbl, 20, 85);
1449 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1450 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1452 panel->fileText = WMCreateTextField(panel->iconFrm);
1453 WMMoveWidget(panel->fileText, 20, 105);
1454 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1455 WMSetTextFieldText(panel->fileText, NULL);
1456 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1458 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1459 WMMoveWidget(panel->alwChk, 20, 130);
1460 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1461 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1462 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1464 panel->wsFrm = WMCreateFrame(panel->win);
1465 WMMoveWidget(panel->wsFrm, 15, 225);
1466 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1467 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1469 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1470 "first shown."), WMWidgetView(panel->wsFrm));
1472 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1473 WMMoveWidget(panel->wsP, 20, 30);
1474 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1475 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1476 for (i = 0; i < wwin->screen_ptr->workspace_count; i++) {
1477 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1480 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1481 if (i >= 0 && i <= wwin->screen_ptr->workspace_count) {
1482 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1483 } else {
1484 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1487 /* application wide attributes */
1488 if (wwin->main_window != None) {
1489 WApplication *wapp = wApplicationOf(wwin->main_window);
1491 panel->appFrm = WMCreateFrame(panel->win);
1492 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1493 WMMoveWidget(panel->appFrm, 15, 50);
1494 WMResizeWidget(panel->appFrm, frame_width, 240);
1496 for (i = 0; i < 3; i++) {
1497 char *caption = NULL;
1498 int flag = 0;
1499 char *descr = NULL;
1501 switch (i) {
1502 case 0:
1503 caption = _("Start hidden");
1504 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1505 descr = _("Automatically hide application when it's started.");
1506 break;
1507 case 1:
1508 caption = _("No application icon");
1509 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1510 descr = _("Disable the application icon for the application.\n"
1511 "Note that you won't be able to dock it anymore,\n"
1512 "and any icons that are already docked will stop\n"
1513 "working correctly.");
1514 break;
1515 case 2:
1516 caption = _("Shared application icon");
1517 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1518 descr = _("Use a single shared application icon for all of\n"
1519 "the instances of this application.\n");
1520 break;
1522 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1523 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1524 WMResizeWidget(panel->appChk[i], 205, 20);
1525 WMSetButtonSelected(panel->appChk[i], flag);
1526 WMSetButtonText(panel->appChk[i], caption);
1528 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1531 if (WFLAGP(wwin, emulate_appicon)) {
1532 WMSetButtonEnabled(panel->appChk[1], False);
1533 WMSetButtonEnabled(panel->moreChk[7], True);
1534 } else {
1535 WMSetButtonEnabled(panel->appChk[1], True);
1536 WMSetButtonEnabled(panel->moreChk[7], False);
1538 } else {
1539 int tmp;
1541 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1542 || !wwin->wm_class || !wwin->wm_instance)
1543 tmp = False;
1544 else
1545 tmp = True;
1546 WMSetButtonEnabled(panel->moreChk[7], tmp);
1548 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1549 panel->appFrm = NULL;
1552 /* if the window is a transient, don't let it have a miniaturize
1553 * button */
1554 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1555 WMSetButtonEnabled(panel->attrChk[3], False);
1556 else
1557 WMSetButtonEnabled(panel->attrChk[3], True);
1559 if (!wwin->wm_class && !wwin->wm_instance) {
1560 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1563 WMRealizeWidget(panel->win);
1565 WMMapSubwidgets(panel->win);
1566 WMMapSubwidgets(panel->specFrm);
1567 WMMapSubwidgets(panel->attrFrm);
1568 WMMapSubwidgets(panel->moreFrm);
1569 WMMapSubwidgets(panel->iconFrm);
1570 WMMapSubwidgets(panel->wsFrm);
1571 if (panel->appFrm)
1572 WMMapSubwidgets(panel->appFrm);
1574 if (showSelectPanel) {
1575 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1576 changePage(panel->pagePopUp, panel);
1577 } else {
1578 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1579 changePage(panel->pagePopUp, panel);
1582 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1583 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1584 panel->parent = parent;
1585 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1587 WMMapWidget(panel->win);
1589 XSetTransientForHint(dpy, parent, wwin->client_win);
1591 if (xpos == UNDEFINED_POS) {
1592 x = wwin->frame_x + wwin->frame->core->width / 2;
1593 y = wwin->frame_y + wwin->frame->top_width * 2;
1594 if (y + PHEIGHT > scr->scr_height)
1595 y = scr->scr_height - PHEIGHT - 30;
1596 if (x + PWIDTH > scr->scr_width)
1597 x = scr->scr_width - PWIDTH;
1598 } else {
1599 x = xpos;
1600 y = ypos;
1603 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1605 if (!selectedBtn)
1606 selectedBtn = panel->defaultRb;
1608 WMSetButtonSelected(selectedBtn, True);
1610 selectSpecification(selectedBtn, panel);
1612 /* kluge to know who should get the key events */
1613 panel->frame->client_leader = WMWidgetXID(panel->win);
1615 WSETUFLAG(panel->frame, no_closable, 0);
1616 WSETUFLAG(panel->frame, no_close_button, 0);
1617 wWindowUpdateButtonImages(panel->frame);
1618 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1619 panel->frame->frame->on_click_right = destroyInspector;
1621 wWindowMap(panel->frame);
1623 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1625 return panel;
1628 void wShowInspectorForWindow(WWindow * wwin)
1630 if (wwin->flags.inspector_open)
1631 return;
1633 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1635 make_keys();
1636 wwin->flags.inspector_open = 1;
1637 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1640 void wHideInspectorForWindow(WWindow * wwin)
1642 WWindow *pwin = wwin->inspector->frame;
1644 wWindowUnmap(pwin);
1645 pwin->flags.hidden = 1;
1647 wClientSetState(pwin, IconicState, None);
1650 void wUnhideInspectorForWindow(WWindow * wwin)
1652 WWindow *pwin = wwin->inspector->frame;
1654 pwin->flags.hidden = 0;
1655 pwin->flags.mapped = 1;
1656 XMapWindow(dpy, pwin->client_win);
1657 XMapWindow(dpy, pwin->frame->core->window);
1658 wClientSetState(pwin, NormalState, None);
1661 WWindow *wGetWindowOfInspectorForWindow(WWindow * wwin)
1663 if (wwin->inspector) {
1664 assert(wwin->flags.inspector_open != 0);
1666 return wwin->inspector->frame;
1667 } else
1668 return NULL;
1671 void wCloseInspectorForWindow(WWindow * wwin)
1673 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1675 (*pwin->frame->on_click_right) (NULL, pwin, NULL);