~ubuntu-branches/ubuntu/hardy/texmacs/hardy

« back to all changes in this revision

Viewing changes to src/Window/X/x_loop.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ralf Treinen
  • Date: 2004-04-19 20:34:00 UTC
  • Revision ID: james.westby@ubuntu.com-20040419203400-g4e34ih0315wcn8v
Tags: upstream-1.0.3-R2
ImportĀ upstreamĀ versionĀ 1.0.3-R2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/******************************************************************************
 
3
* MODULE     : x_loop.cpp
 
4
* DESCRIPTION: The main event loop
 
5
* COPYRIGHT  : (C) 1999  Joris van der Hoeven
 
6
*******************************************************************************
 
7
* This software falls under the GNU general public license and comes WITHOUT
 
8
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
 
9
* If you don't have this file, write to the Free Software Foundation, Inc.,
 
10
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
11
******************************************************************************/
 
12
 
 
13
#include "X/x_display.hpp"
 
14
#include "X/x_window.hpp"
 
15
#include "iterator.hpp"
 
16
 
 
17
#ifdef OS_WIN32
 
18
#include "systime.hpp"
 
19
#include "sysmisc.hpp"
 
20
#include <sys/types.h>
 
21
#else
 
22
#include <sys/time.h>
 
23
#include <sys/types.h>
 
24
#include <unistd.h>
 
25
#endif
 
26
 
 
27
extern hashmap<Window,pointer> Window_to_window;
 
28
int nr_windows=0;
 
29
 
 
30
/******************************************************************************
 
31
* Look up keys and mouse
 
32
******************************************************************************/
 
33
 
 
34
string
 
35
x_display_rep::look_up_key (XKeyEvent* ev) {
 
36
  KeySym key= 0;
 
37
  //cout << ev->state << ", " << ev->keycode << LF;
 
38
 
 
39
  /*
 
40
  // decode non standard keys
 
41
  if (ev->state >= 256) {
 
42
    if ((ev->state&3)==0) key= XLookupKeysym (ev, 2);
 
43
    else {
 
44
      key= XLookupKeysym (ev, 3);
 
45
      if (key==0) key= XLookupKeysym (ev, 2);
 
46
    }
 
47
  }
 
48
 
 
49
  // decode standard keys
 
50
  if (key == 0) {
 
51
    if ((ev->state&3)==0) key= XLookupKeysym (ev, 0);
 
52
    else {
 
53
      key= XLookupKeysym (ev, 1);
 
54
      if (key==0) key= XLookupKeysym (ev, 0);
 
55
    }
 
56
  }
 
57
 
 
58
  // special treatment for num-lock
 
59
  string s= ((ev->state&3)? upper_key [key]: lower_key [key]);
 
60
  if ((N(s)>=2) && (s[0]=='K') && (s[1]=='-')) {
 
61
    if (ev->state&16) {
 
62
      if ((ev->state&3)==0) key= XLookupKeysym (ev, 1);
 
63
      else {
 
64
        key= XLookupKeysym (ev, 0);
 
65
        if (key==0) key= XLookupKeysym (ev, 1);
 
66
      }
 
67
      s= ((ev->state&3)? upper_key [key]: lower_key [key]);
 
68
    }
 
69
    if ((N(s)>=2) && (s[0]=='K') && (s[1]=='-')) s= s (2, N(s));
 
70
  }
 
71
  */
 
72
 
 
73
  XLookupString (ev, NULL, 0, &key, NULL);
 
74
  string s= ((ev->state&3)? upper_key [key]: lower_key [key]);
 
75
  if ((N(s)>=2) && (s[0]=='K') && (s[1]=='-')) s= s (2, N(s));
 
76
 
 
77
  /* other keyboard modifiers */
 
78
  if (N(s)==0) return s;
 
79
  if (ev->state&4) s= "C-" * s;
 
80
  if (ev->state&8) s= "Mod1-" * s;
 
81
  if (ev->state&16) s= "Mod2-" * s;
 
82
  if (ev->state&32) s= "Mod3-" * s;
 
83
  if (ev->state&64) s= "Mod4-" * s;
 
84
  if (ev->state&128) s= "Mod5-" * s;
 
85
  //cout << "key press: " << s << LF;
 
86
  return s;
 
87
}
 
