Fix compiler warnings
[texmacs.git] / src / src / Plugins / X11 / x_window.cpp
blobe72769329d2b364ee9c73fcd1dc7d5fc1662c9b6
2 /******************************************************************************
3 * MODULE : x_window.cpp
4 * DESCRIPTION: Windows under X11
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 "X11/x_window.hpp"
14 #include "message.hpp"
16 extern int nr_windows;
18 hashmap<Window,pointer> Window_to_window (NULL);
20 /******************************************************************************
21 * Creation and deletion of an x_window
22 ******************************************************************************/
24 void
25 x_window_rep::set_hints (SI min_w, SI min_h, SI max_w, SI max_h) {
26 XSizeHints* size_hints;
27 XWMHints* wm_hints;
28 XClassHint* class_hints;
29 if (!(size_hints= XAllocSizeHints ()))
30 fatal_error ("out of memory (X server)", "set_attributes");
31 if (!(wm_hints= XAllocWMHints ()))
32 fatal_error ("out of memory (X server)", "set_attributes");
33 if (!(class_hints= XAllocClassHint ()))
34 fatal_error ("out of memory (X server)", "set_attributes");
36 XTextProperty Window_Name;
37 XTextProperty Icon_Name;
38 if (XStringListToTextProperty (&name, 1, &Window_Name) == 0)
39 fatal_error ("out of memory (X server)", "set_attributes");
40 if (XStringListToTextProperty (&name, 1, &Icon_Name) == 0)
41 fatal_error ("out of memory (X server)", "set_attributes");
43 // int start_1= texmacs_time ();
44 if (!gui->xpm_pixmap->contains ("TeXmacs.xpm"))
45 xpm_initialize ("TeXmacs.xpm");
46 Pixmap pm= (Pixmap) gui->xpm_pixmap ["TeXmacs.xpm"];
47 // cout << "Getting pixmap required " << (texmacs_time ()-start_1) << " ms\n";
49 // int start_2= texmacs_time ();
50 size_hints->flags = PPosition | PSize | PMinSize | PMaxSize;
51 size_hints->min_width = min_w;
52 size_hints->min_height = min_h;
53 size_hints->max_width = max_w;
54 size_hints->max_height = max_h;
55 wm_hints->initial_state = NormalState;
56 wm_hints->input = true;
57 wm_hints->icon_pixmap = pm;
58 wm_hints->flags = StateHint | IconPixmapHint | InputHint;
59 class_hints->res_name = name;
60 class_hints->res_class = name;
62 XSetWMProperties (
63 dpy,
64 win,
65 &Window_Name,
66 &Icon_Name,
67 gui->argv,
68 gui->argc,
69 size_hints,
70 wm_hints,
71 class_hints
73 // cout << "Setting hints required " << (texmacs_time ()-start_2) << " ms\n";
76 void
77 x_window_rep::initialize () {
78 SI min_w= Min_w, min_h= Min_h;
79 SI def_w= Def_w, def_h= Def_h;
80 SI max_w= Max_w, max_h= Max_h;
82 dpy= gui->dpy;
83 gc = gui->gc;
84 full_screen_flag= false;
86 // int start_1= texmacs_time ();
87 set_origin (0, 0);
88 decode (def_w, def_h); def_h= -def_h;
89 decode (min_w, min_h); min_h= -min_h;
90 decode (max_w, max_h); max_h= -max_h;
91 // cout << "Size computation required " << (texmacs_time ()-start_1) << " ms\n";
93 // int start_2= texmacs_time ();
94 unsigned long valuemask= CWOverrideRedirect | CWSaveUnder;
95 //unsigned long valuemask= CWOverrideRedirect | CWSaveUnder | CWBackingStore;
96 XSetWindowAttributes setattr;
97 setattr.override_redirect= (name==NULL);
98 setattr.save_under = True; // (name==NULL);
99 // setattr.backing_store = Always;
100 // FIXME: backing store does not seem to work correctly
101 if (win_w == 0) win_w= def_w;
102 if (win_h == 0) win_h= def_h;
103 if ((win_x+ win_w) > gui->screen_width) win_x= gui->screen_width- win_w;
104 if (win_x < 0) win_x= 0;
105 if ((win_y+ win_h) > gui->screen_height) win_y= gui->screen_height- win_h;
106 if (win_y < 0) win_y=0;
107 win= XCreateWindow (dpy, gui->root, win_x, win_y, win_w, win_h, 0,
108 gui->depth, InputOutput, CopyFromParent,
109 valuemask, &setattr);
110 x_drawable_rep::win= (Drawable) win;
111 // cout << "XWindow creation required " << (texmacs_time ()-start_2) << " ms\n";
113 // cout << "Hints: " << min_w << ", " << min_h << " --- "
114 // << max_w << ", " << max_h << "\n";
115 if (name == NULL) name= const_cast<char*> ("popup");
116 if (the_name == "") the_name= name;
117 set_hints (min_w, min_h, max_w, max_h);
119 unsigned long ic_mask= 0;
120 ic_ok= false;
121 if (gui->im_ok) {
122 ic= XCreateIC (gui->im,
123 XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
124 XNClientWindow, win,
125 NULL);
126 if (ic == NULL)
127 cout << "TeXmacs] Warning: couldn't create input context\n";
128 else {
129 ic_ok= true;
130 XGetICValues (ic, XNFilterEvents, &ic_mask, NULL);
134 XSelectInput (dpy, win,
135 ExposureMask | StructureNotifyMask |
136 SubstructureNotifyMask | FocusChangeMask |
137 PointerMotionMask | EnterWindowMask | LeaveWindowMask |
138 ButtonPressMask | ButtonReleaseMask |
139 KeyPressMask | ic_mask);
141 Atom wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", 1);
142 Atom wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", 1);
143 XSetWMProtocols (dpy, win, &wm_protocols, 1);
144 XSetWMProtocols (dpy, win, &wm_delete_window, 1);
146 nr_windows++;
147 Window_to_window (win)= (void*) this;
148 set_identifier (w, (int) win);
149 notify_position (w, 0, 0);
150 notify_size (w, Def_w, Def_h);
153 x_window_rep::x_window_rep (widget w2, x_gui gui2, char* n2,
154 SI min_w, SI min_h, SI def_w, SI def_h,
155 SI max_w, SI max_h):
156 x_drawable_rep (gui2), window_rep (), w (w2), gui (gui2), name (n2),
157 Min_w (min_w), Min_h (min_h), Def_w (def_w), Def_h (def_h),
158 Max_w (max_w), Max_h (max_h),
159 win_x (0), win_y (0), win_w (Def_w/PIXEL), win_h (Def_h/PIXEL),
160 kbd_focus (w.rep), has_focus (false)
162 initialize ();
163 gui->created_window (win);
166 x_window_rep::~x_window_rep () {
167 set_identifier (w, 0);
169 XEvent report;
170 while (XCheckWindowEvent (dpy, win, 0xffffffff, &report));
172 if (ic_ok) XDestroyIC (ic);
173 Window_to_window->reset (win);
174 nr_windows--;
175 XDestroyWindow (dpy, win);
176 gui->deleted_window (win);
179 widget
180 x_window_rep::get_widget () {
181 return w;
184 void
185 x_window_rep::get_extents (int& w, int& h) {
186 w= win_w;
187 h= win_h;
190 Window
191 get_Window (widget w) {
192 int id= get_identifier (w);
193 if (id == 0) {
194 cerr << "\nwidget = " << w << "\n";
195 fatal_error ("widget is not attached to a window", "get_Window");
197 return (Window) id;
200 x_window
201 get_x_window (widget w) {
202 int id= get_identifier (w);
203 if (id == 0) return NULL;
204 else return (x_window) Window_to_window[(Window) id];
208 get_identifier (window w) {
209 if (w == NULL) return 0;
210 else return (int) (((x_window) w) -> win);
213 window
214 get_window (int id) {
215 if (id == 0) return NULL;
216 else return (window) ((x_window) Window_to_window[(Window) id]);
219 /******************************************************************************
220 * Window apping and appearance
221 ******************************************************************************/
223 void
224 x_window_rep::get_position (SI& x, SI& y) {
225 #ifdef OS_WIN32
226 XGetWindowPos (dpy, win, &win_x, &win_y);
227 x= win_x*PIXEL;
228 y= -win_y*PIXEL;
229 #else
230 int xx, yy;
231 Window ww;
232 bool b;
233 b= XTranslateCoordinates (dpy, win, gui->root, 0, 0, &xx, &yy, &ww);
234 x= xx*PIXEL;
235 y= -yy*PIXEL;
236 #endif
239 void
240 x_window_rep::get_size (SI& ww, SI& hh) {
241 ww= win_w*PIXEL;
242 hh= win_h*PIXEL;
245 void
246 x_window_rep::set_position (SI x, SI y) {
247 x= x/PIXEL;
248 y= -y/PIXEL;
249 if ((x+ win_w) > gui->screen_width) x= gui->screen_width- win_w;
250 if (x<0) x=0;
251 if ((y+ win_h) > gui->screen_height) y= gui->screen_height- win_h;
252 if (y<0) y=0;
253 XMoveWindow (dpy, win, x, y);
256 void
257 x_window_rep::set_size (SI w, SI h) {
258 h=-h; decode (w, h);
259 XResizeWindow (dpy, win, w, h);
262 void
263 x_window_rep::set_name (string name) {
264 char* s= as_charp (name);
265 XStoreName (dpy, win, s);
266 XSetIconName (dpy, win, s);
267 delete[] s;
268 the_name= name;
271 string
272 x_window_rep::get_name () {
273 return the_name;
276 void
277 x_window_rep::set_visibility (bool flag) {
278 if (flag) XMapRaised (dpy, win);
279 else XUnmapWindow (dpy, win);
282 void
283 x_window_rep::set_full_screen (bool flag) {
284 if (full_screen_flag == flag) return;
285 string old_name= get_name ();
286 if (old_name == "")
287 old_name= as_string (name);
288 if (flag) {
289 save_win= win;
290 name= NULL;
291 save_x= win_x; save_y= win_y;
292 save_w= win_w; save_h= win_h;
293 initialize ();
294 XMoveResizeWindow (dpy, win, 0, 0,
295 gui->screen_width, gui->screen_height);
296 move_event (0, 0);
297 resize_event (gui->screen_width, gui->screen_height);
298 set_visibility (true);
299 XSetInputFocus (dpy, win, PointerRoot, CurrentTime);
301 else {
302 set_visibility (false);
303 Window_to_window->reset (win);
304 nr_windows--;
305 XDestroyWindow (dpy, win);
306 win= save_win;
307 set_visibility (false);
308 Window_to_window->reset (win);
309 nr_windows--;
310 XDestroyWindow (dpy, win);
311 name= as_charp (old_name);
312 win_x= save_x; win_y= save_y;
313 win_w= save_w; win_h= save_h;
314 initialize ();
315 set_visibility (true);
316 XMoveResizeWindow (dpy, win, save_x, save_y, save_w, save_h);
317 resize_event (save_w, save_h);
318 move_event (save_x, save_y);
320 set_name (old_name);
321 full_screen_flag= flag;
324 void
325 x_window_rep::move_event (int x, int y) {
326 bool flag= (win_x!=x) || (win_y!=y);
327 win_x= x; win_y= y;
328 if (flag) notify_position (w, win_x*PIXEL, win_y*PIXEL);
331 void
332 x_window_rep::resize_event (int ww, int hh) {
333 bool flag= (win_w!=ww) || (win_h!=hh);
334 win_w= ww; win_h= hh;
335 if (flag) notify_size (w, win_w*PIXEL, win_h*PIXEL);
338 void
339 x_window_rep::destroy_event () {
340 send_destroy (w);
343 /******************************************************************************
344 * Event handling
345 ******************************************************************************/
347 void
348 x_window_rep::invalidate_event (int x1, int y1, int x2, int y2) {
349 invalid_regions= invalid_regions | rectangles (rectangle (x1, y1, x2, y2));
352 void
353 x_window_rep::key_event (string key) {
354 send_keyboard (kbd_focus, key);
357 void
358 x_window_rep::focus_in_event () {
359 if (ic_ok) XSetICFocus (ic);
360 has_focus= true;
361 notify_keyboard_focus (kbd_focus, true);
362 gui->focussed_window (win);
365 void
366 x_window_rep::focus_out_event () {
367 if (ic_ok) XUnsetICFocus (ic);
368 has_focus= false;
369 notify_keyboard_focus (kbd_focus, false);
372 void
373 x_window_rep::mouse_event (string ev, int x, int y, time_t t) {
374 if (nil (gui->grab_ptr) || (get_x_window (gui->grab_ptr->item) == NULL)) {
375 set_origin (0, 0);
376 encode (x, y);
377 send_mouse (w, ev, x, y, gui->state, t);
379 else {
380 x_window grab_win= get_x_window (gui->grab_ptr->item);
381 if (this != grab_win) {
382 x += win_x - grab_win->win_x;
383 y += win_y - grab_win->win_y;
384 // return;
386 set_origin (0, 0);
387 encode (x, y);
388 send_mouse (gui->grab_ptr->item, ev, x, y, gui->state, t);
392 void
393 x_window_rep::repaint_invalid_regions () {
394 //if (!nil (invalid_regions)) cout << invalid_regions << "\n";
395 //else { cout << "."; cout.flush (); }
396 rectangles new_regions;
397 if (!nil (invalid_regions)) {
398 rectangle lub= least_upper_bound (invalid_regions);
399 if (area (lub) < 1.2 * area (invalid_regions))
400 invalid_regions= rectangles (lub);
402 while (!nil (invalid_regions)) {
403 set_origin (0, 0);
404 rectangle r= copy (invalid_regions->item);
405 encode (r->x1, r->y1);
406 encode (r->x2, r->y2);
407 x_drawable_rep::set_clipping (r->x1, r->y2, r->x2, r->y1);
408 send_repaint (w, r->x1, r->y2, r->x2, r->y1);
409 if (interrupted ())
410 new_regions= rectangles (invalid_regions->item, new_regions);
411 invalid_regions= invalid_regions->next;
413 invalid_regions= new_regions;
416 void
417 x_window_rep::set_keyboard_focus (widget wid, bool get_focus) {
418 if (!get_focus)
419 fatal_error ("Explicit loss of keyboard focus not yet implemented",
420 "x_window_rep::set_keyboard_focus");
421 if (has_focus && (kbd_focus != wid.rep)) {
422 notify_keyboard_focus (kbd_focus, false);
423 notify_keyboard_focus (wid, true);
425 kbd_focus= wid.rep;
428 bool
429 x_window_rep::get_keyboard_focus (widget wid) {
430 return has_focus && kbd_focus == wid.rep;
433 void
434 x_window_rep::set_mouse_grab (widget wid, bool get_grab) {
435 if (get_grab) gui->obtain_mouse_grab (wid);
436 else gui->release_mouse_grab ();
439 bool
440 x_window_rep::get_mouse_grab (widget w) {
441 return gui->has_mouse_grab (w);
444 void
445 x_window_rep::set_mouse_pointer (widget wid, string name, string mask) {
446 if (mask == "") gui->set_mouse_pointer (wid, name);
447 else gui->set_mouse_pointer (wid, name, mask);
450 /******************************************************************************
451 * Delayed messages
452 ******************************************************************************/
454 message_rep::message_rep (widget wid2, string s2, time_t t2):
455 wid (wid2), s (s2), t (t2) {}
456 message::message (widget wid, string s, time_t t):
457 rep (new message_rep (wid, s, t)) {}
459 ostream&
460 operator << (ostream& out, message m) {
461 return out << "message " << m->s << " to " << m->wid
462 << "at time " << m->t << "\n";
465 static list<message>
466 insert_message (list<message> l, widget wid, string s, time_t cur, time_t t) {
467 if (nil (l)) return list<message> (message (wid, s, t));
468 time_t ref= l->item->t;
469 if ((t-cur) <= (ref-cur)) return list<message> (message (wid, s, t), l);
470 return list<message> (l->item, insert_message (l->next, wid, s, cur, t));
473 void
474 x_window_rep::delayed_message (widget wid, string s, time_t delay) {
475 time_t ct= texmacs_time ();
476 the_gui->messages= insert_message (the_gui->messages, wid, s, ct, ct+ delay);
479 /******************************************************************************
480 * Routines concerning regions in a window
481 ******************************************************************************/
483 void
484 x_window_rep::translate (SI x1, SI y1, SI x2, SI y2, SI dx, SI dy) {
485 SI X1= x1+ dx;
486 SI Y2= y2+ dy;
487 decode (x1, y1);
488 decode (x2, y2);
489 decode (X1, Y2);
490 dx= X1- x1;
491 dy= Y2- y2;
493 XEvent report;
494 while (XCheckWindowEvent (dpy, win, ExposureMask, &report))
495 gui->process_event (this, &report);
497 rectangles region (rectangle (x1, y2, x2, y1));
498 rectangles invalid_intern= invalid_regions & region;
499 rectangles invalid_extern= invalid_regions - invalid_intern;
500 invalid_intern = ::translate (invalid_intern, dx, dy) & region;
501 invalid_regions= invalid_extern | invalid_intern;
503 if (x1<x2 && y2<y1)
504 XCopyArea (dpy, win, win, gc, x1, y2, x2-x1, y1-y2, X1, Y2);
507 void
508 x_window_rep::invalidate (SI x1, SI y1, SI x2, SI y2) {
509 outer_round (x1, y1, x2, y2);
510 decode (x1, y1);
511 decode (x2, y2);
512 invalidate_event (x1, y2, x2, y1);
515 bool
516 x_window_rep::repainted () {
517 return nil (invalid_regions);
520 /******************************************************************************
521 * Interface
522 ******************************************************************************/
524 window
525 popup_window (widget w, string name, SI min_w, SI min_h,
526 SI def_w, SI def_h, SI max_w, SI max_h)
528 char* _name= as_charp (name);
529 window win= new x_window_rep (w, the_gui, NULL,
530 min_w, min_h, def_w, def_h, max_w, max_h);
531 delete[] _name;
532 return win;
535 window
536 plain_window (widget w, string name, SI min_w, SI min_h,
537 SI def_w, SI def_h, SI max_w, SI max_h)
539 char* _name= as_charp (name);
540 window win= new x_window_rep (w, the_gui, _name,
541 min_w, min_h, def_w, def_h, max_w, max_h);
542 delete[] _name;
543 return win;