ScreenManager.c 8.73 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1
/*
Hisham Muhammad's avatar
Hisham Muhammad committed
2
htop - ScreenManager.c
Hisham Muhammad's avatar
Hisham Muhammad committed
3
(C) 2004-2011 Hisham H. Muhammad
Hisham Muhammad's avatar
Hisham Muhammad committed
4
5
6
7
8
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/

#include "ScreenManager.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
9
#include "ProcessList.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
10

Hisham Muhammad's avatar
Hisham Muhammad committed
11
#include "Object.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
12

Hisham Muhammad's avatar
Hisham Muhammad committed
13
#include <assert.h>
14
#include <time.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
15
#include <stdlib.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
16
17
18
#include <stdbool.h>

/*{
Hisham Muhammad's avatar
Hisham Muhammad committed
19
20
21
#include "FunctionBar.h"
#include "Vector.h"
#include "Header.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
22
23
#include "Settings.h"
#include "Panel.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
24
25
26
27
28
29
30
31
32
33
34
35

typedef enum Orientation_ {
   VERTICAL,
   HORIZONTAL
} Orientation;

typedef struct ScreenManager_ {
   int x1;
   int y1;
   int x2;
   int y2;
   Orientation orientation;
36
   Vector* panels;
37
   Vector* fuBars;
38
   int panelCount;
39
40
   const FunctionBar* fuBar;
   const Header* header;
Hisham Muhammad's avatar
Hisham Muhammad committed
41
   const Settings* settings;
Hisham Muhammad's avatar
Hisham Muhammad committed
42
   bool owner;
43
   bool allowFocusChange;
Hisham Muhammad's avatar
Hisham Muhammad committed
44
45
46
47
} ScreenManager;

}*/

Hisham Muhammad's avatar
Hisham Muhammad committed
48
ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation orientation, const Header* header, const Settings* settings, bool owner) {
Hisham Muhammad's avatar
Hisham Muhammad committed
49
50
51
52
53
54
55
56
   ScreenManager* this;
   this = malloc(sizeof(ScreenManager));
   this->x1 = x1;
   this->y1 = y1;
   this->x2 = x2;
   this->y2 = y2;
   this->fuBar = NULL;
   this->orientation = orientation;
57
58
   this->panels = Vector_new(Class(Panel), owner, DEFAULT_SIZE);
   this->fuBars = Vector_new(Class(FunctionBar), true, DEFAULT_SIZE);
59
   this->panelCount = 0;
60
   this->header = header;
Hisham Muhammad's avatar
Hisham Muhammad committed
61
   this->settings = settings;
Hisham Muhammad's avatar
Hisham Muhammad committed
62
   this->owner = owner;
63
   this->allowFocusChange = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
64
65
66
67
   return this;
}

void ScreenManager_delete(ScreenManager* this) {
68
   Vector_delete(this->panels);
69
   Vector_delete(this->fuBars);
Hisham Muhammad's avatar
Hisham Muhammad committed
70
71
72
73
   free(this);
}

inline int ScreenManager_size(ScreenManager* this) {
74
   return this->panelCount;
Hisham Muhammad's avatar
Hisham Muhammad committed
75
76
}

