2
/******************************************************************************
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
******************************************************************************/
13
#include "X/x_display.hpp"
14
#include "X/x_window.hpp"
15
#include "iterator.hpp"
18
#include "systime.hpp"
19
#include "sysmisc.hpp"
20
#include <sys/types.h>
23
#include <sys/types.h>
27
extern hashmap<Window,pointer> Window_to_window;
30
/******************************************************************************
31
* Look up keys and mouse
32
******************************************************************************/
35
x_display_rep::look_up_key (XKeyEvent* ev) {
37
//cout << ev->state << ", " << ev->keycode << LF;
40
// decode non standard keys
41
if (ev->state >= 256) {
42
if ((ev->state&3)==0) key= XLookupKeysym (ev, 2);
44
key= XLookupKeysym (ev, 3);
45
if (key==0) key= XLookupKeysym (ev, 2);
49
// decode standard keys
51
if ((ev->state&3)==0) key= XLookupKeysym (ev, 0);
53
key= XLookupKeysym (ev, 1);
54
if (key==0) key= XLookupKeysym (ev, 0);
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]=='-')) {
62
if ((ev->state&3)==0) key= XLookupKeysym (ev, 1);
64
key= XLookupKeysym (ev, 0);
65
if (key==0) key= XLookupKeysym (ev, 1);
67
s= ((ev->state&3)? upper_key [key]: lower_key [key]);
69
if ((N(s)>=2) && (s[0]=='K') && (s[1]=='-')) s= s (2, N(s));
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));
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;
90
x_display_rep::look_up_mouse (XButtonEvent* ev) {
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";
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;
113
/******************************************************************************
115
******************************************************************************/
117
char* event_name[]= {
155
x_display_rep::process_event (x_window win, XEvent* ev) {
156
// cout << "Event: " << event_name[ev->type] << "\n";
160
XExposeEvent& ee= ev->xexpose;
162
cout << "Expose: " << ee.x << "," << ee.y << ","
163
<< ee.x+ee.width << "," << ee.y+ee.height << "\n";
165
win->invalidate_event (ee.x, ee.y, ee.x+ee.width, ee.y+ee.height);
170
XGraphicsExposeEvent& ee= ev->xgraphicsexpose;
172
cout << "Expose: " << ee.x << "," << ee.y << ","
173
<< ee.x+ee.width << "," << ee.y+ee.height << "\n";
175
win->invalidate_event (ee.x, ee.y, ee.x+ee.width, ee.y+ee.height);
179
// cout << "No expose\n";
181
case ConfigureNotify:
183
cout << "Configure move : " << ev->xconfigure.x << ","
184
<< ev->xconfigure.y << "\n";
185
cout << "Configure resize: " << ev->xconfigure.width << ","
186
<< ev->xconfigure.height << "\n";
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);
197
// cout << "Destroy\n";
198
win->destroy_event ();
202
// cout << "Unmap\n";
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);
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);
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,
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,
235
win->focus_in_event ();
238
win->focus_out_event ();
241
// cout << "Move to (" << ev->xmotion.x << "," << ev->xmotion.y << ")\n";
243
set_button_state (ev->xmotion.state);
244
win->mouse_event ("move", ev->xmotion.x, ev->xmotion.y, ev->xmotion.time);
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);
256
case SelectionRequest:
259
XSelectionRequestEvent& req= ev->xselectionrequest;
260
if (selection==NULL) flag=false;
261
if ((req.target!=AnyPropertyType) && (req.target!=XA_STRING)) flag=false;
263
XChangeProperty (dpy, req.requestor, req.property, XA_STRING,
265
(unsigned char*) selection,
268
sel.type = SelectionNotify;
269
sel.serial = req.serial;
270
sel.send_event= true;
272
sel.requestor = req.requestor;
273
sel.selection = req.selection;
274
sel.target = req.target;
275
sel.property = flag?req.property:None;
277
XSendEvent (dpy, InputFocus, false, 0, (XEvent*) &sel);
281
clear_selection ("primary");
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();
295
/******************************************************************************
297
******************************************************************************/
299
static void (*the_interpose_handler) (void) = NULL;
300
void set_interpose_handler (void (*r) (void)) { the_interpose_handler= r; }
303
#define MAX_DELAY 1000
304
#define SLEEP_AFTER 120000
307
x_display_rep::event_loop () {
310
int delay= MIN_DELAY;
312
while (nr_windows>0) {
314
if (XPending (dpy) > 0) {
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);
326
// Wait for events on all channels and interpose
333
tv.tv_sec = delay/1000;
334
tv.tv_usec = 1000 * (delay%1000);
335
select (0, NULL, NULL, NULL, &tv);
337
if (count >= SLEEP_AFTER) delay= MAX_DELAY;
340
if (the_interpose_handler != NULL) the_interpose_handler ();
342
// Popup help balloons
343
if (!nil (balloon_wid))
344
if (texmacs_time () >= (balloon_time+666))
345
if (balloon_win == NULL)
348
// Redraw invalid windows
349
iterator<Window> it= iterate (Window_to_window);
351
x_window win= (x_window) Window_to_window[it->next()];
352
win->repaint_invalid_regions();
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);