88
 
 
89
string
 
90
x_display_rep::look_up_mouse (XButtonEvent* ev) {
 
91
  switch (ev->button) {
 
92
  case Button1: return "left";
 
93
  case Button2: return "middle";
 
94
  case Button3: return "right";
 
95
  case Button4: return "up";
 
96
  case Button5: return "down";
 
97
  default: return "unknown";
 
98
  }
 
99
}
 
100
 
 
101
unsigned int
 
102
x_display_rep::get_button_mask (XButtonEvent* ev) {
 
103
  switch (ev->button) {
 
104
  case Button1: return Button1Mask;
 
105
  case Button2: return Button2Mask;
 
106
  case Button3: return Button3Mask;
 
107
  case Button4: return Button4Mask;
 
108
  case Button5: return Button5Mask;
 
109
  default: return 0;
 
110
  }
 
111
}
 
112
 
 
113
/******************************************************************************
 
114
* Process events
 
115
******************************************************************************/
 
116
 
 
117
char* event_name[]= {
 
118
  "?",
 
119
  "?",
 
120
  "Key press",
 
121
  "Key release",
 
122
  "Button press",
 
123
  "Button release",
 
124
  "Motion notify",
 
125
  "Enter notify",
 
126
  "Leave notify",
 
127
  "Focus in",
 
128
  "Focus out",
 
129
  "Keymap notify",
 
130
  "Expose",
 
131
  "Graphics expose",
 
132
  "No expose",
 
133
  "Visibility notify",
 
134
  "Create notify",
 
135
  "Destroy notify",
 
136
  "Unmap notify",
 
137
  "Map request",
 
138
  "Reparent notify",
 
139
  "Configure notify",
 
140
  "Configure request",
 
141
  "Gravity notify",
 
142
  "Resize request",
 
143
  "Circulate notify",
 
144
  "Circulate request",
 
145
  "Property notify",
 
146
  "Selection clear",
 
147
  "Selection request",
 
148
  "Selection notify",
 
149
  "Colormap notify",
 
150
  "Client message",
 
151
  "Mapping notify"
 
152
};
 
153
 
 
154
void
 