77
void ScreenManager_add(ScreenManager* this, Panel* item, FunctionBar* fuBar, int size) {
Hisham Muhammad's avatar
Hisham Muhammad committed
78
79
   if (this->orientation == HORIZONTAL) {
      int lastX = 0;
80
81
      if (this->panelCount > 0) {
         Panel* last = (Panel*) Vector_get(this->panels, this->panelCount - 1);
Hisham Muhammad's avatar
Hisham Muhammad committed
82
83
         lastX = last->x + last->w + 1;
      }
84
      int height = LINES - this->y1 + this->y2;
Hisham Muhammad's avatar
Hisham Muhammad committed
85
      if (size > 0) {
86
         Panel_resize(item, size, height);
Hisham Muhammad's avatar
Hisham Muhammad committed
87
      } else {
88
         Panel_resize(item, COLS-this->x1+this->x2-lastX, height);
Hisham Muhammad's avatar
Hisham Muhammad committed
89
      }
90
      Panel_move(item, lastX, this->y1);
Hisham Muhammad's avatar
Hisham Muhammad committed
91
92
   }
   // TODO: VERTICAL
93
   Vector_add(this->panels, item);
Hisham Muhammad's avatar
Hisham Muhammad committed
94
   if (fuBar)
95
      Vector_add(this->fuBars, fuBar);
Hisham Muhammad's avatar
Hisham Muhammad committed
96
   else
Hisham Muhammad's avatar
Hisham Muhammad committed
97
      Vector_add(this->fuBars, FunctionBar_new(NULL, NULL, NULL));
Hisham Muhammad's avatar
Hisham Muhammad committed
98
99
   if (!this->fuBar && fuBar) this->fuBar = fuBar;
   item->needsRedraw = true;
100
   this->panelCount++;
Hisham Muhammad's avatar
Hisham Muhammad committed
101
102
}

Hisham Muhammad's avatar
Hisham Muhammad committed
103
Panel* ScreenManager_remove(ScreenManager* this, int idx) {
104
105
   assert(this->panelCount > idx);
   Panel* panel = (Panel*) Vector_remove(this->panels, idx);
Hisham Muhammad's avatar
Hisham Muhammad committed
106
   Vector_remove(this->fuBars, idx);
Hisham Muhammad's avatar
Hisham Muhammad committed
107
   this->fuBar = NULL;
108
   this->panelCount--;
Hisham Muhammad's avatar
Hisham Muhammad committed
109
   return panel;
Hisham Muhammad's avatar
Hisham Muhammad committed
110
111
112
113
114
115
116
}

void ScreenManager_resize(ScreenManager* this, int x1, int y1, int x2, int y2) {
   this->x1 = x1;
   this->y1 = y1;
   this->x2 = x2;
   this->y2 = y2;
117
   int panels = this->panelCount;
118
119
120
121
122
123
124
125
126
127
   if (this->orientation == HORIZONTAL) {
      int lastX = 0;
      for (int i = 0; i < panels - 1; i++) {
         Panel* panel = (Panel*) Vector_get(this->panels, i);
         Panel_resize(panel, panel->w, LINES-y1+y2);
         Panel_move(panel, lastX, y1);
         lastX = panel->x + panel->w + 1;
      }
      Panel* panel = (Panel*) Vector_get(this->panels, panels-1);
      Panel_resize(panel, COLS-x1+x2-lastX, LINES-y1+y2);
Hisham Muhammad's avatar
Hisham Muhammad committed
128
      Panel_move(panel, lastX, y1);
Hisham Muhammad's avatar
Hisham Muhammad committed
129
   }
130
   // TODO: VERTICAL
Hisham Muhammad's avatar
Hisham Muhammad committed
131
132
}

133
void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
Hisham Muhammad's avatar
Hisham Muhammad committed
134
135
   bool quit = false;
   int focus = 0;
136
   
137
   Panel* panelFocus = (Panel*) Vector_get(this->panels, focus);
Hisham Muhammad's avatar
Hisham Muhammad committed
138
139
   if (this->fuBar)
      FunctionBar_draw(this->fuBar, NULL);
140

Hisham Muhammad's avatar
Hisham Muhammad committed
141
142
143
144
145
146
147
148
149
150
151
152
153
   struct timeval tv;
   double oldTime = 0.0;

   int ch = ERR;
   int closeTimeout = 0;

   bool drawPanel = true;
   bool timeToRecalculate = true;
   bool doRefresh = true;
   bool forceRecalculate = false;
   int sortTimeout = 0;
   int resetSortTimeout = 5;

