From kde-devel Tue Mar 07 20:53:46 2000 From: Rik Hemsley Date: Tue, 07 Mar 2000 20:53:46 +0000 To: kde-devel Subject: Re: visibility? X-MARC-Message: https://marc.info/?l=kde-devel&m=95246257913097 #if Christopher Molnar > OK, if you have some patience give me an overview of what needs to happen > and I'll ask questions as needed. (A pointer to the right area of code > would be nice as well). Here we go... I'm sending this to kde-devel so that people can see that the app-starting indicator is on its way and simply needs some code writing. Brief explanation: When KApplication::setTopWidget() is called, various properties are set on the toplevel widget (window). One of these is the WM_COMMAND property. This has two parts, res_name and res_class. res_name is set from argv[0] (so we know the name of the binary) and res_class is simply set to "toplevel" - we don't need that. (BTW, thanks to whomever cleaned up that code :) Now, when we launch an app, we want to pass the name of the binary to kicker. kicker will notify the user that the app is starting by _immediately_ creating a taskbar entry for that app. When the application sets a toplevel widget (window), kwin will pass the name of the app (found in WM_COMMAND -> res_name) to kicker. kicker will then replace the 'app starting' indication with a real taskbar entry. kicker already creates taskbar entries when an app is mapped. So all that needs to be done there is to remove the 'app starting' indicator. The 'app starting' indicator, as I said earlier, should be a taskbar entry. This is logical, it's what the user expects. The thing that isn't what they expect is that there is no accompanying window. For this reason the taskbar entry should be marked in some way to make this clear. I suggest the 'white gauze' effect as seen in Window Maker and over toolbar buttons. Feel free to do spinning cogs or something else if you wish, but remember that animations eat bandwidth when you're running X remotely, so this would not be the best solution. Step 1: Find out how applications are being launched. KDE applications should never launch apps themselves with exec() or similar, they should be using the support in kdelibs. You need to know whether there is more than one mechanism that is being used. When I did this before I just assumed that all apps used krun (kio/krun.*) to launch. This might not be the case, so that simply needs checking. You may also want to keep track of the pids of apps you exec and notice when they die. More on this in a bit... Step 2: Edit kicker's taskbar code. You need to receive DCOP signals called: 'clientStarted(QString, int)', 'clientMapped(QString)' and 'clientDied(int)' The first (clientStarted()) will be sent by KRun when it calls exec(). You should create an 'app starting' taskbar entry here, using the name you are passed in the first parameter. The second parameter is the pid of the process that was started. You must remember this so that when the process exits you can remove the taskbar entry. You may say, "Well, I can remove the entry when the window goes away" - see the discussion on buggy clients later for the reasons why. The second (clientMapped()) will be sent by kwin whenever it sees a new window. Step 3: Edit krun (and anywhere else you find code that launches apps). You need to emit a signal via DCOP, that is directed to kicker. Something like this... dcopClient->send( "kicker", "taskbar/something", "clientStarted(QString)", nameOfAppBinary, pid ); You then need to make sure you are notified when the process exits, so don't lose that pid. Step 4: Edit kwin Again you need to emit a signal via DCOP, that is directed to kicker. Something like this... dcopClient->send( "kicker", "taskbar/something", "clientMapped(QString)", WM_CLASS -> res_name ); WM_CLASS is set in kapp.cpp and contains argv[0] and "toplevel". Within WM_CLASS, res_name contains argv[0] and res_class contains "toplevel". Final thoughts... You may wonder how this will work with 'legacy' apps. Well the fact is, most X11 apps already set WM_COMMAND. Only very few apps do not set this property. Examples include Tk apps (though that's generally because the author didn't do it) and KDE 1 apps. So if some apps don't set WM_COMMAND, how do we know when they have mapped ? The answer is, we don't. I can't see a way to be sure, and if we can't be sure, we shouldn't mess, as we'll just get into trouble. How to fix this ? You can't, completely. You can, however, take notes from Window Maker. krun can be notified when the binary it has exec()'ed has died. When this happens, it send a clientDied(pid) DCOP signal to kicker. If kicker finds a taskbar entry with matching associated pid, it simply removes it. The upshot of all of this is that a buggy client will create a taskbar entry which looks permanently like it is starting up. We can remedy the situation further by using .desktop files to our advantage. Because we ship KDE with a set of .desktop files for legacy apps, we can identify some common legacy apps that are buggy (do not set WM_COMMAND) and mention that fact in their .desktop file. If krun is 'running a .desktop file' (I believe it does this ?) then it can simply avoid sending the clientStarted() signal to kicker. I think this might be a good solution. Any other suggestions are welcome. It's also possible that we kicker could get the info from the related .desktop file itself. I think it's ksycoca it would need to chat with. Any questions ? We can take this off-list now if there are no issues that everyone needs to hear about. Rik -- Stop waiting for Godot.