155
x_display_rep::process_event (x_window win, XEvent* ev) {
 
156
  // cout << "Event: " << event_name[ev->type] << "\n";
 
157
  switch (ev->type) {
 
158
  case Expose:
 
159
    {
 
160
      XExposeEvent& ee= ev->xexpose;
 
161
      /*
 
162
      cout << "Expose: " << ee.x << "," << ee.y << ","
 
163
           << ee.x+ee.width << "," << ee.y+ee.height << "\n";
 
164
           */
 
165
      win->invalidate_event (ee.x, ee.y, ee.x+ee.width, ee.y+ee.height);
 
166
      break;
 
167
    }
 
168
  case GraphicsExpose:
 
169
    {
 
170
      XGraphicsExposeEvent& ee= ev->xgraphicsexpose;
 
171
      /*
 
172
      cout << "Expose: " << ee.x << "," << ee.y << ","
 
173
           << ee.x+ee.width << "," << ee.y+ee.height << "\n";
 
174
           */
 
175
      win->invalidate_event (ee.x, ee.y, ee.x+ee.width, ee.y+ee.height);
 
176
      break;
 
177
    }
 
178
  case NoExpose:
 
179
    // cout << "No expose\n";
 
180
    break;
 
181
  case ConfigureNotify:
 
182
    /*
 
183
    cout << "Configure move  : " << ev->xconfigure.x << ","
 
184
         << ev->xconfigure.y << "\n";
 
185
    cout << "Configure resize: " << ev->xconfigure.width << ","
 
186
         << ev->xconfigure.height << "\n";
 
187
         */
 
188
    if ((ev->xconfigure.x!=0) || (ev->xconfigure.y!=0) ||
 
189
        ((ev->xconfigure.width == win->win_w) &&
 
190
         (ev->xconfigure.height == win->win_h)))
 
191
      win->move_event (ev->xconfigure.x, ev->xconfigure.y);
 
192
    win->resize_event (ev->xconfigure.width, ev->xconfigure.height);
 
193
    break;
 
194
  case CreateNotify:
 
195
    break;
 
196
  case DestroyNotify:
 
197
    // cout << "Destroy\n";
 
198
    win->destroy_event ();
 
199
    event_loop ();
 
200
    exit (0);
 
201
  case UnmapNotify:
 
202
    // cout << "Unmap\n";
 
203
    break;
 
204
  case ButtonPress:
 
205
    unmap_balloon ();
 
206
    set_button_state (ev->xbutton.state ^ get_button_mask (&ev->xbutton));
 
207
    win->mouse_event ("press-" * look_up_mouse (&ev->xbutton),
 
208
                      ev->xbutton.x, ev->xbutton.y, ev->xbutton.time);
 
209
    break;
 
210
  case ButtonRelease:
 
211
    unmap_balloon ();
 
212
    set_button_state (ev->xbutton.state ^ get_button_mask (&ev->xbutton));
 
213
    win->mouse_event ("release-" * look_up_mouse (&ev->xbutton),
 
214
                      ev->xbutton.x, ev->xbutton.y, ev->xbutton.time);
 
215
    break;
 
216
  case EnterNotify:
 
217
    unmap_balloon ();
 
218
    if (ev->xcrossing.mode == NotifyNormal) {
 
219
      // cout << "Enter at (" <<ev->xcrossing.x<<","<<ev->xcrossing.y << ")\n";
 
220
      set_button_state (ev->xcrossing.state);
 
221
      win->mouse_event ("enter", ev->xcrossing.x, ev->xcrossing.y,
 
222
                        ev->xcrossing.time);
 
223
    }
 
224
    break;
 
225
  case LeaveNotify:
 
226
    unmap_balloon ();
 
227
    if (ev->xcrossing.mode == NotifyNormal) {
 
228
      // cout << "Leave at (" <<ev->xcrossing.x<<","<<ev->xcrossing.y << ")\n";
 
229
      set_button_state (ev->xcrossing.state);
 
230
      win->mouse_event ("leave", ev->xcrossing.x, ev->xcrossing.y,
 
231
                        ev->xcrossing.time);
 
232
    }
 
233
    break;
 
234
  case FocusIn:
 
235
    win->focus_in_event ();
 
236
    break;
 
237
  case FocusOut:
 
238
    win->focus_out_event ();
 
239
    break;
 
240
  case MotionNotify:
 
241
    // cout << "Move to (" << ev->xmotion.x << "," << ev->xmotion.y << ")\n";
 
242
    unmap_balloon ();
 
243
    set_button_state (ev->xmotion.state);
 
244
    win->mouse_event ("move", ev->xmotion.x, ev->xmotion.y, ev->xmotion.time);
 
245
 
 
246
    break;
 
247
  case KeyPress:
 
248
    unmap_balloon ();
 
249
    {
 
250
      string key= look_up_key (&ev->xkey);
 
251
      // cout << "Press " << key << " at " << ev->xkey.time
 
252
      // << " (" << texmacs_time() << ")\n";
 
253
      if (N(key)>0) win->key_event (key);
 
254
      break;
 
255
    }
 
256
  case SelectionRequest:
 
257
    {
 
258
      bool flag=true;
 
259
      XSelectionRequestEvent& req= ev->xselectionrequest;
 
260
      if (selection==NULL) flag=false;
 
261
      if ((req.target!=AnyPropertyType) && (req.target!=XA_STRING)) flag=false;
 
262
      if (flag)
 
263
        XChangeProperty (dpy, req.requestor, req.property, XA_STRING,
 
264
                         8, PropModeReplace,
 
265
                         (unsigned char*) selection,
 
266
                         strlen (selection));
 
267
      XSelectionEvent sel;
 
268
      sel.type      = SelectionNotify;
 
269
      sel.serial    = req.serial;
 
270
      sel.send_event= true;
 
271
      sel.display   = dpy;
 
272
      sel.requestor = req.requestor;
 
273
      sel.selection = req.selection;
 
274
      sel.target    = req.target;
 
275
      sel.property  = flag?req.property:None;
 
276
      sel.time      = req.time;
 
277
      XSendEvent (dpy, InputFocus, false, 0, (XEvent*) &sel);
 
278
      break;
 
279
    }
 
280
  case SelectionClear:
 
281
    clear_selection ("primary");
 
282
    break;
 
283
  case ClientMessage:
 
284
    {
 
285
      Atom wm_protocols     = XInternAtom(win->dpy, "WM_PROTOCOLS",     1);
 
286
      Atom wm_delete_window = XInternAtom(win->dpy, "WM_DELETE_WINDOW", 1);
 
287
      if ((ev->xclient.message_type == wm_protocols) &&
 
288
          ((Atom)ev->xclient.data.l[0] == wm_delete_window))
 
289
        win->destroy_event();
 
290
      break;
 
291
    }
 
292
  }
 
293
}
 
