1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
diff -up fltk-1.3.2/FL/Fl.H.xhandlers fltk-1.3.2/FL/Fl.H
--- fltk-1.3.2/FL/Fl.H.xhandlers 2014-07-22 15:23:18.087334467 +0200
+++ fltk-1.3.2/FL/Fl.H 2014-07-22 15:23:18.094334589 +0200
@@ -96,6 +96,9 @@ typedef void (*Fl_FD_Handler)(FL_SOCKET
/** Signature of add_handler functions passed as parameters */
typedef int (*Fl_Event_Handler)(int event);
+/** Signature of add_xhandler functions passed as parameters */
+typedef bool (*Fl_XEvent_Handler)(void *event, void *data);
+
/** Signature of set_abort functions passed as parameters */
typedef void (*Fl_Abort_Handler)(const char *format,...);
@@ -712,6 +715,8 @@ public:
static void focus(Fl_Widget*);
static void add_handler(Fl_Event_Handler h);
static void remove_handler(Fl_Event_Handler h);
+ static void add_xhandler(Fl_XEvent_Handler h, void *data);
+ static void remove_xhandler(Fl_XEvent_Handler h);
static void event_dispatch(Fl_Event_Dispatch d);
static Fl_Event_Dispatch event_dispatch();
/** @} */
diff -up fltk-1.3.2/src/Fl_cocoa.mm.xhandlers fltk-1.3.2/src/Fl_cocoa.mm
--- fltk-1.3.2/src/Fl_cocoa.mm.xhandlers 2014-07-22 15:23:18.089334502 +0200
+++ fltk-1.3.2/src/Fl_cocoa.mm 2014-07-22 15:23:18.095334607 +0200
@@ -1269,6 +1269,8 @@ void fl_open_callback(void (*cb)(const c
}
@end
+extern bool fl_send_xhandlers(void *e);
+
static void clipboard_check(void);
@implementation FLApplication
@@ -1276,6 +1278,10 @@ static void clipboard_check(void);
{
// update clipboard status
clipboard_check();
+
+ if (fl_send_xhandlers(theEvent))
+ return;
+
NSEventType type = [theEvent type];
if (type == NSLeftMouseDown) {
fl_lock_function();
diff -up fltk-1.3.2/src/Fl.cxx.xhandlers fltk-1.3.2/src/Fl.cxx
--- fltk-1.3.2/src/Fl.cxx.xhandlers 2014-07-22 15:23:18.085334432 +0200
+++ fltk-1.3.2/src/Fl.cxx 2014-07-22 15:23:18.095334607 +0200
@@ -891,6 +891,67 @@ static int send_handlers(int e) {
return 0;
}
+
+////////////////////////////////////////////////////////////////
+// System event handlers:
+
+
+struct xhandler_link {
+ Fl_XEvent_Handler handle;
+ void *data;
+ xhandler_link *next;
+};
+
+
+static xhandler_link *xhandlers = 0;
+
+
+/**
+ Install a function to intercept system events. FLTK calls each of
+ these functions as soon as a new system event is received. The
+ processing will stop at the first function to return true. If all
+ functions return false then the event is passed on for normal
+ handling by FLTK.
+
+ \see Fl::remove_xhandler(Fl_XEvent_Handler)
+*/
+void Fl::add_xhandler(Fl_XEvent_Handler ha, void *data) {
+ xhandler_link *l = new xhandler_link;
+ l->handle = ha;
+ l->data = data;
+ l->next = xhandlers;
+ xhandlers = l;
+}
+
+
+/**
+ Removes a previously added system event handler.
+*/
+void Fl::remove_xhandler(Fl_XEvent_Handler ha) {
+ xhandler_link *l, *p;
+
+ // Search for the handler in the list...
+ for (l = xhandlers, p = 0; l && l->handle != ha; p = l, l = l->next);
+
+ if (l) {
+ // Found it, so remove it from the list...
+ if (p) p->next = l->next;
+ else xhandlers = l->next;
+
+ // And free the record...
+ delete l;
+ }
+}
+
+bool fl_send_xhandlers(void *e) {
+ for (const xhandler_link *hl = xhandlers; hl; hl = hl->next) {
+ if (hl->handle(e, hl->data))
+ return true;
+ }
+ return false;
+}
+
+
////////////////////////////////////////////////////////////////
Fl_Widget* fl_oldfocus; // kludge for Fl_Group...
diff -up fltk-1.3.2/src/Fl_win32.cxx.xhandlers fltk-1.3.2/src/Fl_win32.cxx
--- fltk-1.3.2/src/Fl_win32.cxx.xhandlers 2014-07-22 15:23:18.092334554 +0200
+++ fltk-1.3.2/src/Fl_win32.cxx 2014-07-22 15:24:44.682843610 +0200
@@ -336,6 +336,8 @@ void* Fl::thread_message() {
return r;
}
+extern bool fl_send_xhandlers(void *e);
+
IActiveIMMApp *fl_aimm = NULL;
MSG fl_msg;
@@ -401,26 +403,25 @@ int fl_wait(double time_to_wait) {
// Execute the message we got, and all other pending messages:
// have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);
- have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE);
- if (have_message > 0) {
- while (have_message != 0 && have_message != -1) {
- // Let applications treat WM_QUIT identical to SIGTERM on *nix
- if (fl_msg.message == WM_QUIT)
- raise(SIGTERM);
- if (fl_msg.message == fl_wake_msg) {
- // Used for awaking wait() from another thread
- thread_message_ = (void*)fl_msg.wParam;
- Fl_Awake_Handler func;
- void *data;
- while (Fl::get_awake_handler_(func, data)==0) {
- func(data);
- }
- }
-
- TranslateMessage(&fl_msg);
- DispatchMessageW(&fl_msg);
- have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE);
+ while ((have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE)) > 0) {
+ if (fl_send_xhandlers(&fl_msg))
+ continue;
+
+ // Let applications treat WM_QUIT identical to SIGTERM on *nix
+ if (fl_msg.message == WM_QUIT)
+ raise(SIGTERM);
+
+ if (fl_msg.message == fl_wake_msg) {
+ // Used for awaking wait() from another thread
+ thread_message_ = (void*)fl_msg.wParam;
+ Fl_Awake_Handler func;
+ void *data;
+ while (Fl::get_awake_handler_(func, data)==0)
+ func(data);
}
+
+ TranslateMessage(&fl_msg);
+ DispatchMessageW(&fl_msg);
}
Fl::flush();
diff -up fltk-1.3.2/src/Fl_x.cxx.xhandlers fltk-1.3.2/src/Fl_x.cxx
--- fltk-1.3.2/src/Fl_x.cxx.xhandlers 2014-07-22 15:23:18.093334572 +0200
+++ fltk-1.3.2/src/Fl_x.cxx 2014-07-22 15:23:18.096334624 +0200
@@ -188,6 +188,8 @@ void Fl::remove_fd(int n) {
remove_fd(n, -1);
}
+extern bool fl_send_xhandlers(void *e);
+
#if CONSOLIDATE_MOTION
static Fl_Window* send_motion;
extern Fl_Window* fl_xmousewin;
@@ -198,6 +200,8 @@ static void do_queued_events() {
while (XEventsQueued(fl_display,QueuedAfterReading)) {
XEvent xevent;
XNextEvent(fl_display, &xevent);
+ if (fl_send_xhandlers(&xevent))
+ continue;
fl_handle(xevent);
}
// we send FL_LEAVE only if the mouse did not enter some other window:
|