2 * Window Maker window manager
4 * Copyright (c) 1997, 1998 Alfredo K. Kojima
5 * Copyright (c) 1998 Dan Pascu
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
30 #include "WindowMaker.h"
35 #endif /* USER_MENU */
38 #include "application.h"
40 #include "properties.h"
45 #include "workspace.h"
54 /******** Global variables ********/
56 extern XContext wAppWinContext
;
57 extern XContext wWinContext
;
58 extern WPreferences wPreferences
;
60 extern WDDomain
*WDWindowAttributes
;
62 /******** Local variables ********/
66 makeMainWindow(WScreen
*scr
, Window window
)
69 XWindowAttributes attr
;
71 if (!XGetWindowAttributes(dpy
, window
, &attr
)) {
75 wwin
= wWindowCreate();
76 wwin
->screen_ptr
= scr
;
77 wwin
->client_win
= window
;
78 wwin
->main_window
= window
;
79 wwin
->wm_hints
= XGetWMHints(dpy
, window
);
80 /* if (!MyXFetchName(dpy, window, &(wwin->frame->title))) {
81 wwin->frame->title = NULL;
84 PropGetWMClass(window
, &wwin
->wm_class
, &wwin
->wm_instance
);
87 wDefaultFillAttributes(scr
, wwin
->wm_instance
, wwin
->wm_class
,
88 &wwin
->user_flags
, &wwin
->defined_user_flags
, True
);
90 XSelectInput(dpy
, window
, attr
.your_event_mask
| PropertyChangeMask
91 | StructureNotifyMask
);
97 wApplicationOf(Window window
)
103 if (XFindContext(dpy
, window
, wAppWinContext
, (XPointer
*)&wapp
)!=XCSUCCESS
)
110 findDockIconFor(WDock
*dock
, Window main_window
)
112 WAppIcon
*aicon
= NULL
;
114 aicon
= wDockFindIconForWindow(dock
, main_window
);
116 wDockTrackWindowLaunch(dock
, main_window
);
117 aicon
= wDockFindIconForWindow(dock
, main_window
);
124 extractIcon(WWindow
*wwin
)
129 if (!XGetCommand(dpy
, wwin
->client_win
, &argv
, &argc
) || argc
< 1)
132 wApplicationExtractDirPackIcon(wwin
->screen_ptr
,argv
[0],
135 XFreeStringList(argv
);
140 saveIconNameFor(char *iconPath
, char *wm_instance
, char *wm_class
)
142 proplist_t dict
= WDWindowAttributes
->dictionary
;
143 proplist_t adict
, key
, iconk
;
150 i
+= strlen(wm_instance
);
152 i
+= strlen(wm_class
);
156 if (wm_class
&& wm_instance
) {
157 sprintf(tmp
, "%s.%s", wm_instance
, wm_class
);
160 strcat(tmp
, wm_instance
);
162 strcat(tmp
, wm_class
);
165 key
= PLMakeString(tmp
);
167 adict
= PLGetDictionaryEntry(dict
, key
);
169 iconk
= PLMakeString("Icon");
172 val
= PLGetDictionaryEntry(adict
, iconk
);
174 /* no dictionary for app, so create one */
175 adict
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
176 PLInsertDictionaryEntry(dict
, key
, adict
);
181 val
= PLMakeString(iconPath
);
182 PLInsertDictionaryEntry(adict
, iconk
, val
);
187 if (val
&& !wPreferences
.flags
.noupdates
)
193 wApplicationExtractDirPackIcon(WScreen
*scr
, char *path
,
194 char *wm_instance
, char *wm_class
)
197 /* Maybe the app is a .app and it has an icon in it, like
198 * /usr/local/GNUstep/Apps/WPrefs.app/WPrefs.tiff
200 if (strstr(path
, ".app")) {
203 tmp
= wmalloc(strlen(path
)+16);
205 if (scr
->flags
.supports_tiff
) {
207 strcat(tmp
, ".tiff");
208 if (access(tmp
, R_OK
)==0)
214 if (access(tmp
, R_OK
)==0)
222 saveIconNameFor(iconPath
, wm_instance
, wm_class
);
230 extractClientIcon(WAppIcon
*icon
)
234 path
= wIconStore(icon
->icon
);
238 saveIconNameFor(path
, icon
->wm_instance
, icon
->wm_class
);
247 wApplicationCreate(WScreen
*scr
, Window main_window
)
252 if (main_window
==None
|| main_window
==scr
->root_win
) {
254 wwarning("trying to create application for %x",(unsigned)main_window
);
263 /* check if the window is valid */
264 if (!XGetGeometry(dpy
, main_window
, &root
, &foo
, &foo
, &bar
, &bar
,
270 wapp
= wApplicationOf(main_window
);
276 wapp
= wmalloc(sizeof(WApplication
));
277 memset(wapp
, 0, sizeof(WApplication
));
280 wapp
->last_focused
= NULL
;
282 wapp
->last_workspace
= 0;
284 wapp
->main_window
= main_window
;
285 wapp
->main_window_desc
= makeMainWindow(scr
, main_window
);
286 if (!wapp
->main_window_desc
) {
291 extractIcon(wapp
->main_window_desc
);
293 leader
= wWindowFor(main_window
);
295 leader
->main_window
= main_window
;
297 wapp
->menu
= wAppMenuGet(scr
, main_window
);
299 if (!wapp
->menu
) wapp
->menu
= wUserMenuGet(scr
, wapp
->main_window_desc
);
300 #endif /* USER_MENU */
304 * Set application wide attributes from the leader.
306 wapp
->flags
.hidden
= WFLAGP(wapp
->main_window_desc
, start_hidden
);
308 wapp
->flags
.emulated
= WFLAGP(wapp
->main_window_desc
, emulate_appicon
);
310 /* application descriptor */
311 XSaveContext(dpy
, main_window
, wAppWinContext
, (XPointer
)wapp
);
313 if (!WFLAGP(wapp
->main_window_desc
, no_appicon
)) {
314 wapp
->app_icon
= NULL
;
316 wapp
->app_icon
= findDockIconFor(scr
->last_dock
, main_window
);
317 /* check main dock if we did not find it in last dock */
318 if (!wapp
->app_icon
&& scr
->dock
) {
319 wapp
->app_icon
= findDockIconFor(scr
->dock
, main_window
);
321 /* finally check clips */
322 if (!wapp
->app_icon
) {
324 for (i
=0; i
<scr
->workspace_count
; i
++) {
325 WDock
*dock
= scr
->workspaces
[i
]->clip
;
327 wapp
->app_icon
= findDockIconFor(dock
, main_window
);
333 if (wapp
->app_icon
) {
334 WWindow
*mainw
= wapp
->main_window_desc
;
336 wapp
->app_icon
->running
= 1;
337 wapp
->app_icon
->icon
->force_paint
= 1;
338 wapp
->app_icon
->icon
->owner
= mainw
;
339 if (mainw
->wm_hints
&& (mainw
->wm_hints
->flags
&IconWindowHint
))
340 wapp
->app_icon
->icon
->icon_win
= mainw
->wm_hints
->icon_window
;
341 wAppIconPaint(wapp
->app_icon
);
343 wapp
->app_icon
= wAppIconCreate(wapp
->main_window_desc
);
344 #ifdef REDUCE_APPICONS
345 /* This is so we get the appearance of invoking the app sitting
346 * on the dock. -cls */
347 if (wapp
->app_icon
) {
348 if (wapp
->app_icon
->docked
&& wapp
->app_icon
->num_apps
== 1) {
349 wapp
->app_icon
->launching
= 0;
350 wapp
->app_icon
->running
= 1;
351 wapp
->app_icon
->icon
->force_paint
= 1;
352 wAppIconPaint(wapp
->app_icon
);
358 wapp
->app_icon
= NULL
;
361 if (wapp
->app_icon
) {
362 wapp
->app_icon
->main_window
= main_window
;
365 #ifndef REDUCE_APPICONS
366 if (wapp
->app_icon
&& !wapp
->app_icon
->docked
) {
368 if (wapp
->app_icon
&& !wapp
->app_icon
->docked
&& wapp
->app_icon
->num_apps
== 1) {
373 WIcon
*icon
= wapp
->app_icon
->icon
;
374 WDock
*clip
= scr
->workspaces
[scr
->current_workspace
]->clip
;
377 if (clip
&& clip
->attract_icons
&& wDockFindFreeSlot(clip
, &x
, &y
)) {
378 wapp
->app_icon
->attracted
= 1;
379 if (!wapp
->app_icon
->icon
->shadowed
) {
380 wapp
->app_icon
->icon
->shadowed
= 1;
381 wapp
->app_icon
->icon
->force_paint
= 1;
382 /* We don't do an wAppIconPaint() here because it's in
383 * wDockAttachIcon(). -Dan.
386 wDockAttachIcon(clip
, wapp
->app_icon
, x
, y
);
388 PlaceIcon(scr
, &x
, &y
);
389 wAppIconMove(wapp
->app_icon
, x
, y
);
390 wLowerFrame(icon
->core
);
392 if (!clip
|| !wapp
->app_icon
->attracted
|| !clip
->collapsed
)
393 XMapWindow(dpy
, icon
->core
->window
);
396 if (wPreferences
.auto_arrange_icons
&& wapp
->app_icon
&& !wapp
->app_icon
->attracted
) {
397 wArrangeIcons(scr
, True
);
400 if (wapp
->app_icon
) {
403 /* if the displayed icon was supplied by the client, save the icon */
404 tmp
= wDefaultGetIconFile(scr
, wapp
->app_icon
->wm_instance
,
405 wapp
->app_icon
->wm_class
, True
);
407 extractClientIcon(wapp
->app_icon
);
411 wapp
->next
= scr
->wapp_list
;
413 scr
->wapp_list
->prev
= wapp
;
414 scr
->wapp_list
= wapp
;
417 wSoundPlay(WMSOUND_APPSTART
);
421 printf("Created application for %x\n", (unsigned)main_window
);
428 wApplicationDestroy(WApplication
*wapp
)
433 #ifdef REDUCE_APPICONS
441 if (wapp
->refcount
>0)
445 scr
= wapp
->main_window_desc
->screen_ptr
;
446 main_window
= wapp
->main_window
;
447 #ifdef REDUCE_APPICONS
448 napps
= wAppIconReduceAppCount(wapp
);
451 if (wapp
== scr
->wapp_list
) {
453 wapp
->next
->prev
= NULL
;
454 scr
->wapp_list
= wapp
->next
;
457 wapp
->next
->prev
= wapp
->prev
;
459 wapp
->prev
->next
= wapp
->next
;
462 XDeleteContext(dpy
, wapp
->main_window
, wAppWinContext
);
463 wAppMenuDestroy(wapp
->menu
);
464 if (wapp
->app_icon
) {
465 if (wapp
->app_icon
->docked
&& !wapp
->app_icon
->attracted
) {
466 #ifdef REDUCE_APPICONS
469 wapp
->app_icon
->running
= 0;
470 /* since we keep it, we don't care if it was attracted or not */
471 wapp
->app_icon
->attracted
= 0;
472 wapp
->app_icon
->icon
->shadowed
= 0;
473 wapp
->app_icon
->main_window
= None
;
474 wapp
->app_icon
->pid
= 0;
475 wapp
->app_icon
->icon
->owner
= NULL
;
476 wapp
->app_icon
->icon
->icon_win
= None
;
477 wapp
->app_icon
->icon
->force_paint
= 1;
478 wAppIconPaint(wapp
->app_icon
);
479 #ifdef REDUCE_APPICONS
482 } else if (wapp
->app_icon
->docked
) {
483 #ifdef REDUCE_APPICONS
486 wapp
->app_icon
->running
= 0;
487 wDockDetach(wapp
->app_icon
->dock
, wapp
->app_icon
);
488 #ifdef REDUCE_APPICONS
492 #ifdef REDUCE_APPICONS
495 wAppIconDestroy(wapp
->app_icon
);
496 #ifdef REDUCE_APPICONS
501 wwin
= wWindowFor(wapp
->main_window_desc
->client_win
);
503 wWindowDestroy(wapp
->main_window_desc
);
505 /* undelete client window context that was deleted in
507 XSaveContext(dpy
, wwin
->client_win
, wWinContext
,
508 (XPointer
)&wwin
->client_descriptor
);
513 printf("Destroyed application for %x\n", (unsigned)main_window
);
515 if (wPreferences
.auto_arrange_icons
) {
516 wArrangeIcons(scr
, True
);
520 wSoundPlay(WMSOUND_APPEXIT
);