294
 
 
295
/******************************************************************************
 
296
* Main event loop
 
297
******************************************************************************/
 
298
 
 
299
static void (*the_interpose_handler) (void) = NULL;
 
300
void set_interpose_handler (void (*r) (void)) { the_interpose_handler= r; }
 
301
 
 
302
#define MIN_DELAY   10
 
303
#define MAX_DELAY   1000
 
304
#define SLEEP_AFTER 120000
 
305
 
 
306
void
 
307
x_display_rep::event_loop () {
 
308
  bool wait= true;
 
309
  int count= 0;
 
310
  int delay= MIN_DELAY;
 
311
 
 
312
  while (nr_windows>0) {
 
313
    // Get events
 
314
    if (XPending (dpy) > 0) {
 
315
      XEvent report;
 
316
      XNextEvent (dpy, &report);
 
317
      // cout << "Event: " << event_name[report.type] << "\n";
 
318
      x_window win= (x_window) Window_to_window[report.xany.window];
 
319
      if (win!=NULL) process_event (win, &report);
 
320
      count= 0;
 
321
      delay= MIN_DELAY;
 
322
      wait = false;
 
323
      continue;
 
324
    }
 
325
 
 
326
    // Wait for events on all channels and interpose
 
327
    if (wait) {
 
328
#ifdef OS_WIN32
 
329
      struct timeval_ tv;
 
330
#else
 
331
      struct timeval tv;
 
332
#endif
 
333
      tv.tv_sec  = delay/1000;
 
334
      tv.tv_usec = 1000 * (delay%1000);
 
335
      select (0, NULL, NULL, NULL, &tv);
 
336
      count += delay;
 
337
      if (count >= SLEEP_AFTER) delay= MAX_DELAY;
 
338
    }
 
339
    else wait= true;
 
340
    if (the_interpose_handler != NULL) the_interpose_handler ();
 
341
 
 
342
    // Popup help balloons
 
343
    if (!nil (balloon_wid))
 
344
      if (texmacs_time () >= (balloon_time+666))
 
345
        if (balloon_win == NULL)
 
346
          map_balloon ();
 
347
 
 
348
    // Redraw invalid windows
 
349
    iterator<Window> it= iterate (Window_to_window);
 
350
    while (it->busy()) {
 
351
      x_window win= (x_window) Window_to_window[it->next()];
 
352
      win->repaint_invalid_regions();
 
353
    }
 
354
 
 
355
    // Handle alarm messages
 
356
    while (!nil (messages)) {
 
357
      time_t ct= texmacs_time ();
 
358
      message m= messages->item;
 
359
      if ((m->t - ct) <= 0) {
 
360
        messages= messages->next;
 
361
        m->wid << emit_alarm (m->s, m->t);
 
362
      }
 
363
      else break;
 
364
    }
 
365
  }
 
366
}