ScreenManager.c 8.35 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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
static void checkRecalculation(ScreenManager* this, double* oldTime, int* sortTimeout, bool* redraw, bool *rescan, bool *timedOut) {
   ProcessList* pl = this->header->pl;

   struct timeval tv;
   gettimeofday(&tv, NULL);
   double newTime = ((double)tv.tv_sec * 10) + ((double)tv.tv_usec / 100000);
   *timedOut = (newTime - *oldTime > this->settings->delay);
   *rescan = *rescan || *timedOut;
   if (newTime < *oldTime) *rescan = true; // clock was adjusted?
   if (*rescan) {
      *oldTime = newTime;
      ProcessList_scan(pl);
      if (*sortTimeout == 0 || this->settings->treeView) {
         ProcessList_sort(pl);
         *sortTimeout = 1;
      }
      *redraw = true;
   }
   if (*redraw) {
      //pl->incFilter = IncSet_filter(inc);
      ProcessList_rebuildPanel(pl);
      Header_draw(this->header);
   }
   *rescan = false;
}

static void ScreenManager_drawPanels(ScreenManager* this, int focus) {
   int nPanels = this->panelCount;
   for (int i = 0; i < nPanels; i++) {
      Panel* panel = (Panel*) Vector_get(this->panels, i);
      Panel_draw(panel, i == focus);
      if (i < nPanels) {
         if (this->orientation == HORIZONTAL) {
            mvvline(panel->y, panel->x+panel->w, ' ', panel->h+1);
         }
      }
   }
}

172
void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
Hisham Muhammad's avatar
Hisham Muhammad committed
173
174
   bool quit = false;
   int focus = 0;
175
   
176
   Panel* panelFocus = (Panel*) Vector_get(this->panels, focus);
Hisham Muhammad's avatar
Hisham Muhammad committed
177
178
   if (this->fuBar)
      FunctionBar_draw(this->fuBar, NULL);
179

Hisham Muhammad's avatar
Hisham Muhammad committed
180
181
182
183
184
   double oldTime = 0.0;

   int ch = ERR;
   int closeTimeout = 0;

185
186
187
   bool timedOut = true;
   bool redraw = true;
   bool rescan = false;
Hisham Muhammad's avatar
Hisham Muhammad committed
188
189
190
   int sortTimeout = 0;
   int resetSortTimeout = 5;

Hisham Muhammad's avatar
Hisham Muhammad committed
191
   while (!quit) {
192
      if (this->header) {
193
         checkRecalculation(this, &oldTime, &sortTimeout, &redraw, &rescan, &timedOut);
194
      }
Hisham Muhammad's avatar
Hisham Muhammad committed
195
      
196
197
      if (redraw) {
         ScreenManager_drawPanels(this, focus);
Hisham Muhammad's avatar
Hisham Muhammad committed
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

Hisham Muhammad's avatar
Hisham Muhammad committed
209
210
211
212
213
214
215
      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 {
216
217
               for (int i = 0; i < this->panelCount; i++) {
                  Panel* panel = (Panel*) Vector_get(this->panels, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
218
                  if (mevent.x > panel->x && mevent.x <= panel->x+panel->w &&
219
220
                     mevent.y > panel->y && mevent.y <= panel->y+panel->h &&
                     (this->allowFocusChange || panelFocus == panel) ) {
Hisham Muhammad's avatar
Hisham Muhammad committed
221
                     focus = i;
Hisham Muhammad's avatar
Hisham Muhammad committed
222
223
                     panelFocus = panel;
                     Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV - 1);
Hisham Muhammad's avatar
Hisham Muhammad committed
224
225
226
227
228
229
                     break;
                  }
               }
            }
         }
      }
230
231
      if (Panel_eventHandlerFn(panelFocus)) {
         HandlerResult result = Panel_eventHandler(panelFocus, ch);
232
233
234
         if (result & SYNTH_KEY) {
            ch = result >> 16;
         }
235
236
         if (result & REDRAW) {
            //redraw = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
237
238
            sortTimeout = 0;
         }
239
240
         if (result & RESCAN) {
            rescan = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
241
242
243
            sortTimeout = 0;
         }
         if (result & HANDLED) {
244
            redraw = 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--;
253
         if (prevCh == ch && !timedOut) {
Hisham Muhammad's avatar
Hisham Muhammad committed
254
255
256
257
258
259
            closeTimeout++;
            if (closeTimeout == 100) {
               break;
            }
         } else
            closeTimeout = 0;
260
         redraw = false;
Hisham Muhammad's avatar
Hisham Muhammad committed
261
         continue;
Hisham Muhammad's avatar
Hisham Muhammad committed
262
      }
263
      redraw = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
264
265
      
      switch (ch) {
Hisham Muhammad's avatar
Hisham Muhammad committed
266
267
268
269
270
271
      case KEY_RESIZE:
      {
         ScreenManager_resize(this, this->x1, this->y1, this->x2, this->y2);
         continue;
      }
      case KEY_LEFT:
272
      case KEY_CTRLB:
273
274
         if (!this->allowFocusChange)
            break;
Hisham Muhammad's avatar
Hisham Muhammad committed
275
276
277
         tryLeft:
         if (focus > 0)
            focus--;
278
         panelFocus = (Panel*) Vector_get(this->panels, focus);
Hisham Muhammad's avatar
Hisham Muhammad committed
279
         if (Panel_size(panelFocus) == 0 && focus > 0)
Hisham Muhammad's avatar
Hisham Muhammad committed
280
281
282
            goto tryLeft;
         break;
      case KEY_RIGHT:
283
      case KEY_CTRLF:
Hisham Muhammad's avatar
Hisham Muhammad committed
284
      case 9:
285
286
         if (!this->allowFocusChange)
            break;
Hisham Muhammad's avatar
Hisham Muhammad committed
287
         tryRight:
288
         if (focus < this->panelCount - 1)
Hisham Muhammad's avatar
Hisham Muhammad committed
289
            focus++;
290
291
         panelFocus = (Panel*) Vector_get(this->panels, focus);
         if (Panel_size(panelFocus) == 0 && focus < this->panelCount - 1)
Hisham Muhammad's avatar
Hisham Muhammad committed
292
293
294
295
296
297
298
299
            goto tryRight;
         break;
      case KEY_F(10):
      case 'q':
      case 27:
         quit = true;
         continue;
      default:
300
         sortTimeout = resetSortTimeout;
Hisham Muhammad's avatar
Hisham Muhammad committed
301
         Panel_onKey(panelFocus, ch);
Hisham Muhammad's avatar
Hisham Muhammad committed
302
303
304
305
         break;
      }
   }

Hisham Muhammad's avatar
Hisham Muhammad committed
306
307
308
309
   if (lastFocus)
      *lastFocus = panelFocus;
   if (lastKey)
      *lastKey = ch;
Hisham Muhammad's avatar
Hisham Muhammad committed
310
}