2 * WindowMaker window manager
4 * Copyright (c) 1997, 1998 Alfredo K. Kojima
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
29 #include "WindowMaker.h"
34 #include "application.h"
36 #include "properties.h"
41 #include "workspace.h"
50 /******** Global variables ********/
52 extern XContext wAppWinContext
;
53 extern XContext wWinContext
;
54 extern WPreferences wPreferences
;
56 extern WDDomain
*WDWindowAttributes
;
58 /******** Local variables ********/
62 makeMainWindow(WScreen
*scr
, Window window
)
65 XWindowAttributes attr
;
68 if (!XGetWindowAttributes(dpy
, window
, &attr
)) {
72 wwin
= wWindowCreate();
73 wwin
->screen_ptr
= scr
;
74 wwin
->client_win
= window
;
75 wwin
->main_window
= window
;
76 wwin
->wm_hints
= XGetWMHints(dpy
, window
);
77 /* if (!MyXFetchName(dpy, window, &(wwin->frame->title))) {
78 wwin->frame->title = NULL;
81 PropGetWMClass(window
, &wwin
->wm_class
, &wwin
->wm_instance
);
83 wDefaultFillAttributes(scr
, wwin
->wm_instance
, wwin
->wm_class
,
84 &wwin
->window_flags
, True
);
86 XSelectInput(dpy
, window
, attr
.your_event_mask
| PropertyChangeMask
87 | StructureNotifyMask
);
93 wApplicationOf(Window window
)
99 if (XFindContext(dpy
, window
, wAppWinContext
, (XPointer
*)&wapp
)!=XCSUCCESS
)
106 findDockIconFor(WDock
*dock
, Window main_window
)
108 WAppIcon
*aicon
= NULL
;
110 aicon
= wDockFindIconFor(dock
, main_window
);
112 wDockTrackWindowLaunch(dock
, main_window
);
113 aicon
= wDockFindIconFor(dock
, main_window
);
120 extractIcon(WWindow
*wwin
)
125 if (!XGetCommand(dpy
, wwin
->client_win
, &argv
, &argc
) || argc
< 1)
128 wApplicationExtractDirPackIcon(wwin
->screen_ptr
,argv
[0],
131 XFreeStringList(argv
);
136 wApplicationExtractDirPackIcon(WScreen
*scr
, char *path
,
137 char *wm_instance
, char *wm_class
)
140 /* Maybe the app is a .app and it has an icon in it, like
141 * /usr/local/GNUstep/Apps/WPrefs.app/WPrefs.tiff
143 if (strstr(path
, ".app")) {
146 tmp
= wmalloc(strlen(path
)+16);
148 if (scr
->flags
.supports_tiff
) {
150 strcat(tmp
, ".tiff");
151 if (access(tmp
, R_OK
)==0)
157 if (access(tmp
, R_OK
)==0)
165 proplist_t dict
= WDWindowAttributes
->dictionary
;
166 proplist_t adict
, key
, iconk
;
173 i
+= strlen(wm_instance
);
175 i
+= strlen(wm_class
);
179 if (wm_class
&& wm_instance
) {
180 sprintf(tmp
, "%s.%s", wm_instance
, wm_class
);
183 strcat(tmp
, wm_instance
);
185 strcat(tmp
, wm_class
);
188 key
= PLMakeString(tmp
);
190 adict
= PLGetDictionaryEntry(dict
, key
);
192 iconk
= PLMakeString("Icon");
195 val
= PLGetDictionaryEntry(adict
, iconk
);
197 /* no dictionary for app, so create one */
198 adict
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
199 PLInsertDictionaryEntry(dict
, key
, adict
);
204 val
= PLMakeString(iconPath
);
205 PLInsertDictionaryEntry(adict
, iconk
, val
);
219 wApplicationCreate(WScreen
*scr
, Window main_window
)
224 if (main_window
==None
|| main_window
==scr
->root_win
) {
226 wwarning("trying to create application for %x",(unsigned)main_window
);
235 /* check if the window is valid */
236 if (!XGetGeometry(dpy
, main_window
, &root
, &foo
, &foo
, &bar
, &bar
,
242 wapp
= wApplicationOf(main_window
);
248 wapp
= wmalloc(sizeof(WApplication
));
249 memset(wapp
, 0, sizeof(WApplication
));
252 wapp
->last_focused
= NULL
;
254 wapp
->last_workspace
= 0;
256 wapp
->main_window
= main_window
;
257 wapp
->main_window_desc
= makeMainWindow(scr
, main_window
);
258 if (!wapp
->main_window_desc
) {
263 extractIcon(wapp
->main_window_desc
);
265 leader
= wWindowFor(main_window
);
267 leader
->main_window
= main_window
;
269 wapp
->menu
= wAppMenuGet(scr
, main_window
);
273 * Set application wide attributes from the leader.
275 wapp
->flags
.hidden
= wapp
->main_window_desc
->window_flags
.start_hidden
;
277 wapp
->flags
.emulated
= wapp
->main_window_desc
->window_flags
.emulate_appicon
;
279 /* application descriptor */
280 XSaveContext(dpy
, main_window
, wAppWinContext
, (XPointer
)wapp
);
282 if (!wapp
->main_window_desc
->window_flags
.no_appicon
) {
283 wapp
->app_icon
= NULL
;
285 wapp
->app_icon
= findDockIconFor(scr
->last_dock
, main_window
);
286 /* check main dock if we did not find it in last dock */
287 if (!wapp
->app_icon
&& scr
->dock
)
288 wapp
->app_icon
= findDockIconFor(scr
->dock
, main_window
);
289 /* finally check clips */
290 if (!wapp
->app_icon
) {
292 for (i
=0; i
<scr
->workspace_count
; i
++) {
293 WDock
*dock
= scr
->workspaces
[i
]->clip
;
295 wapp
->app_icon
= findDockIconFor(dock
, main_window
);
301 if (wapp
->app_icon
) {
302 WWindow
*mainw
= wapp
->main_window_desc
;
304 wapp
->app_icon
->running
= 1;
305 wapp
->app_icon
->icon
->force_paint
= 1;
306 wapp
->app_icon
->icon
->owner
= mainw
;
307 if (mainw
->wm_hints
&& (mainw
->wm_hints
->flags
&IconWindowHint
))
308 wapp
->app_icon
->icon
->icon_win
= mainw
->wm_hints
->icon_window
;
309 wAppIconPaint(wapp
->app_icon
);
311 wapp
->app_icon
= wAppIconCreate(wapp
->main_window_desc
);
312 #ifdef REDUCE_APPICONS
313 /* This is so we get the appearance of invoking the app sitting
314 * on the dock. -cls */
315 if (wapp
->app_icon
) {
316 if (wapp
->app_icon
->docked
&& wapp
->app_icon
->num_apps
== 1) {
317 wapp
->app_icon
->launching
= 0;
318 wapp
->app_icon
->running
= 1;
319 wapp
->app_icon
->icon
->force_paint
= 1;
320 wAppIconPaint(wapp
->app_icon
);
326 wapp
->app_icon
= NULL
;
329 if (wapp
->app_icon
) {
330 wapp
->app_icon
->main_window
= main_window
;
332 wSoundServerGrab(wapp
->app_icon
->wm_class
, main_window
);
336 #ifndef REDUCE_APPICONS
337 if (wapp
->app_icon
&& !wapp
->app_icon
->docked
) {
339 if (wapp
->app_icon
&& !wapp
->app_icon
->docked
&& wapp
->app_icon
->num_apps
== 1) {
341 WIcon
*icon
= wapp
->app_icon
->icon
;
342 WDock
*clip
= scr
->workspaces
[scr
->current_workspace
]->clip
;
345 if (clip
&& clip
->attract_icons
&& wDockFindFreeSlot(clip
, &x
, &y
)) {
346 wapp
->app_icon
->attracted
= 1;
347 if (!clip
->keep_attracted
&& !wapp
->app_icon
->icon
->shadowed
) {
348 wapp
->app_icon
->icon
->shadowed
= 1;
349 wapp
->app_icon
->icon
->force_paint
= 1;
350 /* We don't do an wAppIconPaint() here because it's in
351 * wDockAttachIcon(). -Dan
354 wDockAttachIcon(clip
, wapp
->app_icon
, x
, y
);
356 PlaceIcon(scr
, &x
, &y
);
357 wAppIconMove(wapp
->app_icon
, x
, y
);
359 wLowerFrame(icon
->core
);
362 if (!clip
|| !wapp
->app_icon
->attracted
|| !clip
->collapsed
)
363 XMapWindow(dpy
, icon
->core
->window
);
366 if (wPreferences
.auto_arrange_icons
&& wapp
->app_icon
&& !wapp
->app_icon
->attracted
) {
367 wArrangeIcons(scr
, True
);
371 wapp
->next
= scr
->wapp_list
;
373 scr
->wapp_list
->prev
= wapp
;
374 scr
->wapp_list
= wapp
;
377 wSoundPlay(WMSOUND_APPSTART
);
381 printf("Created application for %x\n", (unsigned)main_window
);
388 wApplicationDestroy(WApplication
*wapp
)
393 #ifdef REDUCE_APPICONS
401 if (wapp
->refcount
>0)
405 scr
= wapp
->main_window_desc
->screen_ptr
;
406 main_window
= wapp
->main_window
;
407 #ifdef REDUCE_APPICONS
408 napps
= wAppIconReduceAppCount(wapp
);
411 if (wapp
== scr
->wapp_list
) {
413 wapp
->next
->prev
= NULL
;
414 scr
->wapp_list
= wapp
->next
;
417 wapp
->next
->prev
= wapp
->prev
;
419 wapp
->prev
->next
= wapp
->next
;
422 XDeleteContext(dpy
, wapp
->main_window
, wAppWinContext
);
423 wAppMenuDestroy(wapp
->menu
);
424 if (wapp
->app_icon
) {
425 if (wapp
->app_icon
->docked
426 && (!wapp
->app_icon
->attracted
||
427 wapp
->app_icon
->dock
->keep_attracted
)) {
428 #ifdef REDUCE_APPICONS
431 wapp
->app_icon
->running
= 0;
432 /* since we keep it, we don't care if it was attracted or not */
433 wapp
->app_icon
->attracted
= 0;
434 wapp
->app_icon
->icon
->shadowed
= 0;
435 wapp
->app_icon
->main_window
= None
;
436 wapp
->app_icon
->pid
= 0;
437 wapp
->app_icon
->icon
->owner
= NULL
;
438 wapp
->app_icon
->icon
->icon_win
= None
;
439 wapp
->app_icon
->icon
->force_paint
= 1;
440 wAppIconPaint(wapp
->app_icon
);
441 #ifdef REDUCE_APPICONS
444 } else if (wapp
->app_icon
->docked
) {
445 #ifdef REDUCE_APPICONS
448 wapp
->app_icon
->running
= 0;
449 wDockDetach(wapp
->app_icon
->dock
, wapp
->app_icon
);
450 #ifdef REDUCE_APPICONS
454 #ifdef REDUCE_APPICONS
457 wAppIconDestroy(wapp
->app_icon
);
458 #ifdef REDUCE_APPICONS
463 wwin
= wWindowFor(wapp
->main_window_desc
->client_win
);
465 wWindowDestroy(wapp
->main_window_desc
);
467 /* undelete client window context that was deleted in
469 XSaveContext(dpy
, wwin
->client_win
, wWinContext
,
470 (XPointer
)&wwin
->client_descriptor
);
475 printf("Destroyed application for %x\n", (unsigned)main_window
);
477 if (wPreferences
.auto_arrange_icons
) {
478 wArrangeIcons(scr
, True
);
482 wSoundPlay(WMSOUND_APPEXIT
);