Hisham Muhammad's avatar
Hisham Muhammad committed
154
   while (!quit) {
155
      int panels = this->panelCount;
156
      if (this->header) {
Hisham Muhammad's avatar
Hisham Muhammad committed
157
158
159
160
         gettimeofday(&tv, NULL);
         double newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
         timeToRecalculate = (newTime - oldTime > this->settings->delay);
         if (newTime < oldTime) timeToRecalculate = true; // clock was adjusted?
161
//fprintf(stderr, "\n%p %f ", this, newTime);
Hisham Muhammad's avatar
Hisham Muhammad committed
162
163
164
         if (doRefresh) {
            if (timeToRecalculate || forceRecalculate) {
               ProcessList_scan(this->header->pl);
165
//fprintf(stderr, "scan ");
Hisham Muhammad's avatar
Hisham Muhammad committed
166
            }
167
//fprintf(stderr, "sortTo=%d ", sortTimeout);
Hisham Muhammad's avatar
Hisham Muhammad committed
168
169
            if (sortTimeout == 0 || this->settings->treeView) {
               ProcessList_sort(this->header->pl);
170
//fprintf(stderr, "sort ");
Hisham Muhammad's avatar
Hisham Muhammad committed
171
172
173
174
               sortTimeout = 1;
            }
            //this->header->pl->incFilter = IncSet_filter(inc);
            ProcessList_rebuildPanel(this->header->pl);
175
//fprintf(stderr, "rebuild ");
Hisham Muhammad's avatar
Hisham Muhammad committed
176
            drawPanel = true;
177
         }
178
179
180
181
182
183
         if (timeToRecalculate || forceRecalculate) {
            Header_draw(this->header);
//fprintf(stderr, "drawHeader ");
            oldTime = newTime;
            forceRecalculate = false;
         }
Hisham Muhammad's avatar
Hisham Muhammad committed
184
         doRefresh = true;
185
      }
Hisham Muhammad's avatar
Hisham Muhammad committed
186
187
188
189
190
      
      if (drawPanel) {
         for (int i = 0; i < panels; i++) {
            Panel* panel = (Panel*) Vector_get(this->panels, i);
            Panel_draw(panel, i == focus);
191
//fprintf(stderr, "drawPanel ");
Hisham Muhammad's avatar
Hisham Muhammad committed
192
193
194
195
            if (i < panels) {
               if (this->orientation == HORIZONTAL) {
                  mvvline(panel->y, panel->x+panel->w, ' ', panel->h+1);
               }
Hisham Muhammad's avatar
Hisham Muhammad committed
196
197
198
            }
         }
      }
Hisham Muhammad's avatar
Hisham Muhammad committed
199
      
200
      FunctionBar* bar = (FunctionBar*) Vector_get(this->fuBars, focus);
Hisham Muhammad's avatar
Hisham Muhammad committed
201
202
203
204
205
      if (bar)
         this->fuBar = bar;
      if (this->fuBar)
         FunctionBar_draw(this->fuBar, NULL);

Hisham Muhammad's avatar
Hisham Muhammad committed
206
      int prevCh = ch;
Hisham Muhammad's avatar
Hisham Muhammad committed
207
      ch = getch();
208
209

//fprintf(stderr, "ch=%d ", ch);
Hisham Muhammad's avatar
Hisham Muhammad committed
210
211
212
213
214
215
216
217
      
      if (ch == KEY_MOUSE) {
         MEVENT mevent;
         int ok = getmouse(&mevent);
         if (ok == OK) {
            if (mevent.y == LINES - 1) {
               ch = FunctionBar_synthesizeEvent(this->fuBar, mevent.x);
            } else {
218
219
               for (int i = 0; i < this->panelCount; i++) {
                  Panel* panel = (Panel*) Vector_get(this->panels, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
220
                  if (mevent.x > panel->x && mevent.x <= panel->x+panel->w &&
221
222
                     mevent.y > panel->y && mevent.y <= panel->y+panel->h &&
                     (this->allowFocusChange || panelFocus == panel) ) {
Hisham Muhammad's avatar
Hisham Muhammad committed
223
                     focus = i;
Hisham Muhammad's avatar
Hisham Muhammad committed
224
225
                     panelFocus = panel;
                     Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1);
Hisham Muhammad's avatar
Hisham Muhammad committed
226
227
228
229
230
231
                     break;
                  }
               }
            }
         }
      }
232
233
      if (Panel_eventHandlerFn(panelFocus)) {
         HandlerResult result = Panel_eventHandler(panelFocus, ch);
234
//fprintf(stderr, "eventResult=%d ", result);
Hisham Muhammad's avatar
Hisham Muhammad committed
235
236
237
238
239
240
241
242
243
         if (result & REFRESH) {
            doRefresh = true;
            sortTimeout = 0;
         }
         if (result & RECALCULATE) {
            forceRecalculate = true;
            sortTimeout = 0;
         }
         if (result & HANDLED) {
244
            drawPanel = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
245
            continue;
Hisham Muhammad's avatar
Hisham Muhammad committed
246
         } else if (result & BREAK_LOOP) {
Hisham Muhammad's avatar
Hisham Muhammad committed
247
248
249
250
            quit = true;
            continue;
         }
      }
Hisham Muhammad's avatar
Hisham Muhammad committed
251
      if (ch == ERR) {
252
         sortTimeout--;
Hisham Muhammad's avatar
Hisham Muhammad committed
253
254
255
256
257
258
259
260
         if (prevCh == ch && !timeToRecalculate) {
            closeTimeout++;
            if (closeTimeout == 100) {
               break;
            }
         } else
            closeTimeout = 0;
         drawPanel = false;
261
//fprintf(stderr, "err ");
Hisham Muhammad's avatar
Hisham Muhammad committed
262
         continue;
Hisham Muhammad's avatar
Hisham Muhammad committed
263
264
265
266
      }
      drawPanel = true;
      
      switch (ch) {
Hisham Muhammad's avatar
Hisham Muhammad committed
267
268
269
270
271
272
      case KEY_RESIZE:
      {
         ScreenManager_resize(this, this->x1, this->y1, this->x2, this->y2);
         continue;
      }
      case KEY_LEFT:
273
      case KEY_CTRLB:
274
275
         if (!this->allowFocusChange)
            break;
Hisham Muhammad's avatar
Hisham Muhammad committed
276
277
278
         tryLeft:
         if (focus > 0)
            focus--;
279
         panelFocus = (Panel*) Vector_get(this->panels, focus);
Hisham Muhammad's avatar
Hisham Muhammad committed
280
         if (Panel_size(panelFocus) == 0 && focus > 0)
Hisham Muhammad's avatar
Hisham Muhammad committed
281
282
283
            goto tryLeft;
         break;
      case KEY_RIGHT:
284
      case KEY_CTRLF:
Hisham Muhammad's avatar
Hisham Muhammad committed
285
      case 9:
286
287
         if (!this->allowFocusChange)
            break;
Hisham Muhammad's avatar
Hisham Muhammad committed
288
         tryRight:
289
         if (focus < this->panelCount - 1)
Hisham Muhammad's avatar
Hisham Muhammad committed
290
            focus++;
291
292
         panelFocus = (Panel*) Vector_get(this->panels, focus);
         if (Panel_size(panelFocus) == 0 && focus < this->panelCount - 1)
Hisham Muhammad's avatar
Hisham Muhammad committed
293
294
295
296
297
298
299
300
            goto tryRight;
         break;
      case KEY_F(10):
      case 'q':
      case 27:
         quit = true;
         continue;
      default:
301
302
//fprintf(stderr, "onKey ");
         sortTimeout = resetSortTimeout;
Hisham Muhammad's avatar
Hisham Muhammad committed
303
         Panel_onKey(panelFocus, ch);
Hisham Muhammad's avatar
Hisham Muhammad committed
304
305
         break;
      }
306
//fprintf(stderr, "loop ");
Hisham Muhammad's avatar
Hisham Muhammad committed
307
308
   }

Hisham Muhammad's avatar
Hisham Muhammad committed
309
310
311
312
   if (lastFocus)
      *lastFocus = panelFocus;
   if (lastKey)
      *lastKey = ch;
Hisham Muhammad's avatar
Hisham Muhammad committed
313
}