revert 213 commits (to 56092) from the last month. 10 still need work to resolve...
[AROS.git] / workbench / system / SysMon / tasks.c
blob37f169c483b7d8c610d0e45d62f988b97e2f849d
1 /*
2 Copyright ©2010-2017, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/config.h>
8 #define DEBUG 0
9 #include <aros/debug.h>
11 #include <proto/utility.h>
12 #include <proto/intuition.h>
13 #include <proto/muimaster.h>
14 #include <proto/task.h>
15 #include <proto/dos.h>
17 #include <exec/execbase.h>
18 #include <exec/rawfmt.h>
20 #include <libraries/mui.h>
21 #include <resources/task.h>
23 #include "locale.h"
25 #include "tasks.h"
27 #define DLIST(x)
29 /* uncomment the following line to force full-refresh */
30 //#define TASKLIST_FLUSHUPDATE
31 /* uncomment the following line to prevent updating */
32 //#define TASKLIST_NOTIMER
34 /* Task information handling*/
35 struct TaskInfo
37 struct Node ti_Node;
38 struct Task *ti_Task;
39 #if defined(__AROSPLATFORM_SMP__)
40 cpuid_t ti_CPU;
41 #endif
42 struct timeval ti_TimeCurrent;
43 struct timeval ti_TimeLast;
44 ULONG ti_CPUUsage;
45 ULONG ti_Flags;
48 #define TIF_ENABLED (1 << 0)
49 #define TIF_VALID (1 << 1)
51 struct Tasklist_DATA
53 APTR tld_taskresBase;
55 struct MUI_EventHandlerNode tld_InputEvent;
56 struct MUI_InputHandlerNode tld_TimerEvent;
58 struct Hook tld_ConstructHook;
59 struct Hook tld_DestructHook;
60 struct Hook tld_DisplayHook;
61 struct Hook tld_CompareHook;
63 #ifdef TASKLIST_FLUSHUPDATE
64 struct Hook tld_SelectedHook;
65 struct Task *tld_TaskSelected;
66 #endif
67 struct List tld_TaskList;
69 ULONG tld_TasksTotal;
71 ULONG tld_TasksWaiting;
72 ULONG tld_TasksReady;
73 ULONG tld_TaskTotalRuntime;
75 STRPTR msg_task;
76 STRPTR msg_process;
77 STRPTR msg_task_name;
78 STRPTR msg_task_priority;
79 STRPTR msg_task_type;
80 STRPTR msg_task_tombstoned;
81 STRPTR msg_task_unknown;
83 #if defined(__AROSPLATFORM_SMP__)
84 TEXT tld_BufCPU[5];
85 #endif
86 TEXT tld_BufUsage[10];
87 TEXT tld_BufTime[20];
88 TEXT tld_BufName[100];
89 TEXT tld_BufType[20];
90 TEXT tld_BufPrio[20];
91 TEXT tld_BufSortCol[20];
92 ULONG tasklistSortColumn;
93 ULONG tasklistSortMode;
94 ULONG updateSpeed;
97 #define SETUP_TASKLIST_INST_DATA struct Tasklist_DATA *data = INST_DATA(CLASS, self)
98 #define TaskResBase data->tld_taskresBase
100 CONST_STRPTR badstr_tmpl = " " MUIX_PH MUIX_B "%s";
101 CONST_STRPTR badval_tmpl = MUIX_PH MUIX_B "%d ";
103 static inline int refreshRetVal(int val, int a, int b)
105 if ((val < 0) || (a == b))
106 return -1;
107 return 1;
110 int Tasklist__Refresh(struct Tasklist_DATA *data, struct TaskInfo *ti, int col)
112 struct TagItem QueryTaskTags[] =
114 {TaskTag_CPUTime, 0 },
115 {TaskTag_CPUUsage, 0 },
116 #if defined(__AROSPLATFORM_SMP__)
117 {TaskTag_CPUNumber, 0 },
118 #endif
119 {TAG_DONE, 0 }
121 #if defined(__AROSPLATFORM_SMP__)
122 IPTR cpuNum;
123 #endif
124 int retVal = 0, startcol = 1;
125 ULONG cpuusage = 0;
127 /* Cache values we need incase something happens to the task .. */
128 ti->ti_TimeLast.tv_secs = ti->ti_TimeCurrent.tv_secs;
129 QueryTaskTags[0].ti_Data = (IPTR)&ti->ti_TimeCurrent;
130 QueryTaskTags[1].ti_Data = (IPTR)&cpuusage;
131 #if defined(__AROSPLATFORM_SMP__)
132 QueryTaskTags[2].ti_Data = (IPTR)&cpuNum;
133 #endif
135 if (ti->ti_Task)
137 switch (ti->ti_Task->tc_State)
139 case TS_RUN:
140 case TS_READY:
141 case TS_SPIN:
142 case TS_WAIT:
143 QueryTaskTagList(ti->ti_Task, QueryTaskTags);
144 cpuusage = ((cpuusage >> 16) * 10000) >> 16;
145 #if defined(__AROSPLATFORM_SMP__)
146 if (ti->ti_CPU != (cpuid_t)cpuNum)
147 retVal = refreshRetVal(retVal, col, startcol);
148 ti->ti_CPU = (cpuid_t)cpuNum;
149 startcol++;
150 #endif
152 if (ti->ti_CPUUsage != cpuusage)
153 retVal = refreshRetVal(retVal, col, startcol);
154 ti->ti_CPUUsage = cpuusage;
155 startcol++;
157 if (ti->ti_TimeLast.tv_secs != ti->ti_TimeCurrent.tv_secs)
158 retVal = refreshRetVal(retVal, col, startcol);
159 startcol++;
161 if (ti->ti_Node.ln_Pri != ti->ti_Task->tc_Node.ln_Pri)
162 retVal = refreshRetVal(retVal, col, startcol);
163 ti->ti_Node.ln_Pri = ti->ti_Task->tc_Node.ln_Pri;
164 startcol++;
166 if (ti->ti_Node.ln_Type != ti->ti_Task->tc_Node.ln_Type)
167 retVal = refreshRetVal(retVal, col, startcol);
168 ti->ti_Node.ln_Type = ti->ti_Task->tc_Node.ln_Type;
170 if (!(ti->ti_Flags & TIF_ENABLED))
171 retVal = refreshRetVal(retVal, 1, 0);
172 ti->ti_Flags |= TIF_ENABLED;
174 break;
176 default:
177 if (!(ti->ti_Flags & TIF_ENABLED))
178 retVal = refreshRetVal(retVal, 1, 0);
179 ti->ti_Flags &= ~TIF_ENABLED;
180 break;
183 return retVal;
186 #ifndef TASKLIST_FLUSHUPDATE
187 IPTR Tasklist__DeleteTaskEntry(Class *CLASS, Object *self, struct TaskInfo *ti)
189 int i;
191 for (i=0;;i++)
193 struct TaskInfo *le_ti = NULL;
195 DoMethod(self, MUIM_List_GetEntry, i, &le_ti);
196 if (!le_ti) break;
198 if (ti == le_ti)
200 D(bug("[SysMon:TaskList] deleting entry ...\n"));
201 DoMethod(self, MUIM_List_Remove, i);
202 break;
205 return (IPTR)NULL;
207 #endif
209 AROS_UFH3(struct TaskInfo *, TasksListConstructFunction,
210 AROS_UFHA(struct Hook *, h, A0),
211 AROS_UFHA(APTR, pool, A2),
212 AROS_UFHA(struct Task *, curTask, A1))
214 AROS_USERFUNC_INIT
216 struct Tasklist_DATA *data = h->h_Data;
217 struct TaskInfo *ti = NULL;
219 DLIST(bug("[SysMon:TaskList] %s()\n", __func__));
221 if ((ti = AllocVecPooled(pool, sizeof(struct TaskInfo))) != NULL)
223 ti->ti_Task = curTask;
224 ti->ti_Flags = 0;
226 Tasklist__Refresh(data, ti, data->tasklistSortColumn);
228 switch (curTask->tc_State)
230 case TS_REMOVED:
231 ti->ti_Node.ln_Name = StrDup(data->msg_task_tombstoned);
232 break;
233 case TS_RUN:
234 case TS_READY:
235 case TS_SPIN:
236 case TS_WAIT:
237 ti->ti_Flags |= TIF_VALID;
238 if (curTask->tc_Node.ln_Name)
240 ti->ti_Node.ln_Name = StrDup(curTask->tc_Node.ln_Name);
241 break;
243 default:
244 ti->ti_Node.ln_Name = StrDup(data->msg_task_unknown);
245 break;
248 data->tld_TasksTotal++;
249 AddTail(&data->tld_TaskList, &ti->ti_Node);
251 return ti;
253 AROS_USERFUNC_EXIT
256 AROS_UFH3(VOID, TasksListDestructFunction,
257 AROS_UFHA(struct Hook *, h, A0),
258 AROS_UFHA(APTR, pool, A2),
259 AROS_UFHA(struct TaskInfo *, ti, A1))
261 AROS_USERFUNC_INIT
263 struct Tasklist_DATA *data = h->h_Data;
265 DLIST(bug("[SysMon:TaskList] %s()\n", __func__));
267 Remove(&ti->ti_Node);
268 data->tld_TasksTotal--;
270 FreeVec(ti->ti_Node.ln_Name);
271 FreeVecPooled(pool, ti);
273 AROS_USERFUNC_EXIT
276 #ifdef TASKLIST_FLUSHUPDATE
277 AROS_UFH3(VOID, TaskSelectedFunction,
278 AROS_UFHA(struct Hook *, h, A0),
279 AROS_UFHA(Object *, obj, A2),
280 AROS_UFHA(APTR, msg, A1))
282 AROS_USERFUNC_INIT
284 struct Tasklist_DATA *data = h->h_Data;
285 struct TaskInfo *ti = NULL;
287 DoMethod(obj, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &ti);
288 DLIST(bug("[SysMon:TaskList] ti @ 0x%p\n", ti);)
290 if (ti != NULL)
292 data->tld_TaskSelected = ti->ti_Task;
294 else
295 data->tld_TaskSelected = NULL;
297 AROS_USERFUNC_EXIT
299 #endif
301 AROS_UFH3(LONG, TaskCompareFunction,
302 AROS_UFHA(struct Hook *, h, A0),
303 AROS_UFHA(struct TaskInfo *, ti2, A2),
304 AROS_UFHA(struct TaskInfo *, ti1, A1))
306 AROS_USERFUNC_INIT
308 struct Tasklist_DATA *data = h->h_Data;
309 LONG retval;
311 DLIST(bug("[SysMon:TaskList] %s()\n", __func__));
313 switch (data->tasklistSortColumn)
315 #if defined(__AROSPLATFORM_SMP__)
316 #define COLUMNOFFSET 1
317 case 1:
318 if (!data->tasklistSortMode)
320 retval = (LONG)(ti2->ti_CPU - ti1->ti_CPU);
321 if (retval == 0)
323 retval = (LONG)(stricmp(ti1->ti_Node.ln_Name, ti2->ti_Node.ln_Name));
326 else
328 retval = (LONG)(ti1->ti_CPU - ti2->ti_CPU);
329 if (retval == 0)
331 retval = (LONG)(stricmp(ti2->ti_Node.ln_Name, ti1->ti_Node.ln_Name));
334 break;
335 #else
336 #define COLUMNOFFSET 0
337 #endif
338 case (COLUMNOFFSET + 1):
339 if (!data->tasklistSortMode)
341 retval = (LONG)(ti2->ti_CPUUsage - ti1->ti_CPUUsage);
342 if (retval == 0)
344 retval = (LONG)(ti2->ti_TimeCurrent.tv_usec - ti1->ti_TimeCurrent.tv_usec);
345 if (retval == 0)
346 retval = (LONG)(stricmp(ti1->ti_Node.ln_Name, ti2->ti_Node.ln_Name));
349 else
351 retval = (LONG)(ti1->ti_CPUUsage - ti2->ti_CPUUsage);
352 if (retval == 0)
354 retval = (LONG)(ti1->ti_TimeCurrent.tv_usec - ti2->ti_TimeCurrent.tv_usec);
355 if (retval == 0)
356 retval = (LONG)(stricmp(ti2->ti_Node.ln_Name, ti1->ti_Node.ln_Name));
359 break;
362 case (COLUMNOFFSET + 2):
363 if (!data->tasklistSortMode)
365 retval = (LONG)(ti2->ti_TimeCurrent.tv_secs - ti1->ti_TimeCurrent.tv_secs);
366 if (retval == 0)
368 retval = (LONG)(ti2->ti_TimeCurrent.tv_usec - ti1->ti_TimeCurrent.tv_usec);
369 if (retval == 0)
370 retval = (LONG)(stricmp(ti1->ti_Node.ln_Name, ti2->ti_Node.ln_Name));
373 else
375 retval = (LONG)(ti1->ti_TimeCurrent.tv_secs - ti2->ti_TimeCurrent.tv_secs);
376 if (retval == 0)
378 retval = (LONG)(ti1->ti_TimeCurrent.tv_usec - ti2->ti_TimeCurrent.tv_usec);
379 if (retval == 0)
380 retval = (LONG)(stricmp(ti2->ti_Node.ln_Name, ti1->ti_Node.ln_Name));
383 break;
385 case (COLUMNOFFSET + 3):
386 if (!data->tasklistSortMode)
388 retval = (LONG)(ti2->ti_Node.ln_Pri - ti1->ti_Node.ln_Pri);
389 if (retval == 0)
391 retval = (LONG)(stricmp(ti1->ti_Node.ln_Name, ti2->ti_Node.ln_Name));
394 else
396 retval = (LONG)(ti1->ti_Node.ln_Pri - ti2->ti_Node.ln_Pri);
397 if (retval == 0)
399 retval = (LONG)(stricmp(ti2->ti_Node.ln_Name, ti1->ti_Node.ln_Name));
402 break;
403 case (COLUMNOFFSET + 4):
404 if (!data->tasklistSortMode)
406 retval = (LONG)(ti1->ti_Node.ln_Type - ti2->ti_Node.ln_Type);
407 if (retval == 0)
409 retval = (LONG)(stricmp(ti1->ti_Node.ln_Name, ti2->ti_Node.ln_Name));
412 else
414 retval = (LONG)(ti2->ti_Node.ln_Type - ti1->ti_Node.ln_Type);
415 if (retval == 0)
417 retval = (LONG)(stricmp(ti2->ti_Node.ln_Name, ti1->ti_Node.ln_Name));
420 break;
421 default:
422 if (!data->tasklistSortMode)
423 retval = (LONG)(stricmp(ti1->ti_Node.ln_Name, ti2->ti_Node.ln_Name));
424 else
425 retval = (LONG)(stricmp(ti2->ti_Node.ln_Name, ti1->ti_Node.ln_Name));
426 break;
429 return retval;
431 AROS_USERFUNC_EXIT
434 AROS_UFH3(APTR, TasksListDisplayFunction,
435 AROS_UFHA(struct Hook *, h, A0),
436 AROS_UFHA(STRPTR *, strings, A2),
437 AROS_UFHA(struct TaskInfo *, ti, A1))
439 AROS_USERFUNC_INIT
441 struct Tasklist_DATA *data = h->h_Data;
442 IPTR fmtdata[] =
450 char *type;
451 int col= 0;
453 DLIST(bug("[SysMon:TaskList] %s()\n", __func__));
455 if (ti)
457 type = (ti->ti_Node.ln_Type == NT_TASK) ? data->msg_task : data->msg_process;
459 if (!(ti->ti_Flags & TIF_VALID))
461 fmtdata[0] = (IPTR)ti->ti_Node.ln_Name;
462 RawDoFmt(badstr_tmpl, (RAWARG)&fmtdata, RAWFMTFUNC_STRING, data->tld_BufName);
463 fmtdata[0] = (IPTR)ti->ti_Node.ln_Pri;
464 RawDoFmt(badval_tmpl, (RAWARG)&fmtdata, RAWFMTFUNC_STRING, data->tld_BufPrio);
465 fmtdata[0] = (IPTR)type;
466 RawDoFmt(badstr_tmpl, (RAWARG)&fmtdata, RAWFMTFUNC_STRING, data->tld_BufType);
467 strings[col++] = data->tld_BufName;
468 #if defined(__AROSPLATFORM_SMP__)
469 strings[col++] = "---";
470 strings[col++] = "---.--.--";
471 #endif
472 strings[col++] = data->tld_BufPrio;
473 strings[col++] = data->tld_BufType;
475 else
477 fmtdata[0] = (IPTR)ti->ti_Node.ln_Pri;
478 RawDoFmt("%id ", (RAWARG)&fmtdata, RAWFMTFUNC_STRING, data->tld_BufPrio);
479 strings[col++] = ti->ti_Node.ln_Name;
480 #if defined(__AROSPLATFORM_SMP__)
481 fmtdata[0] = (IPTR)ti->ti_CPU;
482 RawDoFmt("%03iu ", (RAWARG)&fmtdata, RAWFMTFUNC_STRING, data->tld_BufCPU);
483 strings[col++] = data->tld_BufCPU;
484 #endif
485 fmtdata[0] = (IPTR)ti->ti_CPUUsage / 100;
486 fmtdata[1] = (IPTR)ti->ti_CPUUsage % 100;
487 RawDoFmt("%3id.%02id%% ", (RAWARG)&fmtdata, RAWFMTFUNC_STRING, data->tld_BufUsage);
488 strings[col++] = data->tld_BufUsage;
490 fmtdata[0] = (IPTR)(ti->ti_TimeCurrent.tv_secs / 60 / 60);
491 fmtdata[1] = (IPTR)((ti->ti_TimeCurrent.tv_secs / 60) % 60);
492 fmtdata[2] = (IPTR)(ti->ti_TimeCurrent.tv_secs % 60);
493 fmtdata[3] = (IPTR)((ti->ti_TimeCurrent.tv_usec + 500) / 10000);
494 RawDoFmt("%3id:%02id:%02id.%02id", (RAWARG)&fmtdata, RAWFMTFUNC_STRING, data->tld_BufTime);
495 strings[col++] = data->tld_BufTime;
496 strings[col++] = data->tld_BufPrio;
497 strings[col++] = type;
500 else
502 char *dir;
504 if (data->tasklistSortMode == 0)
505 dir = "+";
506 else
507 dir = "-";
509 fmtdata[1] = (IPTR)dir;
510 if (data->tasklistSortColumn == col)
512 fmtdata[0] = (IPTR)data->msg_task_name;
513 RawDoFmt(MUIX_B "%s %s", (RAWARG)&fmtdata, RAWFMTFUNC_STRING, data->tld_BufSortCol);
514 strings[col++] = data->tld_BufSortCol;
516 else
517 strings[col++] = data->msg_task_name;
519 #if defined(__AROSPLATFORM_SMP__)
520 if (data->tasklistSortColumn == col)
522 fmtdata[0] = (IPTR)"CPU";
523 RawDoFmt(MUIX_B "%s %s", (RAWARG)&fmtdata, RAWFMTFUNC_STRING, data->tld_BufSortCol);
524 strings[col++] = data->tld_BufSortCol;
526 else
527 strings[col++] = "CPU";
528 #endif
530 if (data->tasklistSortColumn == col)
532 fmtdata[0] = (IPTR)"CPU %";
533 RawDoFmt(MUIX_B "%s %s", (RAWARG)&fmtdata, RAWFMTFUNC_STRING, data->tld_BufSortCol);
534 strings[col++] = data->tld_BufSortCol;
536 else
537 strings[col++] = "CPU %";
539 if (data->tasklistSortColumn == col)
541 fmtdata[0] = (IPTR)"CPU Time";
542 RawDoFmt(MUIX_B "%s %s", (RAWARG)&fmtdata, RAWFMTFUNC_STRING, data->tld_BufSortCol);
543 strings[col++] = data->tld_BufSortCol;
545 else
546 strings[col++] = "CPU Time";
548 if (data->tasklistSortColumn == col)
550 fmtdata[0] = (IPTR)data->msg_task_priority;
551 RawDoFmt(MUIX_B "%s %s", (RAWARG)&fmtdata, RAWFMTFUNC_STRING, data->tld_BufSortCol);
552 strings[col++] = data->tld_BufSortCol;
554 else
555 strings[col++] = data->msg_task_priority;
557 if (data->tasklistSortColumn == col)
559 fmtdata[0] = (IPTR)data->msg_task_type;
560 RawDoFmt(MUIX_B "%s %s", (RAWARG)&fmtdata, RAWFMTFUNC_STRING, data->tld_BufSortCol);
561 strings[col++] = data->tld_BufSortCol;
563 else
564 strings[col++] = data->msg_task_type;
567 return NULL;
569 AROS_USERFUNC_EXIT
572 Object *Tasklist__OM_NEW(Class *CLASS, Object *self, struct opSet *message)
574 D(bug("[SysMon:TaskList] %s()\n", __func__));
576 self = (Object *) DoSuperNewTags(CLASS, self, NULL,
577 ReadListFrame,
578 MUIA_List_Format,
579 #if !defined(__AROSPLATFORM_SMP__)
580 "MIW=50 BAR,BAR,BAR,BAR P=\033r,",
581 #else
582 "MIW=50 BAR,BAR,BAR,BAR,BAR P=\033r,",
583 #endif
584 MUIA_List_Title, (IPTR)TRUE,
585 TAG_MORE, (IPTR) message->ops_AttrList
588 if (self != NULL)
590 SETUP_TASKLIST_INST_DATA;
592 data->tld_taskresBase = OpenResource("task.resource");
593 if (data->tld_taskresBase)
595 NewList(&data->tld_TaskList);
597 data->updateSpeed = (ULONG)GetTagData(MUIA_Tasklist_RefreshMSecs, MUIV_Tasklist_Refresh_Normal, message->ops_AttrList);
599 data->tld_TaskTotalRuntime = 0;
600 data->tasklistSortColumn = 1;
602 data->msg_task = (STRPTR)_(MSG_TASK);
603 data->msg_process = (STRPTR)_(MSG_PROCESS);
604 data->msg_task_name = (STRPTR)_(MSG_TASK_NAME);
605 data->msg_task_priority = (STRPTR)_(MSG_TASK_PRIORITY);
606 data->msg_task_type = (STRPTR)_(MSG_TASK_TYPE);
607 data->msg_task_tombstoned = (STRPTR)_(MSG_TASK_TOMBSTONE);
608 data->msg_task_unknown = (STRPTR)_(MSG_TASK_UNKNOWN);
610 data->tld_ConstructHook.h_Entry = (APTR)TasksListConstructFunction;
611 data->tld_ConstructHook.h_Data = (APTR)data;
612 data->tld_DestructHook.h_Entry = (APTR)TasksListDestructFunction;
613 data->tld_DestructHook.h_Data = (APTR)data;
614 data->tld_DisplayHook.h_Entry = (APTR)TasksListDisplayFunction;
615 data->tld_DisplayHook.h_Data = (APTR)data;
616 data->tld_CompareHook.h_Entry = (APTR)TaskCompareFunction;
617 data->tld_CompareHook.h_Data = (APTR)data;
619 SET(self, MUIA_List_ConstructHook, &data->tld_ConstructHook);
620 SET(self, MUIA_List_DestructHook, &data->tld_DestructHook);
621 SET(self, MUIA_List_DisplayHook, &data->tld_DisplayHook);
622 SET(self, MUIA_List_CompareHook, &data->tld_CompareHook);
624 #ifdef TASKLIST_FLUSHUPDATE
625 data->tld_TaskSelected = NULL;
626 data->tld_SelectedHook.h_Entry = (APTR)TaskSelectedFunction;
627 data->tld_SelectedHook.h_Data = (APTR)data;
628 DoMethod(self, MUIM_Notify, MUIA_List_Active, MUIV_EveryTime,
629 self, 2, MUIM_CallHook, (IPTR)&data->tld_SelectedHook);
630 #endif
632 else
634 FPuts(Output(), (STRPTR)_(MSG_CANT_OPEN_TASK_RESOURCE));
636 CoerceMethod(CLASS, self, OM_DISPOSE);
638 self = NULL;
642 return self;
645 IPTR Tasklist__OM_DISPOSE(Class *CLASS, Object *self, Msg message)
647 D(bug("[SysMon:TaskList] %s()\n", __func__));
649 return DoSuperMethodA(CLASS, self, message);
652 IPTR Tasklist__OM_SET(Class *CLASS, Object *self, struct opSet *message)
654 SETUP_TASKLIST_INST_DATA;
655 struct TagItem *tstate = message->ops_AttrList, *tag;
657 D(bug("[SysMon:TaskList] %s()\n", __func__));
659 while ((tag = NextTagItem((struct TagItem **)&tstate)) != NULL)
661 switch (tag->ti_Tag)
663 case MUIA_Tasklist_RefreshMSecs:
664 data->updateSpeed = (ULONG)tag->ti_Data;
665 #ifndef TASKLIST_NOTIMER
666 if (data->tld_TimerEvent.ihn_Method != 0)
668 DoMethod(_app(self), MUIM_Application_RemInputHandler, (IPTR) &data->tld_TimerEvent);
669 data->tld_TimerEvent.ihn_Millis = data->updateSpeed;
670 DoMethod(_app(self), MUIM_Application_AddInputHandler, (IPTR) &data->tld_TimerEvent);
672 #endif
673 break;
674 case MUIA_Tasklist_Refreshed:
675 break;
678 return DoSuperMethodA(CLASS, self, (Msg) message);
681 IPTR Tasklist__OM_GET(Class *CLASS, Object *self, struct opGet *message)
683 SETUP_TASKLIST_INST_DATA;
684 IPTR *store = message->opg_Storage;
685 IPTR retval = 0;
687 D(bug("[SysMon:TaskList] %s()\n", __func__));
689 switch (message->opg_AttrID)
691 case MUIA_Tasklist_Refreshed:
692 *store = (IPTR)TRUE;
693 retval = 1;
694 break;
695 case MUIA_Tasklist_RefreshMSecs:
696 *store = (IPTR)data->updateSpeed;
697 retval = 1;
698 break;
699 case MUIA_Tasklist_ReadyCount:
700 *store = (IPTR)data->tld_TasksReady;
701 retval = 1;
702 break;
703 case MUIA_Tasklist_WaitingCount:
704 *store = (IPTR)data->tld_TasksWaiting;
705 retval = 1;
706 break;
709 if (!retval)
710 retval = DoSuperMethodA(CLASS, self, (Msg) message);
712 return retval;
715 IPTR Tasklist__MUIM_Show(Class *CLASS, Object *self, struct MUIP_Show *message)
717 IPTR retval;
719 SETUP_TASKLIST_INST_DATA;
721 D(bug("[SysMon:TaskList] %s()\n", __func__));
723 retval = DoSuperMethodA(CLASS, self, (Msg) message);
725 data->tld_InputEvent.ehn_Events = IDCMP_MOUSEBUTTONS;
726 data->tld_InputEvent.ehn_Priority = 10;
727 data->tld_InputEvent.ehn_Flags = 0;
728 data->tld_InputEvent.ehn_Object = self;
729 data->tld_InputEvent.ehn_Class = CLASS;
730 DoMethod(_win(self), MUIM_Window_AddEventHandler, (IPTR)&data->tld_InputEvent);
732 #ifndef TASKLIST_NOTIMER
733 data->tld_TimerEvent.ihn_Flags = MUIIHNF_TIMER;
734 data->tld_TimerEvent.ihn_Millis = data->updateSpeed;
735 data->tld_TimerEvent.ihn_Object = self;
736 data->tld_TimerEvent.ihn_Method = MUIM_Tasklist_HandleTimer;
738 DoMethod( _app(self), MUIM_Application_AddInputHandler, (IPTR) &data->tld_TimerEvent);
739 #endif
741 DoMethod(self, MUIM_Tasklist_Refresh);
743 return retval;
746 IPTR Tasklist__MUIM_Hide(Class *CLASS, Object *self, struct MUIP_Hide *message)
748 SETUP_TASKLIST_INST_DATA;
750 D(bug("[SysMon:TaskList] %s()\n", __func__));
752 #ifndef TASKLIST_NOTIMER
753 DoMethod(_app(self), MUIM_Application_RemInputHandler, (IPTR) &data->tld_TimerEvent);
754 data->tld_TimerEvent.ihn_Method = 0;
755 #endif
757 DoMethod(_win(self), MUIM_Window_RemEventHandler, (IPTR)&data->tld_InputEvent);
759 return DoSuperMethodA(CLASS, self, (Msg) message);
762 IPTR Tasklist__MUIM_HandleEvent(Class *CLASS, Object *self, struct MUIP_HandleEvent *message)
764 SETUP_TASKLIST_INST_DATA;
765 struct MUI_List_TestPos_Result selectres;
767 D(bug("[SysMon:TaskList] %s()\n", __func__));
769 if ((message->imsg->MouseX > _mleft(self)) &&
770 (message->imsg->MouseY > _mtop(self)) &&
771 (message->imsg->MouseX < _mright(self)) &&
772 (message->imsg->MouseY < _mbottom(self)))
774 if ((message->imsg) && (message->imsg->Class == IDCMP_MOUSEBUTTONS))
776 if (message->imsg->Code == SELECTUP)
778 D(bug("[SysMon:TaskList] %s: Click @ %d, %d\n", __func__, message->imsg->MouseX, message->imsg->MouseY));
779 DoMethod(self, MUIM_List_TestPos, message->imsg->MouseX, message->imsg->MouseY, &selectres);
780 if ((selectres.entry == -1) && (selectres.column != -1) && (message->imsg->MouseY < (_mtop(self) + _font(self)->tf_YSize + 4)))
782 if (data->tasklistSortColumn == selectres.column)
783 data->tasklistSortMode = ~data->tasklistSortMode;
784 else
785 data->tasklistSortMode = 0;
786 data->tasklistSortColumn = selectres.column;
787 SET(self, MUIA_List_Quiet, TRUE);
788 DoMethod(self, MUIM_List_Sort);
789 DoMethod(self, MUIM_List_Redraw, MUIV_List_Redraw_All);
790 SET(self, MUIA_List_Quiet, FALSE);
796 return DoSuperMethodA(CLASS, self, (Msg) message);
799 IPTR Tasklist__MUIM_Tasklist_Refresh(Class *CLASS, Object *self, Msg message)
801 SETUP_TASKLIST_INST_DATA;
803 D(bug("[SysMon:TaskList] %s()\n", __func__));
805 struct TaskList *systasklist;
806 struct Task * task;
807 #ifndef TASKLIST_FLUSHUPDATE
808 struct TaskInfo *ti = NULL, *titmp;
809 #else
810 struct Task *selected = data->tld_TaskSelected;
811 IPTR firstvis = 0;
812 IPTR entryid = 0;
813 #endif
814 BOOL doSort = FALSE;
816 SET(self, MUIA_List_Quiet, TRUE);
818 #ifdef TASKLIST_FLUSHUPDATE
819 get(self, MUIA_List_First, &firstvis);
820 DoMethod(self, MUIM_List_Clear);
821 #else
822 ForeachNode(&data->tld_TaskList, ti)
824 ti->ti_Flags &= ~TIF_ENABLED;
826 #endif
828 data->tld_TasksWaiting = 0;
829 data->tld_TasksReady = 0;
830 data->tld_TaskTotalRuntime = 0;
832 systasklist = LockTaskList(LTF_ALL);
833 while ((task = NextTaskEntry(systasklist, LTF_ALL)) != NULL)
835 D(bug("[SysMon:TaskList] task %s state %d\n", task->tc_Node.ln_Name, task->tc_State));
837 if (task->tc_State == TS_READY)
839 data->tld_TasksReady++;
841 if ((task->tc_State == TS_WAIT) || (task->tc_State == TS_SPIN))
843 data->tld_TasksWaiting++;
846 #ifndef TASKLIST_FLUSHUPDATE
847 ti = NULL;
848 ForeachNode(&data->tld_TaskList, ti)
850 if (ti->ti_Task == task)
852 int taskUpdate;
854 D(bug("[SysMon:TaskList] updating entry @ 0x%p\n", ti));
856 if ((taskUpdate = Tasklist__Refresh(data, ti, data->tasklistSortColumn)) != 0)
858 DoMethod(self, MUIM_List_Redraw, MUIV_List_Redraw_Entry, ti);
859 if (taskUpdate < 0)
860 doSort = TRUE;
863 task = NULL;
864 break;
867 #endif
868 if (task)
870 D(bug("[SysMon:TaskList] creating new entry ...\n"));
871 #ifdef TASKLIST_FLUSHUPDATE
872 entryid =
873 #endif
874 DoMethod(self, MUIM_List_InsertSingle, task, MUIV_List_Insert_Sorted);
875 #ifdef TASKLIST_FLUSHUPDATE
876 if (task == selected)
878 SET(self, MUIA_List_Active, entryid);
880 #endif
883 UnLockTaskList(systasklist, LTF_ALL);
885 #ifndef TASKLIST_FLUSHUPDATE
886 ti = NULL;
887 ForeachNodeSafe(&data->tld_TaskList, ti, titmp)
889 if (!(ti->ti_Flags & TIF_ENABLED))
891 Tasklist__DeleteTaskEntry(CLASS, self, ti);
894 #else
895 if (XGET(self, MUIA_List_Active) == 0)
896 data->tld_TaskSelected = NULL;
898 /* Keep the "pre-refresh" view on List as much as possible */
899 LONG v = (LONG)firstvis;
900 if (firstvis + XGET(self, MUIA_List_Visible) >= XGET(self, MUIA_List_Entries))
902 v = XGET(self, MUIA_List_Entries) - XGET(self, MUIA_List_Visible);
903 if (v < 0) v = 0;
906 SET(self, MUIA_List_First, v);
907 #endif
909 if (doSort)
910 DoMethod(self, MUIM_List_Sort);
912 SET(self, MUIA_List_Quiet, FALSE);
913 SET(self, MUIA_Tasklist_Refreshed, TRUE);
915 return (IPTR)TRUE;
918 IPTR Tasklist__MUIM_Tasklist_HandleTimer(Class *CLASS, Object *self, Msg message)
920 D(bug("[SysMon:TaskList] %s()\n", __func__));
922 DoMethod(self, MUIM_Tasklist_Refresh);
924 return (IPTR)FALSE;
927 /*** Setup ******************************************************************/
928 TASKLIST_CUSTOMCLASS
930 Tasklist, NULL, MUIC_List, NULL,
931 OM_NEW, struct opSet *,
932 OM_DISPOSE, Msg,
933 OM_SET, struct opSet *,
934 OM_GET, struct opGet *,
935 MUIM_Show, struct MUIP_Show *,
936 MUIM_Hide, struct MUIP_Hide *,
937 MUIM_HandleEvent, struct MUIP_HandleEvent *,
938 MUIM_Tasklist_Refresh, Msg,
939 MUIM_Tasklist_HandleTimer, Msg