1 /* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */
2
3 #include "ui_window.h"
4
5 #include <stdlib.h> /* abs */
6 #include <string.h> /* memset/memcpy */
7 #include <pobl/bl_debug.h>
8 #include <pobl/bl_mem.h> /* realloc/free */
9
10 #include "../ui_xic.h"
11 #include "../ui_picture.h"
12 #include "../ui_imagelib.h"
13 #ifndef DISABLE_XDND
14 #include "../ui_dnd.h"
15 #endif
16
17 #include "ui_display.h" /* ui_display_get_cursor */
18 #include "beos.h"
19
20 /* win->width is not multiples of (win)->width_inc if window is maximized. */
21 #define RIGHT_MARGIN(win) \
22 ((win)->width_inc ? ((win)->width - (win)->min_width) % (win)->width_inc : 0)
23 #define BOTTOM_MARGIN(win) \
24 ((win)->height_inc ? ((win)->height - (win)->min_height) % (win)->height_inc : 0)
25
26 #define ParentRelative (1L)
27
28 #define IS_UILAYOUT(win) ((win)->child_window_resized)
29 #define IS_IM_WINDOW(win) ((win)->window_resized == NULL)
30
31 #if 0
32 #define DEBUG_SCROLLABLE
33 #endif
34
35 #if 0
36 #define __DEBUG
37 #endif
38
39 /* --- static variables --- */
40
41 static int click_interval = 250; /* millisecond, same as xterm. */
42 static int use_urgent_bell;
43
44 /* --- static functions --- */
45
urgent_bell(ui_window_t * win,int on)46 static void urgent_bell(ui_window_t *win, int on) {
47 if (use_urgent_bell && (!win->is_focused || !on)) {
48 win = ui_get_root_window(win);
49
50 app_urgent_bell(on);
51 }
52 }
53
notify_focus_in_to_children(ui_window_t * win)54 static void notify_focus_in_to_children(ui_window_t *win) {
55 u_int count;
56
57 if (!win->is_focused) {
58 if (win->inputtable > 0 || win->parent == NULL) /* check_scrollable checks root->is_focused */
59 {
60 win->is_focused = 1;
61 }
62
63 if (win->inputtable > 0) {
64 ui_xic_set_focus(win);
65
66 if (win->window_focused) {
67 (*win->window_focused)(win);
68 }
69 }
70 }
71
72 for (count = 0; count < win->num_children; count++) {
73 notify_focus_in_to_children(win->children[count]);
74 }
75 }
76
notify_focus_out_to_children(ui_window_t * win)77 static void notify_focus_out_to_children(ui_window_t *win) {
78 u_int count;
79
80 if (win->is_focused) {
81 win->is_focused = 0;
82
83 ui_xic_unset_focus(win);
84
85 if (win->window_unfocused) {
86 (*win->window_unfocused)(win);
87 }
88 }
89
90 for (count = 0; count < win->num_children; count++) {
91 notify_focus_out_to_children(win->children[count]);
92 }
93 }
94
notify_move_to_children(ui_window_t * win)95 static void notify_move_to_children(ui_window_t *win) {
96 int count;
97
98 for (count = 0; count < win->num_children; count++) {
99 notify_move_to_children(win->children[count]);
100 }
101 }
102
max_width_inc(ui_window_t * win)103 static u_int max_width_inc(ui_window_t *win) {
104 u_int count;
105 u_int width_inc;
106
107 width_inc = win->width_inc;
108
109 for (count = 0; count < win->num_children; count++) {
110 if (win->children[count]->is_mapped &&
111 (win->children[count]->sizehint_flag & SIZEHINT_WIDTH)) {
112 u_int sub_inc;
113
114 /*
115 * XXX
116 * we should calculate least common multiple of width_inc and sub_inc.
117 */
118 if ((sub_inc = max_width_inc(win->children[count])) > width_inc) {
119 width_inc = sub_inc;
120 }
121 }
122 }
123
124 return width_inc;
125 }
126
max_height_inc(ui_window_t * win)127 static u_int max_height_inc(ui_window_t *win) {
128 u_int count;
129 u_int height_inc;
130
131 height_inc = win->height_inc;
132
133 for (count = 0; count < win->num_children; count++) {
134 if (win->children[count]->is_mapped &&
135 (win->children[count]->sizehint_flag & SIZEHINT_HEIGHT)) {
136 u_int sub_inc;
137
138 /*
139 * XXX
140 * we should calculate least common multiple of width_inc and sub_inc.
141 */
142 if ((sub_inc = max_height_inc(win->children[count])) > height_inc) {
143 height_inc = sub_inc;
144 }
145 }
146 }
147
148 return height_inc;
149 }
150
reset_input_focus(ui_window_t * win)151 static void reset_input_focus(ui_window_t *win) {
152 u_int count;
153
154 if (win->inputtable) {
155 win->inputtable = -1;
156 } else {
157 win->inputtable = 0;
158 }
159
160 for (count = 0; count < win->num_children; count++) {
161 reset_input_focus(win->children[count]);
162 }
163 }
164
clear_margin_area(ui_window_t * win)165 static void clear_margin_area(ui_window_t *win) {
166 void *view;
167 u_int right_margin;
168 u_int bottom_margin;
169 u_int win_width;
170 u_int win_height;
171
172 if (win->parent) {
173 view = win->my_window;
174 } else if (!(view = window_get_orphan(win->my_window, 0))) {
175 return;
176 }
177
178 right_margin = RIGHT_MARGIN(win);
179 bottom_margin = BOTTOM_MARGIN(win);
180 win_width = win->width - right_margin;
181 win_height = win->height - bottom_margin;
182
183 if (win->wall_picture) {
184 Pixmap pic;
185 int src_x;
186 int src_y;
187
188 if (win->wall_picture == ParentRelative) {
189 pic = win->parent->wall_picture;
190 src_x = win->x;
191 src_y = win->y;
192 } else {
193 pic = win->wall_picture;
194 src_x = src_y = 0;
195 }
196
197 if (win->hmargin > 0 || right_margin > 0) {
198 view_copy_area(view, pic, src_x, src_y, win->hmargin, ACTUAL_HEIGHT(win), 0, 0);
199 view_copy_area(view, pic, src_x + win_width + win->hmargin, src_y,
200 win->hmargin + right_margin, ACTUAL_HEIGHT(win), win_width + win->hmargin, 0);
201 }
202
203 if (win->vmargin > 0 || bottom_margin > 0) {
204 view_copy_area(view, pic, src_x + win->hmargin, src_y, win_width, win->vmargin,
205 win->hmargin, 0);
206 view_copy_area(view, pic, src_x + win->hmargin, src_y + win_height + win->vmargin,
207 win_width, win->vmargin + bottom_margin, win->hmargin,
208 win_height + win->vmargin);
209 }
210 } else {
211 if (win->hmargin > 0 || right_margin > 0) {
212 view_fill_with(view, &win->bg_color, 0, 0, win->hmargin, ACTUAL_HEIGHT(win));
213 view_fill_with(view, &win->bg_color, win_width + win->hmargin, 0,
214 ACTUAL_WIDTH(win) - win_width - win->hmargin, ACTUAL_HEIGHT(win));
215 }
216
217 if (win->vmargin > 0 || bottom_margin > 0) {
218 view_fill_with(view, &win->bg_color, win->hmargin, 0, win_width, win->vmargin);
219 view_fill_with(view, &win->bg_color, win->hmargin, win_height + win->vmargin,
220 win_width, ACTUAL_HEIGHT(win) - win_height - win->vmargin);
221 }
222 }
223 }
224
clear_margin_area_all(ui_window_t * win)225 static void clear_margin_area_all(ui_window_t *win) {
226 u_int count;
227
228 clear_margin_area(win);
229
230 for (count = 0; count < win->num_children; count++) {
231 clear_margin_area_all(win->children[count]);
232 }
233 }
234
expose(ui_window_t * win,XExposeEvent * event)235 static void expose(ui_window_t *win, XExposeEvent *event) {
236 int clear_margin;
237
238 if (event->force_expose) {
239 event->x = win->hmargin;
240 event->y = win->vmargin;
241 event->width = win->width;
242 event->height = win->height;
243 clear_margin = 1;
244 } else if (win->update_window_flag) {
245 if (win->update_window) {
246 (*win->update_window)(win, win->update_window_flag);
247 }
248
249 return;
250 } else {
251 clear_margin = 0;
252
253 if (event->x < win->hmargin) {
254 event->width -= (win->hmargin - event->x);
255 event->x = win->hmargin;
256 clear_margin = 1;
257 }
258
259 if (event->y < win->vmargin) {
260 event->height -= (win->vmargin - event->y);
261 event->y = win->vmargin;
262 clear_margin = 1;
263 }
264
265 if (!clear_margin && (event->x + event->width > win->hmargin + win->width ||
266 event->y + event->height > win->vmargin + win->height)) {
267 clear_margin = 1;
268 }
269 }
270
271 if (clear_margin) {
272 clear_margin_area(win);
273 }
274
275 if (win->window_exposed) {
276 (*win->window_exposed)(win, event->x - win->hmargin, event->y - win->vmargin, event->width,
277 event->height);
278 }
279 }
280
281 /* --- global functions --- */
282
ui_window_init(ui_window_t * win,u_int width,u_int height,u_int min_width,u_int min_height,u_int width_inc,u_int height_inc,u_int hmargin,u_int vmargin,int create_gc,int inputtable)283 int ui_window_init(ui_window_t *win, u_int width, u_int height, u_int min_width, u_int min_height,
284 u_int width_inc, u_int height_inc, u_int hmargin, u_int vmargin,
285 int create_gc, /* ignored */
286 int inputtable) {
287 memset(win, 0, sizeof(ui_window_t));
288
289 win->fg_color.pixel = 0xff000000;
290 win->bg_color.pixel = 0xffffffff;
291
292 win->is_scrollable = 0;
293
294 win->is_focused = 0;
295
296 win->inputtable = inputtable;
297
298 /* This flag will map window automatically in ui_window_show(). */
299 win->is_mapped = 1;
300
301 win->create_gc = create_gc;
302
303 win->width = width;
304 win->height = height;
305 win->min_width = min_width;
306 win->min_height = min_height;
307 win->width_inc = width_inc;
308 win->height_inc = height_inc;
309 win->sizehint_flag = SIZEHINT_WIDTH|SIZEHINT_HEIGHT;
310 win->hmargin = hmargin;
311 win->vmargin = vmargin;
312
313 win->prev_clicked_button = -1;
314
315 win->app_name = "mlterm";
316
317 return 1;
318 }
319
ui_window_final(ui_window_t * win)320 void ui_window_final(ui_window_t *win) {
321 u_int count;
322 Window my_window;
323 int is_window;
324
325 #ifdef __DEBUG
326 bl_debug_printf("[deleting child windows]\n");
327 ui_window_dump_children(win);
328 #endif
329
330 for (count = 0; count < win->num_children; count++) {
331 ui_window_final(win->children[count]);
332 }
333
334 my_window = win->my_window;
335 if (win->my_window) {
336 /*
337 * win->parent may be NULL because this function is called
338 * from ui_layout after ui_window_remove_child(),
339 * not only win->parent but also IS_UILAYOUT(win) is necessary.
340 */
341 if (!win->parent && (IS_UILAYOUT(win) || IS_IM_WINDOW(win))) {
342 is_window = 1;
343 } else {
344 is_window = -1;
345 }
346
347 win->my_window = None;
348 } else {
349 is_window = 0;
350 }
351
352 free(win->children);
353 win->num_children = 0;
354
355 ui_display_clear_selection(win->disp, win);
356
357 ui_xic_deactivate(win);
358
359 if (win->window_finalized) {
360 (*win->window_finalized)(win);
361 }
362
363 if (is_window == 1) {
364 window_dealloc(my_window);
365 /* Not reach. */
366 } else if (is_window == -1) {
367 view_dealloc(my_window);
368 }
369 }
370
ui_window_set_type_engine(ui_window_t * win,ui_type_engine_t type_engine)371 void ui_window_set_type_engine(ui_window_t *win, ui_type_engine_t type_engine) {}
372
ui_window_add_event_mask(ui_window_t * win,long event_mask)373 void ui_window_add_event_mask(ui_window_t *win, long event_mask) {
374 if (event_mask & PointerMotionMask) {
375 win->event_mask = PointerMotionMask;
376 }
377 }
378
ui_window_remove_event_mask(ui_window_t * win,long event_mask)379 void ui_window_remove_event_mask(ui_window_t *win, long event_mask) {
380 if (event_mask & PointerMotionMask) {
381 win->event_mask = 0;
382 }
383 }
384
ui_window_ungrab_pointer(ui_window_t * win)385 void ui_window_ungrab_pointer(ui_window_t *win) {}
386
ui_window_set_wall_picture(ui_window_t * win,Pixmap pic,int do_expose)387 int ui_window_set_wall_picture(ui_window_t *win, Pixmap pic, int do_expose) {
388 u_int count;
389
390 win->wall_picture = pic;
391
392 #if 1
393 if (win->my_window != None && do_expose) {
394 if (win->parent) {
395 view_update(win->my_window, 1);
396 } else {
397 void *view;
398
399 if ((view = window_get_orphan(win->my_window, 0))) {
400 view_update(view, 1);
401 }
402 }
403 }
404 #endif
405
406 for (count = 0; count < win->num_children; count++) {
407 ui_window_set_wall_picture(win->children[count], ParentRelative, do_expose);
408 }
409
410 return 1;
411 }
412
ui_window_unset_wall_picture(ui_window_t * win,int do_expose)413 int ui_window_unset_wall_picture(ui_window_t *win, int do_expose) {
414 u_int count;
415
416 win->wall_picture = None;
417
418 if (win->my_window != None) {
419 #if 0
420 InvalidateRect(win->my_window, NULL, FALSE);
421 #endif
422 }
423
424 for (count = 0; count < win->num_children; count++) {
425 ui_window_unset_wall_picture(win->children[count], do_expose);
426 }
427
428 return 1;
429 }
430
ui_window_set_transparent(ui_window_t * win,ui_picture_modifier_t * pic_mod)431 int ui_window_set_transparent(ui_window_t *win, ui_picture_modifier_t *pic_mod) { return 0; }
432
ui_window_unset_transparent(ui_window_t * win)433 int ui_window_unset_transparent(ui_window_t *win) { return 0; }
434
ui_window_set_cursor(ui_window_t * win,u_int cursor_shape)435 void ui_window_set_cursor(ui_window_t *win, u_int cursor_shape) {
436 win->cursor_shape = cursor_shape;
437 }
438
ui_window_set_fg_color(ui_window_t * win,ui_color_t * fg_color)439 int ui_window_set_fg_color(ui_window_t *win, ui_color_t *fg_color) {
440 if (win->fg_color.pixel == fg_color->pixel) {
441 return 0;
442 }
443
444 win->fg_color = *fg_color;
445
446 return 1;
447 }
448
ui_window_set_bg_color(ui_window_t * win,ui_color_t * bg_color)449 int ui_window_set_bg_color(ui_window_t *win, ui_color_t *bg_color) {
450 if (win->bg_color.pixel == bg_color->pixel) {
451 return 0;
452 }
453
454 win->bg_color = *bg_color;
455
456 if (win->my_window && win->parent) {
457 view_bg_color_changed(win->my_window);
458 ui_window_update_all(win);
459 }
460
461 return 1;
462 }
463
ui_window_add_child(ui_window_t * win,ui_window_t * child,int x,int y,int map)464 int ui_window_add_child(ui_window_t *win, ui_window_t *child, int x, int y, int map) {
465 void *p;
466
467 if ((p = realloc(win->children, sizeof(*win->children) * (win->num_children + 1))) == NULL) {
468 #ifdef DEBUG
469 bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n");
470 #endif
471
472 return 0;
473 }
474
475 win->children = p;
476
477 child->parent = win;
478 child->x = x + win->hmargin;
479 child->y = y + win->vmargin;
480
481 if (!(child->is_mapped = map) && child->inputtable > 0) {
482 child->inputtable = -1;
483 }
484
485 win->children[win->num_children++] = child;
486
487 return 1;
488 }
489
ui_window_remove_child(ui_window_t * win,ui_window_t * child)490 int ui_window_remove_child(ui_window_t *win, ui_window_t *child) {
491 u_int count;
492
493 for (count = 0; count < win->num_children; count++) {
494 if (win->children[count] == child) {
495 child->parent = NULL;
496 win->children[count] = win->children[--win->num_children];
497
498 return 1;
499 }
500 }
501
502 return 0;
503 }
504
ui_window_get_fg_gc(ui_window_t * win)505 GC ui_window_get_fg_gc(ui_window_t *win) { return None; }
506
ui_window_get_bg_gc(ui_window_t * win)507 GC ui_window_get_bg_gc(ui_window_t *win) { return None; }
508
ui_get_root_window(ui_window_t * win)509 ui_window_t *ui_get_root_window(ui_window_t *win) {
510 while (win->parent != NULL) {
511 win = win->parent;
512 }
513
514 return win;
515 }
516
ui_window_show(ui_window_t * win,int hint)517 int ui_window_show(ui_window_t *win,
518 int hint /* If win->parent(_window) is None,
519 specify XValue|YValue to localte window at win->x/win->y. */
520 ) {
521 u_int count;
522
523 if (win->my_window) {
524 /* already shown */
525
526 return 0;
527 }
528
529 #ifndef USE_BEOS
530 if (hint & XNegative) {
531 win->x += (win->disp->width - ACTUAL_WIDTH(win));
532 }
533
534 if (hint & YNegative) {
535 win->y += (win->disp->height - ACTUAL_HEIGHT(win));
536 }
537 #endif
538
539 if (win->parent) {
540 win->disp = win->parent->disp;
541 win->parent_window = win->parent->my_window;
542 win->gc = win->parent->gc;
543
544 view_alloc(win, win->x, win->y, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win));
545 } else {
546 window_alloc(win, win->x, win->y, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win),
547 IS_IM_WINDOW(win), hint);
548 }
549
550 #ifndef DISABLE_XDND
551 /* DragAcceptFiles( win->my_window , TRUE) ; */
552 #endif
553
554 if (win->parent && !win->parent->is_transparent && win->parent->wall_picture) {
555 ui_window_set_wall_picture(win, ParentRelative, 0);
556 }
557
558 /*
559 * This should be called after Window Manager settings, because
560 * ui_set_{window|icon}_name() can be called in win->window_realized().
561 */
562 if (win->window_realized) {
563 (*win->window_realized)(win);
564 }
565
566 /*
567 * showing child windows.
568 */
569
570 for (count = 0; count < win->num_children; count++) {
571 ui_window_show(win->children[count], 0);
572 }
573
574 if (!win->parent) {
575 window_show(win->my_window);
576 }
577
578 /*
579 * really visualized.
580 */
581
582 if (win->is_mapped) {
583 if (win->inputtable > 0) {
584 reset_input_focus(ui_get_root_window(win));
585 win->inputtable = 1;
586 }
587 }
588
589 if (win->is_transparent) {
590 ui_window_set_transparent(win, win->pic_mod);
591 }
592
593 return 1;
594 }
595
ui_window_map(ui_window_t * win)596 void ui_window_map(ui_window_t *win) {
597 if (win->is_mapped) {
598 return;
599 }
600
601 if (win->parent) {
602 view_set_hidden(win->my_window, 0);
603 }
604
605 win->is_mapped = 1;
606 }
607
ui_window_unmap(ui_window_t * win)608 void ui_window_unmap(ui_window_t *win) {
609 if (!win->is_mapped) {
610 return;
611 }
612
613 if (win->parent) {
614 view_set_hidden(win->my_window, 1);
615
616 #if 0
617 /* Scrollbar position is corrupt without this. */
618 ui_window_move(win, -1, -1);
619 #endif
620 }
621
622 win->is_mapped = 0;
623 }
624
ui_window_resize(ui_window_t * win,u_int width,u_int height,ui_resize_flag_t flag)625 int ui_window_resize(ui_window_t *win, u_int width, /* excluding margin */
626 u_int height, /* excluding margin */
627 ui_resize_flag_t flag /* NOTIFY_TO_PARENT , NOTIFY_TO_MYSELF */
628 ) {
629 if (win->width == width && win->height == height) {
630 return 0;
631 }
632
633 /* Max width of each window is screen width. */
634 if ((flag & LIMIT_RESIZE) && win->disp->width < width) {
635 win->width = win->disp->width - win->hmargin * 2;
636 } else {
637 win->width = width;
638 }
639
640 /* Max.height of each window is screen height. */
641 if ((flag & LIMIT_RESIZE) && win->disp->height < height) {
642 win->height = win->disp->height - win->vmargin * 2;
643 } else {
644 win->height = height;
645 }
646
647 if (win->parent) {
648 view_resize(win->my_window, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win));
649
650 if ((flag & NOTIFY_TO_PARENT) && win->parent->child_window_resized) {
651 (*win->parent->child_window_resized)(win->parent, win);
652 }
653 } else {
654 /*
655 * win->parent may be NULL because this function is called
656 * from ui_layout after ui_window_remove_child(),
657 * not only win->parent but also IS_UILAYOUT(win) is necessary.
658 */
659 if (IS_UILAYOUT(win) || IS_IM_WINDOW(win)) {
660 window_resize(win->my_window, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win));
661 }
662 }
663
664 if ((flag & NOTIFY_TO_MYSELF) && win->window_resized) {
665 (*win->window_resized)(win);
666 win->update_window_flag = 0; /* force redraw */
667 }
668
669 return 1;
670 }
671
672 /*
673 * !! Notice !!
674 * This function is not recommended.
675 * Use ui_window_resize if at all possible.
676 */
ui_window_resize_with_margin(ui_window_t * win,u_int width,u_int height,ui_resize_flag_t flag)677 int ui_window_resize_with_margin(ui_window_t *win, u_int width, u_int height,
678 ui_resize_flag_t flag /* NOTIFY_TO_PARENT , NOTIFY_TO_MYSELF */
679 ) {
680 return ui_window_resize(win, width - win->hmargin * 2, height - win->vmargin * 2, flag);
681 }
682
ui_window_set_maximize_flag(ui_window_t * win,ui_maximize_flag_t flag)683 void ui_window_set_maximize_flag(ui_window_t *win, ui_maximize_flag_t flag) {
684 if (flag) {
685 u_int w;
686 u_int h;
687 int x;
688 int y;
689
690 win = ui_get_root_window(win);
691
692 window_get_position(win->my_window, &x, &y);
693
694 if (flag & MAXIMIZE_HORIZONTAL) {
695 w = win->disp->width;
696 x = 0;
697 } else {
698 w = win->width;
699 }
700
701 if (flag & MAXIMIZE_VERTICAL) {
702 h = win->disp->height;
703 y = 0;
704 } else {
705 h = win->height;
706 }
707
708 window_resize(win->my_window, w, h);
709 window_move(win->my_window, x, y);
710
711 /* Same processing as ui_window_resize() */
712 if (win->window_resized) {
713 (*win->window_resized)(win);
714 win->update_window_flag = 0; /* force redraw */
715 }
716 } else {
717 /* XXX MAXIMIZE_RESTORE is not supported for now. */
718 }
719 }
720
ui_window_set_normal_hints(ui_window_t * win,u_int min_width,u_int min_height,u_int width_inc,u_int height_inc)721 void ui_window_set_normal_hints(ui_window_t *win, u_int min_width, u_int min_height,
722 u_int width_inc, u_int height_inc) {
723 win->min_width = min_width;
724 win->min_height = min_height;
725 win->width_inc = width_inc;
726 win->height_inc = height_inc;
727 }
728
ui_window_set_override_redirect(ui_window_t * win,int flag)729 void ui_window_set_override_redirect(ui_window_t *win, int flag) {}
730
ui_window_set_borderless_flag(ui_window_t * win,int flag)731 int ui_window_set_borderless_flag(ui_window_t *win, int flag) { return 0; }
732
ui_window_move(ui_window_t * win,int x,int y)733 int ui_window_move(ui_window_t *win, int x, int y) {
734 if (win->parent) {
735 x += win->parent->hmargin;
736 y += win->parent->vmargin;
737 }
738
739 if (win->x == x && win->y == y) {
740 return 0;
741 }
742
743 win->x = x;
744 win->y = y;
745
746 if (win->parent) {
747 view_move(win->my_window, x, y);
748 } else {
749 window_move(win->my_window, x, y);
750 }
751
752 return 1;
753 }
754
755 /*
756 * This function can be used in context except window_exposed and update_window
757 * events.
758 */
ui_window_clear(ui_window_t * win,int x,int y,u_int width,u_int height)759 void ui_window_clear(ui_window_t *win, int x, int y, u_int width, u_int height) {
760 void *view;
761
762 #ifdef AUTO_CLEAR_MARGIN
763 if (x + width >= win->width) {
764 /* Clearing margin area */
765 width += win->hmargin;
766 }
767
768 if (x > 0)
769 #endif
770 {
771 x += win->hmargin;
772 }
773 #ifdef AUTO_CLEAR_MARGIN
774 else {
775 /* Clearing margin area */
776 width += win->hmargin;
777 }
778
779 if (y + height >= win->height) {
780 /* Clearing margin area */
781 height += win->vmargin;
782 }
783
784 if (y > 0)
785 #endif
786 {
787 y += win->vmargin;
788 }
789 #ifdef AUTO_CLEAR_MARGIN
790 else {
791 /* Clearing margin area */
792 height += win->vmargin;
793 }
794 #endif
795
796 if (win->parent) {
797 view = win->my_window;
798 } else if (!(view = window_get_orphan(win->my_window, 0))) {
799 return;
800 }
801
802 if (win->wall_picture) {
803 Pixmap pic;
804 int src_x;
805 int src_y;
806
807 if (win->wall_picture == ParentRelative) {
808 pic = win->parent->wall_picture;
809 src_x = win->x;
810 src_y = win->y;
811 } else {
812 pic = win->wall_picture;
813 src_x = src_y = 0;
814 }
815
816 view_copy_area(view, pic, src_x + x, src_y + y, width, height, x, y);
817 } else {
818 view_fill_with(view, &win->bg_color, x, y, width, height);
819 }
820 }
821
ui_window_clear_all(ui_window_t * win)822 void ui_window_clear_all(ui_window_t *win) {
823 ui_window_clear(win, 0, 0, win->width, win->height);
824 }
825
ui_window_fill(ui_window_t * win,int x,int y,u_int width,u_int height)826 void ui_window_fill(ui_window_t *win, int x, int y, u_int width, u_int height) {
827 ui_window_fill_with(win, &win->fg_color, x, y, width, height);
828 }
829
ui_window_fill_with(ui_window_t * win,ui_color_t * color,int x,int y,u_int width,u_int height)830 void ui_window_fill_with(ui_window_t *win, ui_color_t *color, int x, int y, u_int width,
831 u_int height) {
832 void *view;
833
834 if (win->parent) {
835 view = win->my_window;
836 } else if (!(view = window_get_orphan(win->my_window, 0))) {
837 return;
838 }
839
840 view_fill_with(view, color, x + win->hmargin, y + win->vmargin, width, height);
841 }
842
843 /*
844 * This function can be used in context except window_exposed and update_window
845 * events.
846 */
ui_window_blank(ui_window_t * win)847 void ui_window_blank(ui_window_t *win) {}
848
849 #if 0
850 /*
851 * XXX
852 * at the present time , not used and not maintained.
853 */
854 void ui_window_fill_all_with(ui_window_t *win, ui_color_t *color) {}
855 #endif
856
ui_window_update(ui_window_t * win,int flag)857 void ui_window_update(ui_window_t *win, int flag) {
858 void *view;
859
860 if (win->parent) {
861 view = win->my_window;
862 }
863 /*
864 * ui_screen which is removed and becomes an orphan is resized by
865 * ui_window_resize() in ui_layout_remove_child(), then ui_window_update()
866 * is called.
867 * In this case win->parent is NULL but win->my_window is not MLWindow* but
868 * MLView*, so window_get_orphan(win->my_window) fails.
869 * 'if ((!IS_UILAYOUT(win) && !IS_IM_WINDOW(win)))' avoids the failure.
870 */
871 else if ((!IS_UILAYOUT(win) && !IS_IM_WINDOW(win)) ||
872 !(view = window_get_orphan(win->my_window, 0))) {
873 return;
874 }
875
876 win->update_window_flag |= flag;
877 view_update(view, 0);
878 }
879
ui_window_update_all(ui_window_t * win)880 void ui_window_update_all(ui_window_t *win) {
881 void *view;
882 u_int count;
883
884 if (win->parent) {
885 view = win->my_window;
886 } else if (!(view = window_get_orphan(win->my_window, 0))) {
887 return;
888 }
889
890 view_update(view, 1);
891
892 for (count = 0; count < win->num_children; count++) {
893 ui_window_update_all(win->children[count]);
894 }
895 }
896
ui_window_idling(ui_window_t * win)897 void ui_window_idling(ui_window_t *win) {
898 u_int count;
899
900 for (count = 0; count < win->num_children; count++) {
901 ui_window_idling(win->children[count]);
902 }
903
904 #ifdef __DEBUG
905 if (win->button_is_pressing) {
906 bl_debug_printf(BL_DEBUG_TAG " button is pressing...\n");
907 }
908 #endif
909
910 if (win->button_is_pressing && win->button_press_continued) {
911 (*win->button_press_continued)(win, &win->prev_button_press_event);
912 } else if (win->idling) {
913 (*win->idling)(win);
914 }
915 }
916
917 /*
918 * Return value: 0 => different window.
919 * 1 => finished processing.
920 * -1 => continuing default processing.
921 */
ui_window_receive_event(ui_window_t * win,XEvent * event)922 int ui_window_receive_event(ui_window_t *win, XEvent *event) {
923 switch (event->type) {
924 case UI_KEY_FOCUS_IN:
925 reset_input_focus(ui_get_root_window(win));
926 win->inputtable = 1;
927 win = ui_get_root_window(win);
928 notify_focus_out_to_children(win);
929 /* Fall through */
930
931 case UI_FOCUS_IN:
932 urgent_bell(win, 0);
933 notify_focus_in_to_children(win);
934 break;
935
936 case UI_FOCUS_OUT:
937 notify_focus_out_to_children(win);
938 break;
939
940 case UI_BUTTON_PRESS:
941 if (win->button_pressed) {
942 XButtonEvent *bev;
943
944 bev = (XButtonEvent*)event;
945 bev->x -= win->hmargin;
946 bev->y -= win->vmargin;
947
948 (*win->button_pressed)(win, bev, bev->click_count);
949
950 win->button_is_pressing = 1;
951 win->prev_button_press_event = *bev;
952 }
953 break;
954
955 case UI_BUTTON_RELEASE:
956 if (win->button_released) {
957 XButtonEvent *bev;
958
959 bev = (XButtonEvent*)event;
960 bev->x -= win->hmargin;
961 bev->y -= win->vmargin;
962
963 (*win->button_released)(win, bev);
964
965 win->button_is_pressing = 0;
966 }
967 break;
968
969 case UI_BUTTON_MOTION:
970 if (win->button_motion) {
971 XMotionEvent *mev;
972
973 mev = (XMotionEvent*)event;
974 mev->x -= win->hmargin;
975 mev->y -= win->vmargin;
976
977 (*win->button_motion)(win, mev);
978
979 /* following button motion ... */
980 win->prev_button_press_event.x = mev->x;
981 win->prev_button_press_event.y = mev->y;
982 win->prev_button_press_event.time = mev->time;
983 }
984 break;
985
986 case UI_POINTER_MOTION:
987 if (win->pointer_motion) {
988 XMotionEvent *mev;
989
990 mev = (XMotionEvent*)event;
991 mev->x -= win->hmargin;
992 mev->y -= win->vmargin;
993
994 (*win->pointer_motion)(win, mev);
995 }
996 break;
997
998 case UI_KEY_PRESS:
999 if (win->key_pressed) {
1000 (*win->key_pressed)(win, (XKeyEvent*)event);
1001 }
1002 break;
1003
1004 case UI_EXPOSE:
1005 expose(win, (XExposeEvent*)event);
1006 break;
1007
1008 case UI_SELECTION_REQUESTED:
1009 if (win->utf_selection_requested) {
1010 (*win->utf_selection_requested)(win, (XSelectionRequestEvent*)event, 0);
1011 }
1012 break;
1013
1014 case UI_SELECTION_NOTIFIED:
1015 if (win->utf_selection_notified) {
1016 (*win->utf_selection_notified)(win, ((XSelectionNotifyEvent*)event)->data,
1017 ((XSelectionNotifyEvent*)event)->len);
1018 }
1019 break;
1020
1021 case UI_CLOSE_WINDOW:
1022 /* root window */
1023 if (win->window_destroyed) {
1024 (*win->window_destroyed)(win);
1025 }
1026 break;
1027
1028 case UI_RESIZE:
1029 if (win->window_resized) {
1030 (*win->window_resized)(win);
1031 }
1032 clear_margin_area_all(win);
1033
1034 break;
1035 }
1036
1037 return 1;
1038 }
1039
ui_window_get_str(ui_window_t * win,u_char * seq,size_t seq_len,ef_parser_t ** parser,KeySym * keysym,XKeyEvent * event)1040 size_t ui_window_get_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser,
1041 KeySym *keysym, XKeyEvent *event) {
1042 return ui_xic_get_str(win, seq, seq_len, parser, keysym, event);
1043 }
1044
1045 /*
1046 * Scroll functions.
1047 * The caller side should clear the scrolled area.
1048 */
1049
ui_window_scroll_upward(ui_window_t * win,u_int height)1050 int ui_window_scroll_upward(ui_window_t *win, u_int height) {
1051 return ui_window_scroll_upward_region(win, 0, win->height, height);
1052 }
1053
ui_window_scroll_upward_region(ui_window_t * win,int boundary_start,int boundary_end,u_int height)1054 int ui_window_scroll_upward_region(ui_window_t *win, int boundary_start, int boundary_end,
1055 u_int height) {
1056 if (!win->is_scrollable) {
1057 return 0;
1058 }
1059
1060 if (boundary_start < 0 || boundary_end > win->height || boundary_end <= boundary_start + height) {
1061 #ifdef DEBUG
1062 bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d height %d in window((h) %d (w) %d)\n",
1063 boundary_start, boundary_end, height, win->height, win->width);
1064 #endif
1065
1066 return 0;
1067 }
1068
1069 if (win->parent) {
1070 view_scroll(win->my_window, win->hmargin, win->vmargin + boundary_start + height, /* src */
1071 win->width, boundary_end - boundary_start - height, /* size */
1072 win->hmargin, win->vmargin + boundary_start); /* dst */
1073 }
1074
1075 return 1;
1076 }
1077
ui_window_scroll_downward(ui_window_t * win,u_int height)1078 int ui_window_scroll_downward(ui_window_t *win, u_int height) {
1079 return ui_window_scroll_downward_region(win, 0, win->height, height);
1080 }
1081
ui_window_scroll_downward_region(ui_window_t * win,int boundary_start,int boundary_end,u_int height)1082 int ui_window_scroll_downward_region(ui_window_t *win, int boundary_start, int boundary_end,
1083 u_int height) {
1084 if (!win->is_scrollable) {
1085 return 0;
1086 }
1087
1088 if (boundary_start < 0 || boundary_end > win->height || boundary_end <= boundary_start + height) {
1089 #ifdef DEBUG
1090 bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d height %d\n", boundary_start,
1091 boundary_end, height);
1092 #endif
1093
1094 return 0;
1095 }
1096
1097 if (win->parent) {
1098 view_scroll(win->my_window, win->hmargin, win->vmargin + boundary_start, /* src */
1099 win->width, boundary_end - boundary_start - height, /* size */
1100 win->hmargin, win->vmargin + boundary_start + height); /* dst */
1101 }
1102
1103 return 1;
1104 }
1105
ui_window_scroll_leftward(ui_window_t * win,u_int width)1106 int ui_window_scroll_leftward(ui_window_t *win, u_int width) {
1107 return ui_window_scroll_leftward_region(win, 0, win->width, width);
1108 }
1109
ui_window_scroll_leftward_region(ui_window_t * win,int boundary_start,int boundary_end,u_int width)1110 int ui_window_scroll_leftward_region(ui_window_t *win, int boundary_start, int boundary_end,
1111 u_int width) {
1112 if (!win->is_scrollable) {
1113 return 0;
1114 }
1115
1116 if (boundary_start < 0 || boundary_end > win->width || boundary_end <= boundary_start + width) {
1117 #ifdef DEBUG
1118 bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d width %d in window((h) %d (w) %d)\n",
1119 boundary_start, boundary_end, width, win->height, win->width);
1120 #endif
1121
1122 return 0;
1123 }
1124
1125 if (win->parent) {
1126 view_scroll(win->my_window, win->hmargin + boundary_start + width, win->vmargin, /* src */
1127 boundary_end - boundary_start - width, win->height, /* size */
1128 win->hmargin + boundary_start, win->vmargin); /* dst */
1129 }
1130
1131 return 1;
1132 }
1133
ui_window_scroll_rightward(ui_window_t * win,u_int width)1134 int ui_window_scroll_rightward(ui_window_t *win, u_int width) {
1135 return ui_window_scroll_rightward_region(win, 0, win->width, width);
1136 }
1137
ui_window_scroll_rightward_region(ui_window_t * win,int boundary_start,int boundary_end,u_int width)1138 int ui_window_scroll_rightward_region(ui_window_t *win, int boundary_start, int boundary_end,
1139 u_int width) {
1140 if (!win->is_scrollable) {
1141 return 0;
1142 }
1143
1144 if (boundary_start < 0 || boundary_end > win->width || boundary_end <= boundary_start + width) {
1145 #ifdef DEBUG
1146 bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d width %d\n", boundary_start,
1147 boundary_end, width);
1148 #endif
1149
1150 return 0;
1151 }
1152
1153 if (win->parent) {
1154 view_scroll(win->my_window, win->hmargin + boundary_start, win->vmargin, /* src */
1155 boundary_end - boundary_start - width, win->height, /* size */
1156 win->hmargin + boundary_start + width, win->vmargin); /* dst */
1157 }
1158
1159 return 1;
1160 }
1161
ui_window_copy_area(ui_window_t * win,Pixmap src,PixmapMask mask,int src_x,int src_y,u_int width,u_int height,int dst_x,int dst_y)1162 int ui_window_copy_area(ui_window_t *win, Pixmap src, PixmapMask mask, int src_x, /* >= 0 */
1163 int src_y, /* >= 0 */
1164 u_int width, u_int height, int dst_x, /* >= 0 */
1165 int dst_y /* >= 0 */
1166 ) {
1167 if (dst_x >= win->width || dst_y >= win->height) {
1168 return 0;
1169 }
1170
1171 if (dst_x + width > win->width) {
1172 width = win->width - dst_x;
1173 }
1174
1175 if (dst_y + height > win->height) {
1176 height = win->height - dst_y;
1177 }
1178
1179 if (win->parent) {
1180 view_copy_area(win->my_window, src, src_x, src_y, width, height, dst_x + win->hmargin,
1181 dst_y + win->vmargin);
1182 }
1183
1184 return 1;
1185 }
1186
ui_window_set_clip(ui_window_t * win,int x,int y,u_int width,u_int height)1187 void ui_window_set_clip(ui_window_t *win, int x, int y, u_int width, u_int height) {
1188 if (win->parent) {
1189 view_set_clip(win->my_window, x + win->hmargin, y + win->vmargin, width, height);
1190 }
1191 }
1192
ui_window_unset_clip(ui_window_t * win)1193 void ui_window_unset_clip(ui_window_t *win) {
1194 if (win->parent) {
1195 view_unset_clip(win->my_window);
1196 }
1197 }
1198
ui_window_draw_decsp_string(ui_window_t * win,ui_font_t * font,ui_color_t * fg_color,int x,int y,u_char * str,u_int len)1199 void ui_window_draw_decsp_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x,
1200 int y, u_char *str, u_int len) {
1201 ui_window_draw_string(win, font, fg_color, x, y, str, len);
1202 }
1203
ui_window_draw_string(ui_window_t * win,ui_font_t * font,ui_color_t * fg_color,int x,int y,u_char * str,u_int len)1204 void ui_window_draw_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y,
1205 u_char *str, u_int len) {
1206 void *view;
1207
1208 if (win->parent) {
1209 view = win->my_window;
1210 } else if (!(view = window_get_orphan(win->my_window, 0))) {
1211 return;
1212 }
1213
1214 view_draw_string(view, font, fg_color, x + win->hmargin, y + win->vmargin, str, len);
1215 }
1216
ui_window_draw_string16(ui_window_t * win,ui_font_t * font,ui_color_t * fg_color,int x,int y,XChar2b * str,u_int len)1217 void ui_window_draw_string16(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y,
1218 XChar2b *str, u_int len) {
1219 void *view;
1220
1221 if (win->parent) {
1222 view = win->my_window;
1223 } else if (!(view = window_get_orphan(win->my_window, 0))) {
1224 return;
1225 }
1226
1227 view_draw_string16(view, font, fg_color, x + win->hmargin, y + win->vmargin, str, len);
1228 }
1229
ui_window_draw_rect_frame(ui_window_t * win,int x1,int y1,int x2,int y2)1230 void ui_window_draw_rect_frame(ui_window_t *win, int x1, int y1, int x2, int y2) {
1231 if (win->parent) {
1232 view_draw_rect_frame(win->my_window, &win->fg_color, x1 + win->hmargin, y1 + win->vmargin,
1233 x2 + win->hmargin, y2 + win->vmargin);
1234 }
1235 }
1236
ui_set_use_clipboard_selection(int use_it)1237 void ui_set_use_clipboard_selection(int use_it) {}
1238
ui_is_using_clipboard_selection(void)1239 int ui_is_using_clipboard_selection(void) { return 0; }
1240
ui_window_set_selection_owner(ui_window_t * win,Time time)1241 int ui_window_set_selection_owner(ui_window_t *win, Time time) {
1242 if (ui_window_is_selection_owner(win)) {
1243 /* Already owner */
1244
1245 return 1;
1246 }
1247
1248 #if 0
1249 bl_debug_printf(BL_DEBUG_TAG " ui_window_set_selection_owner.\n");
1250 #endif
1251
1252 if (win->utf_selection_requested) {
1253 (*win->utf_selection_requested)(win, NULL, 0);
1254 }
1255
1256 return 1;
1257 }
1258
ui_window_xct_selection_request(ui_window_t * win,Time time)1259 int ui_window_xct_selection_request(ui_window_t *win, Time time) { return 0; }
1260
ui_window_utf_selection_request(ui_window_t * win,Time time)1261 int ui_window_utf_selection_request(ui_window_t *win, Time time) {
1262 if (win->utf_selection_notified) {
1263 u_char *str;
1264 size_t len;
1265
1266 if (beos_clipboard_get(&str, &len)) {
1267 (*win->utf_selection_notified)(win, str, len);
1268
1269 return 1;
1270 }
1271 }
1272
1273 return 0;
1274 }
1275
ui_window_send_picture_selection(ui_window_t * win,Pixmap pixmap,u_int width,u_int height)1276 void ui_window_send_picture_selection(ui_window_t *win, Pixmap pixmap, u_int width, u_int height) {}
1277
ui_window_send_text_selection(ui_window_t * win,XSelectionRequestEvent * req_ev,u_char * sel_data,size_t sel_len,Atom sel_type)1278 void ui_window_send_text_selection(ui_window_t *win, XSelectionRequestEvent *req_ev,
1279 u_char *sel_data, size_t sel_len, Atom sel_type) {
1280 beos_clipboard_set(sel_data, sel_len);
1281 }
1282
ui_set_window_name(ui_window_t * win,u_char * name)1283 void ui_set_window_name(ui_window_t *win, u_char *name) {
1284 ui_window_t *root = ui_get_root_window(win);
1285
1286 if (name == NULL) {
1287 name = root->app_name;
1288 }
1289
1290 /* name is utf8 (see vt_parser.c) */
1291 window_set_title(root->my_window, name);
1292 }
1293
ui_set_icon_name(ui_window_t * win,u_char * name)1294 void ui_set_icon_name(ui_window_t *win, u_char *name) {}
1295
ui_window_set_icon(ui_window_t * win,ui_icon_picture_t * icon)1296 void ui_window_set_icon(ui_window_t *win, ui_icon_picture_t *icon) {}
1297
ui_window_remove_icon(ui_window_t * win)1298 void ui_window_remove_icon(ui_window_t *win) {}
1299
ui_window_reset_group(ui_window_t * win)1300 void ui_window_reset_group(ui_window_t *win) {}
1301
ui_set_click_interval(int interval)1302 void ui_set_click_interval(int interval) {
1303 click_interval = interval;
1304 }
1305
ui_get_click_interval(void)1306 int ui_get_click_interval(void) {
1307 return click_interval;
1308 }
1309
ui_window_get_mod_ignore_mask(ui_window_t * win,KeySym * keysyms)1310 u_int ui_window_get_mod_ignore_mask(ui_window_t *win, KeySym *keysyms) { return ~0; }
1311
ui_window_get_mod_meta_mask(ui_window_t * win,char * mod_key)1312 u_int ui_window_get_mod_meta_mask(ui_window_t *win, char *mod_key) { return ModMask; }
1313
ui_set_use_urgent_bell(int use)1314 void ui_set_use_urgent_bell(int use) {
1315 use_urgent_bell = use;
1316 }
1317
ui_window_bell(ui_window_t * win,ui_bel_mode_t mode)1318 void ui_window_bell(ui_window_t *win, ui_bel_mode_t mode) {
1319 urgent_bell(win, 1);
1320
1321 if (mode & BEL_VISUAL) {
1322 if (win->parent) {
1323 view_visual_bell(win->my_window);
1324 }
1325 }
1326
1327 if (mode & BEL_SOUND) {
1328 beos_beep();
1329 }
1330 }
1331
ui_window_translate_coordinates(ui_window_t * win,int x,int y,int * global_x,int * global_y)1332 void ui_window_translate_coordinates(ui_window_t *win, int x, int y, int *global_x, int *global_y) {
1333 win = ui_get_root_window(win);
1334 window_get_position(win->my_window, global_x, global_y);
1335 *global_x += x;
1336 *global_y += y;
1337 }
1338
ui_window_set_input_focus(ui_window_t * win)1339 void ui_window_set_input_focus(ui_window_t *win) {
1340 reset_input_focus(ui_get_root_window(win));
1341 win->inputtable = 1;
1342
1343 if (win->parent) {
1344 view_set_input_focus(win->my_window);
1345 }
1346 }
1347
1348 #ifdef DEBUG
ui_window_dump_children(ui_window_t * win)1349 void ui_window_dump_children(ui_window_t *win) {
1350 u_int count;
1351
1352 bl_msg_printf("%p(%li) => ", win, win->my_window);
1353 for (count = 0; count < win->num_children; count++) {
1354 bl_msg_printf("%p(%li) ", win->children[count], win->children[count]->my_window);
1355 }
1356 bl_msg_printf("\n");
1357
1358 for (count = 0; count < win->num_children; count++) {
1359 ui_window_dump_children(win->children[count]);
1360 }
1361 }
1362 #endif
1363