Change to the linux kernel coding style
[wmaker-crm.git] / src / winspector.c
1 /* winspector.c - window attribute inspector
2 *
3 * Window Maker window manager
4 *
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * Copyright (c) 1998-2003 Dan Pascu
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
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.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 * USA.
22 */
23
24 #include "wconfig.h"
25
26 #include <X11/Xlib.h>
27 #include <X11/Xutil.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31
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
50 #ifdef NETWM_HINTS
51 #include "wmspec.h"
52 #endif
53
54 #include "xinerama.h"
55
56 #include <WINGs/WUtil.h>
57
58 typedef struct InspectorPanel {
59 struct InspectorPanel *nextPtr;
60
61 WWindow *frame;
62
63 WWindow *inspected; /* the window that's being inspected */
64
65 WMWindow *win;
66
67 Window parent;
68
69 /* common stuff */
70 WMButton *revertBtn;
71 WMButton *applyBtn;
72 WMButton *saveBtn;
73
74 WMPopUpButton *pagePopUp;
75
76 /* first page. general stuff */
77
78 WMFrame *specFrm;
79 WMButton *instRb;
80 WMButton *clsRb;
81 WMButton *bothRb;
82 WMButton *defaultRb;
83
84 WMButton *selWinB;
85
86 WMLabel *specLbl;
87
88 /* second page. attributes */
89
90 WMFrame *attrFrm;
91 WMButton *attrChk[11];
92
93 /* 3rd page. more attributes */
94 WMFrame *moreFrm;
95 #ifdef XKB_BUTTON_HINT
96 WMButton *moreChk[9];
97 #else
98 WMButton *moreChk[8];
99 #endif
100
101 /* 4th page. icon and workspace */
102 WMFrame *iconFrm;
103 WMLabel *iconLbl;
104 WMLabel *fileLbl;
105 WMTextField *fileText;
106 WMButton *alwChk;
107 /*
108 WMButton *updateIconBtn;
109 */
110 WMButton *browseIconBtn;
111
112 WMFrame *wsFrm;
113 WMPopUpButton *wsP;
114
115 /* 5th page. application wide attributes */
116 WMFrame *appFrm;
117 WMButton *appChk[3];
118
119 unsigned int done:1;
120 unsigned int destroyed:1;
121 unsigned int choosingIcon:1;
122 } InspectorPanel;
123
124 extern Cursor wCursor[WCUR_LAST];
125
126 extern WDDomain *WDWindowAttributes;
127
128 static InspectorPanel *panelList = NULL;
129
130 extern WPreferences wPreferences;
131
132 static WMPropList *ANoTitlebar = NULL;
133 static WMPropList *ANoResizebar;
134 static WMPropList *ANoMiniaturizeButton;
135 static WMPropList *ANoCloseButton;
136 static WMPropList *ANoBorder;
137 static WMPropList *ANoHideOthers;
138 static WMPropList *ANoMouseBindings;
139 static WMPropList *ANoKeyBindings;
140 static WMPropList *ANoAppIcon;
141 static WMPropList *AKeepOnTop;
142 static WMPropList *AKeepOnBottom;
143 static WMPropList *AOmnipresent;
144 static WMPropList *ASkipWindowList;
145 static WMPropList *AKeepInsideScreen;
146 static WMPropList *AUnfocusable;
147 static WMPropList *AAlwaysUserIcon;
148 static WMPropList *AStartMiniaturized;
149 static WMPropList *AStartMaximized;
150 static WMPropList *ADontSaveSession;
151 static WMPropList *AEmulateAppIcon;
152 static WMPropList *AFullMaximize;
153 static WMPropList *ASharedAppIcon;
154 #ifdef XKB_BUTTON_HINT
155 static WMPropList *ANoLanguageButton;
156 #endif
157
158 static WMPropList *AStartWorkspace;
159
160 static WMPropList *AIcon;
161
162 /* application wide options */
163 static WMPropList *AStartHidden;
164
165 static WMPropList *AnyWindow;
166 static WMPropList *EmptyString;
167 static WMPropList *Yes, *No;
168
169 #define PWIDTH 270
170 #define PHEIGHT 350
171
172 static char *spec_text;
173
174 static void applySettings(WMButton * button, InspectorPanel * panel);
175
176 #define UNDEFINED_POS 0xffffff
177
178 static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel);
179
180 static void make_keys()
181 {
182 if (ANoTitlebar != NULL)
183 return;
184
185 AIcon = WMCreatePLString("Icon");
186 ANoTitlebar = WMCreatePLString("NoTitlebar");
187 ANoResizebar = WMCreatePLString("NoResizebar");
188 ANoMiniaturizeButton = WMCreatePLString("NoMiniaturizeButton");
189 ANoCloseButton = WMCreatePLString("NoCloseButton");
190 ANoBorder = WMCreatePLString("NoBorder");
191 ANoHideOthers = WMCreatePLString("NoHideOthers");
192 ANoMouseBindings = WMCreatePLString("NoMouseBindings");
193 ANoKeyBindings = WMCreatePLString("NoKeyBindings");
194 ANoAppIcon = WMCreatePLString("NoAppIcon");
195 AKeepOnTop = WMCreatePLString("KeepOnTop");
196 AKeepOnBottom = WMCreatePLString("KeepOnBottom");
197 AOmnipresent = WMCreatePLString("Omnipresent");
198 ASkipWindowList = WMCreatePLString("SkipWindowList");
199 AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
200 AUnfocusable = WMCreatePLString("Unfocusable");
201 AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
202 AStartMiniaturized = WMCreatePLString("StartMiniaturized");
203 AStartMaximized = WMCreatePLString("StartMaximized");
204 AStartHidden = WMCreatePLString("StartHidden");
205 ADontSaveSession = WMCreatePLString("DontSaveSession");
206 AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
207 AFullMaximize = WMCreatePLString("FullMaximize");
208 ASharedAppIcon = WMCreatePLString("SharedAppIcon");
209 #ifdef XKB_BUTTON_HINT
210 ANoLanguageButton = WMCreatePLString("NoLanguageButton");
211 #endif
212
213 AStartWorkspace = WMCreatePLString("StartWorkspace");
214
215 AnyWindow = WMCreatePLString("*");
216 EmptyString = WMCreatePLString("");
217 Yes = WMCreatePLString("Yes");
218 No = WMCreatePLString("No");
219 }
220
221 static void freeInspector(InspectorPanel * panel)
222 {
223 panel->destroyed = 1;
224 if (panel->choosingIcon)
225 return;
226
227 WMDestroyWidget(panel->win);
228
229 XDestroyWindow(dpy, panel->parent);
230
231 wfree(panel);
232 }
233
234 static void destroyInspector(WCoreWindow * foo, void *data, XEvent * event)
235 {
236 InspectorPanel *panel;
237 InspectorPanel *tmp;
238
239 panel = panelList;
240 while (panel->frame != data)
241 panel = panel->nextPtr;
242
243 if (panelList == panel)
244 panelList = panel->nextPtr;
245 else {
246 tmp = panelList;
247 while (tmp->nextPtr != panel) {
248 tmp = tmp->nextPtr;
249 }
250 tmp->nextPtr = panel->nextPtr;
251 }
252 panel->inspected->flags.inspector_open = 0;
253 panel->inspected->inspector = NULL;
254
255 WMRemoveNotificationObserver(panel);
256
257 wWindowUnmap(panel->frame);
258 wUnmanageWindow(panel->frame, True, False);
259
260 freeInspector(panel);
261 }
262
263 void wDestroyInspectorPanels()
264 {
265 InspectorPanel *panel;
266
267 while (panelList != NULL) {
268 panel = panelList;
269 panelList = panelList->nextPtr;
270 wUnmanageWindow(panel->frame, False, False);
271 WMDestroyWidget(panel->win);
272
273 panel->inspected->flags.inspector_open = 0;
274 panel->inspected->inspector = NULL;
275
276 wfree(panel);
277 }
278 }
279
280 static void changePage(WMPopUpButton * bPtr, InspectorPanel * panel)
281 {
282 int page;
283
284 page = WMGetPopUpButtonSelectedItem(bPtr);
285
286 if (page == 0) {
287 WMMapWidget(panel->specFrm);
288 WMMapWidget(panel->specLbl);
289 } else if (page == 1) {
290 WMMapWidget(panel->attrFrm);
291 } else if (page == 2) {
292 WMMapWidget(panel->moreFrm);
293 } else if (page == 3) {
294 WMMapWidget(panel->iconFrm);
295 WMMapWidget(panel->wsFrm);
296 } else {
297 WMMapWidget(panel->appFrm);
298 }
299
300 if (page != 0) {
301 WMUnmapWidget(panel->specFrm);
302 WMUnmapWidget(panel->specLbl);
303 }
304 if (page != 1)
305 WMUnmapWidget(panel->attrFrm);
306 if (page != 2)
307 WMUnmapWidget(panel->moreFrm);
308 if (page != 3) {
309 WMUnmapWidget(panel->iconFrm);
310 WMUnmapWidget(panel->wsFrm);
311 }
312 if (page != 4 && panel->appFrm)
313 WMUnmapWidget(panel->appFrm);
314 }
315
316 #define USE_TEXT_FIELD 1
317 #define UPDATE_TEXT_FIELD 2
318 #define REVERT_TO_DEFAULT 4
319
320 static int showIconFor(WMScreen * scrPtr, InspectorPanel * panel, char *wm_instance, char *wm_class, int flags)
321 {
322 WMPixmap *pixmap = (WMPixmap *) NULL;
323 char *file = NULL, *path = NULL;
324 char *db_icon = NULL;
325
326 if ((flags & USE_TEXT_FIELD) != 0) {
327 file = WMGetTextFieldText(panel->fileText);
328 if (file && file[0] == 0) {
329 wfree(file);
330 file = NULL;
331 }
332 } else {
333 db_icon = wDefaultGetIconFile(panel->inspected->screen_ptr, wm_instance, wm_class, False);
334 if (db_icon != NULL)
335 file = wstrdup(db_icon);
336 }
337 if (db_icon != NULL && (flags & REVERT_TO_DEFAULT) != 0) {
338 if (file)
339 file = wstrdup(db_icon);
340 flags |= UPDATE_TEXT_FIELD;
341 }
342
343 if ((flags & UPDATE_TEXT_FIELD) != 0) {
344 WMSetTextFieldText(panel->fileText, file);
345 }
346
347 if (file) {
348 path = FindImage(wPreferences.icon_path, file);
349
350 if (!path) {
351 char *buf;
352 int len = strlen(file) + 80;
353
354 buf = wmalloc(len);
355 snprintf(buf, len, _("Could not find icon \"%s\" specified for this window"), file);
356 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
357 wfree(buf);
358 wfree(file);
359 return -1;
360 }
361
362 pixmap = WMCreatePixmapFromFile(scrPtr, path);
363 wfree(path);
364
365 if (!pixmap) {
366 char *buf;
367 int len = strlen(file) + 80;
368
369 buf = wmalloc(len);
370 snprintf(buf, len, _("Could not open specified icon \"%s\":%s"),
371 file, RMessageForError(RErrorCode));
372 wMessageDialog(panel->frame->screen_ptr, _("Error"), buf, _("OK"), NULL, NULL);
373 wfree(buf);
374 wfree(file);
375 return -1;
376 }
377 wfree(file);
378 }
379
380 WMSetLabelImage(panel->iconLbl, pixmap);
381 if (pixmap)
382 WMReleasePixmap(pixmap);
383
384 return 0;
385 }
386
387 #if 0
388 static void updateIcon(WMButton * button, InspectorPanel * panel)
389 {
390 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
391 }
392 #endif
393
394 static int getBool(WMPropList * value)
395 {
396 char *val;
397
398 if (!WMIsPLString(value)) {
399 return 0;
400 }
401 if (!(val = WMGetFromPLString(value))) {
402 return 0;
403 }
404
405 if ((val[1] == '\0' && (val[0] == 'y' || val[0] == 'Y' || val[0] == 'T' || val[0] == 't' || val[0] == '1'))
406 || (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0)) {
407
408 return 1;
409 } else if ((val[1] == '\0'
410 && (val[0] == 'n' || val[0] == 'N' || val[0] == 'F' || val[0] == 'f' || val[0] == '0'))
411 || (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0)) {
412
413 return 0;
414 } else {
415 wwarning(_("can't convert \"%s\" to boolean"), val);
416 return 0;
417 }
418 }
419
420 #define UPDATE_DEFAULTS 1
421 #define IS_BOOLEAN 2
422
423 /*
424 * Will insert the attribute = value; pair in window's list,
425 * if it's different from the defaults.
426 * Defaults means either defaults database, or attributes saved
427 * for the default window "*". This is to let one revert options that are
428 * global because they were saved for all windows ("*").
429 *
430 */
431
432 static int
433 insertAttribute(WMPropList * dict, WMPropList * window, WMPropList * attr, WMPropList * value, int flags)
434 {
435 WMPropList *def_win, *def_value = NULL;
436 int update = 0;
437 int modified = 0;
438
439 if (!(flags & UPDATE_DEFAULTS) && dict) {
440 if ((def_win = WMGetFromPLDictionary(dict, AnyWindow)) != NULL) {
441 def_value = WMGetFromPLDictionary(def_win, attr);
442 }
443 }
444
445 /* If we could not find defaults in database, fall to hardcoded values.
446 * Also this is true if we save defaults for all windows
447 */
448 if (!def_value)
449 def_value = ((flags & IS_BOOLEAN) != 0) ? No : EmptyString;
450
451 if ((flags & IS_BOOLEAN))
452 update = (getBool(value) != getBool(def_value));
453 else {
454 update = !WMIsPropListEqualTo(value, def_value);
455 }
456
457 if (update) {
458 WMPutInPLDictionary(window, attr, value);
459 modified = 1;
460 }
461
462 return modified;
463 }
464
465 static void saveSettings(WMButton * button, InspectorPanel * panel)
466 {
467 WWindow *wwin = panel->inspected;
468 WDDomain *db = WDWindowAttributes;
469 WMPropList *dict = db->dictionary;
470 WMPropList *winDic, *appDic, *value, *key, *key2;
471 char *icon_file;
472 int flags = 0;
473 int different = 0, different2 = 0;
474
475 /* Save will apply the changes and save them */
476 applySettings(panel->applyBtn, panel);
477
478 if (WMGetButtonSelected(panel->instRb) != 0)
479 key = WMCreatePLString(wwin->wm_instance);
480 else if (WMGetButtonSelected(panel->clsRb) != 0)
481 key = WMCreatePLString(wwin->wm_class);
482 else if (WMGetButtonSelected(panel->bothRb) != 0) {
483 char *buffer;
484
485 buffer = StrConcatDot(wwin->wm_instance, wwin->wm_class);
486 key = WMCreatePLString(buffer);
487 wfree(buffer);
488 } else if (WMGetButtonSelected(panel->defaultRb) != 0) {
489 key = WMRetainPropList(AnyWindow);
490 flags = UPDATE_DEFAULTS;
491 } else
492 key = NULL;
493
494 if (!key)
495 return;
496
497 if (!dict) {
498 dict = WMCreatePLDictionary(NULL, NULL);
499 if (dict) {
500 db->dictionary = dict;
501 } else {
502 WMReleasePropList(key);
503 return;
504 }
505 }
506
507 if (showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD) < 0)
508 return;
509
510 WMPLSetCaseSensitive(True);
511
512 winDic = WMCreatePLDictionary(NULL, NULL);
513 appDic = WMCreatePLDictionary(NULL, NULL);
514
515 /* Update icon for window */
516 icon_file = WMGetTextFieldText(panel->fileText);
517 if (icon_file) {
518 if (icon_file[0] != 0) {
519 value = WMCreatePLString(icon_file);
520 different |= insertAttribute(dict, winDic, AIcon, value, flags);
521 different2 |= insertAttribute(dict, appDic, AIcon, value, flags);
522 WMReleasePropList(value);
523 }
524 wfree(icon_file);
525 }
526
527 {
528 int i = WMGetPopUpButtonSelectedItem(panel->wsP);
529
530 i--;
531
532 if (i >= 0 && i < panel->frame->screen_ptr->workspace_count) {
533 value = WMCreatePLString(panel->frame->screen_ptr->workspaces[i]->name);
534 different |= insertAttribute(dict, winDic, AStartWorkspace, value, flags);
535 WMReleasePropList(value);
536 }
537 }
538
539 flags |= IS_BOOLEAN;
540
541 value = (WMGetButtonSelected(panel->alwChk) != 0) ? Yes : No;
542 different |= insertAttribute(dict, winDic, AAlwaysUserIcon, value, flags);
543
544 value = (WMGetButtonSelected(panel->attrChk[0]) != 0) ? Yes : No;
545 different |= insertAttribute(dict, winDic, ANoTitlebar, value, flags);
546
547 value = (WMGetButtonSelected(panel->attrChk[1]) != 0) ? Yes : No;
548 different |= insertAttribute(dict, winDic, ANoResizebar, value, flags);
549
550 value = (WMGetButtonSelected(panel->attrChk[2]) != 0) ? Yes : No;
551 different |= insertAttribute(dict, winDic, ANoCloseButton, value, flags);
552
553 value = (WMGetButtonSelected(panel->attrChk[3]) != 0) ? Yes : No;
554 different |= insertAttribute(dict, winDic, ANoMiniaturizeButton, value, flags);
555
556 value = (WMGetButtonSelected(panel->attrChk[4]) != 0) ? Yes : No;
557 different |= insertAttribute(dict, winDic, ANoBorder, value, flags);
558
559 value = (WMGetButtonSelected(panel->attrChk[5]) != 0) ? Yes : No;
560 different |= insertAttribute(dict, winDic, AKeepOnTop, value, flags);
561
562 value = (WMGetButtonSelected(panel->attrChk[6]) != 0) ? Yes : No;
563 different |= insertAttribute(dict, winDic, AKeepOnBottom, value, flags);
564
565 value = (WMGetButtonSelected(panel->attrChk[7]) != 0) ? Yes : No;
566 different |= insertAttribute(dict, winDic, AOmnipresent, value, flags);
567
568 value = (WMGetButtonSelected(panel->attrChk[8]) != 0) ? Yes : No;
569 different |= insertAttribute(dict, winDic, AStartMiniaturized, value, flags);
570
571 value = (WMGetButtonSelected(panel->attrChk[9]) != 0) ? Yes : No;
572 different |= insertAttribute(dict, winDic, AStartMaximized, value, flags);
573
574 value = (WMGetButtonSelected(panel->attrChk[10]) != 0) ? Yes : No;
575 different |= insertAttribute(dict, winDic, AFullMaximize, value, flags);
576
577 value = (WMGetButtonSelected(panel->moreChk[0]) != 0) ? Yes : No;
578 different |= insertAttribute(dict, winDic, ANoKeyBindings, value, flags);
579
580 value = (WMGetButtonSelected(panel->moreChk[1]) != 0) ? Yes : No;
581 different |= insertAttribute(dict, winDic, ANoMouseBindings, value, flags);
582
583 value = (WMGetButtonSelected(panel->moreChk[2]) != 0) ? Yes : No;
584 different |= insertAttribute(dict, winDic, ASkipWindowList, value, flags);
585
586 value = (WMGetButtonSelected(panel->moreChk[3]) != 0) ? Yes : No;
587 different |= insertAttribute(dict, winDic, AUnfocusable, value, flags);
588
589 value = (WMGetButtonSelected(panel->moreChk[4]) != 0) ? Yes : No;
590 different |= insertAttribute(dict, winDic, AKeepInsideScreen, value, flags);
591
592 value = (WMGetButtonSelected(panel->moreChk[5]) != 0) ? Yes : No;
593 different |= insertAttribute(dict, winDic, ANoHideOthers, value, flags);
594
595 value = (WMGetButtonSelected(panel->moreChk[6]) != 0) ? Yes : No;
596 different |= insertAttribute(dict, winDic, ADontSaveSession, value, flags);
597
598 value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No;
599 different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
600
601 #ifdef XKB_BUTTON_HINT
602 value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No;
603 different |= insertAttribute(dict, winDic, ANoLanguageButton, value, flags);
604 #endif
605
606 if (wwin->main_window != None && wApplicationOf(wwin->main_window) != NULL) {
607 value = (WMGetButtonSelected(panel->appChk[0]) != 0) ? Yes : No;
608 different2 |= insertAttribute(dict, appDic, AStartHidden, value, flags);
609
610 value = (WMGetButtonSelected(panel->appChk[1]) != 0) ? Yes : No;
611 different2 |= insertAttribute(dict, appDic, ANoAppIcon, value, flags);
612
613 value = (WMGetButtonSelected(panel->appChk[2]) != 0) ? Yes : No;
614 different2 |= insertAttribute(dict, appDic, ASharedAppIcon, value, flags);
615 }
616
617 if (wwin->fake_group) {
618 key2 = WMCreatePLString(wwin->fake_group->identifier);
619 if (WMIsPropListEqualTo(key, key2)) {
620 WMMergePLDictionaries(winDic, appDic, True);
621 different |= different2;
622 } else {
623 WMRemoveFromPLDictionary(dict, key2);
624 if (different2) {
625 WMPutInPLDictionary(dict, key2, appDic);
626 }
627 }
628 WMReleasePropList(key2);
629 WMReleasePropList(appDic);
630 } else if (wwin->main_window != wwin->client_win) {
631 WApplication *wapp = wApplicationOf(wwin->main_window);
632
633 if (wapp) {
634 char *instance = wapp->main_window_desc->wm_instance;
635 char *class = wapp->main_window_desc->wm_class;
636 char *buffer;
637
638 buffer = StrConcatDot(instance, class);
639 key2 = WMCreatePLString(buffer);
640 wfree(buffer);
641
642 if (WMIsPropListEqualTo(key, key2)) {
643 WMMergePLDictionaries(winDic, appDic, True);
644 different |= different2;
645 } else {
646 WMRemoveFromPLDictionary(dict, key2);
647 if (different2) {
648 WMPutInPLDictionary(dict, key2, appDic);
649 }
650 }
651 WMReleasePropList(key2);
652 WMReleasePropList(appDic);
653 }
654 } else {
655 WMMergePLDictionaries(winDic, appDic, True);
656 different |= different2;
657 WMReleasePropList(appDic);
658 }
659
660 WMRemoveFromPLDictionary(dict, key);
661 if (different) {
662 WMPutInPLDictionary(dict, key, winDic);
663 }
664
665 WMReleasePropList(key);
666 WMReleasePropList(winDic);
667
668 UpdateDomainFile(db);
669
670 /* clean up */
671 WMPLSetCaseSensitive(False);
672 }
673
674 static void makeAppIconFor(WApplication * wapp)
675 {
676 WScreen *scr = wapp->main_window_desc->screen_ptr;
677
678 if (wapp->app_icon)
679 return;
680
681 if (!WFLAGP(wapp->main_window_desc, no_appicon))
682 wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
683 else
684 wapp->app_icon = NULL;
685
686 if (wapp->app_icon) {
687 WIcon *icon = wapp->app_icon->icon;
688 WDock *clip = scr->workspaces[scr->current_workspace]->clip;
689 int x = 0, y = 0;
690
691 wapp->app_icon->main_window = wapp->main_window;
692
693 if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
694 wapp->app_icon->attracted = 1;
695 if (!wapp->app_icon->icon->shadowed) {
696 wapp->app_icon->icon->shadowed = 1;
697 wapp->app_icon->icon->force_paint = 1;
698 }
699 wDockAttachIcon(clip, wapp->app_icon, x, y);
700 } else {
701 PlaceIcon(scr, &x, &y, wGetHeadForWindow(wapp->main_window_desc));
702 wAppIconMove(wapp->app_icon, x, y);
703 }
704 if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
705 XMapWindow(dpy, icon->core->window);
706
707 if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted)
708 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
709 }
710 }
711
712 static void removeAppIconFor(WApplication * wapp)
713 {
714 if (!wapp->app_icon)
715 return;
716
717 if (wapp->app_icon->docked && !wapp->app_icon->attracted) {
718 wapp->app_icon->running = 0;
719 /* since we keep it, we don't care if it was attracted or not */
720 wapp->app_icon->attracted = 0;
721 wapp->app_icon->icon->shadowed = 0;
722 wapp->app_icon->main_window = None;
723 wapp->app_icon->pid = 0;
724 wapp->app_icon->icon->owner = NULL;
725 wapp->app_icon->icon->icon_win = None;
726 wapp->app_icon->icon->force_paint = 1;
727 wAppIconPaint(wapp->app_icon);
728 } else if (wapp->app_icon->docked) {
729 wapp->app_icon->running = 0;
730 wDockDetach(wapp->app_icon->dock, wapp->app_icon);
731 } else {
732 wAppIconDestroy(wapp->app_icon);
733 }
734 wapp->app_icon = NULL;
735 if (wPreferences.auto_arrange_icons)
736 wArrangeIcons(wapp->main_window_desc->screen_ptr, True);
737 }
738
739 static void applySettings(WMButton * button, InspectorPanel * panel)
740 {
741 WWindow *wwin = panel->inspected;
742 WApplication *wapp = wApplicationOf(wwin->main_window);
743 int floating, sunken, skip_window_list;
744 int old_omnipresent;
745 int old_no_bind_keys;
746 int old_no_bind_mouse;
747
748 old_omnipresent = WFLAGP(wwin, omnipresent);
749 old_no_bind_keys = WFLAGP(wwin, no_bind_keys);
750 old_no_bind_mouse = WFLAGP(wwin, no_bind_mouse);
751
752 showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
753
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]));
765
766 WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
767 WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
768 skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
769 WSETUFLAG(wwin, no_focusable, WMGetButtonSelected(panel->moreChk[3]));
770 WSETUFLAG(wwin, dont_move_off, WMGetButtonSelected(panel->moreChk[4]));
771 WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[5]));
772 WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[6]));
773 WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[7]));
774 #ifdef XKB_BUTTON_HINT
775 WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[8]));
776 #endif
777 WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
778
779 if (WFLAGP(wwin, no_titlebar) && wwin->flags.shaded)
780 wUnshadeWindow(wwin);
781
782 WSETUFLAG(wwin, no_shadeable, WFLAGP(wwin, no_titlebar));
783
784 if (floating) {
785 if (!WFLAGP(wwin, floating))
786 ChangeStackingLevel(wwin->frame->core, WMFloatingLevel);
787 } else if (sunken) {
788 if (!WFLAGP(wwin, sunken))
789 ChangeStackingLevel(wwin->frame->core, WMSunkenLevel);
790 } else {
791 if (WFLAGP(wwin, floating) || WFLAGP(wwin, sunken))
792 ChangeStackingLevel(wwin->frame->core, WMNormalLevel);
793 }
794
795 WSETUFLAG(wwin, sunken, sunken);
796 WSETUFLAG(wwin, floating, floating);
797 wwin->flags.omnipresent = 0;
798
799 if (WFLAGP(wwin, skip_window_list) != skip_window_list) {
800 WSETUFLAG(wwin, skip_window_list, skip_window_list);
801 UpdateSwitchMenu(wwin->screen_ptr, wwin, skip_window_list ? ACTION_REMOVE : ACTION_ADD);
802 } else {
803 if (WFLAGP(wwin, omnipresent) != old_omnipresent) {
804 WMPostNotificationName(WMNChangedState, wwin, "omnipresent");
805 }
806 }
807
808 if (WFLAGP(wwin, no_bind_keys) != old_no_bind_keys) {
809 if (WFLAGP(wwin, no_bind_keys)) {
810 XUngrabKey(dpy, AnyKey, AnyModifier, wwin->frame->core->window);
811 } else {
812 wWindowSetKeyGrabs(wwin);
813 }
814 }
815
816 if (WFLAGP(wwin, no_bind_mouse) != old_no_bind_mouse) {
817 wWindowResetMouseGrabs(wwin);
818 }
819
820 wwin->frame->flags.need_texture_change = 1;
821 wWindowConfigureBorders(wwin);
822 wFrameWindowPaint(wwin->frame);
823 #ifdef NETWM_HINTS
824 wNETWMUpdateActions(wwin, False);
825 #endif
826
827 /*
828 * Can't apply emulate_appicon because it will probably cause problems.
829 */
830
831 if (wapp) {
832 /* do application wide stuff */
833 WSETUFLAG(wapp->main_window_desc, start_hidden, WMGetButtonSelected(panel->appChk[0]));
834
835 WSETUFLAG(wapp->main_window_desc, no_appicon, WMGetButtonSelected(panel->appChk[1]));
836
837 WSETUFLAG(wapp->main_window_desc, shared_appicon, WMGetButtonSelected(panel->appChk[2]));
838
839 if (WFLAGP(wapp->main_window_desc, no_appicon))
840 removeAppIconFor(wapp);
841 else
842 makeAppIconFor(wapp);
843
844 if (wapp->app_icon && wapp->main_window == wwin->client_win) {
845 char *file = WMGetTextFieldText(panel->fileText);
846
847 if (file[0] == 0) {
848 wfree(file);
849 file = NULL;
850 }
851 wIconChangeImageFile(wapp->app_icon->icon, file);
852 if (file)
853 wfree(file);
854 wAppIconPaint(wapp->app_icon);
855 }
856 }
857 }
858
859 static void revertSettings(WMButton * button, InspectorPanel * panel)
860 {
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;
867
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;
875 }
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));
879
880 wWindowSetupInitialAttributes(wwin, &level, &workspace);
881
882 for (i = 0; i < 11; i++) {
883 int flag = 0;
884
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;
919 }
920 WMSetButtonSelected(panel->attrChk[i], flag);
921 }
922 for (i = 0; i < 8; i++) {
923 int flag = 0;
924
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, no_focusable);
937 break;
938 case 4:
939 flag = WFLAGP(wwin, dont_move_off);
940 break;
941 case 5:
942 flag = WFLAGP(wwin, no_hide_others);
943 break;
944 case 6:
945 flag = WFLAGP(wwin, dont_save_session);
946 break;
947 case 7:
948 flag = WFLAGP(wwin, emulate_appicon);
949 break;
950 #ifdef XKB_BUTTON_HINT
951 case 8:
952 flag = WFLAGP(wwin, no_language_button);
953 break;
954 #endif
955 }
956 WMSetButtonSelected(panel->moreChk[i], flag);
957 }
958 if (panel->appFrm && wapp) {
959 for (i = 0; i < 2; i++) {
960 int flag = 0;
961
962 switch (i) {
963 case 0:
964 flag = WFLAGP(wapp->main_window_desc, start_hidden);
965 break;
966 case 1:
967 flag = WFLAGP(wapp->main_window_desc, no_appicon);
968 break;
969 case 2:
970 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
971 break;
972 }
973 WMSetButtonSelected(panel->appChk[i], flag);
974 }
975 }
976 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
977
978 showIconFor(WMWidgetScreen(panel->alwChk), panel, wm_instance, wm_class, REVERT_TO_DEFAULT);
979
980 n = wDefaultGetStartWorkspace(wwin->screen_ptr, wm_instance, wm_class);
981
982 if (n >= 0 && n < wwin->screen_ptr->workspace_count) {
983 WMSetPopUpButtonSelectedItem(panel->wsP, n + 1);
984 } else {
985 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
986 }
987
988 /* must auto apply, so that there wno't be internal
989 * inconsistencies between the state in the flags and
990 * the actual state of the window */
991 applySettings(panel->applyBtn, panel);
992 }
993
994 static void chooseIconCallback(WMWidget * self, void *clientData)
995 {
996 char *file;
997 InspectorPanel *panel = (InspectorPanel *) clientData;
998 int result;
999
1000 panel->choosingIcon = 1;
1001
1002 WMSetButtonEnabled(panel->browseIconBtn, False);
1003
1004 result = wIconChooserDialog(panel->frame->screen_ptr, &file,
1005 panel->inspected->wm_instance, panel->inspected->wm_class);
1006
1007 panel->choosingIcon = 0;
1008
1009 if (!panel->destroyed) { /* kluge */
1010 if (result) {
1011 WMSetTextFieldText(panel->fileText, file);
1012 showIconFor(WMWidgetScreen(self), panel, NULL, NULL, USE_TEXT_FIELD);
1013 wfree(file);
1014 }
1015 WMSetButtonEnabled(panel->browseIconBtn, True);
1016 } else {
1017 freeInspector(panel);
1018 }
1019 }
1020
1021 static void textEditedObserver(void *observerData, WMNotification * notification)
1022 {
1023 InspectorPanel *panel = (InspectorPanel *) observerData;
1024
1025 if ((long)WMGetNotificationClientData(notification) != WMReturnTextMovement)
1026 return;
1027
1028 showIconFor(WMWidgetScreen(panel->win), panel, NULL, NULL, USE_TEXT_FIELD);
1029 /*
1030 WMPerformButtonClick(panel->updateIconBtn);
1031 */
1032 }
1033
1034 static void selectSpecification(WMWidget * bPtr, void *data)
1035 {
1036 InspectorPanel *panel = (InspectorPanel *) data;
1037 char *str;
1038 WWindow *wwin = panel->inspected;
1039 int len;
1040
1041 if (bPtr == panel->defaultRb && (wwin->wm_instance || wwin->wm_class)) {
1042 WMSetButtonEnabled(panel->applyBtn, False);
1043 } else {
1044 WMSetButtonEnabled(panel->applyBtn, True);
1045 }
1046
1047 len = 16 + strlen(wwin->wm_instance ? wwin->wm_instance : "?")
1048 + strlen(wwin->wm_class ? wwin->wm_class : "?");
1049
1050 str = wmalloc(len);
1051
1052 snprintf(str, len, _("Inspecting %s.%s"),
1053 wwin->wm_instance ? wwin->wm_instance : "?", wwin->wm_class ? wwin->wm_class : "?");
1054
1055 wFrameWindowChangeTitle(panel->frame->frame, str);
1056
1057 wfree(str);
1058 }
1059
1060 static void selectWindow(WMWidget * bPtr, void *data)
1061 {
1062 InspectorPanel *panel = (InspectorPanel *) data;
1063 WWindow *wwin = panel->inspected;
1064 WScreen *scr = wwin->screen_ptr;
1065 XEvent event;
1066 WWindow *iwin;
1067
1068 if (XGrabPointer(dpy, scr->root_win, True,
1069 ButtonPressMask, GrabModeAsync, GrabModeAsync, None,
1070 wCursor[WCUR_SELECT], CurrentTime) != GrabSuccess) {
1071 wwarning("could not grab mouse pointer");
1072 return;
1073 }
1074
1075 WMSetLabelText(panel->specLbl, _("Click in the window you wish to inspect."));
1076
1077 WMMaskEvent(dpy, ButtonPressMask, &event);
1078
1079 XUngrabPointer(dpy, CurrentTime);
1080
1081 iwin = wWindowFor(event.xbutton.subwindow);
1082
1083 if (iwin && !iwin->flags.internal_window && iwin != wwin && !iwin->flags.inspector_open) {
1084
1085 iwin->flags.inspector_open = 1;
1086 iwin->inspector = createInspectorForWindow(iwin,
1087 panel->frame->frame_x, panel->frame->frame_y, True);
1088 wCloseInspectorForWindow(wwin);
1089 } else {
1090 WMSetLabelText(panel->specLbl, spec_text);
1091 }
1092 }
1093
1094 static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int ypos, Bool showSelectPanel)
1095 {
1096 WScreen *scr = wwin->screen_ptr;
1097 InspectorPanel *panel;
1098 Window parent;
1099 int i;
1100 int x, y;
1101 int btn_width, frame_width;
1102 WMButton *selectedBtn = NULL;
1103 #ifdef wrong_behaviour
1104 WMPixmap *pixmap;
1105 #endif
1106
1107 spec_text = _("The configuration will apply to all\n"
1108 "windows that have their WM_CLASS\n"
1109 "property set to the above selected\n" "name, when saved.");
1110
1111 panel = wmalloc(sizeof(InspectorPanel));
1112 memset(panel, 0, sizeof(InspectorPanel));
1113
1114 panel->destroyed = 0;
1115
1116 panel->inspected = wwin;
1117
1118 panel->nextPtr = panelList;
1119 panelList = panel;
1120
1121 panel->win = WMCreateWindow(scr->wmscreen, "windowInspector");
1122 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
1123
1124 /**** create common stuff ****/
1125
1126 /* command buttons */
1127 /* (PWIDTH - (left and right margin) - (btn interval)) / 3 */
1128 btn_width = (PWIDTH - (2 * 15) - (2 * 10)) / 3;
1129 panel->saveBtn = WMCreateCommandButton(panel->win);
1130 WMSetButtonAction(panel->saveBtn, (WMAction *) saveSettings, panel);
1131 WMMoveWidget(panel->saveBtn, (2 * (btn_width + 10)) + 15, 310);
1132 WMSetButtonText(panel->saveBtn, _("Save"));
1133 WMResizeWidget(panel->saveBtn, btn_width, 28);
1134 if (wPreferences.flags.noupdates || !(wwin->wm_class || wwin->wm_instance))
1135 WMSetButtonEnabled(panel->saveBtn, False);
1136
1137 panel->applyBtn = WMCreateCommandButton(panel->win);
1138 WMSetButtonAction(panel->applyBtn, (WMAction *) applySettings, panel);
1139 WMMoveWidget(panel->applyBtn, btn_width + 10 + 15, 310);
1140 WMSetButtonText(panel->applyBtn, _("Apply"));
1141 WMResizeWidget(panel->applyBtn, btn_width, 28);
1142
1143 panel->revertBtn = WMCreateCommandButton(panel->win);
1144 WMSetButtonAction(panel->revertBtn, (WMAction *) revertSettings, panel);
1145 WMMoveWidget(panel->revertBtn, 15, 310);
1146 WMSetButtonText(panel->revertBtn, _("Reload"));
1147 WMResizeWidget(panel->revertBtn, btn_width, 28);
1148
1149 /* page selection popup button */
1150 panel->pagePopUp = WMCreatePopUpButton(panel->win);
1151 WMSetPopUpButtonAction(panel->pagePopUp, (WMAction *) changePage, panel);
1152 WMMoveWidget(panel->pagePopUp, 25, 15);
1153 WMResizeWidget(panel->pagePopUp, PWIDTH - 50, 20);
1154
1155 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Specification"));
1156 WMAddPopUpButtonItem(panel->pagePopUp, _("Window Attributes"));
1157 WMAddPopUpButtonItem(panel->pagePopUp, _("Advanced Options"));
1158 WMAddPopUpButtonItem(panel->pagePopUp, _("Icon and Initial Workspace"));
1159 WMAddPopUpButtonItem(panel->pagePopUp, _("Application Specific"));
1160
1161 /**** window spec ****/
1162 frame_width = PWIDTH - (2 * 15);
1163
1164 panel->specFrm = WMCreateFrame(panel->win);
1165 WMSetFrameTitle(panel->specFrm, _("Window Specification"));
1166 WMMoveWidget(panel->specFrm, 15, 65);
1167 WMResizeWidget(panel->specFrm, frame_width, 145);
1168
1169 panel->defaultRb = WMCreateRadioButton(panel->specFrm);
1170 WMMoveWidget(panel->defaultRb, 10, 78);
1171 WMResizeWidget(panel->defaultRb, frame_width - (2 * 10), 20);
1172 WMSetButtonText(panel->defaultRb, _("Defaults for all windows"));
1173 WMSetButtonSelected(panel->defaultRb, False);
1174 WMSetButtonAction(panel->defaultRb, selectSpecification, panel);
1175
1176 if (wwin->wm_class && wwin->wm_instance) {
1177 char *str, *tmp;
1178
1179 tmp = wstrconcat(wwin->wm_instance, ".");
1180 str = wstrconcat(tmp, wwin->wm_class);
1181
1182 panel->bothRb = WMCreateRadioButton(panel->specFrm);
1183 WMMoveWidget(panel->bothRb, 10, 18);
1184 WMResizeWidget(panel->bothRb, frame_width - (2 * 10), 20);
1185 WMSetButtonText(panel->bothRb, str);
1186 wfree(tmp);
1187 wfree(str);
1188 WMGroupButtons(panel->defaultRb, panel->bothRb);
1189
1190 if (!selectedBtn)
1191 selectedBtn = panel->bothRb;
1192
1193 WMSetButtonAction(panel->bothRb, selectSpecification, panel);
1194 }
1195
1196 if (wwin->wm_instance) {
1197 panel->instRb = WMCreateRadioButton(panel->specFrm);
1198 WMMoveWidget(panel->instRb, 10, 38);
1199 WMResizeWidget(panel->instRb, frame_width - (2 * 10), 20);
1200 WMSetButtonText(panel->instRb, wwin->wm_instance);
1201 WMGroupButtons(panel->defaultRb, panel->instRb);
1202
1203 if (!selectedBtn)
1204 selectedBtn = panel->instRb;
1205
1206 WMSetButtonAction(panel->instRb, selectSpecification, panel);
1207 }
1208
1209 if (wwin->wm_class) {
1210 panel->clsRb = WMCreateRadioButton(panel->specFrm);
1211 WMMoveWidget(panel->clsRb, 10, 58);
1212 WMResizeWidget(panel->clsRb, frame_width - (2 * 10), 20);
1213 WMSetButtonText(panel->clsRb, wwin->wm_class);
1214 WMGroupButtons(panel->defaultRb, panel->clsRb);
1215
1216 if (!selectedBtn)
1217 selectedBtn = panel->clsRb;
1218
1219 WMSetButtonAction(panel->clsRb, selectSpecification, panel);
1220 }
1221
1222 panel->selWinB = WMCreateCommandButton(panel->specFrm);
1223 WMMoveWidget(panel->selWinB, 20, 145 - 24 - 10);
1224 WMResizeWidget(panel->selWinB, frame_width - 2 * 10 - 20, 24);
1225 WMSetButtonText(panel->selWinB, _("Select window"));
1226 WMSetButtonAction(panel->selWinB, selectWindow, panel);
1227
1228 panel->specLbl = WMCreateLabel(panel->win);
1229 WMMoveWidget(panel->specLbl, 15, 210);
1230 WMResizeWidget(panel->specLbl, frame_width, 100);
1231 WMSetLabelText(panel->specLbl, spec_text);
1232 WMSetLabelWraps(panel->specLbl, True);
1233
1234 WMSetLabelTextAlignment(panel->specLbl, WALeft);
1235
1236 /**** attributes ****/
1237 panel->attrFrm = WMCreateFrame(panel->win);
1238 WMSetFrameTitle(panel->attrFrm, _("Attributes"));
1239 WMMoveWidget(panel->attrFrm, 15, 45);
1240 WMResizeWidget(panel->attrFrm, frame_width, 250);
1241
1242 for (i = 0; i < 11; i++) {
1243 char *caption = NULL;
1244 int flag = 0;
1245 char *descr = NULL;
1246
1247 switch (i) {
1248 case 0:
1249 caption = _("Disable titlebar");
1250 flag = WFLAGP(wwin, no_titlebar);
1251 descr = _("Remove the titlebar of this window.\n"
1252 "To access the window commands menu of a window\n"
1253 "without it's titlebar, press Control+Esc (or the\n"
1254 "equivalent shortcut, if you changed the default\n" "settings).");
1255 break;
1256 case 1:
1257 caption = _("Disable resizebar");
1258 flag = WFLAGP(wwin, no_resizebar);
1259 descr = _("Remove the resizebar of this window.");
1260 break;
1261 case 2:
1262 caption = _("Disable close button");
1263 flag = WFLAGP(wwin, no_close_button);
1264 descr = _("Remove the `close window' button of this window.");
1265 break;
1266 case 3:
1267 caption = _("Disable miniaturize button");
1268 flag = WFLAGP(wwin, no_miniaturize_button);
1269 descr = _("Remove the `miniaturize window' button of the window.");
1270 break;
1271 case 4:
1272 caption = _("Disable border");
1273 flag = WFLAGP(wwin, no_border);
1274 descr = _("Remove the 1 pixel black border around the window.");
1275 break;
1276 case 5:
1277 caption = _("Keep on top (floating)");
1278 flag = WFLAGP(wwin, floating);
1279 descr = _("Keep the window over other windows, not allowing\n" "them to cover it.");
1280 break;
1281 case 6:
1282 caption = _("Keep at bottom (sunken)");
1283 flag = WFLAGP(wwin, sunken);
1284 descr = _("Keep the window under all other windows.");
1285 break;
1286 case 7:
1287 caption = _("Omnipresent");
1288 flag = WFLAGP(wwin, omnipresent);
1289 descr = _("Make window present in all workspaces.");
1290 break;
1291 case 8:
1292 caption = _("Start miniaturized");
1293 flag = WFLAGP(wwin, start_miniaturized);
1294 descr = _("Make the window be automatically miniaturized when it's\n" "first shown.");
1295 break;
1296 case 9:
1297 caption = _("Start maximized");
1298 flag = WFLAGP(wwin, start_maximized != 0);
1299 descr = _("Make the window be automatically maximized when it's\n" "first shown.");
1300 break;
1301 case 10:
1302 caption = _("Full screen maximization");
1303 flag = WFLAGP(wwin, full_maximize);
1304 descr = _("Make the window use the whole screen space when it's\n"
1305 "maximized. The titlebar and resizebar will be moved\n"
1306 "to outside the screen.");
1307 break;
1308 }
1309 panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm);
1310 WMMoveWidget(panel->attrChk[i], 10, 20 * (i + 1));
1311 WMResizeWidget(panel->attrChk[i], frame_width - 15, 20);
1312 WMSetButtonSelected(panel->attrChk[i], flag);
1313 WMSetButtonText(panel->attrChk[i], caption);
1314
1315 WMSetBalloonTextForView(descr, WMWidgetView(panel->attrChk[i]));
1316 }
1317
1318 /**** more attributes ****/
1319 panel->moreFrm = WMCreateFrame(panel->win);
1320 WMSetFrameTitle(panel->moreFrm, _("Advanced"));
1321 WMMoveWidget(panel->moreFrm, 15, 45);
1322 WMResizeWidget(panel->moreFrm, frame_width, 250);
1323
1324 for (i = 0;
1325 #ifdef XKB_BUTTON_HINT
1326 i < 9;
1327 #else
1328 i < 8;
1329 #endif
1330 i++) {
1331 char *caption = NULL;
1332 int flag = 0;
1333 char *descr = NULL;
1334
1335 switch (i) {
1336 case 0:
1337 caption = _("Do not bind keyboard shortcuts");
1338 flag = WFLAGP(wwin, no_bind_keys);
1339 descr = _("Do not bind keyboard shortcuts from Window Maker\n"
1340 "when this window is focused. This will allow the\n"
1341 "window to receive all key combinations regardless\n"
1342 "of your shortcut configuration.");
1343 break;
1344 case 1:
1345 caption = _("Do not bind mouse clicks");
1346 flag = WFLAGP(wwin, no_bind_mouse);
1347 descr = _("Do not bind mouse actions, such as `Alt'+drag\n"
1348 "in the window (when alt is the modifier you have\n" "configured).");
1349 break;
1350 case 2:
1351 caption = _("Do not show in the window list");
1352 flag = WFLAGP(wwin, skip_window_list);
1353 descr = _("Do not list the window in the window list menu.");
1354 break;
1355 case 3:
1356 caption = _("Do not let it take focus");
1357 flag = WFLAGP(wwin, no_focusable);
1358 descr = _("Do not let the window take keyboard focus when you\n" "click on it.");
1359 break;
1360 case 4:
1361 caption = _("Keep inside screen");
1362 flag = WFLAGP(wwin, dont_move_off);
1363 descr = _("Do not allow the window to move itself completely\n"
1364 "outside the screen. For bug compatibility.\n");
1365 break;
1366 case 5:
1367 caption = _("Ignore 'Hide Others'");
1368 flag = WFLAGP(wwin, no_hide_others);
1369 descr = _("Do not hide the window when issuing the\n" "`HideOthers' command.");
1370 break;
1371 case 6:
1372 caption = _("Ignore 'Save Session'");
1373 flag = WFLAGP(wwin, dont_save_session);
1374 descr = _("Do not save the associated application in the\n"
1375 "session's state, so that it won't be restarted\n"
1376 "together with other applications when Window Maker\n" "starts.");
1377 break;
1378 case 7:
1379 caption = _("Emulate application icon");
1380 flag = WFLAGP(wwin, emulate_appicon);
1381 descr = _("Make this window act as an application that provides\n"
1382 "enough information to Window Maker for a dockable\n"
1383 "application icon to be created.");
1384 break;
1385 #ifdef XKB_BUTTON_HINT
1386 case 8:
1387 caption = _("Disable language button");
1388 flag = WFLAGP(wwin, no_language_button);
1389 descr = _("Remove the `toggle language' button of the window.");
1390 break;
1391 #endif
1392 }
1393 panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm);
1394 WMMoveWidget(panel->moreChk[i], 10, 20 * (i + 1));
1395 WMResizeWidget(panel->moreChk[i], frame_width - 15, 20);
1396 WMSetButtonSelected(panel->moreChk[i], flag);
1397 WMSetButtonText(panel->moreChk[i], caption);
1398
1399 WMSetBalloonTextForView(descr, WMWidgetView(panel->moreChk[i]));
1400 }
1401
1402 /* miniwindow/workspace */
1403 panel->iconFrm = WMCreateFrame(panel->win);
1404 WMMoveWidget(panel->iconFrm, 15, 50);
1405 WMResizeWidget(panel->iconFrm, PWIDTH - (2 * 15), 170);
1406 WMSetFrameTitle(panel->iconFrm, _("Miniwindow Image"));
1407
1408 panel->iconLbl = WMCreateLabel(panel->iconFrm);
1409 WMMoveWidget(panel->iconLbl, PWIDTH - (2 * 15) - 22 - 64, 20);
1410 WMResizeWidget(panel->iconLbl, 64, 64);
1411 WMSetLabelRelief(panel->iconLbl, WRGroove);
1412 WMSetLabelImagePosition(panel->iconLbl, WIPImageOnly);
1413
1414 panel->browseIconBtn = WMCreateCommandButton(panel->iconFrm);
1415 WMSetButtonAction(panel->browseIconBtn, chooseIconCallback, panel);
1416 WMMoveWidget(panel->browseIconBtn, 22, 32);
1417 WMResizeWidget(panel->browseIconBtn, 120, 26);
1418 WMSetButtonText(panel->browseIconBtn, _("Browse..."));
1419
1420 #ifdef wrong_behaviour
1421 WMSetButtonImagePosition(panel->updateIconBtn, WIPRight);
1422 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIReturnArrow);
1423 WMSetButtonImage(panel->updateIconBtn, pixmap);
1424 WMReleasePixmap(pixmap);
1425 pixmap = WMGetSystemPixmap(scr->wmscreen, WSIHighlightedReturnArrow);
1426 WMSetButtonAltImage(panel->updateIconBtn, pixmap);
1427 WMReleasePixmap(pixmap);
1428 #endif
1429
1430 panel->fileLbl = WMCreateLabel(panel->iconFrm);
1431 WMMoveWidget(panel->fileLbl, 20, 85);
1432 WMResizeWidget(panel->fileLbl, PWIDTH - (2 * 15) - (2 * 20), 14);
1433 WMSetLabelText(panel->fileLbl, _("Icon filename:"));
1434
1435 panel->fileText = WMCreateTextField(panel->iconFrm);
1436 WMMoveWidget(panel->fileText, 20, 105);
1437 WMResizeWidget(panel->fileText, PWIDTH - (2 * 20) - (2 * 15), 20);
1438 WMSetTextFieldText(panel->fileText, NULL);
1439 WMAddNotificationObserver(textEditedObserver, panel, WMTextDidEndEditingNotification, panel->fileText);
1440
1441 panel->alwChk = WMCreateSwitchButton(panel->iconFrm);
1442 WMMoveWidget(panel->alwChk, 20, 130);
1443 WMResizeWidget(panel->alwChk, PWIDTH - (2 * 15) - (2 * 15), 30);
1444 WMSetButtonText(panel->alwChk, _("Ignore client supplied icon"));
1445 WMSetButtonSelected(panel->alwChk, WFLAGP(wwin, always_user_icon));
1446
1447 panel->wsFrm = WMCreateFrame(panel->win);
1448 WMMoveWidget(panel->wsFrm, 15, 225);
1449 WMResizeWidget(panel->wsFrm, PWIDTH - (2 * 15), 70);
1450 WMSetFrameTitle(panel->wsFrm, _("Initial Workspace"));
1451
1452 WMSetBalloonTextForView(_("The workspace to place the window when it's"
1453 "first shown."), WMWidgetView(panel->wsFrm));
1454
1455 panel->wsP = WMCreatePopUpButton(panel->wsFrm);
1456 WMMoveWidget(panel->wsP, 20, 30);
1457 WMResizeWidget(panel->wsP, PWIDTH - (2 * 15) - (2 * 20), 20);
1458 WMAddPopUpButtonItem(panel->wsP, _("Nowhere in particular"));
1459 for (i = 0; i < wwin->screen_ptr->workspace_count; i++) {
1460 WMAddPopUpButtonItem(panel->wsP, scr->workspaces[i]->name);
1461 }
1462
1463 i = wDefaultGetStartWorkspace(wwin->screen_ptr, wwin->wm_instance, wwin->wm_class);
1464 if (i >= 0 && i <= wwin->screen_ptr->workspace_count) {
1465 WMSetPopUpButtonSelectedItem(panel->wsP, i + 1);
1466 } else {
1467 WMSetPopUpButtonSelectedItem(panel->wsP, 0);
1468 }
1469
1470 /* application wide attributes */
1471 if (wwin->main_window != None) {
1472 WApplication *wapp = wApplicationOf(wwin->main_window);
1473
1474 panel->appFrm = WMCreateFrame(panel->win);
1475 WMSetFrameTitle(panel->appFrm, _("Application Attributes"));
1476 WMMoveWidget(panel->appFrm, 15, 50);
1477 WMResizeWidget(panel->appFrm, frame_width, 240);
1478
1479 for (i = 0; i < 3; i++) {
1480 char *caption = NULL;
1481 int flag = 0;
1482 char *descr = NULL;
1483
1484 switch (i) {
1485 case 0:
1486 caption = _("Start hidden");
1487 flag = WFLAGP(wapp->main_window_desc, start_hidden);
1488 descr = _("Automatically hide application when it's started.");
1489 break;
1490 case 1:
1491 caption = _("No application icon");
1492 flag = WFLAGP(wapp->main_window_desc, no_appicon);
1493 descr = _("Disable the application icon for the application.\n"
1494 "Note that you won't be able to dock it anymore,\n"
1495 "and any icons that are already docked will stop\n"
1496 "working correctly.");
1497 break;
1498 case 2:
1499 caption = _("Shared application icon");
1500 flag = WFLAGP(wapp->main_window_desc, shared_appicon);
1501 descr = _("Use a single shared application icon for all of\n"
1502 "the instances of this application.\n");
1503 break;
1504 }
1505 panel->appChk[i] = WMCreateSwitchButton(panel->appFrm);
1506 WMMoveWidget(panel->appChk[i], 10, 20 * (i + 1));
1507 WMResizeWidget(panel->appChk[i], 205, 20);
1508 WMSetButtonSelected(panel->appChk[i], flag);
1509 WMSetButtonText(panel->appChk[i], caption);
1510
1511 WMSetBalloonTextForView(descr, WMWidgetView(panel->appChk[i]));
1512 }
1513
1514 if (WFLAGP(wwin, emulate_appicon)) {
1515 WMSetButtonEnabled(panel->appChk[1], False);
1516 WMSetButtonEnabled(panel->moreChk[7], True);
1517 } else {
1518 WMSetButtonEnabled(panel->appChk[1], True);
1519 WMSetButtonEnabled(panel->moreChk[7], False);
1520 }
1521 } else {
1522 int tmp;
1523
1524 if ((wwin->transient_for != None && wwin->transient_for != scr->root_win)
1525 || !wwin->wm_class || !wwin->wm_instance)
1526 tmp = False;
1527 else
1528 tmp = True;
1529 WMSetButtonEnabled(panel->moreChk[7], tmp);
1530
1531 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 4, False);
1532 panel->appFrm = NULL;
1533 }
1534
1535 /* if the window is a transient, don't let it have a miniaturize
1536 * button */
1537 if (wwin->transient_for != None && wwin->transient_for != scr->root_win)
1538 WMSetButtonEnabled(panel->attrChk[3], False);
1539 else
1540 WMSetButtonEnabled(panel->attrChk[3], True);
1541
1542 if (!wwin->wm_class && !wwin->wm_instance) {
1543 WMSetPopUpButtonItemEnabled(panel->pagePopUp, 0, False);
1544 }
1545
1546 WMRealizeWidget(panel->win);
1547
1548 WMMapSubwidgets(panel->win);
1549 WMMapSubwidgets(panel->specFrm);
1550 WMMapSubwidgets(panel->attrFrm);
1551 WMMapSubwidgets(panel->moreFrm);
1552 WMMapSubwidgets(panel->iconFrm);
1553 WMMapSubwidgets(panel->wsFrm);
1554 if (panel->appFrm)
1555 WMMapSubwidgets(panel->appFrm);
1556
1557 if (showSelectPanel) {
1558 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 0);
1559 changePage(panel->pagePopUp, panel);
1560 } else {
1561 WMSetPopUpButtonSelectedItem(panel->pagePopUp, 1);
1562 changePage(panel->pagePopUp, panel);
1563 }
1564
1565 parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 0, 0, 0);
1566 XSelectInput(dpy, parent, KeyPressMask | KeyReleaseMask);
1567 panel->parent = parent;
1568 XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
1569
1570 WMMapWidget(panel->win);
1571
1572 XSetTransientForHint(dpy, parent, wwin->client_win);
1573
1574 if (xpos == UNDEFINED_POS) {
1575 x = wwin->frame_x + wwin->frame->core->width / 2;
1576 y = wwin->frame_y + wwin->frame->top_width * 2;
1577 if (y + PHEIGHT > scr->scr_height)
1578 y = scr->scr_height - PHEIGHT - 30;
1579 if (x + PWIDTH > scr->scr_width)
1580 x = scr->scr_width - PWIDTH;
1581 } else {
1582 x = xpos;
1583 y = ypos;
1584 }
1585
1586 panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, "Inspector", x, y, PWIDTH, PHEIGHT);
1587
1588 if (!selectedBtn)
1589 selectedBtn = panel->defaultRb;
1590
1591 WMSetButtonSelected(selectedBtn, True);
1592
1593 selectSpecification(selectedBtn, panel);
1594
1595 /* kluge to know who should get the key events */
1596 panel->frame->client_leader = WMWidgetXID(panel->win);
1597
1598 WSETUFLAG(panel->frame, no_closable, 0);
1599 WSETUFLAG(panel->frame, no_close_button, 0);
1600 wWindowUpdateButtonImages(panel->frame);
1601 wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
1602 panel->frame->frame->on_click_right = destroyInspector;
1603
1604 wWindowMap(panel->frame);
1605
1606 showIconFor(WMWidgetScreen(panel->alwChk), panel, wwin->wm_instance, wwin->wm_class, UPDATE_TEXT_FIELD);
1607
1608 return panel;
1609 }
1610
1611 void wShowInspectorForWindow(WWindow * wwin)
1612 {
1613 if (wwin->flags.inspector_open)
1614 return;
1615
1616 WMSetBalloonEnabled(wwin->screen_ptr->wmscreen, wPreferences.help_balloon);
1617
1618 make_keys();
1619 wwin->flags.inspector_open = 1;
1620 wwin->inspector = createInspectorForWindow(wwin, UNDEFINED_POS, UNDEFINED_POS, False);
1621 }
1622
1623 void wHideInspectorForWindow(WWindow * wwin)
1624 {
1625 WWindow *pwin = wwin->inspector->frame;
1626
1627 wWindowUnmap(pwin);
1628 pwin->flags.hidden = 1;
1629
1630 wClientSetState(pwin, IconicState, None);
1631 }
1632
1633 void wUnhideInspectorForWindow(WWindow * wwin)
1634 {
1635 WWindow *pwin = wwin->inspector->frame;
1636
1637 pwin->flags.hidden = 0;
1638 pwin->flags.mapped = 1;
1639 XMapWindow(dpy, pwin->client_win);
1640 XMapWindow(dpy, pwin->frame->core->window);
1641 wClientSetState(pwin, NormalState, None);
1642 }
1643
1644 WWindow *wGetWindowOfInspectorForWindow(WWindow * wwin)
1645 {
1646 if (wwin->inspector) {
1647 assert(wwin->flags.inspector_open != 0);
1648
1649 return wwin->inspector->frame;
1650 } else
1651 return NULL;
1652 }
1653
1654 void wCloseInspectorForWindow(WWindow * wwin)
1655 {
1656 WWindow *pwin = wwin->inspector->frame; /* the inspector window */
1657
1658 (*pwin->frame->on_click_right) (NULL, pwin, NULL);
1659 }