This source file includes following definitions.
- android_window_to_frame
- android_clear_frame
- android_show_hourglass
- android_hide_hourglass
- android_flash
- android_ring_bell
- make_invisible_cursor
- android_toggle_visible_pointer
- android_toggle_invisible_pointer
- android_update_begin
- android_update_end
- show_back_buffer
- android_flush_dirty_back_buffer_on
- android_android_to_emacs_modifiers
- android_emacs_to_android_modifiers
- android_lower_frame
- android_raise_frame
- android_new_focus_frame
- android_focus_changed
- android_detect_focus_change
- android_note_mouse_movement
- mouse_or_wdesc_frame
- android_construct_mouse_click
- android_update_tools
- android_find_tool
- android_decode_utf16
- android_request_cursor_updates
- android_handle_ime_event
- handle_one_android_event
- android_read_socket
- android_frame_up_to_date
- android_buffer_flipping_unblocked_hook
- android_query_frame_background_color
- android_parse_color
- android_alloc_nearest_color
- android_query_colors
- android_mouse_position
- android_get_focus_frame
- android_focus_frame
- android_frame_highlight
- android_frame_unhighlight
- android_frame_rehighlight
- android_frame_rehighlight_hook
- android_frame_raise_lower
- android_make_frame_visible
- android_make_frame_invisible
- android_make_frame_visible_invisible
- android_fullscreen_hook
- android_iconify_frame
- android_wait_for_event
- android_set_window_size_1
- android_set_window_size
- android_set_offset
- android_set_alpha
- android_new_font
- android_bitmap_icon
- android_free_pixmap_hook
- android_free_frame_resources
- android_delete_frame
- android_delete_terminal
- android_scroll_run
- android_after_update_window_line
- android_flip_and_flush
- android_clear_rectangle
- android_reset_clip_rectangles
- android_clip_to_row
- android_draw_fringe_bitmap
- android_set_cursor_gc
- android_set_mouse_face_gc
- android_set_mode_line_face_gc
- android_set_glyph_string_gc
- android_set_glyph_string_clipping
- android_set_glyph_string_clipping_exactly
- android_compute_glyph_string_overhangs
- android_clear_glyph_string_rect
- android_draw_glyph_string_background
- android_fill_triangle
- android_make_point
- android_inside_rect_p
- android_clear_point
- android_draw_relief_rect
- android_draw_box_rect
- android_alloc_lighter_color
- android_setup_relief_color
- android_setup_relief_colors
- android_draw_glyph_string_box
- android_draw_glyph_string_bg_rect
- android_draw_image_relief
- android_draw_image_foreground
- android_draw_image_glyph_string
- android_draw_stretch_glyph_string
- android_get_scale_factor
- android_draw_underwave
- android_draw_glyph_string_foreground
- android_draw_composite_glyph_string_foreground
- android_draw_glyphless_glyph_string_foreground
- android_draw_glyph_string
- android_define_frame_cursor
- android_clear_frame_area
- android_clear_under_internal_border
- android_draw_hollow_cursor
- android_draw_bar_cursor
- android_draw_window_cursor
- android_draw_vertical_window_border
- android_draw_window_divider
- android_sync_edit
- android_copy_java_string
- android_perform_conversion_query
- android_text_to_string
- android_get_selection
- android_get_extracted_text
- android_build_extracted_text
- android_get_surrounding_text
- android_get_surrounding_text_internal
- android_update_selection
- android_event_is_for_frame
- android_reset_conversion
- android_set_point
- android_compose_region_changed
- android_notify_conversion
- frame_set_mouse_pixel_position
- get_keysym_name
- android_create_terminal
- android_term_init
- android_set_build_fingerprint
- syms_of_androidterm
- mark_androidterm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <math.h>
23 #include <stdlib.h>
24 #include <assert.h>
25 #include <semaphore.h>
26
27 #include "lisp.h"
28 #include "androidterm.h"
29 #include "keyboard.h"
30 #include "blockinput.h"
31 #include "android.h"
32 #include "buffer.h"
33 #include "window.h"
34 #include "textconv.h"
35 #include "coding.h"
36 #include "pdumper.h"
37
38
39
40
41 struct android_display_info *x_display_list;
42
43
44
45
46
47 #ifndef ANDROID_STUBIFY
48
49 #include <android/log.h>
50
51
52
53
54 static bool any_help_event_p;
55
56
57
58
59 static double wheel_event_x, wheel_event_y;
60
61 enum
62 {
63 ANDROID_EVENT_NORMAL,
64 ANDROID_EVENT_GOTO_OUT,
65 ANDROID_EVENT_DROP,
66 };
67
68
69
70
71
72
73
74 static struct frame *
75 android_window_to_frame (struct android_display_info *dpyinfo,
76 android_window wdesc)
77 {
78 Lisp_Object tail, frame;
79 struct frame *f;
80
81 if (wdesc == ANDROID_NONE)
82 return NULL;
83
84 FOR_EACH_FRAME (tail, frame)
85 {
86 f = XFRAME (frame);
87
88 if (!FRAME_ANDROID_P (f))
89 continue;
90
91 if (FRAME_ANDROID_WINDOW (f) == wdesc)
92 return f;
93 }
94
95 return NULL;
96 }
97
98 static void
99 android_clear_frame (struct frame *f)
100 {
101
102
103 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
104 android_clear_window (FRAME_ANDROID_DRAWABLE (f));
105 }
106
107 static void
108 android_show_hourglass (struct frame *f)
109 {
110 struct android_output *x;
111
112
113
114
115 x = FRAME_ANDROID_OUTPUT (f);
116
117
118
119
120
121
122
123 if (popup_activated ())
124 return;
125
126 x->hourglass = true;
127
128 if (!f->pointer_invisible)
129 android_define_cursor (FRAME_ANDROID_WINDOW (f),
130 x->hourglass_cursor);
131 }
132
133 static void
134 android_hide_hourglass (struct frame *f)
135 {
136 struct android_output *x;
137
138 x = FRAME_ANDROID_OUTPUT (f);
139 x->hourglass = false;
140
141 if (!f->pointer_invisible)
142 android_define_cursor (FRAME_ANDROID_WINDOW (f),
143 x->current_cursor);
144 }
145
146 static void
147 android_flash (struct frame *f)
148 {
149 struct android_gc *gc;
150 struct android_gc_values values;
151 int rc;
152 fd_set fds;
153
154 block_input ();
155
156 values.function = ANDROID_GC_XOR;
157 values.foreground = (FRAME_FOREGROUND_PIXEL (f)
158 ^ FRAME_BACKGROUND_PIXEL (f));
159
160 gc = android_create_gc ((ANDROID_GC_FUNCTION
161 | ANDROID_GC_FOREGROUND),
162 &values);
163
164
165 int height = FRAME_PIXEL_HEIGHT (f);
166
167 int flash_height = FRAME_LINE_HEIGHT (f);
168
169 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
170 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
171 int width = flash_right - flash_left;
172
173
174 if (height > 3 * FRAME_LINE_HEIGHT (f))
175 {
176 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc,
177 flash_left,
178 (FRAME_INTERNAL_BORDER_WIDTH (f)
179 + FRAME_TOP_MARGIN_HEIGHT (f)),
180 width, flash_height);
181 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc,
182 flash_left,
183 (height - flash_height
184 - FRAME_INTERNAL_BORDER_WIDTH (f)
185 - FRAME_BOTTOM_MARGIN_HEIGHT (f)),
186 width, flash_height);
187
188 }
189 else
190
191 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc,
192 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
193 width, (height - 2
194 * FRAME_INTERNAL_BORDER_WIDTH (f)));
195
196 flush_frame (f);
197
198 struct timespec delay = make_timespec (0, 150 * 1000 * 1000);
199 struct timespec wakeup = timespec_add (current_timespec (), delay);
200
201
202
203 while (! detect_input_pending ())
204 {
205 struct timespec current = current_timespec ();
206 struct timespec timeout;
207
208
209 if (timespec_cmp (wakeup, current) <= 0)
210 break;
211
212
213 timeout = make_timespec (0, 10 * 1000 * 1000);
214
215
216
217 FD_ZERO (&fds);
218
219
220 rc = pselect (0, &fds, NULL, NULL, &timeout, NULL);
221
222
223 if (rc >= 0)
224 break;
225 }
226
227
228 if (height > 3 * FRAME_LINE_HEIGHT (f))
229 {
230 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc,
231 flash_left,
232 (FRAME_INTERNAL_BORDER_WIDTH (f)
233 + FRAME_TOP_MARGIN_HEIGHT (f)),
234 width, flash_height);
235 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc,
236 flash_left,
237 (height - flash_height
238 - FRAME_INTERNAL_BORDER_WIDTH (f)
239 - FRAME_BOTTOM_MARGIN_HEIGHT (f)),
240 width, flash_height);
241 }
242 else
243
244 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc,
245 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
246 width, (height - 2
247 * FRAME_INTERNAL_BORDER_WIDTH (f)));
248
249 android_free_gc (gc);
250 flush_frame (f);
251
252 unblock_input ();
253 }
254
255 static void
256 android_ring_bell (struct frame *f)
257 {
258 if (visible_bell)
259 android_flash (f);
260 else
261 {
262 block_input ();
263 android_bell ();
264 unblock_input ();
265 }
266 }
267
268 static android_cursor
269 make_invisible_cursor (struct android_display_info *dpyinfo)
270 {
271 return android_create_font_cursor (ANDROID_XC_NULL);
272 }
273
274 static void
275 android_toggle_visible_pointer (struct frame *f, bool invisible)
276 {
277 struct android_display_info *dpyinfo;
278
279 dpyinfo = FRAME_DISPLAY_INFO (f);
280
281 if (!dpyinfo->invisible_cursor)
282 dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
283
284 if (invisible)
285 android_define_cursor (FRAME_ANDROID_WINDOW (f),
286 dpyinfo->invisible_cursor);
287 else
288 android_define_cursor (FRAME_ANDROID_WINDOW (f),
289 (FRAME_ANDROID_OUTPUT (f)->hourglass
290 ? f->output_data.android->hourglass_cursor
291 : f->output_data.android->current_cursor));
292
293 f->pointer_invisible = invisible;
294 }
295
296 static void
297 android_toggle_invisible_pointer (struct frame *f, bool invisible)
298 {
299 block_input ();
300 android_toggle_visible_pointer (f, invisible);
301 unblock_input ();
302 }
303
304
305
306
307
308
309
310 static void
311 android_update_begin (struct frame *f)
312 {
313
314
315 FRAME_ANDROID_COMPLETE_P (f) = false;
316 }
317
318
319
320
321 static void
322 android_update_end (struct frame *f)
323 {
324
325 MOUSE_HL_INFO (f)->mouse_face_defer = false;
326 }
327
328 static void
329 show_back_buffer (struct frame *f)
330 {
331 struct android_swap_info swap_info;
332
333 memset (&swap_info, 0, sizeof (swap_info));
334 swap_info.swap_window = FRAME_ANDROID_WINDOW (f);
335 swap_info.swap_action = ANDROID_COPIED;
336 android_swap_buffers (&swap_info, 1);
337
338
339 FRAME_ANDROID_NEED_BUFFER_FLIP (f) = false;
340 }
341
342
343
344 static void
345 android_flush_dirty_back_buffer_on (struct frame *f)
346 {
347 if (FRAME_GARBAGED_P (f)
348 || buffer_flipping_blocked_p ()
349
350
351 || !FRAME_ANDROID_COMPLETE_P (f)
352 || !FRAME_ANDROID_NEED_BUFFER_FLIP (f))
353 return;
354
355 show_back_buffer (f);
356 }
357
358
359
360
361 static int
362 android_android_to_emacs_modifiers (struct android_display_info *dpyinfo,
363 int state)
364 {
365 return (((state & ANDROID_CONTROL_MASK) ? ctrl_modifier : 0)
366 | ((state & ANDROID_SHIFT_MASK) ? shift_modifier : 0)
367 | ((state & ANDROID_ALT_MASK) ? meta_modifier : 0)
368 | ((state & ANDROID_SUPER_MASK) ? super_modifier : 0)
369 | ((state & ANDROID_META_MASK) ? alt_modifier : 0));
370 }
371
372 static int
373 android_emacs_to_android_modifiers (struct android_display_info *dpyinfo,
374 intmax_t state)
375 {
376 return (((state & ctrl_modifier) ? ANDROID_CONTROL_MASK : 0)
377 | ((state & shift_modifier) ? ANDROID_SHIFT_MASK : 0)
378 | ((state & meta_modifier) ? ANDROID_ALT_MASK : 0)
379 | ((state & super_modifier) ? ANDROID_SUPER_MASK : 0)
380 | ((state & alt_modifier) ? ANDROID_META_MASK : 0));
381 }
382
383 static void android_frame_rehighlight (struct android_display_info *);
384
385 static void
386 android_lower_frame (struct frame *f)
387 {
388 android_lower_window (FRAME_ANDROID_WINDOW (f));
389 }
390
391 static void
392 android_raise_frame (struct frame *f)
393 {
394 android_raise_window (FRAME_ANDROID_WINDOW (f));
395 }
396
397 static void
398 android_new_focus_frame (struct android_display_info *dpyinfo,
399 struct frame *frame)
400 {
401 struct frame *old_focus;
402
403 old_focus = dpyinfo->focus_frame;
404
405 if (frame != dpyinfo->focus_frame)
406 {
407
408
409 dpyinfo->focus_frame = frame;
410
411 if (old_focus && old_focus->auto_lower)
412 android_lower_frame (old_focus);
413
414 if (dpyinfo->focus_frame && dpyinfo->focus_frame->auto_raise)
415 dpyinfo->pending_autoraise_frame = dpyinfo->focus_frame;
416 else
417 dpyinfo->pending_autoraise_frame = NULL;
418 }
419
420 android_frame_rehighlight (dpyinfo);
421 }
422
423 static void
424 android_focus_changed (int type, int state,
425 struct android_display_info *dpyinfo,
426 struct frame *frame, struct input_event *bufp)
427 {
428 if (type == ANDROID_FOCUS_IN)
429 {
430 if (dpyinfo->x_focus_event_frame != frame)
431 {
432 android_new_focus_frame (dpyinfo, frame);
433 dpyinfo->x_focus_event_frame = frame;
434 bufp->kind = FOCUS_IN_EVENT;
435 XSETFRAME (bufp->frame_or_window, frame);
436 }
437
438 frame->output_data.android->focus_state |= state;
439 }
440 else if (type == ANDROID_FOCUS_OUT)
441 {
442 frame->output_data.android->focus_state &= ~state;
443
444 if (dpyinfo->x_focus_event_frame == frame)
445 {
446 dpyinfo->x_focus_event_frame = 0;
447 android_new_focus_frame (dpyinfo, 0);
448
449 bufp->kind = FOCUS_OUT_EVENT;
450 XSETFRAME (bufp->frame_or_window, frame);
451 }
452
453 if (frame->pointer_invisible)
454 android_toggle_invisible_pointer (frame, false);
455 }
456 }
457
458 static void
459 android_detect_focus_change (struct android_display_info *dpyinfo,
460 struct frame *frame,
461 union android_event *event,
462 struct input_event *bufp)
463 {
464 if (!frame)
465 return;
466
467 switch (event->type)
468 {
469 case ANDROID_FOCUS_IN:
470 case ANDROID_FOCUS_OUT:
471 android_focus_changed (event->type, FOCUS_EXPLICIT,
472 dpyinfo, frame, bufp);
473 break;
474
475 default:
476 break;
477 }
478 }
479
480 static bool
481 android_note_mouse_movement (struct frame *frame,
482 struct android_motion_event *event)
483 {
484 struct android_display_info *dpyinfo;
485 Emacs_Rectangle *r;
486
487 if (!FRAME_ANDROID_OUTPUT (frame))
488 return false;
489
490 dpyinfo = FRAME_DISPLAY_INFO (frame);
491 dpyinfo->last_mouse_motion_frame = frame;
492 dpyinfo->last_mouse_motion_x = event->x;
493 dpyinfo->last_mouse_motion_y = event->y;
494 dpyinfo->last_mouse_movement_time = event->time;
495
496
497 r = &dpyinfo->last_mouse_glyph;
498 if (frame != dpyinfo->last_mouse_glyph_frame
499 || event->x < r->x || event->x >= r->x + r->width
500 || event->y < r->y || event->y >= r->y + r->height)
501 {
502 frame->mouse_moved = true;
503 note_mouse_highlight (frame, event->x, event->y);
504
505 remember_mouse_glyph (frame, event->x, event->y, r);
506 dpyinfo->last_mouse_glyph_frame = frame;
507 return true;
508 }
509
510 return false;
511 }
512
513 static struct frame *
514 mouse_or_wdesc_frame (struct android_display_info *dpyinfo, int wdesc)
515 {
516 struct frame *lm_f = (gui_mouse_grabbed (dpyinfo)
517 ? dpyinfo->last_mouse_frame
518 : NULL);
519
520 if (lm_f && !EQ (track_mouse, Qdropping)
521 && !EQ (track_mouse, Qdrag_source))
522 return lm_f;
523 else
524 {
525 struct frame *w_f = android_window_to_frame (dpyinfo, wdesc);
526
527
528 if (!w_f || FRAME_TOOLTIP_P (w_f))
529 return EQ (track_mouse, Qdropping) ? lm_f : NULL;
530 else
531
532
533 return w_f;
534 }
535 }
536
537 static Lisp_Object
538 android_construct_mouse_click (struct input_event *result,
539 struct android_button_event *event,
540 struct frame *f)
541 {
542 struct android_display_info *dpyinfo;
543 int x, y;
544
545 dpyinfo = FRAME_DISPLAY_INFO (f);
546 x = event->x;
547 y = event->y;
548
549
550
551 result->kind = MOUSE_CLICK_EVENT;
552 result->code = event->button - 1;
553 result->timestamp = event->time;
554 result->modifiers = (android_android_to_emacs_modifiers (dpyinfo,
555 event->state)
556 | (event->type == ANDROID_BUTTON_RELEASE
557 ? up_modifier : down_modifier));
558
559 XSETINT (result->x, x);
560 XSETINT (result->y, y);
561 XSETFRAME (result->frame_or_window, f);
562 result->arg = Qnil;
563 return Qnil;
564 }
565
566
567
568
569
570 static void
571 android_update_tools (struct frame *f, struct input_event *ie)
572 {
573 struct android_touch_point *touchpoint;
574
575 ie->kind = TOUCHSCREEN_UPDATE_EVENT;
576 XSETFRAME (ie->frame_or_window, f);
577 ie->arg = Qnil;
578
579
580 for (touchpoint = FRAME_OUTPUT_DATA (f)->touch_points;
581 touchpoint; touchpoint = touchpoint->next)
582 {
583
584
585 if (touchpoint->tool_bar_p)
586 continue;
587
588 ie->arg = Fcons (list3i (touchpoint->x,
589 touchpoint->y,
590 touchpoint->tool_id),
591 ie->arg);
592 }
593 }
594
595
596
597
598 static struct android_touch_point *
599 android_find_tool (struct frame *f, int pointer_id)
600 {
601 struct android_touch_point *touchpoint;
602
603 for (touchpoint = FRAME_OUTPUT_DATA (f)->touch_points;
604 touchpoint; touchpoint = touchpoint->next)
605 {
606 if (touchpoint->tool_id == pointer_id)
607 return touchpoint;
608 }
609
610 return NULL;
611 }
612
613
614
615
616
617 static Lisp_Object
618 android_decode_utf16 (unsigned short *utf16, size_t n)
619 {
620 struct coding_system coding;
621 ptrdiff_t size;
622
623 if (INT_MULTIPLY_WRAPV (n, sizeof *utf16, &size))
624 return Qnil;
625
626
627
628
629 memset (&coding, 0, sizeof coding);
630
631 setup_coding_system (Qutf_16le, &coding);
632 coding.source = (const unsigned char *) utf16;
633 decode_coding_object (&coding, Qnil, 0, 0, size,
634 size, Qt);
635
636 return coding.dst_object;
637 }
638
639
640
641
642
643
644
645
646
647
648
649 static void
650 android_request_cursor_updates (struct frame *f, int mode)
651 {
652 struct window *w;
653
654 if (mode & ANDROID_CURSOR_UPDATE_IMMEDIATE
655 && WINDOWP (WINDOW_LIVE_P (f->old_selected_window)
656 ? f->old_selected_window
657 : f->selected_window))
658 {
659
660
661
662 w = XWINDOW (WINDOW_LIVE_P (f->old_selected_window)
663 ? f->old_selected_window
664 : f->selected_window);
665 android_set_preeditarea (w, w->cursor.x, w->cursor.y);
666 }
667
668
669 FRAME_OUTPUT_DATA (f)->need_cursor_updates
670 = (mode & ANDROID_CURSOR_UPDATE_MONITOR);
671 }
672
673
674
675
676
677
678 static void
679 android_handle_ime_event (union android_event *event, struct frame *f)
680 {
681 Lisp_Object text UNINIT;
682 struct android_output *output;
683
684
685
686 switch (event->ime.operation)
687 {
688 case ANDROID_IME_COMMIT_TEXT:
689 case ANDROID_IME_SET_COMPOSING_TEXT:
690 text = android_decode_utf16 (event->ime.text,
691 event->ime.length);
692 xfree (event->ime.text);
693 break;
694
695 default:
696 break;
697 }
698
699
700
701 switch (event->ime.operation)
702 {
703 case ANDROID_IME_COMMIT_TEXT:
704 commit_text (f, text, event->ime.position,
705 event->ime.counter);
706 break;
707
708 case ANDROID_IME_DELETE_SURROUNDING_TEXT:
709 delete_surrounding_text (f, event->ime.start,
710 event->ime.end,
711 event->ime.counter);
712 break;
713
714 case ANDROID_IME_FINISH_COMPOSING_TEXT:
715
716 if (event->ime.length == 2)
717 {
718 output = FRAME_ANDROID_OUTPUT (f);
719
720
721
722
723
724 output->extracted_text_flags = 0;
725 output->extracted_text_token = 0;
726 output->extracted_text_hint = 0;
727 output->need_cursor_updates = false;
728 }
729
730 finish_composing_text (f, event->ime.counter,
731 event->ime.length == 1);
732
733 if (event->ime.length == 2)
734 {
735
736
737
738 f->conversion.batch_edit_flags = 0;
739 f->conversion.batch_edit_count = 0;
740 }
741
742 break;
743
744 case ANDROID_IME_SET_COMPOSING_TEXT:
745 set_composing_text (f, text, event->ime.position,
746 event->ime.counter);
747 break;
748
749 case ANDROID_IME_SET_COMPOSING_REGION:
750 set_composing_region (f, event->ime.start,
751 event->ime.end,
752 event->ime.counter);
753 break;
754
755 case ANDROID_IME_SET_POINT:
756 textconv_set_point_and_mark (f, event->ime.start,
757 event->ime.end,
758 event->ime.counter);
759 break;
760
761 case ANDROID_IME_START_BATCH_EDIT:
762 start_batch_edit (f, event->ime.counter);
763 break;
764
765 case ANDROID_IME_END_BATCH_EDIT:
766 end_batch_edit (f, event->ime.counter);
767 break;
768
769 case ANDROID_IME_REQUEST_SELECTION_UPDATE:
770 request_point_update (f, event->ime.counter);
771 break;
772
773 case ANDROID_IME_REQUEST_CURSOR_UPDATES:
774 android_request_cursor_updates (f, event->ime.length);
775 break;
776 }
777 }
778
779
780
781
782 static void android_notify_conversion (unsigned long);
783
784 static int
785 handle_one_android_event (struct android_display_info *dpyinfo,
786 union android_event *event, int *finish,
787 struct input_event *hold_quit)
788 {
789 union android_event configureEvent;
790 struct frame *f, *any, *mouse_frame;
791 Mouse_HLInfo *hlinfo;
792 union buffered_input_event inev;
793 int modifiers, count, do_help;
794 struct android_touch_point *touchpoint, **last;
795 Lisp_Object window;
796 int scroll_height;
797 double scroll_unit;
798 int keysym;
799 ptrdiff_t nchars, i;
800 struct window *w;
801
802
803
804
805
806 do_help = count = 0;
807 hlinfo = &dpyinfo->mouse_highlight;
808 *finish = ANDROID_EVENT_NORMAL;
809 any = android_window_to_frame (dpyinfo, event->xany.window);
810 nchars = 0;
811
812 if (any && any->wait_event_type == event->type)
813 any->wait_event_type = 0;
814
815 EVENT_INIT (inev.ie);
816
817 switch (event->type)
818 {
819 case ANDROID_CONFIGURE_NOTIFY:
820 configureEvent = *event;
821
822 f = android_window_to_frame (dpyinfo,
823 configureEvent.xconfigure.window);
824
825 if (!f)
826 goto OTHER;
827
828 if (FRAME_TOOLTIP_P (f))
829 {
830 if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height
831 || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width)
832 SET_FRAME_GARBAGED (f);
833
834 FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height;
835 FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width;
836 }
837
838 int width = configureEvent.xconfigure.width;
839 int height = configureEvent.xconfigure.height;
840
841 if (CONSP (frame_size_history))
842 frame_size_history_extra (f, build_string ("ConfigureNotify"),
843 FRAME_PIXEL_WIDTH (f),
844 FRAME_PIXEL_HEIGHT (f),
845 width, height, f->new_width,
846 f->new_height);
847
848
849
850
851
852 if (width != FRAME_PIXEL_WIDTH (f)
853 || height != FRAME_PIXEL_HEIGHT (f)
854 || (f->new_size_p
855 && ((f->new_width >= 0 && width != f->new_width)
856 || (f->new_height >= 0 && height != f->new_height))))
857 {
858 change_frame_size (f, width, height, false, true, false);
859 android_clear_under_internal_border (f);
860 SET_FRAME_GARBAGED (f);
861 cancel_mouse_face (f);
862 }
863
864
865
866 {
867 int old_left = f->left_pos;
868 int old_top = f->top_pos;
869 Lisp_Object frame;
870
871 XSETFRAME (frame, f);
872
873 {
874 android_window root;
875 unsigned int dummy_uint;
876
877 android_get_geometry (FRAME_ANDROID_WINDOW (f),
878 &root, &f->left_pos, &f->top_pos,
879 &dummy_uint, &dummy_uint,
880 &dummy_uint);
881 }
882
883 if (!FRAME_TOOLTIP_P (f)
884 && (old_left != f->left_pos || old_top != f->top_pos))
885 {
886 inev.ie.kind = MOVE_FRAME_EVENT;
887 XSETFRAME (inev.ie.frame_or_window, f);
888 }
889
890 if (f && FRAME_OUTPUT_DATA (f)->need_cursor_updates)
891 {
892 w = XWINDOW (f->selected_window);
893 android_set_preeditarea (w, w->cursor.x, w->cursor.y);
894 }
895 }
896
897 goto OTHER;
898
899 case ANDROID_KEY_PRESS:
900
901
902 f = any;
903
904
905
906 if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
907 && (any == 0
908 || !EQ (any->tool_bar_window, hlinfo->mouse_face_window)
909 || !EQ (any->tab_bar_window, hlinfo->mouse_face_window)))
910 {
911 mouse_frame = hlinfo->mouse_face_mouse_frame;
912
913 clear_mouse_face (hlinfo);
914 hlinfo->mouse_face_hidden = true;
915
916 if (mouse_frame)
917 android_flush_dirty_back_buffer_on (mouse_frame);
918 }
919
920 if (!f)
921 goto OTHER;
922
923 if (event->xkey.counter)
924
925
926 textconv_barrier (f, event->xkey.counter);
927
928 wchar_t copy_buffer[129];
929 wchar_t *copy_bufptr = copy_buffer;
930 int copy_bufsiz = 128 * sizeof (wchar_t);
931
932 event->xkey.state
933 |= android_emacs_to_android_modifiers (dpyinfo,
934 extra_keyboard_modifiers);
935 modifiers = event->xkey.state;
936
937
938 XSETFRAME (inev.ie.frame_or_window, any);
939 inev.ie.modifiers
940 = android_android_to_emacs_modifiers (dpyinfo, modifiers);
941 inev.ie.timestamp = event->xkey.time;
942
943 keysym = event->xkey.keycode;
944
945 {
946 enum android_lookup_status status_return;
947
948 nchars = android_wc_lookup_string (&event->xkey, copy_bufptr,
949 copy_bufsiz, &keysym,
950 &status_return);
951
952
953
954 if (status_return == ANDROID_BUFFER_OVERFLOW)
955 goto done_keysym;
956 else if (status_return == ANDROID_LOOKUP_NONE)
957 {
958
959 if (event->xkey.keycode != (uint32_t) -1)
960 goto done_keysym;
961 }
962 else if (status_return == ANDROID_LOOKUP_CHARS)
963 keysym = ANDROID_NO_SYMBOL;
964 else if (status_return != ANDROID_LOOKUP_KEYSYM
965 && status_return != ANDROID_LOOKUP_BOTH)
966 emacs_abort ();
967
968
969
970
971
972 if (event->xkey.keycode == (uint32_t) -1)
973 {
974 inev.ie.kind = PREEDIT_TEXT_EVENT;
975 inev.ie.arg = Qnil;
976
977
978
979
980 if (status_return == ANDROID_LOOKUP_CHARS && nchars)
981 {
982 copy_bufptr[nchars] = 0;
983 inev.ie.arg = from_unicode_buffer (copy_bufptr);
984 }
985
986 goto done_keysym;
987 }
988 }
989
990 if (nchars == 1 && copy_bufptr[0] >= 32)
991 {
992
993
994 if (copy_bufptr[0] < 128)
995 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
996 else
997 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
998
999 inev.ie.code = copy_bufptr[0];
1000 }
1001 else if (nchars < 2 && keysym)
1002 {
1003
1004 if (ANDROID_IS_MODIFIER_KEY (keysym))
1005 goto done_keysym;
1006
1007
1008
1009 inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
1010 inev.ie.code = keysym;
1011 }
1012 else
1013 {
1014
1015
1016 for (i = 0; i < nchars; ++i)
1017 {
1018 inev.ie.kind = (SINGLE_BYTE_CHAR_P (copy_bufptr[i])
1019 ? ASCII_KEYSTROKE_EVENT
1020 : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
1021 inev.ie.code = copy_bufptr[i];
1022
1023
1024
1025
1026 if (copy_bufptr[i] == '\n')
1027 {
1028 inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
1029 inev.ie.code = 66;
1030 }
1031
1032 kbd_buffer_store_buffered_event (&inev, hold_quit);
1033 }
1034
1035 count += nchars;
1036 inev.ie.kind = NO_EVENT;
1037 }
1038
1039 goto done_keysym;
1040
1041 done_keysym:
1042
1043
1044
1045
1046 if (f && FRAME_OUTPUT_DATA (f)->need_cursor_updates)
1047 {
1048 w = XWINDOW (f->selected_window);
1049 android_set_preeditarea (w, w->cursor.x, w->cursor.y);
1050 }
1051
1052 goto OTHER;
1053
1054 case ANDROID_FOCUS_IN:
1055 case ANDROID_FOCUS_OUT:
1056 android_detect_focus_change (dpyinfo, any, event, &inev.ie);
1057 goto OTHER;
1058
1059 case ANDROID_WINDOW_ACTION:
1060
1061
1062
1063
1064 if (!event->xaction.window && !event->xaction.action)
1065
1066
1067
1068
1069
1070 goto OTHER;
1071
1072 f = any;
1073
1074 if (event->xaction.action == 0)
1075 {
1076
1077
1078
1079 if (event->xaction.window)
1080 {
1081 if (!f)
1082 goto OTHER;
1083
1084 inev.ie.kind = DELETE_WINDOW_EVENT;
1085 XSETFRAME (inev.ie.frame_or_window, f);
1086 }
1087 }
1088
1089 case ANDROID_ENTER_NOTIFY:
1090 f = any;
1091
1092 if (f)
1093 android_note_mouse_movement (f, &event->xmotion);
1094 goto OTHER;
1095
1096 case ANDROID_MOTION_NOTIFY:
1097
1098 previous_help_echo_string = help_echo_string;
1099 help_echo_string = Qnil;
1100
1101 if (hlinfo->mouse_face_hidden)
1102 {
1103 hlinfo->mouse_face_hidden = false;
1104 clear_mouse_face (hlinfo);
1105 }
1106
1107 f = any;
1108
1109 if (f)
1110 {
1111
1112
1113
1114 if (!NILP (Vmouse_autoselect_window)
1115 && !popup_activated ()
1116
1117
1118
1119
1120
1121 && !MINI_WINDOW_P (XWINDOW (selected_window))
1122
1123
1124 && (f == XFRAME (selected_frame)
1125 || !NILP (focus_follows_mouse)))
1126 {
1127 static Lisp_Object last_mouse_window;
1128 Lisp_Object window
1129 = window_from_coordinates (f, event->xmotion.x,
1130 event->xmotion.y, 0,
1131 false, false);
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141 if (WINDOWP (window)
1142 && !EQ (window, last_mouse_window)
1143 && !EQ (window, selected_window))
1144 {
1145 inev.ie.kind = SELECT_WINDOW_EVENT;
1146 inev.ie.frame_or_window = window;
1147 }
1148
1149
1150 last_mouse_window = window;
1151 }
1152
1153 if (!android_note_mouse_movement (f, &event->xmotion))
1154 help_echo_string = previous_help_echo_string;
1155 }
1156
1157
1158
1159 if (!NILP (help_echo_string)
1160 || !NILP (previous_help_echo_string))
1161 do_help = 1;
1162
1163 if (f)
1164 android_flush_dirty_back_buffer_on (f);
1165
1166 goto OTHER;
1167
1168 case ANDROID_LEAVE_NOTIFY:
1169 f = any;
1170
1171 if (f)
1172 {
1173
1174
1175
1176
1177
1178 if (f == dpyinfo->last_mouse_motion_frame)
1179 dpyinfo->last_mouse_motion_frame = NULL;
1180
1181
1182
1183 if (f == dpyinfo->last_mouse_glyph_frame)
1184 dpyinfo->last_mouse_glyph_frame = NULL;
1185
1186 if (f == hlinfo->mouse_face_mouse_frame)
1187 {
1188
1189
1190 clear_mouse_face (hlinfo);
1191 hlinfo->mouse_face_mouse_frame = 0;
1192 android_flush_dirty_back_buffer_on (f);
1193 }
1194
1195
1196
1197
1198
1199 if (any_help_event_p
1200
1201
1202
1203 && !((EQ (track_mouse, Qdrag_source)
1204 || EQ (track_mouse, Qdropping))
1205 && gui_mouse_grabbed (dpyinfo)))
1206 do_help = -1;
1207 }
1208
1209 goto OTHER;
1210
1211 case ANDROID_EXPOSE:
1212
1213 f = any;
1214
1215 if (f)
1216 {
1217 if (!FRAME_VISIBLE_P (f))
1218 {
1219 f->output_data.android->has_been_visible = true;
1220 SET_FRAME_GARBAGED (f);
1221 }
1222
1223 if (!FRAME_GARBAGED_P (f))
1224 {
1225 expose_frame (f, event->xexpose.x, event->xexpose.y,
1226 event->xexpose.width, event->xexpose.height);
1227 show_back_buffer (f);
1228 }
1229 }
1230
1231 goto OTHER;
1232
1233 case ANDROID_BUTTON_PRESS:
1234 case ANDROID_BUTTON_RELEASE:
1235
1236
1237
1238 f = any;
1239
1240 Lisp_Object tab_bar_arg = Qnil;
1241 bool tab_bar_p = false;
1242 bool tool_bar_p = false;
1243
1244 dpyinfo->last_mouse_glyph_frame = NULL;
1245
1246 f = mouse_or_wdesc_frame (dpyinfo, event->xbutton.window);
1247
1248 if (f && event->xbutton.type == ANDROID_BUTTON_PRESS
1249 && !popup_activated ()
1250
1251
1252 && !FRAME_NO_ACCEPT_FOCUS (f))
1253 {
1254
1255
1256
1257
1258 struct frame *hf = dpyinfo->highlight_frame;
1259
1260 if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
1261 {
1262 android_set_input_focus (FRAME_ANDROID_WINDOW (f),
1263 event->xbutton.time);
1264
1265 if (FRAME_PARENT_FRAME (f))
1266 android_raise_window (FRAME_ANDROID_WINDOW (f));
1267 }
1268 }
1269
1270 if (f)
1271 {
1272
1273 if (WINDOWP (f->tab_bar_window)
1274 && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)))
1275 {
1276 Lisp_Object window;
1277 int x = event->xbutton.x;
1278 int y = event->xbutton.y;
1279
1280 window = window_from_coordinates (f, x, y, 0, true, true);
1281 tab_bar_p = EQ (window, f->tab_bar_window);
1282
1283 if (tab_bar_p)
1284 {
1285 tab_bar_arg = handle_tab_bar_click
1286 (f, x, y, (event->xbutton.type
1287 == ANDROID_BUTTON_PRESS),
1288 android_android_to_emacs_modifiers (dpyinfo,
1289 event->xbutton.state));
1290 android_flush_dirty_back_buffer_on (f);
1291 }
1292 }
1293
1294
1295 if (WINDOWP (f->tool_bar_window)
1296 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
1297 {
1298 Lisp_Object window;
1299 int x = event->xbutton.x;
1300 int y = event->xbutton.y;
1301
1302 window = window_from_coordinates (f, x, y, 0, true, true);
1303 tool_bar_p = (EQ (window, f->tool_bar_window)
1304 && ((event->xbutton.type
1305 != ANDROID_BUTTON_RELEASE)
1306 || f->last_tool_bar_item != -1));
1307
1308 if (tool_bar_p && event->xbutton.button < 4)
1309 {
1310 handle_tool_bar_click
1311 (f, x, y, (event->xbutton.type
1312 == ANDROID_BUTTON_PRESS),
1313 android_android_to_emacs_modifiers (dpyinfo,
1314 event->xbutton.state));
1315 android_flush_dirty_back_buffer_on (f);
1316 }
1317 }
1318
1319 if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p)
1320 if (! popup_activated ())
1321 {
1322 android_construct_mouse_click (&inev.ie, &event->xbutton, f);
1323
1324 if (!NILP (tab_bar_arg))
1325 inev.ie.arg = tab_bar_arg;
1326 }
1327 }
1328
1329 if (event->type == ANDROID_BUTTON_PRESS)
1330 {
1331 dpyinfo->grabbed |= (1 << event->xbutton.button);
1332 dpyinfo->last_mouse_frame = f;
1333 if (f && !tab_bar_p)
1334 f->last_tab_bar_item = -1;
1335 if (f && !tool_bar_p)
1336 f->last_tool_bar_item = -1;
1337 }
1338 else
1339 dpyinfo->grabbed &= ~(1 << event->xbutton.button);
1340
1341
1342
1343
1344 if (f != 0)
1345 f->mouse_moved = false;
1346
1347 goto OTHER;
1348
1349
1350 case ANDROID_TOUCH_DOWN:
1351
1352 if (!any)
1353 goto OTHER;
1354
1355
1356
1357
1358
1359
1360
1361 touchpoint = android_find_tool (any, event->touch.pointer_id);
1362
1363 if (touchpoint)
1364 {
1365
1366 touchpoint->x = event->touch.x;
1367 touchpoint->y = event->touch.x;
1368 android_update_tools (any, &inev.ie);
1369 inev.ie.timestamp = event->touch.time;
1370
1371 goto OTHER;
1372 }
1373
1374
1375
1376
1377 touchpoint = xmalloc (sizeof *touchpoint);
1378 touchpoint->tool_id = event->touch.pointer_id;
1379 touchpoint->x = event->touch.x;
1380 touchpoint->y = event->touch.x;
1381 touchpoint->next = FRAME_OUTPUT_DATA (any)->touch_points;
1382 touchpoint->tool_bar_p = false;
1383 FRAME_OUTPUT_DATA (any)->touch_points = touchpoint;
1384
1385
1386
1387
1388
1389
1390 if (WINDOWP (any->tool_bar_window)
1391 && WINDOW_TOTAL_LINES (XWINDOW (any->tool_bar_window)))
1392 {
1393 Lisp_Object window;
1394 int x = event->touch.x;
1395 int y = event->touch.y;
1396
1397 window = window_from_coordinates (any, x, y, 0, true,
1398 true);
1399
1400
1401
1402
1403
1404 if (EQ (window, any->tool_bar_window))
1405 {
1406
1407
1408
1409
1410
1411
1412
1413 if (!NILP (Vmouse_highlight))
1414 {
1415
1416
1417 any->pointer_invisible = false;
1418 note_mouse_highlight (any, x, y);
1419
1420
1421
1422
1423 memset (&dpyinfo->last_mouse_glyph, 0,
1424 sizeof dpyinfo->last_mouse_glyph);
1425 dpyinfo->last_mouse_glyph_frame = any;
1426 }
1427
1428 handle_tool_bar_click (any, x, y, true, 0);
1429
1430
1431
1432 android_flush_dirty_back_buffer_on (any);
1433
1434
1435
1436 touchpoint->tool_bar_p = true;
1437 goto OTHER;
1438 }
1439 }
1440
1441
1442 inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
1443 inev.ie.timestamp = event->touch.time;
1444 XSETFRAME (inev.ie.frame_or_window, any);
1445 XSETINT (inev.ie.x, event->touch.x);
1446 XSETINT (inev.ie.y, event->touch.y);
1447 XSETINT (inev.ie.arg, event->touch.pointer_id);
1448
1449 goto OTHER;
1450
1451 case ANDROID_TOUCH_MOVE:
1452
1453 if (!any)
1454 goto OTHER;
1455
1456
1457
1458 touchpoint = android_find_tool (any, event->touch.pointer_id);
1459
1460
1461
1462
1463 if (!touchpoint || touchpoint->tool_bar_p)
1464 goto OTHER;
1465
1466
1467
1468 touchpoint->x = event->touch.x;
1469 touchpoint->y = event->touch.y;
1470 android_update_tools (any, &inev.ie);
1471 inev.ie.timestamp = event->touch.time;
1472
1473 goto OTHER;
1474
1475 case ANDROID_TOUCH_UP:
1476
1477 if (!any)
1478 goto OTHER;
1479
1480
1481
1482 last = &FRAME_OUTPUT_DATA (any)->touch_points;
1483 while ((touchpoint = *last))
1484 {
1485 if (touchpoint->tool_id == event->touch.pointer_id)
1486 {
1487 *last = touchpoint->next;
1488
1489 if (touchpoint->tool_bar_p)
1490 {
1491 xfree (touchpoint);
1492
1493
1494
1495
1496 if (any->last_tool_bar_item != -1)
1497 handle_tool_bar_click (any, event->touch.x,
1498 event->touch.y, false,
1499 0);
1500
1501
1502 note_mouse_highlight (any, -1, -1);
1503 android_flush_dirty_back_buffer_on (any);
1504
1505 goto OTHER;
1506 }
1507
1508
1509
1510
1511 xfree (touchpoint);
1512
1513 inev.ie.kind = TOUCHSCREEN_END_EVENT;
1514 inev.ie.timestamp = event->touch.time;
1515
1516
1517
1518 if (event->touch.flags & ANDROID_TOUCH_SEQUENCE_CANCELED)
1519 inev.ie.modifiers = 1;
1520
1521 XSETFRAME (inev.ie.frame_or_window, any);
1522 XSETINT (inev.ie.x, event->touch.x);
1523 XSETINT (inev.ie.y, event->touch.y);
1524 XSETINT (inev.ie.arg, event->touch.pointer_id);
1525
1526
1527 goto OTHER;
1528 }
1529 else
1530 last = &touchpoint->next;
1531 }
1532
1533
1534 goto OTHER;
1535
1536
1537
1538
1539 case ANDROID_WHEEL:
1540
1541 if (!any)
1542 goto OTHER;
1543
1544 if (fabs (event->wheel.x_delta) > 0
1545 || fabs (event->wheel.y_delta) > 0)
1546 {
1547 if (mwheel_coalesce_scroll_events)
1548 {
1549 if (signbit (event->wheel.x_delta)
1550 != signbit (wheel_event_x))
1551 wheel_event_x = 0.0;
1552
1553 if (signbit (event->wheel.y_delta)
1554 != signbit (wheel_event_y))
1555 wheel_event_y = 0.0;
1556
1557
1558 wheel_event_x += event->wheel.x_delta;
1559 wheel_event_y += event->wheel.y_delta;
1560
1561 if (fabs (wheel_event_x) < 1.0
1562 && fabs (wheel_event_y) < 1.0)
1563 goto OTHER;
1564 }
1565 else
1566 {
1567
1568 wheel_event_x = event->wheel.x_delta;
1569 wheel_event_y = event->wheel.y_delta;
1570 }
1571
1572
1573 inev.ie.kind = ((fabs (wheel_event_y)
1574 >= fabs (wheel_event_x))
1575 ? WHEEL_EVENT : HORIZ_WHEEL_EVENT);
1576 inev.ie.timestamp = event->wheel.time;
1577
1578
1579 XSETINT (inev.ie.x, event->wheel.x);
1580 XSETINT (inev.ie.y, event->wheel.y);
1581
1582
1583 XSETFRAME (inev.ie.frame_or_window, any);
1584
1585
1586 inev.ie.modifiers = (signbit ((fabs (wheel_event_x)
1587 >= fabs (wheel_event_y))
1588 ? wheel_event_x
1589 : wheel_event_y)
1590 ? down_modifier : up_modifier);
1591
1592
1593 window = window_from_coordinates (any, event->wheel.x,
1594 event->wheel.y, NULL,
1595 false, false);
1596
1597 if (WINDOWP (window))
1598 scroll_height = XWINDOW (window)->pixel_height;
1599 else
1600
1601
1602
1603 scroll_height = FRAME_PIXEL_HEIGHT (any);
1604
1605 scroll_unit = pow (scroll_height, 2.0 / 3.0);
1606
1607
1608 inev.ie.modifiers
1609 |= android_android_to_emacs_modifiers (dpyinfo,
1610 event->wheel.state);
1611
1612
1613 inev.ie.arg = list3 (Qnil,
1614 make_float (wheel_event_x
1615 * scroll_unit),
1616 make_float (wheel_event_y
1617 * scroll_unit));
1618
1619 wheel_event_x = 0.0;
1620 wheel_event_y = 0.0;
1621 }
1622
1623 goto OTHER;
1624
1625
1626 case ANDROID_ICONIFIED:
1627
1628 if (!any)
1629 goto OTHER;
1630
1631 if (FRAME_ICONIFIED_P (any))
1632 goto OTHER;
1633
1634 SET_FRAME_VISIBLE (any, false);
1635 SET_FRAME_ICONIFIED (any, true);
1636
1637 inev.ie.kind = ICONIFY_EVENT;
1638 XSETFRAME (inev.ie.frame_or_window, any);
1639 goto OTHER;
1640
1641 case ANDROID_DEICONIFIED:
1642
1643 if (!any)
1644 goto OTHER;
1645
1646 if (!FRAME_ICONIFIED_P (any))
1647 goto OTHER;
1648
1649 SET_FRAME_VISIBLE (any, true);
1650 SET_FRAME_ICONIFIED (any, false);
1651
1652 inev.ie.kind = DEICONIFY_EVENT;
1653 XSETFRAME (inev.ie.frame_or_window, any);
1654 goto OTHER;
1655
1656
1657 case ANDROID_CONTEXT_MENU:
1658
1659 if (dpyinfo->menu_event_id == -1
1660
1661
1662
1663
1664 && event->menu.menu_event_serial == current_menu_serial)
1665 dpyinfo->menu_event_id = event->menu.menu_event_id;
1666
1667 goto OTHER;
1668
1669
1670
1671
1672 case ANDROID_INPUT_METHOD:
1673
1674 if (!any)
1675 {
1676
1677 xfree (event->ime.text);
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688 android_notify_conversion (event->ime.counter);
1689 }
1690 else
1691 android_handle_ime_event (event, any);
1692
1693 goto OTHER;
1694
1695 default:
1696 goto OTHER;
1697 }
1698
1699 OTHER:
1700 if (inev.ie.kind != NO_EVENT)
1701 {
1702 kbd_buffer_store_buffered_event (&inev, hold_quit);
1703 count++;
1704 }
1705
1706 if (do_help
1707 && !(hold_quit && hold_quit->kind != NO_EVENT))
1708 {
1709 Lisp_Object frame;
1710
1711 if (f)
1712 XSETFRAME (frame, f);
1713 else
1714 frame = Qnil;
1715
1716 if (do_help > 0)
1717 {
1718 any_help_event_p = true;
1719 gen_help_event (help_echo_string, frame, help_echo_window,
1720 help_echo_object, help_echo_pos);
1721 }
1722 else
1723 {
1724 help_echo_string = Qnil;
1725 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
1726 }
1727 count++;
1728 }
1729
1730 return count;
1731 }
1732
1733 static int
1734 android_read_socket (struct terminal *terminal,
1735 struct input_event *hold_quit)
1736 {
1737 int count = 0;
1738 struct android_display_info *dpyinfo;
1739
1740 dpyinfo = terminal->display_info.android;
1741
1742 block_input ();
1743 while (android_pending ())
1744 {
1745 int finish;
1746 union android_event event;
1747
1748 android_next_event (&event);
1749 count += handle_one_android_event (dpyinfo, &event, &finish,
1750 hold_quit);
1751
1752 if (finish == ANDROID_EVENT_GOTO_OUT)
1753 break;
1754 }
1755 unblock_input ();
1756
1757
1758
1759 if (dpyinfo->pending_autoraise_frame)
1760 {
1761 android_raise_frame (dpyinfo->pending_autoraise_frame);
1762 dpyinfo->pending_autoraise_frame = NULL;
1763 }
1764
1765 return count;
1766 }
1767
1768 static void
1769 android_frame_up_to_date (struct frame *f)
1770 {
1771 eassert (FRAME_ANDROID_P (f));
1772 block_input ();
1773 FRAME_MOUSE_UPDATE (f);
1774
1775 if (!buffer_flipping_blocked_p ()
1776 && FRAME_ANDROID_NEED_BUFFER_FLIP (f))
1777 show_back_buffer (f);
1778
1779
1780 FRAME_ANDROID_COMPLETE_P (f) = true;
1781
1782
1783 sfntfont_android_shrink_scanline_buffer ();
1784 unblock_input ();
1785 }
1786
1787 static void
1788 android_buffer_flipping_unblocked_hook (struct frame *f)
1789 {
1790 block_input ();
1791
1792 if (FRAME_ANDROID_NEED_BUFFER_FLIP (f))
1793 show_back_buffer (f);
1794
1795 unblock_input ();
1796 }
1797
1798 static void
1799 android_query_frame_background_color (struct frame *f, Emacs_Color *bgcolor)
1800 {
1801 unsigned long background;
1802
1803 background = FRAME_BACKGROUND_PIXEL (f);
1804 bgcolor->pixel = background;
1805
1806 android_query_colors (f, bgcolor, 1);
1807 }
1808
1809 int
1810 android_parse_color (struct frame *f, const char *color_name,
1811 Emacs_Color *color)
1812 {
1813 unsigned short r, g, b;
1814 Lisp_Object tem, tem1;
1815 unsigned long lisp_color;
1816
1817 if (parse_color_spec (color_name, &r, &g, &b))
1818 {
1819 color->red = r;
1820 color->green = g;
1821 color->blue = b;
1822
1823 return 1;
1824 }
1825
1826 tem = x_display_list->color_map;
1827 for (; CONSP (tem); tem = XCDR (tem))
1828 {
1829 tem1 = XCAR (tem);
1830
1831 if (CONSP (tem1)
1832 && !xstrcasecmp (SSDATA (XCAR (tem1)), color_name))
1833 {
1834 lisp_color = XFIXNUM (XCDR (tem1));
1835 color->red = RED_FROM_ULONG (lisp_color) * 257;
1836 color->green = GREEN_FROM_ULONG (lisp_color) * 257;
1837 color->blue = BLUE_FROM_ULONG (lisp_color) * 257;
1838 return 1;
1839 }
1840 }
1841
1842 return 0;
1843 }
1844
1845 bool
1846 android_alloc_nearest_color (struct frame *f, Emacs_Color *color)
1847 {
1848 gamma_correct (f, color);
1849 color->pixel = RGB_TO_ULONG (color->red / 256,
1850 color->green / 256,
1851 color->blue / 256);
1852
1853 return true;
1854 }
1855
1856 void
1857 android_query_colors (struct frame *f, Emacs_Color *colors, int ncolors)
1858 {
1859 int i;
1860
1861 for (i = 0; i < ncolors; ++i)
1862 {
1863 colors[i].red = RED_FROM_ULONG (colors[i].pixel) * 257;
1864 colors[i].green = RED_FROM_ULONG (colors[i].pixel) * 257;
1865 colors[i].blue = RED_FROM_ULONG (colors[i].pixel) * 257;
1866 }
1867 }
1868
1869 static void
1870 android_mouse_position (struct frame **fp, int insist,
1871 Lisp_Object *bar_window,
1872 enum scroll_bar_part *part, Lisp_Object *x,
1873 Lisp_Object *y, Time *timestamp)
1874 {
1875 Lisp_Object tail, frame;
1876 struct android_display_info *dpyinfo;
1877
1878 dpyinfo = FRAME_DISPLAY_INFO (*fp);
1879
1880
1881
1882
1883
1884 if (dpyinfo->last_mouse_motion_frame)
1885 {
1886 *fp = dpyinfo->last_mouse_motion_frame;
1887 *timestamp = dpyinfo->last_mouse_movement_time;
1888 *x = make_fixnum (dpyinfo->last_mouse_motion_x);
1889 *y = make_fixnum (dpyinfo->last_mouse_motion_y);
1890 *bar_window = Qnil;
1891 *part = scroll_bar_nowhere;
1892
1893 FOR_EACH_FRAME (tail, frame)
1894 {
1895 if (FRAME_ANDROID_P (XFRAME (frame)))
1896 XFRAME (frame)->mouse_moved = false;
1897 }
1898
1899 dpyinfo->last_mouse_motion_frame->mouse_moved = false;
1900 }
1901 }
1902
1903 static Lisp_Object
1904 android_get_focus_frame (struct frame *f)
1905 {
1906 Lisp_Object lisp_focus;
1907 struct frame *focus;
1908
1909 focus = FRAME_DISPLAY_INFO (f)->focus_frame;
1910
1911 if (!focus)
1912 return Qnil;
1913
1914 XSETFRAME (lisp_focus, focus);
1915 return lisp_focus;
1916 }
1917
1918 static void
1919 android_focus_frame (struct frame *f, bool noactivate)
1920 {
1921
1922
1923 android_set_input_focus (FRAME_ANDROID_WINDOW (f),
1924 ANDROID_CURRENT_TIME);
1925 }
1926
1927
1928
1929
1930 static void
1931 android_frame_highlight (struct frame *f)
1932 {
1933 gui_update_cursor (f, true);
1934 }
1935
1936 static void
1937 android_frame_unhighlight (struct frame *f)
1938 {
1939 gui_update_cursor (f, true);
1940 }
1941
1942 static void
1943 android_frame_rehighlight (struct android_display_info *dpyinfo)
1944 {
1945 struct frame *old_highlight;
1946
1947 old_highlight = dpyinfo->highlight_frame;
1948
1949 if (dpyinfo->focus_frame)
1950 {
1951 dpyinfo->highlight_frame
1952 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->focus_frame)))
1953 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->focus_frame))
1954 : dpyinfo->focus_frame);
1955 if (!FRAME_LIVE_P (dpyinfo->highlight_frame))
1956 {
1957 fset_focus_frame (dpyinfo->focus_frame, Qnil);
1958 dpyinfo->highlight_frame = dpyinfo->focus_frame;
1959 }
1960 }
1961 else
1962 dpyinfo->highlight_frame = 0;
1963
1964 if (dpyinfo->highlight_frame != old_highlight)
1965 {
1966
1967 if (old_highlight)
1968 android_frame_unhighlight (old_highlight);
1969 if (dpyinfo->highlight_frame)
1970 android_frame_highlight (dpyinfo->highlight_frame);
1971 }
1972 }
1973
1974 static void
1975 android_frame_rehighlight_hook (struct frame *f)
1976 {
1977 android_frame_rehighlight (FRAME_DISPLAY_INFO (f));
1978 }
1979
1980 static void
1981 android_frame_raise_lower (struct frame *f, bool raise_flag)
1982 {
1983 if (raise_flag)
1984 android_raise_frame (f);
1985 else
1986 android_lower_frame (f);
1987 }
1988
1989 void
1990 android_make_frame_visible (struct frame *f)
1991 {
1992 android_map_window (FRAME_ANDROID_WINDOW (f));
1993
1994 SET_FRAME_VISIBLE (f, true);
1995 SET_FRAME_ICONIFIED (f, false);
1996 }
1997
1998 void
1999 android_make_frame_invisible (struct frame *f)
2000 {
2001
2002 if (FRAME_DISPLAY_INFO (f)->highlight_frame == f)
2003 FRAME_DISPLAY_INFO (f)->highlight_frame = 0;
2004
2005 android_unmap_window (FRAME_ANDROID_WINDOW (f));
2006
2007 SET_FRAME_VISIBLE (f, false);
2008 SET_FRAME_ICONIFIED (f, false);
2009 }
2010
2011 static void
2012 android_make_frame_visible_invisible (struct frame *f, bool visible)
2013 {
2014 if (visible)
2015 android_make_frame_visible (f);
2016 else
2017 android_make_frame_invisible (f);
2018 }
2019
2020 static void
2021 android_fullscreen_hook (struct frame *f)
2022 {
2023 Lisp_Object wanted;
2024
2025 if (!FRAME_PARENT_FRAME (f))
2026 {
2027
2028
2029
2030 wanted = (f->want_fullscreen == FULLSCREEN_BOTH
2031 ? Qfullscreen : Qmaximized);
2032
2033 if (android_set_fullscreen (FRAME_ANDROID_WINDOW (f),
2034 EQ (wanted, Qfullscreen)))
2035 store_frame_param (f, Qfullscreen, Qmaximized);
2036 else
2037 store_frame_param (f, Qfullscreen, wanted);
2038 }
2039 else
2040 {
2041 store_frame_param (f, Qfullscreen, Qnil);
2042
2043
2044
2045 android_set_fullscreen (FRAME_ANDROID_WINDOW (f), false);
2046 }
2047 }
2048
2049 void
2050 android_iconify_frame (struct frame *f)
2051 {
2052
2053 error ("Can't notify window manager of iconification");
2054 }
2055
2056 static void
2057 android_wait_for_event (struct frame *f, int eventtype)
2058 {
2059 if (!FLOATP (Vandroid_wait_for_event_timeout))
2060 return;
2061
2062 int level = interrupt_input_blocked;
2063 struct timespec tmo, tmo_at, time_now;
2064
2065 f->wait_event_type = eventtype;
2066
2067
2068 double timeout = XFLOAT_DATA (Vandroid_wait_for_event_timeout);
2069 time_t timeout_seconds = (time_t) timeout;
2070 tmo = make_timespec (timeout_seconds,
2071 (long int) ((timeout - timeout_seconds)
2072 * 1000 * 1000 * 1000));
2073 tmo_at = timespec_add (current_timespec (), tmo);
2074
2075 while (f->wait_event_type)
2076 {
2077 pending_signals = true;
2078 totally_unblock_input ();
2079
2080 block_input ();
2081 interrupt_input_blocked = level;
2082
2083 time_now = current_timespec ();
2084 if (timespec_cmp (tmo_at, time_now) < 0)
2085 break;
2086
2087 tmo = timespec_sub (tmo_at, time_now);
2088 if (android_select (0, NULL, NULL, NULL, &tmo) == 0)
2089 break;
2090 }
2091
2092 f->wait_event_type = 0;
2093 }
2094
2095 static void
2096 android_set_window_size_1 (struct frame *f, bool change_gravity,
2097 int width, int height)
2098 {
2099 if (change_gravity)
2100 f->win_gravity = NorthWestGravity;
2101
2102 android_resize_window (FRAME_ANDROID_WINDOW (f), width,
2103 height);
2104
2105 SET_FRAME_GARBAGED (f);
2106
2107 if (FRAME_VISIBLE_P (f))
2108 {
2109 android_wait_for_event (f, ANDROID_CONFIGURE_NOTIFY);
2110
2111 if (CONSP (frame_size_history))
2112 frame_size_history_extra (f, build_string ("set_window_size_1 visible"),
2113 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
2114 width, height, f->new_width, f->new_height);
2115 }
2116 else
2117 {
2118 if (CONSP (frame_size_history))
2119 frame_size_history_extra (f, build_string ("set_window_size_1 "
2120 "invisible"),
2121 FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f),
2122 width, height, f->new_width, f->new_height);
2123
2124 adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, width),
2125 FRAME_PIXEL_TO_TEXT_HEIGHT (f, height),
2126 5, 0, Qx_set_window_size_1);
2127 }
2128 }
2129
2130 void
2131 android_set_window_size (struct frame *f, bool change_gravity,
2132 int width, int height)
2133 {
2134 block_input ();
2135
2136 android_set_window_size_1 (f, change_gravity, width, height);
2137 android_clear_under_internal_border (f);
2138
2139
2140 mark_window_cursors_off (XWINDOW (f->root_window));
2141
2142
2143
2144
2145
2146 cancel_mouse_face (f);
2147
2148 unblock_input ();
2149
2150 do_pending_window_change (false);
2151 }
2152
2153 static void
2154 android_set_offset (struct frame *f, int xoff, int yoff,
2155 int change_gravity)
2156 {
2157 if (change_gravity > 0)
2158 {
2159 f->top_pos = yoff;
2160 f->left_pos = xoff;
2161 f->size_hint_flags &= ~ (XNegative | YNegative);
2162 if (xoff < 0)
2163 f->size_hint_flags |= XNegative;
2164 if (yoff < 0)
2165 f->size_hint_flags |= YNegative;
2166 f->win_gravity = NorthWestGravity;
2167 }
2168
2169 android_move_window (FRAME_ANDROID_WINDOW (f), xoff, yoff);
2170 }
2171
2172 static void
2173 android_set_alpha (struct frame *f)
2174 {
2175
2176 }
2177
2178 static Lisp_Object
2179 android_new_font (struct frame *f, Lisp_Object font_object, int fontset)
2180 {
2181 struct font *font = XFONT_OBJECT (font_object);
2182 int unit, font_ascent, font_descent;
2183
2184 if (fontset < 0)
2185 fontset = fontset_from_font (font_object);
2186 FRAME_FONTSET (f) = fontset;
2187 if (FRAME_FONT (f) == font)
2188
2189
2190 return font_object;
2191
2192 FRAME_FONT (f) = font;
2193 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
2194 FRAME_COLUMN_WIDTH (f) = font->average_width;
2195 get_font_ascent_descent (font, &font_ascent, &font_descent);
2196 FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
2197
2198
2199 FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
2200
2201
2202
2203
2204
2205 unit = FRAME_COLUMN_WIDTH (f);
2206 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
2207 FRAME_CONFIG_SCROLL_BAR_COLS (f)
2208 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
2209 else
2210 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
2211
2212
2213
2214
2215
2216 if (FRAME_ANDROID_WINDOW (f) != 0 && !FRAME_TOOLTIP_P (f))
2217 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
2218 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3,
2219 false, Qfont);
2220
2221 return font_object;
2222 }
2223
2224 static bool
2225 android_bitmap_icon (struct frame *f, Lisp_Object file)
2226 {
2227 return false;
2228 }
2229
2230 static void
2231 android_free_pixmap_hook (struct frame *f, Emacs_Pixmap pixmap)
2232 {
2233 android_free_pixmap (pixmap);
2234 }
2235
2236 void
2237 android_free_frame_resources (struct frame *f)
2238 {
2239 struct android_display_info *dpyinfo;
2240 Mouse_HLInfo *hlinfo;
2241 struct android_touch_point *last, *next;
2242
2243 dpyinfo = FRAME_DISPLAY_INFO (f);
2244 hlinfo = &dpyinfo->mouse_highlight;
2245
2246 block_input ();
2247 free_frame_faces (f);
2248
2249
2250 if (FRAME_ANDROID_WINDOW (f))
2251 android_destroy_window (FRAME_ANDROID_WINDOW (f));
2252
2253 android_free_gcs (f);
2254
2255
2256 if (f->output_data.android->text_cursor)
2257 android_free_cursor (f->output_data.android->text_cursor);
2258 if (f->output_data.android->nontext_cursor)
2259 android_free_cursor (f->output_data.android->nontext_cursor);
2260 if (f->output_data.android->modeline_cursor)
2261 android_free_cursor (f->output_data.android->modeline_cursor);
2262 if (f->output_data.android->hand_cursor)
2263 android_free_cursor (f->output_data.android->hand_cursor);
2264 if (f->output_data.android->hourglass_cursor)
2265 android_free_cursor (f->output_data.android->hourglass_cursor);
2266 if (f->output_data.android->horizontal_drag_cursor)
2267 android_free_cursor (f->output_data.android->horizontal_drag_cursor);
2268 if (f->output_data.android->vertical_drag_cursor)
2269 android_free_cursor (f->output_data.android->vertical_drag_cursor);
2270 if (f->output_data.android->left_edge_cursor)
2271 android_free_cursor (f->output_data.android->left_edge_cursor);
2272 if (f->output_data.android->top_left_corner_cursor)
2273 android_free_cursor (f->output_data.android->top_left_corner_cursor);
2274 if (f->output_data.android->top_edge_cursor)
2275 android_free_cursor (f->output_data.android->top_edge_cursor);
2276 if (f->output_data.android->top_right_corner_cursor)
2277 android_free_cursor (f->output_data.android->top_right_corner_cursor);
2278 if (f->output_data.android->right_edge_cursor)
2279 android_free_cursor (f->output_data.android->right_edge_cursor);
2280 if (f->output_data.android->bottom_right_corner_cursor)
2281 android_free_cursor (f->output_data.android->bottom_right_corner_cursor);
2282 if (f->output_data.android->bottom_edge_cursor)
2283 android_free_cursor (f->output_data.android->bottom_edge_cursor);
2284 if (f->output_data.android->bottom_left_corner_cursor)
2285 android_free_cursor (f->output_data.android->bottom_left_corner_cursor);
2286
2287
2288 if (f->output_data.android->white_relief.gc)
2289 {
2290 android_free_gc (f->output_data.android->white_relief.gc);
2291 f->output_data.android->white_relief.gc = 0;
2292 }
2293 if (f->output_data.android->black_relief.gc)
2294 {
2295 android_free_gc (f->output_data.android->black_relief.gc);
2296 f->output_data.android->black_relief.gc = 0;
2297 }
2298
2299 if (f == dpyinfo->focus_frame)
2300 dpyinfo->focus_frame = 0;
2301 if (f == dpyinfo->x_focus_event_frame)
2302 dpyinfo->x_focus_event_frame = 0;
2303 if (f == dpyinfo->highlight_frame)
2304 dpyinfo->highlight_frame = 0;
2305 if (f == hlinfo->mouse_face_mouse_frame)
2306 reset_mouse_highlight (hlinfo);
2307
2308
2309
2310 if (f == dpyinfo->last_mouse_motion_frame)
2311 dpyinfo->last_mouse_motion_frame = NULL;
2312 if (f == dpyinfo->last_mouse_frame)
2313 dpyinfo->last_mouse_frame = NULL;
2314
2315
2316 next = FRAME_OUTPUT_DATA (f)->touch_points;
2317 while (next)
2318 {
2319 last = next;
2320 next = next->next;
2321 xfree (last);
2322 }
2323
2324
2325 FRAME_OUTPUT_DATA (f)->touch_points = NULL;
2326
2327 unblock_input ();
2328 }
2329
2330 static void
2331 android_delete_frame (struct frame *f)
2332 {
2333 android_free_frame_resources (f);
2334 xfree (f->output_data.android);
2335 f->output_data.android = NULL;
2336 }
2337
2338 static void
2339 android_delete_terminal (struct terminal *terminal)
2340 {
2341 error ("Cannot terminate connection to Android display server");
2342 }
2343
2344
2345
2346
2347
2348 static void
2349 android_scroll_run (struct window *w, struct run *run)
2350 {
2351 struct frame *f = XFRAME (w->frame);
2352 int x, y, width, height, from_y, to_y, bottom_y;
2353
2354
2355
2356
2357 window_box (w, ANY_AREA, &x, &y, &width, &height);
2358
2359 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2360 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2361 bottom_y = y + height;
2362
2363 if (to_y < from_y)
2364 {
2365
2366
2367 if (from_y + run->height > bottom_y)
2368 height = bottom_y - from_y;
2369 else
2370 height = run->height;
2371 }
2372 else
2373 {
2374
2375
2376 if (to_y + run->height > bottom_y)
2377 height = bottom_y - to_y;
2378 else
2379 height = run->height;
2380 }
2381
2382 block_input ();
2383
2384
2385 gui_clear_cursor (w);
2386
2387
2388
2389 android_copy_area (FRAME_ANDROID_DRAWABLE (f),
2390 FRAME_ANDROID_WINDOW (f),
2391 f->output_data.android->normal_gc,
2392 x, from_y, width, height, x, to_y);
2393
2394 unblock_input ();
2395 }
2396
2397 static void
2398 android_after_update_window_line (struct window *w, struct glyph_row *desired_row)
2399 {
2400 eassert (w);
2401
2402 if (!desired_row->mode_line_p && !w->pseudo_window_p)
2403 desired_row->redraw_fringe_bitmaps_p = true;
2404 }
2405
2406 static void
2407 android_flip_and_flush (struct frame *f)
2408 {
2409 block_input ();
2410
2411 if (FRAME_ANDROID_NEED_BUFFER_FLIP (f))
2412 show_back_buffer (f);
2413
2414
2415
2416 FRAME_ANDROID_COMPLETE_P (f) = true;
2417 unblock_input ();
2418 }
2419
2420 static void
2421 android_clear_rectangle (struct frame *f, struct android_gc *gc, int x,
2422 int y, int width, int height)
2423 {
2424 struct android_gc_values xgcv;
2425
2426 android_get_gc_values (gc, (ANDROID_GC_BACKGROUND
2427 | ANDROID_GC_FOREGROUND),
2428 &xgcv);
2429 android_set_foreground (gc, xgcv.background);
2430 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc,
2431 x, y, width, height);
2432 android_set_foreground (gc, xgcv.foreground);
2433 }
2434
2435 static void
2436 android_reset_clip_rectangles (struct frame *f, struct android_gc *gc)
2437 {
2438 android_set_clip_mask (gc, ANDROID_NONE);
2439 }
2440
2441 static void
2442 android_clip_to_row (struct window *w, struct glyph_row *row,
2443 enum glyph_row_area area, struct android_gc *gc)
2444 {
2445 struct android_rectangle clip_rect;
2446 int window_x, window_y, window_width;
2447
2448 window_box (w, area, &window_x, &window_y, &window_width, 0);
2449
2450 clip_rect.x = window_x;
2451 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
2452 clip_rect.y = max (clip_rect.y, window_y);
2453 clip_rect.width = window_width;
2454 clip_rect.height = row->visible_height;
2455
2456 android_set_clip_rectangles (gc, 0, 0, &clip_rect, 1);
2457 }
2458
2459 static void
2460 android_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
2461 struct draw_fringe_bitmap_params *p)
2462 {
2463 struct frame *f = XFRAME (WINDOW_FRAME (w));
2464 struct android_gc *gc = f->output_data.android->normal_gc;
2465 struct face *face = p->face;
2466
2467
2468 android_clip_to_row (w, row, ANY_AREA, gc);
2469
2470 if (p->bx >= 0 && !p->overlay_p)
2471 {
2472
2473
2474
2475
2476
2477 if (face->stipple)
2478 {
2479 android_set_fill_style (face->gc, ANDROID_FILL_OPAQUE_STIPPLED);
2480 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), face->gc,
2481 p->bx, p->by, p->nx, p->ny);
2482 android_set_fill_style (face->gc, ANDROID_FILL_SOLID);
2483
2484 row->stipple_p = true;
2485 }
2486 else
2487 {
2488 android_set_background (face->gc, face->background);
2489 android_clear_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
2490 android_set_foreground (face->gc, face->foreground);
2491 }
2492 }
2493
2494 if (p->which)
2495 {
2496 android_drawable drawable;
2497 char *bits;
2498 android_pixmap pixmap, clipmask;
2499 struct android_gc_values gcv;
2500 unsigned long background, cursor_pixel;
2501 int depth;
2502
2503 drawable = FRAME_ANDROID_DRAWABLE (f);
2504 clipmask = ANDROID_NONE;
2505 background = face->background;
2506 cursor_pixel = f->output_data.android->cursor_pixel;
2507 depth = FRAME_DISPLAY_INFO (f)->n_planes;
2508
2509 if (p->wd > 8)
2510 bits = (char *) (p->bits + p->dh);
2511 else
2512 bits = (char *) p->bits + p->dh;
2513
2514 pixmap = android_create_pixmap_from_bitmap_data (bits, p->wd, p->h,
2515 (p->cursor_p
2516 ? (p->overlay_p
2517 ? face->background
2518 : cursor_pixel)
2519 : face->foreground),
2520 background, depth);
2521
2522 if (p->overlay_p)
2523 {
2524 clipmask = android_create_pixmap_from_bitmap_data (bits, p->wd, p->h,
2525 1, 0, 1);
2526
2527 gcv.clip_mask = clipmask;
2528 gcv.clip_x_origin = p->x;
2529 gcv.clip_y_origin = p->y;
2530 android_change_gc (gc, (ANDROID_GC_CLIP_MASK
2531 | ANDROID_GC_CLIP_X_ORIGIN
2532 | ANDROID_GC_CLIP_Y_ORIGIN),
2533 &gcv);
2534 }
2535
2536 android_copy_area (pixmap, drawable, gc, 0, 0, p->wd, p->h,
2537 p->x, p->y);
2538 android_free_pixmap (pixmap);
2539
2540 if (p->overlay_p)
2541 {
2542 gcv.clip_mask = ANDROID_NONE;
2543 android_change_gc (gc, ANDROID_GC_CLIP_MASK, &gcv);
2544 android_free_pixmap (clipmask);
2545 }
2546 }
2547
2548 android_reset_clip_rectangles (f, gc);
2549 }
2550
2551
2552
2553
2554 static void
2555 android_set_cursor_gc (struct glyph_string *s)
2556 {
2557 if (s->font == FRAME_FONT (s->f)
2558 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2559 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2560 && !s->cmp)
2561 s->gc = s->f->output_data.android->cursor_gc;
2562 else
2563 {
2564
2565 struct android_gc_values xgcv;
2566 unsigned long mask;
2567
2568 xgcv.background = s->f->output_data.android->cursor_pixel;
2569 xgcv.foreground = s->face->background;
2570
2571
2572 if (xgcv.foreground == xgcv.background)
2573 xgcv.foreground = s->face->foreground;
2574 if (xgcv.foreground == xgcv.background)
2575 xgcv.foreground = s->f->output_data.android->cursor_foreground_pixel;
2576 if (xgcv.foreground == xgcv.background)
2577 xgcv.foreground = s->face->foreground;
2578
2579
2580 if (xgcv.background == s->face->background
2581 && xgcv.foreground == s->face->foreground)
2582 {
2583 xgcv.background = s->face->foreground;
2584 xgcv.foreground = s->face->background;
2585 }
2586
2587 mask = (ANDROID_GC_FOREGROUND | ANDROID_GC_BACKGROUND);
2588
2589 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2590 android_change_gc (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2591 mask, &xgcv);
2592 else
2593 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
2594 = android_create_gc (mask, &xgcv);
2595
2596 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2597 }
2598 }
2599
2600
2601
2602
2603 static void
2604 android_set_mouse_face_gc (struct glyph_string *s)
2605 {
2606 if (s->font == s->face->font)
2607 s->gc = s->face->gc;
2608 else
2609 {
2610
2611
2612 struct android_gc_values xgcv;
2613 unsigned long mask;
2614
2615 xgcv.background = s->face->background;
2616 xgcv.foreground = s->face->foreground;
2617
2618 mask = (ANDROID_GC_FOREGROUND | ANDROID_GC_BACKGROUND);
2619
2620 if (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2621 android_change_gc (FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2622 mask, &xgcv);
2623 else
2624 FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc
2625 = android_create_gc (mask, &xgcv);
2626
2627 s->gc = FRAME_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2628 }
2629
2630 eassert (s->gc != 0);
2631 }
2632
2633
2634
2635
2636
2637
2638 static void
2639 android_set_mode_line_face_gc (struct glyph_string *s)
2640 {
2641 s->gc = s->face->gc;
2642 }
2643
2644
2645
2646
2647
2648 static void
2649 android_set_glyph_string_gc (struct glyph_string *s)
2650 {
2651 prepare_face_for_display (s->f, s->face);
2652
2653 if (s->hl == DRAW_NORMAL_TEXT)
2654 {
2655 s->gc = s->face->gc;
2656 s->stippled_p = s->face->stipple != 0;
2657 }
2658 else if (s->hl == DRAW_INVERSE_VIDEO)
2659 {
2660 android_set_mode_line_face_gc (s);
2661 s->stippled_p = s->face->stipple != 0;
2662 }
2663 else if (s->hl == DRAW_CURSOR)
2664 {
2665 android_set_cursor_gc (s);
2666 s->stippled_p = false;
2667 }
2668 else if (s->hl == DRAW_MOUSE_FACE)
2669 {
2670 android_set_mouse_face_gc (s);
2671 s->stippled_p = s->face->stipple != 0;
2672 }
2673 else if (s->hl == DRAW_IMAGE_RAISED
2674 || s->hl == DRAW_IMAGE_SUNKEN)
2675 {
2676 s->gc = s->face->gc;
2677 s->stippled_p = s->face->stipple != 0;
2678 }
2679 else
2680 emacs_abort ();
2681
2682
2683 eassert (s->gc != 0);
2684 }
2685
2686
2687
2688
2689
2690 static void
2691 android_set_glyph_string_clipping (struct glyph_string *s)
2692 {
2693 struct android_rectangle *r = s->clip;
2694 int n = get_glyph_string_clip_rects (s, r, 2);
2695
2696 if (n > 0)
2697 android_set_clip_rectangles (s->gc, 0, 0, r, n);
2698 s->num_clips = n;
2699 }
2700
2701
2702
2703
2704
2705
2706 static void
2707 android_set_glyph_string_clipping_exactly (struct glyph_string *src,
2708 struct glyph_string *dst)
2709 {
2710 struct android_rectangle r;
2711
2712 r.x = src->x;
2713 r.width = src->width;
2714 r.y = src->y;
2715 r.height = src->height;
2716 dst->clip[0] = r;
2717 dst->num_clips = 1;
2718 android_set_clip_rectangles (dst->gc, 0, 0, &r, 1);
2719 }
2720
2721 static void
2722 android_compute_glyph_string_overhangs (struct glyph_string *s)
2723 {
2724 if (s->cmp == NULL
2725 && (s->first_glyph->type == CHAR_GLYPH
2726 || s->first_glyph->type == COMPOSITE_GLYPH))
2727 {
2728 struct font_metrics metrics;
2729
2730 if (s->first_glyph->type == CHAR_GLYPH)
2731 {
2732 struct font *font = s->font;
2733 font->driver->text_extents (font, s->char2b, s->nchars, &metrics);
2734 }
2735 else
2736 {
2737 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
2738
2739 composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
2740 }
2741 s->right_overhang = (metrics.rbearing > metrics.width
2742 ? metrics.rbearing - metrics.width : 0);
2743 s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
2744 }
2745 else if (s->cmp)
2746 {
2747 s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
2748 s->left_overhang = - s->cmp->lbearing;
2749 }
2750 }
2751
2752 static void
2753 android_clear_glyph_string_rect (struct glyph_string *s, int x, int y,
2754 int w, int h)
2755 {
2756 android_clear_rectangle (s->f, s->gc, x, y, w, h);
2757 }
2758
2759 static void
2760 android_draw_glyph_string_background (struct glyph_string *s, bool force_p)
2761 {
2762
2763
2764 if (!s->background_filled_p)
2765 {
2766 int box_line_width = max (s->face->box_horizontal_line_width, 0);
2767
2768 if (s->stippled_p)
2769 {
2770
2771 android_set_fill_style (s->gc, ANDROID_FILL_OPAQUE_STIPPLED);
2772 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc,
2773 s->x, s->y + box_line_width,
2774 s->background_width,
2775 s->height - 2 * box_line_width);
2776 android_set_fill_style (s->gc, ANDROID_FILL_SOLID);
2777 s->background_filled_p = true;
2778 }
2779 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2780
2781
2782
2783
2784 || FONT_TOO_HIGH (s->font)
2785 || s->font_not_found_p
2786 || s->extends_to_end_of_line_p
2787 || force_p)
2788 {
2789 android_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2790 s->background_width,
2791 s->height - 2 * box_line_width);
2792 s->background_filled_p = true;
2793 }
2794 }
2795 }
2796
2797 static void
2798 android_fill_triangle (struct frame *f, struct android_gc *gc,
2799 struct android_point point1,
2800 struct android_point point2,
2801 struct android_point point3)
2802 {
2803 struct android_point abc[3];
2804
2805 abc[0] = point1;
2806 abc[1] = point2;
2807 abc[2] = point3;
2808
2809 android_fill_polygon (FRAME_ANDROID_DRAWABLE (f),
2810 gc, abc, 3, ANDROID_CONVEX,
2811 ANDROID_COORD_MODE_ORIGIN);
2812 }
2813
2814 static struct android_point
2815 android_make_point (int x, int y)
2816 {
2817 struct android_point pt;
2818
2819 pt.x = x;
2820 pt.y = y;
2821
2822 return pt;
2823 }
2824
2825 static bool
2826 android_inside_rect_p (struct android_rectangle *rects, int nrects, int x,
2827 int y)
2828 {
2829 int i;
2830
2831 for (i = 0; i < nrects; ++i)
2832 {
2833 if (x >= rects[i].x && y >= rects[i].y
2834 && x < rects[i].x + rects[i].width
2835 && y < rects[i].y + rects[i].height)
2836 return true;
2837 }
2838
2839 return false;
2840 }
2841
2842 static void
2843 android_clear_point (struct frame *f, struct android_gc *gc,
2844 int x, int y)
2845 {
2846 struct android_gc_values xgcv;
2847
2848 android_get_gc_values (gc, ANDROID_GC_BACKGROUND | ANDROID_GC_FOREGROUND,
2849 &xgcv);
2850 android_set_foreground (gc, xgcv.background);
2851 android_draw_point (FRAME_ANDROID_DRAWABLE (f), gc, x, y);
2852 android_set_foreground (gc, xgcv.foreground);
2853 }
2854
2855 static void
2856 android_draw_relief_rect (struct frame *f, int left_x, int top_y, int right_x,
2857 int bottom_y, int hwidth, int vwidth, bool raised_p,
2858 bool top_p, bool bot_p, bool left_p, bool right_p,
2859 struct android_rectangle *clip_rect)
2860 {
2861 struct android_gc *gc, *white_gc, *black_gc, *normal_gc;
2862 android_drawable drawable;
2863
2864
2865
2866
2867
2868
2869 white_gc = f->output_data.android->white_relief.gc;
2870 black_gc = f->output_data.android->black_relief.gc;
2871 normal_gc = f->output_data.android->normal_gc;
2872
2873 drawable = FRAME_ANDROID_DRAWABLE (f);
2874
2875 android_set_clip_rectangles (white_gc, 0, 0, clip_rect, 1);
2876 android_set_clip_rectangles (black_gc, 0, 0, clip_rect, 1);
2877
2878 if (raised_p)
2879 gc = white_gc;
2880 else
2881 gc = black_gc;
2882
2883
2884
2885 if (top_p)
2886 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc, left_x, top_y,
2887 right_x - left_x + 1, hwidth);
2888
2889 if (left_p)
2890 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc, left_x, top_y,
2891 vwidth, bottom_y - top_y + 1);
2892
2893 if (raised_p)
2894 gc = black_gc;
2895 else
2896 gc = white_gc;
2897
2898 if (bot_p)
2899 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc, left_x,
2900 bottom_y - hwidth + 1,
2901 right_x - left_x + 1, hwidth);
2902
2903 if (right_p)
2904 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc,
2905 right_x - vwidth + 1,
2906 top_y, vwidth, bottom_y - top_y + 1);
2907
2908
2909
2910 if (bot_p && left_p)
2911 android_fill_triangle (f, raised_p ? white_gc : black_gc,
2912 android_make_point (left_x, bottom_y - hwidth),
2913 android_make_point (left_x + vwidth,
2914 bottom_y - hwidth),
2915 android_make_point (left_x, bottom_y));
2916
2917 if (top_p && right_p)
2918 android_fill_triangle (f, raised_p ? white_gc : black_gc,
2919 android_make_point (right_x - vwidth, top_y),
2920 android_make_point (right_x, top_y),
2921 android_make_point (right_x - vwidth,
2922 top_y + hwidth));
2923
2924
2925
2926 if (top_p && left_p && bot_p && right_p
2927 && hwidth > 1 && vwidth > 1)
2928 android_draw_rectangle (FRAME_ANDROID_DRAWABLE (f),
2929 black_gc, left_x, top_y,
2930 right_x - left_x, bottom_y - top_y);
2931 else
2932 {
2933 if (top_p && hwidth > 1)
2934 android_draw_line (drawable, black_gc, left_x, top_y,
2935 right_x + 1, top_y);
2936
2937 if (bot_p && hwidth > 1)
2938 android_draw_line (drawable, black_gc, left_x, bottom_y,
2939 right_x + 1, bottom_y);
2940
2941 if (left_p && vwidth > 1)
2942 android_draw_line (drawable, black_gc, left_x, top_y,
2943 left_x, bottom_y + 1);
2944
2945 if (right_p && vwidth > 1)
2946 android_draw_line (drawable, black_gc, right_x, top_y,
2947 right_x, bottom_y + 1);
2948 }
2949
2950
2951
2952 if (hwidth > 1 && vwidth > 1)
2953 {
2954 if (left_p && top_p && android_inside_rect_p (clip_rect, 1,
2955 left_x, top_y))
2956 android_clear_point (f, normal_gc, left_x, top_y);
2957
2958 if (left_p && bot_p && android_inside_rect_p (clip_rect, 1,
2959 left_x, bottom_y))
2960 android_clear_point (f, normal_gc, left_x, bottom_y);
2961
2962 if (right_p && top_p && android_inside_rect_p (clip_rect, 1,
2963 right_x, top_y))
2964 android_clear_point (f, normal_gc, right_x, top_y);
2965
2966 if (right_p && bot_p && android_inside_rect_p (clip_rect, 1,
2967 right_x, bottom_y))
2968 android_clear_point (f, normal_gc, right_x, bottom_y);
2969 }
2970
2971 android_reset_clip_rectangles (f, white_gc);
2972 android_reset_clip_rectangles (f, black_gc);
2973 }
2974
2975 static void
2976 android_draw_box_rect (struct glyph_string *s,
2977 int left_x, int top_y, int right_x, int bottom_y,
2978 int hwidth, int vwidth, bool left_p, bool right_p,
2979 struct android_rectangle *clip_rect)
2980 {
2981 struct android_gc_values xgcv;
2982
2983 android_get_gc_values (s->gc, ANDROID_GC_FOREGROUND, &xgcv);
2984 android_set_foreground (s->gc, s->face->box_color);
2985 android_set_clip_rectangles (s->gc, 0, 0, clip_rect, 1);
2986
2987
2988 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc, left_x,
2989 top_y, right_x - left_x + 1, hwidth);
2990
2991
2992 if (left_p)
2993 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc, left_x,
2994 top_y, vwidth, bottom_y - top_y + 1);
2995
2996
2997 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc, left_x,
2998 bottom_y - hwidth + 1, right_x - left_x + 1,
2999 hwidth);
3000
3001
3002 if (right_p)
3003 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc,
3004 right_x - vwidth + 1, top_y, vwidth,
3005 bottom_y - top_y + 1);
3006
3007 android_set_foreground (s->gc, xgcv.foreground);
3008 android_reset_clip_rectangles (s->f, s->gc);
3009 }
3010
3011 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3012
3013 static bool
3014 android_alloc_lighter_color (struct frame *f, unsigned long *pixel,
3015 double factor, int delta)
3016 {
3017 Emacs_Color color, new;
3018 long bright;
3019 bool success_p;
3020
3021
3022 color.pixel = *pixel;
3023 android_query_colors (f, &color, 1);
3024
3025
3026 eassert (factor >= 0);
3027 new.red = min (0xffff, factor * color.red);
3028 new.green = min (0xffff, factor * color.green);
3029 new.blue = min (0xffff, factor * color.blue);
3030
3031
3032 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
3033
3034
3035
3036 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3037
3038
3039 {
3040
3041 double dimness = 1 - (double) bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3042
3043 int min_delta = delta * dimness * factor / 2;
3044
3045 if (factor < 1)
3046 {
3047 new.red = max (0, new.red - min_delta);
3048 new.green = max (0, new.green - min_delta);
3049 new.blue = max (0, new.blue - min_delta);
3050 }
3051 else
3052 {
3053 new.red = min (0xffff, min_delta + new.red);
3054 new.green = min (0xffff, min_delta + new.green);
3055 new.blue = min (0xffff, min_delta + new.blue);
3056 }
3057 }
3058
3059
3060 success_p = android_alloc_nearest_color (f, &new);
3061
3062 if (success_p)
3063 {
3064 if (new.pixel == *pixel)
3065 {
3066
3067
3068 new.red = min (0xffff, delta + color.red);
3069 new.green = min (0xffff, delta + color.green);
3070 new.blue = min (0xffff, delta + color.blue);
3071 success_p = android_alloc_nearest_color (f, &new);
3072 }
3073 else
3074 success_p = true;
3075
3076 *pixel = new.pixel;
3077 }
3078
3079 return success_p;
3080 }
3081
3082
3083
3084
3085
3086
3087
3088
3089 static void
3090 android_setup_relief_color (struct frame *f, struct relief *relief,
3091 double factor, int delta,
3092 unsigned long default_pixel)
3093 {
3094 struct android_gc_values xgcv;
3095 struct android_output *di = f->output_data.android;
3096 unsigned long mask = ANDROID_GC_FOREGROUND;
3097 unsigned long pixel;
3098 unsigned long background = di->relief_background;
3099 struct android_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
3100
3101 if (relief->gc && relief->pixel != -1)
3102 relief->pixel = -1;
3103
3104
3105 xgcv.foreground = default_pixel;
3106 pixel = background;
3107
3108 if (dpyinfo->n_planes != 1
3109 && android_alloc_lighter_color (f, &pixel, factor, delta))
3110 xgcv.foreground = relief->pixel = pixel;
3111
3112 if (relief->gc == 0)
3113 relief->gc = android_create_gc (mask, &xgcv);
3114 else
3115 android_change_gc (relief->gc, mask, &xgcv);
3116 }
3117
3118
3119
3120 static void
3121 android_setup_relief_colors (struct glyph_string *s)
3122 {
3123 struct android_output *di;
3124 unsigned long color;
3125
3126 di = s->f->output_data.android;
3127
3128 if (s->face->use_box_color_for_shadows_p)
3129 color = s->face->box_color;
3130 else if (s->first_glyph->type == IMAGE_GLYPH
3131 && s->img->pixmap
3132 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3133 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3134 else
3135 {
3136 struct android_gc_values xgcv;
3137
3138
3139 android_get_gc_values (s->gc, ANDROID_GC_BACKGROUND, &xgcv);
3140 color = xgcv.background;
3141 }
3142
3143 if (di->white_relief.gc == 0
3144 || color != di->relief_background)
3145 {
3146 di->relief_background = color;
3147 android_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3148 WHITE_PIX_DEFAULT (s->f));
3149 android_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3150 BLACK_PIX_DEFAULT (s->f));
3151 }
3152 }
3153
3154 static void
3155 android_draw_glyph_string_box (struct glyph_string *s)
3156 {
3157 int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
3158 bool raised_p, left_p, right_p;
3159 struct glyph *last_glyph;
3160 struct android_rectangle clip_rect;
3161
3162 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
3163 ? WINDOW_RIGHT_EDGE_X (s->w)
3164 : window_box_right (s->w, s->area));
3165
3166
3167
3168
3169 if (s->cmp || s->img)
3170 last_glyph = s->first_glyph;
3171 else if (s->first_glyph->type == COMPOSITE_GLYPH
3172 && s->first_glyph->u.cmp.automatic)
3173 {
3174
3175
3176 struct glyph *end = s->row->glyphs[s->area] + s->row->used[s->area];
3177 struct glyph *g = s->first_glyph;
3178 for (last_glyph = g++;
3179 g < end && g->u.cmp.automatic && g->u.cmp.id == s->cmp_id
3180 && g->slice.cmp.to < s->cmp_to;
3181 last_glyph = g++)
3182 ;
3183 }
3184 else
3185 last_glyph = s->first_glyph + s->nchars - 1;
3186
3187 vwidth = eabs (s->face->box_vertical_line_width);
3188 hwidth = eabs (s->face->box_horizontal_line_width);
3189 raised_p = s->face->box == FACE_RAISED_BOX;
3190 left_x = s->x;
3191 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3192 ? last_x - 1
3193 : min (last_x, s->x + s->background_width) - 1);
3194 top_y = s->y;
3195 bottom_y = top_y + s->height - 1;
3196
3197 left_p = (s->first_glyph->left_box_line_p
3198 || (s->hl == DRAW_MOUSE_FACE
3199 && (s->prev == NULL
3200 || s->prev->hl != s->hl)));
3201 right_p = (last_glyph->right_box_line_p
3202 || (s->hl == DRAW_MOUSE_FACE
3203 && (s->next == NULL
3204 || s->next->hl != s->hl)));
3205
3206 get_glyph_string_clip_rect (s, &clip_rect);
3207
3208 if (s->face->box == FACE_SIMPLE_BOX)
3209 android_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
3210 vwidth, left_p, right_p, &clip_rect);
3211 else
3212 {
3213 android_setup_relief_colors (s);
3214 android_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, hwidth,
3215 vwidth, raised_p, true, true, left_p, right_p,
3216 &clip_rect);
3217 }
3218 }
3219
3220 static void
3221 android_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y,
3222 int w, int h)
3223 {
3224 if (s->stippled_p)
3225 {
3226
3227 android_set_fill_style (s->gc, ANDROID_FILL_OPAQUE_STIPPLED);
3228 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc, x,
3229 y, w, h);
3230 android_set_fill_style (s->gc, ANDROID_FILL_SOLID);
3231 }
3232 else
3233 android_clear_glyph_string_rect (s, x, y, w, h);
3234 }
3235
3236 static void
3237 android_draw_image_relief (struct glyph_string *s)
3238 {
3239 int x1, y1, thick;
3240 bool raised_p, top_p, bot_p, left_p, right_p;
3241 int extra_x, extra_y;
3242 struct android_rectangle r;
3243 int x = s->x;
3244 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3245
3246
3247
3248 if (s->face->box != FACE_NO_BOX
3249 && s->first_glyph->left_box_line_p
3250 && s->slice.x == 0)
3251 x += max (s->face->box_vertical_line_width, 0);
3252
3253
3254
3255 if (s->slice.x == 0)
3256 x += s->img->hmargin;
3257 if (s->slice.y == 0)
3258 y += s->img->vmargin;
3259
3260 if (s->hl == DRAW_IMAGE_SUNKEN
3261 || s->hl == DRAW_IMAGE_RAISED)
3262 {
3263 if (s->face->id == TAB_BAR_FACE_ID)
3264 thick = (tab_bar_button_relief < 0
3265 ? DEFAULT_TAB_BAR_BUTTON_RELIEF
3266 : min (tab_bar_button_relief, 1000000));
3267 else
3268 thick = (tool_bar_button_relief < 0
3269 ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
3270 : min (tool_bar_button_relief, 1000000));
3271 raised_p = s->hl == DRAW_IMAGE_RAISED;
3272 }
3273 else
3274 {
3275 thick = eabs (s->img->relief);
3276 raised_p = s->img->relief > 0;
3277 }
3278
3279 x1 = x + s->slice.width - 1;
3280 y1 = y + s->slice.height - 1;
3281
3282 extra_x = extra_y = 0;
3283 if (s->face->id == TAB_BAR_FACE_ID)
3284 {
3285 if (CONSP (Vtab_bar_button_margin)
3286 && FIXNUMP (XCAR (Vtab_bar_button_margin))
3287 && FIXNUMP (XCDR (Vtab_bar_button_margin)))
3288 {
3289 extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)) - thick;
3290 extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)) - thick;
3291 }
3292 else if (FIXNUMP (Vtab_bar_button_margin))
3293 extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin) - thick;
3294 }
3295
3296 if (s->face->id == TOOL_BAR_FACE_ID)
3297 {
3298 if (CONSP (Vtool_bar_button_margin)
3299 && FIXNUMP (XCAR (Vtool_bar_button_margin))
3300 && FIXNUMP (XCDR (Vtool_bar_button_margin)))
3301 {
3302 extra_x = XFIXNUM (XCAR (Vtool_bar_button_margin));
3303 extra_y = XFIXNUM (XCDR (Vtool_bar_button_margin));
3304 }
3305 else if (FIXNUMP (Vtool_bar_button_margin))
3306 extra_x = extra_y = XFIXNUM (Vtool_bar_button_margin);
3307 }
3308
3309 top_p = bot_p = left_p = right_p = false;
3310
3311 if (s->slice.x == 0)
3312 x -= thick + extra_x, left_p = true;
3313 if (s->slice.y == 0)
3314 y -= thick + extra_y, top_p = true;
3315 if (s->slice.x + s->slice.width == s->img->width)
3316 x1 += thick + extra_x, right_p = true;
3317 if (s->slice.y + s->slice.height == s->img->height)
3318 y1 += thick + extra_y, bot_p = true;
3319
3320 android_setup_relief_colors (s);
3321 get_glyph_string_clip_rect (s, &r);
3322 android_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
3323 top_p, bot_p, left_p, right_p, &r);
3324 }
3325
3326 static void
3327 android_draw_image_foreground (struct glyph_string *s)
3328 {
3329 int x = s->x;
3330 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3331
3332
3333
3334 if (s->face->box != FACE_NO_BOX
3335 && s->first_glyph->left_box_line_p
3336 && s->slice.x == 0)
3337 x += max (s->face->box_vertical_line_width, 0);
3338
3339
3340
3341 if (s->slice.x == 0)
3342 x += s->img->hmargin;
3343 if (s->slice.y == 0)
3344 y += s->img->vmargin;
3345
3346 if (s->img->pixmap)
3347 {
3348 unsigned long mask = (ANDROID_GC_CLIP_MASK
3349 | ANDROID_GC_CLIP_X_ORIGIN
3350 | ANDROID_GC_CLIP_Y_ORIGIN
3351 | ANDROID_GC_FUNCTION);
3352 struct android_gc_values xgcv;
3353 struct android_rectangle clip_rect, image_rect, r;
3354
3355 xgcv.clip_mask = s->img->mask;
3356 xgcv.clip_x_origin = x - s->slice.x;
3357 xgcv.clip_y_origin = y - s->slice.y;
3358 xgcv.function = ANDROID_GC_COPY;
3359 android_change_gc (s->gc, mask, &xgcv);
3360
3361 get_glyph_string_clip_rect (s, &clip_rect);
3362 image_rect.x = x;
3363 image_rect.y = y;
3364 image_rect.width = s->slice.width;
3365 image_rect.height = s->slice.height;
3366
3367 if (gui_intersect_rectangles (&clip_rect, &image_rect, &r))
3368 android_copy_area (s->img->pixmap,
3369 FRAME_ANDROID_DRAWABLE (s->f),
3370 s->gc, s->slice.x + r.x - x,
3371 s->slice.y + r.y - y,
3372 r.width, r.height, r.x, r.y);
3373
3374
3375
3376
3377
3378
3379 if (s->hl == DRAW_CURSOR && !s->img->mask)
3380 {
3381 int relief = eabs (s->img->relief);
3382 android_draw_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc,
3383 x - relief, y - relief,
3384 s->slice.width + relief*2 - 1,
3385 s->slice.height + relief*2 - 1);
3386 }
3387
3388 android_set_clip_mask (s->gc, ANDROID_NONE);
3389 }
3390 else
3391
3392 android_draw_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc, x, y,
3393 s->slice.width - 1, s->slice.height - 1);
3394 }
3395
3396 static void
3397 android_draw_image_glyph_string (struct glyph_string *s)
3398 {
3399 int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
3400 int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
3401 int height;
3402
3403 height = s->height;
3404 if (s->slice.y == 0)
3405 height -= box_line_vwidth;
3406 if (s->slice.y + s->slice.height >= s->img->height)
3407 height -= box_line_vwidth;
3408
3409
3410
3411
3412 s->stippled_p = s->face->stipple != 0;
3413 if (height > s->slice.height
3414 || s->img->hmargin
3415 || s->img->vmargin
3416 || s->img->mask
3417 || s->img->pixmap == 0
3418 || s->width != s->background_width)
3419 {
3420 if (s->stippled_p)
3421 s->row->stipple_p = true;
3422
3423 int x = s->x;
3424 int y = s->y;
3425 int width = s->background_width;
3426
3427 if (s->first_glyph->left_box_line_p
3428 && s->slice.x == 0)
3429 {
3430 x += box_line_hwidth;
3431 width -= box_line_hwidth;
3432 }
3433
3434 if (s->slice.y == 0)
3435 y += box_line_vwidth;
3436
3437 android_draw_glyph_string_bg_rect (s, x, y, width, height);
3438
3439 s->background_filled_p = true;
3440 }
3441
3442
3443 android_draw_image_foreground (s);
3444 android_set_glyph_string_clipping (s);
3445
3446
3447 if (s->img->relief
3448 || s->hl == DRAW_IMAGE_RAISED
3449 || s->hl == DRAW_IMAGE_SUNKEN)
3450 android_draw_image_relief (s);
3451 }
3452
3453 static void
3454 android_draw_stretch_glyph_string (struct glyph_string *s)
3455 {
3456 eassert (s->first_glyph->type == STRETCH_GLYPH);
3457
3458 if (s->hl == DRAW_CURSOR && !x_stretch_cursor_p)
3459 {
3460
3461
3462 int width, background_width = s->background_width;
3463 int x = s->x;
3464
3465 if (!s->row->reversed_p)
3466 {
3467 int left_x = window_box_left_offset (s->w, TEXT_AREA);
3468
3469 if (x < left_x)
3470 {
3471 background_width -= left_x - x;
3472 x = left_x;
3473 }
3474 }
3475 else
3476 {
3477
3478
3479 int right_x = window_box_right (s->w, TEXT_AREA);
3480
3481 if (x + background_width > right_x)
3482 background_width -= x - right_x;
3483 x += background_width;
3484 }
3485 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
3486 if (s->row->reversed_p)
3487 x -= width;
3488
3489
3490 android_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
3491
3492
3493 if (width < background_width)
3494 {
3495 int y = s->y;
3496 int w = background_width - width, h = s->height;
3497 struct android_rectangle r;
3498 struct android_gc *gc;
3499
3500 if (!s->row->reversed_p)
3501 x += width;
3502 else
3503 x = s->x;
3504 if (s->row->mouse_face_p
3505 && cursor_in_mouse_face_p (s->w))
3506 {
3507 android_set_mouse_face_gc (s);
3508 gc = s->gc;
3509 }
3510 else
3511 gc = s->face->gc;
3512
3513 get_glyph_string_clip_rect (s, &r);
3514 android_set_clip_rectangles (gc, 0, 0, &r, 1);
3515
3516 if (s->face->stipple)
3517 {
3518
3519 android_set_fill_style (gc, ANDROID_FILL_OPAQUE_STIPPLED);
3520 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f),
3521 gc, x, y, w, h);
3522 android_set_fill_style (gc, ANDROID_FILL_SOLID);
3523
3524 s->row->stipple_p = true;
3525 }
3526 else
3527 {
3528 struct android_gc_values xgcv;
3529 android_get_gc_values (gc, (ANDROID_GC_FOREGROUND
3530 | ANDROID_GC_BACKGROUND),
3531 &xgcv);
3532 android_set_foreground (gc, xgcv.background);
3533 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f),
3534 gc, x, y, w, h);
3535 android_set_foreground (gc, xgcv.foreground);
3536 }
3537
3538 android_reset_clip_rectangles (s->f, gc);
3539 }
3540 }
3541 else if (!s->background_filled_p)
3542 {
3543 int background_width = s->background_width;
3544 int x = s->x, text_left_x = window_box_left (s->w, TEXT_AREA);
3545
3546
3547
3548 if (s->area == TEXT_AREA
3549 && x < text_left_x && !s->row->mode_line_p)
3550 {
3551 background_width -= text_left_x - x;
3552 x = text_left_x;
3553 }
3554
3555 if (!s->row->stipple_p)
3556 s->row->stipple_p = s->stippled_p;
3557
3558 if (background_width > 0)
3559 android_draw_glyph_string_bg_rect (s, x, s->y,
3560 background_width,
3561 s->height);
3562 }
3563
3564 s->background_filled_p = true;
3565 }
3566
3567 static void
3568 android_get_scale_factor (int *scale_x, int *scale_y)
3569 {
3570
3571 const int base_res = 160;
3572 struct android_display_info *dpyinfo;
3573
3574 dpyinfo = x_display_list;
3575 *scale_x = *scale_y = 1;
3576
3577 if (dpyinfo)
3578 {
3579 if (dpyinfo->resx > base_res)
3580 *scale_x = floor (dpyinfo->resx / base_res);
3581 if (dpyinfo->resy > base_res)
3582 *scale_y = floor (dpyinfo->resy / base_res);
3583 }
3584 }
3585
3586 static void
3587 android_draw_underwave (struct glyph_string *s, int decoration_width)
3588 {
3589 int scale_x, scale_y;
3590
3591 android_get_scale_factor (&scale_x, &scale_y);
3592
3593 int wave_height = 3 * scale_y, wave_length = 2 * scale_x;
3594
3595 int dx, dy, x0, y0, width, x1, y1, x2, y2, xmax;
3596 bool odd;
3597 struct android_rectangle wave_clip, string_clip, final_clip;
3598
3599 dx = wave_length;
3600 dy = wave_height - 1;
3601 x0 = s->x;
3602 y0 = s->ybase + wave_height / 2;
3603 width = decoration_width;
3604 xmax = x0 + width;
3605
3606
3607
3608 wave_clip.x = x0;
3609 wave_clip.y = y0;
3610 wave_clip.width = width;
3611 wave_clip.height = wave_height;
3612 get_glyph_string_clip_rect (s, &string_clip);
3613
3614 if (!gui_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
3615 return;
3616
3617 android_set_clip_rectangles (s->gc, 0, 0, &final_clip, 1);
3618
3619
3620
3621 x1 = x0 - (x0 % dx);
3622 x2 = x1 + dx;
3623 odd = (x1 / dx) & 1;
3624 y1 = y2 = y0;
3625
3626 if (odd)
3627 y1 += dy;
3628 else
3629 y2 += dy;
3630
3631 if (INT_MAX - dx < xmax)
3632 emacs_abort ();
3633
3634 while (x1 <= xmax)
3635 {
3636 android_draw_line (FRAME_ANDROID_DRAWABLE (s->f), s->gc,
3637 x1, y1, x2, y2);
3638 x1 = x2, y1 = y2;
3639 x2 += dx, y2 = y0 + odd*dy;
3640 odd = !odd;
3641 }
3642
3643
3644 android_set_clip_rectangles (s->gc, 0, 0, s->clip, s->num_clips);
3645 }
3646
3647 static void
3648 android_draw_glyph_string_foreground (struct glyph_string *s)
3649 {
3650 int i, x;
3651
3652
3653
3654 if (s->face->box != FACE_NO_BOX
3655 && s->first_glyph->left_box_line_p)
3656 x = s->x + max (s->face->box_vertical_line_width, 0);
3657 else
3658 x = s->x;
3659
3660
3661
3662 if (s->font_not_found_p)
3663 {
3664 for (i = 0; i < s->nchars; ++i)
3665 {
3666 struct glyph *g = s->first_glyph + i;
3667 android_draw_rectangle (FRAME_ANDROID_DRAWABLE (s->f),
3668 s->gc, x, s->y,
3669 g->pixel_width - 1,
3670 s->height - 1);
3671 x += g->pixel_width;
3672 }
3673 }
3674 else
3675 {
3676 struct font *font = s->font;
3677 int boff = font->baseline_offset;
3678 int y;
3679
3680 if (font->vertical_centering)
3681 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
3682
3683 y = s->ybase - boff;
3684 if (s->for_overlaps
3685 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3686 font->driver->draw (s, 0, s->nchars, x, y, false);
3687 else
3688 font->driver->draw (s, 0, s->nchars, x, y, true);
3689 if (s->face->overstrike)
3690 font->driver->draw (s, 0, s->nchars, x + 1, y, false);
3691 }
3692 }
3693
3694 static void
3695 android_draw_composite_glyph_string_foreground (struct glyph_string *s)
3696 {
3697 int i, j, x;
3698 struct font *font = s->font;
3699
3700
3701
3702 if (s->face && s->face->box != FACE_NO_BOX
3703 && s->first_glyph->left_box_line_p)
3704 x = s->x + max (s->face->box_vertical_line_width, 0);
3705 else
3706 x = s->x;
3707
3708
3709
3710
3711
3712
3713
3714
3715 if (s->font_not_found_p)
3716 {
3717 if (s->cmp_from == 0)
3718 android_draw_rectangle (FRAME_ANDROID_DRAWABLE (s->f),
3719 s->gc, x, s->y,
3720 s->width - 1, s->height - 1);
3721 }
3722 else if (! s->first_glyph->u.cmp.automatic)
3723 {
3724 int y = s->ybase;
3725
3726 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
3727
3728
3729 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
3730 {
3731 int xx = x + s->cmp->offsets[j * 2];
3732 int yy = y - s->cmp->offsets[j * 2 + 1];
3733
3734 font->driver->draw (s, j, j + 1, xx, yy, false);
3735 if (s->face->overstrike)
3736 font->driver->draw (s, j, j + 1, xx + 1, yy, false);
3737 }
3738 }
3739 else
3740 {
3741 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
3742 Lisp_Object glyph;
3743 int y = s->ybase;
3744 int width = 0;
3745
3746 for (i = j = s->cmp_from; i < s->cmp_to; i++)
3747 {
3748 glyph = LGSTRING_GLYPH (gstring, i);
3749 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
3750 width += LGLYPH_WIDTH (glyph);
3751 else
3752 {
3753 int xoff, yoff, wadjust;
3754
3755 if (j < i)
3756 {
3757 font->driver->draw (s, j, i, x, y, false);
3758 if (s->face->overstrike)
3759 font->driver->draw (s, j, i, x + 1, y, false);
3760 x += width;
3761 }
3762 xoff = LGLYPH_XOFF (glyph);
3763 yoff = LGLYPH_YOFF (glyph);
3764 wadjust = LGLYPH_WADJUST (glyph);
3765 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
3766 if (s->face->overstrike)
3767 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
3768 false);
3769 x += wadjust;
3770 j = i + 1;
3771 width = 0;
3772 }
3773 }
3774 if (j < i)
3775 {
3776 font->driver->draw (s, j, i, x, y, false);
3777 if (s->face->overstrike)
3778 font->driver->draw (s, j, i, x + 1, y, false);
3779 }
3780 }
3781 }
3782
3783 static void
3784 android_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
3785 {
3786 struct glyph *glyph = s->first_glyph;
3787 unsigned char2b[8];
3788 int x, i, j;
3789
3790
3791
3792 if (s->face && s->face->box != FACE_NO_BOX
3793 && s->first_glyph->left_box_line_p)
3794 x = s->x + max (s->face->box_vertical_line_width, 0);
3795 else
3796 x = s->x;
3797
3798 s->char2b = char2b;
3799
3800 for (i = 0; i < s->nchars; i++, glyph++)
3801 {
3802 #ifdef GCC_LINT
3803 enum { PACIFY_GCC_BUG_81401 = 1 };
3804 #else
3805 enum { PACIFY_GCC_BUG_81401 = 0 };
3806 #endif
3807 char buf[7 + PACIFY_GCC_BUG_81401];
3808 char *str = NULL;
3809 int len = glyph->u.glyphless.len;
3810
3811 if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
3812 {
3813 if (len > 0
3814 && CHAR_TABLE_P (Vglyphless_char_display)
3815 && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
3816 >= 1))
3817 {
3818 Lisp_Object acronym
3819 = (! glyph->u.glyphless.for_no_font
3820 ? CHAR_TABLE_REF (Vglyphless_char_display,
3821 glyph->u.glyphless.ch)
3822 : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
3823 if (CONSP (acronym))
3824 acronym = XCAR (acronym);
3825 if (STRINGP (acronym))
3826 str = SSDATA (acronym);
3827 }
3828 }
3829 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
3830 {
3831 unsigned int ch = glyph->u.glyphless.ch;
3832 eassume (ch <= MAX_CHAR);
3833 sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch);
3834 str = buf;
3835 }
3836
3837 if (str)
3838 {
3839 int upper_len = (len + 1) / 2;
3840
3841
3842 for (j = 0; j < len; j++)
3843 char2b[j] = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF;
3844 s->font->driver->draw (s, 0, upper_len,
3845 x + glyph->slice.glyphless.upper_xoff,
3846 s->ybase + glyph->slice.glyphless.upper_yoff,
3847 false);
3848 s->font->driver->draw (s, upper_len, len,
3849 x + glyph->slice.glyphless.lower_xoff,
3850 s->ybase + glyph->slice.glyphless.lower_yoff,
3851 false);
3852 }
3853 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
3854 android_draw_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc,
3855 x, s->ybase - glyph->ascent,
3856 glyph->pixel_width - 1,
3857 glyph->ascent + glyph->descent - 1);
3858 x += glyph->pixel_width;
3859 }
3860
3861
3862
3863 s->char2b = NULL;
3864 }
3865
3866 static void
3867 android_draw_glyph_string (struct glyph_string *s)
3868 {
3869 bool relief_drawn_p = false;
3870
3871
3872
3873
3874 if (s->next && s->right_overhang && !s->for_overlaps)
3875 {
3876 int width;
3877 struct glyph_string *next;
3878
3879 for (width = 0, next = s->next;
3880 next && width < s->right_overhang;
3881 width += next->width, next = next->next)
3882 if (next->first_glyph->type != IMAGE_GLYPH)
3883 {
3884 android_set_glyph_string_gc (next);
3885 android_set_glyph_string_clipping (next);
3886 if (next->first_glyph->type == STRETCH_GLYPH)
3887 android_draw_stretch_glyph_string (next);
3888 else
3889 android_draw_glyph_string_background (next, true);
3890 next->num_clips = 0;
3891 }
3892 }
3893
3894
3895 android_set_glyph_string_gc (s);
3896
3897
3898
3899 if (!s->for_overlaps
3900 && s->face->box != FACE_NO_BOX
3901 && (s->first_glyph->type == CHAR_GLYPH
3902 || s->first_glyph->type == COMPOSITE_GLYPH))
3903
3904 {
3905 android_set_glyph_string_clipping (s);
3906 android_draw_glyph_string_background (s, true);
3907 android_draw_glyph_string_box (s);
3908 android_set_glyph_string_clipping (s);
3909 relief_drawn_p = true;
3910 }
3911 else if (!s->clip_head
3912 && !s->clip_tail
3913 && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
3914 || (s->next && s->next->hl != s->hl && s->right_overhang)))
3915
3916
3917
3918 android_set_glyph_string_clipping_exactly (s, s);
3919 else
3920 android_set_glyph_string_clipping (s);
3921
3922 switch (s->first_glyph->type)
3923 {
3924 case IMAGE_GLYPH:
3925 android_draw_image_glyph_string (s);
3926 break;
3927
3928 case XWIDGET_GLYPH:
3929 emacs_abort ();
3930 break;
3931
3932 case STRETCH_GLYPH:
3933 android_draw_stretch_glyph_string (s);
3934 break;
3935
3936 case CHAR_GLYPH:
3937 if (s->for_overlaps)
3938 s->background_filled_p = true;
3939 else
3940 android_draw_glyph_string_background (s, false);
3941 android_draw_glyph_string_foreground (s);
3942 break;
3943
3944 case COMPOSITE_GLYPH:
3945 if (s->for_overlaps || (s->cmp_from > 0
3946 && ! s->first_glyph->u.cmp.automatic))
3947 s->background_filled_p = true;
3948 else
3949 android_draw_glyph_string_background (s, true);
3950 android_draw_composite_glyph_string_foreground (s);
3951 break;
3952
3953 case GLYPHLESS_GLYPH:
3954 if (s->for_overlaps)
3955 s->background_filled_p = true;
3956 else
3957 android_draw_glyph_string_background (s, true);
3958 android_draw_glyphless_glyph_string_foreground (s);
3959 break;
3960
3961 default:
3962 emacs_abort ();
3963 }
3964
3965 if (!s->for_overlaps)
3966 {
3967 int area_x, area_y, area_width, area_height;
3968 int area_max_x, decoration_width;
3969
3970
3971
3972 window_box (s->w, s->area, &area_x, &area_y,
3973 &area_width, &area_height);
3974 area_max_x = area_x + area_width - 1;
3975
3976 decoration_width = s->width;
3977 if (!s->row->mode_line_p
3978 && !s->row->tab_line_p
3979 && area_max_x < (s->x + decoration_width - 1))
3980 decoration_width -= (s->x + decoration_width - 1) - area_max_x;
3981
3982
3983 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3984 android_draw_glyph_string_box (s);
3985
3986
3987 if (s->face->underline)
3988 {
3989 if (s->face->underline == FACE_UNDER_WAVE)
3990 {
3991 if (s->face->underline_defaulted_p)
3992 android_draw_underwave (s, decoration_width);
3993 else
3994 {
3995 struct android_gc_values xgcv;
3996 android_get_gc_values (s->gc, ANDROID_GC_FOREGROUND, &xgcv);
3997 android_set_foreground (s->gc, s->face->underline_color);
3998 android_draw_underwave (s, decoration_width);
3999 android_set_foreground (s->gc, xgcv.foreground);
4000 }
4001 }
4002 else if (s->face->underline == FACE_UNDER_LINE)
4003 {
4004 unsigned long thickness, position;
4005 int y;
4006
4007 if (s->prev
4008 && s->prev->face->underline == FACE_UNDER_LINE
4009 && (s->prev->face->underline_at_descent_line_p
4010 == s->face->underline_at_descent_line_p)
4011 && (s->prev->face->underline_pixels_above_descent_line
4012 == s->face->underline_pixels_above_descent_line))
4013 {
4014
4015 thickness = s->prev->underline_thickness;
4016 position = s->prev->underline_position;
4017 }
4018 else
4019 {
4020 struct font *font = font_for_underline_metrics (s);
4021 unsigned long minimum_offset;
4022 bool underline_at_descent_line;
4023 bool use_underline_position_properties;
4024 Lisp_Object val = (WINDOW_BUFFER_LOCAL_VALUE
4025 (Qunderline_minimum_offset, s->w));
4026
4027 if (FIXNUMP (val))
4028 minimum_offset = max (0, XFIXNUM (val));
4029 else
4030 minimum_offset = 1;
4031
4032 val = (WINDOW_BUFFER_LOCAL_VALUE
4033 (Qx_underline_at_descent_line, s->w));
4034 underline_at_descent_line
4035 = (!(NILP (val) || BASE_EQ (val, Qunbound))
4036 || s->face->underline_at_descent_line_p);
4037
4038 val = (WINDOW_BUFFER_LOCAL_VALUE
4039 (Qx_use_underline_position_properties, s->w));
4040 use_underline_position_properties
4041 = !(NILP (val) || BASE_EQ (val, Qunbound));
4042
4043
4044 if (font && font->underline_thickness > 0)
4045 thickness = font->underline_thickness;
4046 else
4047 thickness = 1;
4048 if (underline_at_descent_line)
4049 position = ((s->height - thickness)
4050 - (s->ybase - s->y)
4051 - s->face->underline_pixels_above_descent_line);
4052 else
4053 {
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063 if (use_underline_position_properties
4064 && font && font->underline_position >= 0)
4065 position = font->underline_position;
4066 else if (font)
4067 position = (font->descent + 1) / 2;
4068 else
4069 position = minimum_offset;
4070 }
4071
4072
4073
4074 if (!s->face->underline_pixels_above_descent_line)
4075 position = max (position, minimum_offset);
4076 }
4077
4078
4079 if (s->y + s->height <= s->ybase + position)
4080 position = (s->height - 1) - (s->ybase - s->y);
4081 if (s->y + s->height < s->ybase + position + thickness)
4082 thickness = (s->y + s->height) - (s->ybase + position);
4083 s->underline_thickness = thickness;
4084 s->underline_position = position;
4085 y = s->ybase + position;
4086 if (s->face->underline_defaulted_p)
4087 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc,
4088 s->x, y, decoration_width, thickness);
4089 else
4090 {
4091 struct android_gc_values xgcv;
4092 android_get_gc_values (s->gc, ANDROID_GC_FOREGROUND, &xgcv);
4093 android_set_foreground (s->gc, s->face->underline_color);
4094 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc,
4095 s->x, y, decoration_width, thickness);
4096 android_set_foreground (s->gc, xgcv.foreground);
4097 }
4098 }
4099 }
4100
4101 if (s->face->overline_p)
4102 {
4103 unsigned long dy = 0, h = 1;
4104
4105 if (s->face->overline_color_defaulted_p)
4106 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f),
4107 s->gc, s->x, s->y + dy,
4108 decoration_width, h);
4109 else
4110 {
4111 struct android_gc_values xgcv;
4112 android_get_gc_values (s->gc, ANDROID_GC_FOREGROUND, &xgcv);
4113 android_set_foreground (s->gc, s->face->overline_color);
4114 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc,
4115 s->x, s->y + dy, decoration_width, h);
4116 android_set_foreground (s->gc, xgcv.foreground);
4117 }
4118 }
4119
4120
4121 if (s->face->strike_through_p)
4122 {
4123
4124
4125
4126
4127
4128 int glyph_y = s->ybase - s->first_glyph->ascent;
4129 int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
4130
4131
4132 unsigned long h = 1;
4133 unsigned long dy = (glyph_height - h) / 2;
4134
4135 if (s->face->strike_through_color_defaulted_p)
4136 android_fill_rectangle (FRAME_ANDROID_WINDOW (s->f),
4137 s->gc, s->x, glyph_y + dy,
4138 s->width, h);
4139 else
4140 {
4141 struct android_gc_values xgcv;
4142 android_get_gc_values (s->gc, ANDROID_GC_FOREGROUND, &xgcv);
4143 android_set_foreground (s->gc, s->face->strike_through_color);
4144 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc,
4145 s->x, glyph_y + dy, decoration_width,
4146 h);
4147 android_set_foreground (s->gc, xgcv.foreground);
4148 }
4149 }
4150
4151 if (s->prev)
4152 {
4153 struct glyph_string *prev;
4154
4155 for (prev = s->prev; prev; prev = prev->prev)
4156 if (prev->hl != s->hl
4157 && prev->x + prev->width + prev->right_overhang > s->x)
4158 {
4159
4160
4161 enum draw_glyphs_face save = prev->hl;
4162
4163 prev->hl = s->hl;
4164 android_set_glyph_string_gc (prev);
4165 android_set_glyph_string_clipping_exactly (s, prev);
4166 if (prev->first_glyph->type == CHAR_GLYPH)
4167 android_draw_glyph_string_foreground (prev);
4168 else
4169 android_draw_composite_glyph_string_foreground (prev);
4170 android_reset_clip_rectangles (prev->f, prev->gc);
4171 prev->hl = save;
4172 prev->num_clips = 0;
4173 }
4174 }
4175
4176 if (s->next)
4177 {
4178 struct glyph_string *next;
4179
4180 for (next = s->next; next; next = next->next)
4181 if (next->hl != s->hl
4182 && next->x - next->left_overhang < s->x + s->width)
4183 {
4184
4185
4186 enum draw_glyphs_face save = next->hl;
4187
4188 next->hl = s->hl;
4189 android_set_glyph_string_gc (next);
4190 android_set_glyph_string_clipping_exactly (s, next);
4191 if (next->first_glyph->type == CHAR_GLYPH)
4192 android_draw_glyph_string_foreground (next);
4193 else
4194 android_draw_composite_glyph_string_foreground (next);
4195 android_reset_clip_rectangles (next->f, next->gc);
4196 next->hl = save;
4197 next->num_clips = 0;
4198 next->clip_head = s->next;
4199 }
4200 }
4201 }
4202
4203
4204 android_reset_clip_rectangles (s->f, s->gc);
4205 s->num_clips = 0;
4206
4207
4208
4209
4210 if (s->first_glyph->type != STRETCH_GLYPH
4211 && s->first_glyph->type != IMAGE_GLYPH
4212 && !s->row->stipple_p)
4213 s->row->stipple_p = s->stippled_p;
4214 }
4215
4216 static void
4217 android_define_frame_cursor (struct frame *f, Emacs_Cursor cursor)
4218 {
4219 if (!f->pointer_invisible
4220 && !FRAME_ANDROID_OUTPUT (f)->hourglass
4221 && f->output_data.android->current_cursor != cursor)
4222 android_define_cursor (FRAME_ANDROID_WINDOW (f), cursor);
4223
4224 f->output_data.android->current_cursor = cursor;
4225 }
4226
4227 static void
4228 android_clear_frame_area (struct frame *f, int x, int y,
4229 int width, int height)
4230 {
4231 android_clear_area (FRAME_ANDROID_DRAWABLE (f),
4232 x, y, width, height);
4233 }
4234
4235 void
4236 android_clear_under_internal_border (struct frame *f)
4237 {
4238 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
4239 {
4240 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
4241 int width = FRAME_PIXEL_WIDTH (f);
4242 int height = FRAME_PIXEL_HEIGHT (f);
4243 int margin = FRAME_TOP_MARGIN_HEIGHT (f);
4244 int bottom_margin = FRAME_BOTTOM_MARGIN_HEIGHT (f);
4245 int face_id = (FRAME_PARENT_FRAME (f)
4246 ? (!NILP (Vface_remapping_alist)
4247 ? lookup_basic_face (NULL, f,
4248 CHILD_FRAME_BORDER_FACE_ID)
4249 : CHILD_FRAME_BORDER_FACE_ID)
4250 : (!NILP (Vface_remapping_alist)
4251 ? lookup_basic_face (NULL, f,
4252 INTERNAL_BORDER_FACE_ID)
4253 : INTERNAL_BORDER_FACE_ID));
4254 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
4255
4256 if (face)
4257 {
4258 unsigned long color = face->background;
4259 struct android_gc *gc = f->output_data.android->normal_gc;
4260
4261 android_set_foreground (gc, color);
4262 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc, 0, margin,
4263 width, border);
4264 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc, 0, 0,
4265 border, height);
4266 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc, width - border,
4267 0, border, height);
4268 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc, 0,
4269 height - bottom_margin - border,
4270 width, border);
4271 android_set_foreground (gc, FRAME_FOREGROUND_PIXEL (f));
4272 }
4273 else
4274 {
4275 android_clear_area (FRAME_ANDROID_DRAWABLE (f), 0, 0,
4276 border, height);
4277 android_clear_area (FRAME_ANDROID_DRAWABLE (f), 0,
4278 margin, width, border);
4279 android_clear_area (FRAME_ANDROID_DRAWABLE (f), width - border,
4280 0, border, height);
4281 android_clear_area (FRAME_ANDROID_DRAWABLE (f), 0,
4282 height - bottom_margin - border,
4283 width, border);
4284 }
4285 }
4286 }
4287
4288 static void
4289 android_draw_hollow_cursor (struct window *w, struct glyph_row *row)
4290 {
4291 struct frame *f = XFRAME (WINDOW_FRAME (w));
4292 struct android_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
4293 int x, y, wd, h;
4294 struct android_gc_values xgcv;
4295 struct glyph *cursor_glyph;
4296 struct android_gc *gc;
4297
4298
4299
4300 cursor_glyph = get_phys_cursor_glyph (w);
4301 if (cursor_glyph == NULL)
4302 return;
4303
4304
4305 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
4306 wd = w->phys_cursor_width - 1;
4307
4308
4309
4310 xgcv.foreground = f->output_data.android->cursor_pixel;
4311 if (dpyinfo->scratch_cursor_gc)
4312 android_change_gc (dpyinfo->scratch_cursor_gc,
4313 ANDROID_GC_FOREGROUND, &xgcv);
4314 else
4315 dpyinfo->scratch_cursor_gc
4316 = android_create_gc (ANDROID_GC_FOREGROUND, &xgcv);
4317 gc = dpyinfo->scratch_cursor_gc;
4318
4319
4320
4321
4322 if ((cursor_glyph->resolved_level & 1) != 0
4323 && cursor_glyph->pixel_width > wd)
4324 {
4325 x += cursor_glyph->pixel_width - wd;
4326 if (wd > 0)
4327 wd -= 1;
4328 }
4329
4330 android_clip_to_row (w, row, TEXT_AREA, gc);
4331 android_draw_rectangle (FRAME_ANDROID_DRAWABLE (f), gc, x, y, wd, h - 1);
4332 android_reset_clip_rectangles (f, gc);
4333 }
4334
4335 static void
4336 android_draw_bar_cursor (struct window *w, struct glyph_row *row, int width,
4337 enum text_cursor_kinds kind)
4338 {
4339 struct frame *f = XFRAME (w->frame);
4340 struct glyph *cursor_glyph;
4341 int cursor_start_y;
4342
4343
4344
4345
4346 cursor_glyph = get_phys_cursor_glyph (w);
4347 if (cursor_glyph == NULL)
4348 return;
4349
4350
4351 if (cursor_glyph->type == XWIDGET_GLYPH)
4352 return;
4353
4354
4355
4356
4357 if (cursor_glyph->type == IMAGE_GLYPH)
4358 {
4359 struct glyph_row *r;
4360 r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
4361 draw_phys_cursor_glyph (w, r, DRAW_CURSOR);
4362 }
4363 else
4364 {
4365 struct android_gc *gc = FRAME_DISPLAY_INFO (f)->scratch_cursor_gc;
4366 unsigned long mask = ANDROID_GC_FOREGROUND | ANDROID_GC_BACKGROUND;
4367 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
4368 struct android_gc_values xgcv;
4369
4370
4371
4372
4373
4374
4375 if (face->background == f->output_data.android->cursor_pixel)
4376 xgcv.background = xgcv.foreground = face->foreground;
4377 else
4378 xgcv.background = xgcv.foreground = f->output_data.android->cursor_pixel;
4379
4380 if (gc)
4381 android_change_gc (gc, mask, &xgcv);
4382 else
4383 {
4384 gc = android_create_gc (mask, &xgcv);
4385 FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
4386 }
4387
4388 android_clip_to_row (w, row, TEXT_AREA, gc);
4389
4390 if (kind == BAR_CURSOR)
4391 {
4392 int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4393
4394 if (width < 0)
4395 width = FRAME_CURSOR_WIDTH (f);
4396 width = min (cursor_glyph->pixel_width, width);
4397
4398 w->phys_cursor_width = width;
4399
4400
4401
4402 if ((cursor_glyph->resolved_level & 1) != 0)
4403 x += cursor_glyph->pixel_width - width;
4404
4405 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc, x,
4406 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
4407 width, row->height);
4408 }
4409 else
4410 {
4411 int dummy_x, dummy_y, dummy_h;
4412 int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4413
4414 if (width < 0)
4415 width = row->height;
4416
4417 width = min (row->height, width);
4418
4419 get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
4420 &dummy_y, &dummy_h);
4421
4422 cursor_start_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y
4423 + row->height - width);
4424
4425 if ((cursor_glyph->resolved_level & 1) != 0
4426 && cursor_glyph->pixel_width > w->phys_cursor_width - 1)
4427 x += cursor_glyph->pixel_width - w->phys_cursor_width + 1;
4428 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f), gc, x,
4429 cursor_start_y,
4430 w->phys_cursor_width - 1, width);
4431 }
4432
4433 android_reset_clip_rectangles (f, gc);
4434 }
4435 }
4436
4437 static void
4438 android_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
4439 int x, int y, enum text_cursor_kinds cursor_type,
4440 int cursor_width, bool on_p, bool active_p)
4441 {
4442 struct frame *f;
4443
4444 f = WINDOW_XFRAME (w);
4445
4446 if (on_p)
4447 {
4448 w->phys_cursor_type = cursor_type;
4449 w->phys_cursor_on_p = true;
4450
4451 if (glyph_row->exact_window_width_line_p
4452 && (glyph_row->reversed_p
4453 ? (w->phys_cursor.hpos < 0)
4454 : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
4455 {
4456 glyph_row->cursor_in_fringe_p = true;
4457 draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
4458 }
4459 else
4460 {
4461 switch (cursor_type)
4462 {
4463 case HOLLOW_BOX_CURSOR:
4464 android_draw_hollow_cursor (w, glyph_row);
4465 break;
4466
4467 case FILLED_BOX_CURSOR:
4468 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
4469 break;
4470
4471 case BAR_CURSOR:
4472 android_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
4473 break;
4474
4475 case HBAR_CURSOR:
4476 android_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
4477 break;
4478
4479 case NO_CURSOR:
4480 w->phys_cursor_width = 0;
4481 break;
4482
4483 default:
4484 emacs_abort ();
4485 }
4486 }
4487
4488
4489
4490
4491 if (FRAME_OUTPUT_DATA (f)->need_cursor_updates
4492 && w == XWINDOW (f->selected_window))
4493 android_set_preeditarea (w, x, y);
4494 }
4495 }
4496
4497 static void
4498 android_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
4499 {
4500 struct frame *f = XFRAME (WINDOW_FRAME (w));
4501 struct face *face;
4502
4503 face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
4504 if (face)
4505 android_set_foreground (f->output_data.android->normal_gc,
4506 face->foreground);
4507
4508 android_draw_line (FRAME_ANDROID_DRAWABLE (f),
4509 f->output_data.android->normal_gc,
4510 x, y0, x, y1);
4511 }
4512
4513 static void
4514 android_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
4515 {
4516 struct frame *f = XFRAME (WINDOW_FRAME (w));
4517 struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID);
4518 struct face *face_first
4519 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
4520 struct face *face_last
4521 = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
4522 unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
4523 unsigned long color_first = (face_first
4524 ? face_first->foreground
4525 : FRAME_FOREGROUND_PIXEL (f));
4526 unsigned long color_last = (face_last
4527 ? face_last->foreground
4528 : FRAME_FOREGROUND_PIXEL (f));
4529
4530 if ((y1 - y0 > x1 - x0) && (x1 - x0 >= 3))
4531
4532
4533 {
4534 android_set_foreground (f->output_data.android->normal_gc,
4535 color_first);
4536 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f),
4537 f->output_data.android->normal_gc,
4538 x0, y0, 1, y1 - y0);
4539 android_set_foreground (f->output_data.android->normal_gc,
4540 color);
4541 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f),
4542 f->output_data.android->normal_gc,
4543 x0 + 1, y0, x1 - x0 - 2, y1 - y0);
4544 android_set_foreground (f->output_data.android->normal_gc,
4545 color_last);
4546 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f),
4547 f->output_data.android->normal_gc,
4548 x1 - 1, y0, 1, y1 - y0);
4549 }
4550 else if ((x1 - x0 > y1 - y0) && (y1 - y0 >= 3))
4551
4552
4553 {
4554 android_set_foreground (f->output_data.android->normal_gc,
4555 color_first);
4556 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f),
4557 f->output_data.android->normal_gc,
4558 x0, y0, x1 - x0, 1);
4559 android_set_foreground (f->output_data.android->normal_gc, color);
4560 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f),
4561 f->output_data.android->normal_gc,
4562 x0, y0 + 1, x1 - x0, y1 - y0 - 2);
4563 android_set_foreground (f->output_data.android->normal_gc,
4564 color_last);
4565 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f),
4566 f->output_data.android->normal_gc,
4567 x0, y1 - 1, x1 - x0, 1);
4568 }
4569 else
4570 {
4571
4572
4573 android_set_foreground (f->output_data.android->normal_gc, color);
4574 android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f),
4575 f->output_data.android->normal_gc,
4576 x0, y0, x1 - x0, y1 - y0);
4577 }
4578 }
4579
4580
4581
4582 #ifdef __clang__
4583 #pragma clang diagnostic push
4584 #pragma clang diagnostic ignored "-Wmissing-prototypes"
4585 #else
4586 #pragma GCC diagnostic push
4587 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
4588 #endif
4589
4590
4591
4592
4593
4594 static unsigned long edit_counter;
4595
4596
4597 static unsigned long last_edit_counter;
4598
4599
4600 static sem_t edit_sem;
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610 static void
4611 android_sync_edit (void)
4612 {
4613 struct timespec start, end, rem;
4614 unsigned long counter;
4615
4616 counter = __atomic_load_n (&last_edit_counter,
4617 __ATOMIC_SEQ_CST);
4618
4619 if (counter == edit_counter)
4620 return;
4621
4622 start = current_timespec ();
4623 end = timespec_add (start, make_timespec (0, 100000000));
4624
4625 while (true)
4626 {
4627 rem = timespec_sub (end, current_timespec ());
4628
4629
4630 if (timespec_sign (rem) < 0)
4631 break;
4632
4633 if (__atomic_load_n (&last_edit_counter,
4634 __ATOMIC_SEQ_CST)
4635 == edit_counter)
4636 break;
4637
4638 sem_timedwait (&edit_sem, &end);
4639 }
4640 }
4641
4642
4643
4644
4645
4646 static unsigned short *
4647 android_copy_java_string (JNIEnv *env, jstring string, size_t *length)
4648 {
4649 jsize size, i;
4650 const jchar *java;
4651 unsigned short *buffer;
4652
4653 size = (*env)->GetStringLength (env, string);
4654 buffer = malloc (size * sizeof *buffer);
4655
4656 if (!buffer)
4657 return NULL;
4658
4659 java = (*env)->GetStringChars (env, string, NULL);
4660
4661 if (!java)
4662 {
4663 free (buffer);
4664 return NULL;
4665 }
4666
4667 for (i = 0; i < size; ++i)
4668 buffer[i] = java[i];
4669
4670 *length = size;
4671 (*env)->ReleaseStringChars (env, string, java);
4672 return buffer;
4673 }
4674
4675 JNIEXPORT void JNICALL
4676 NATIVE_NAME (beginBatchEdit) (JNIEnv *env, jobject object, jshort window)
4677 {
4678 JNI_STACK_ALIGNMENT_PROLOGUE;
4679
4680 union android_event event;
4681
4682 event.ime.type = ANDROID_INPUT_METHOD;
4683 event.ime.serial = ++event_serial;
4684 event.ime.window = window;
4685 event.ime.operation = ANDROID_IME_START_BATCH_EDIT;
4686 event.ime.start = 0;
4687 event.ime.end = 0;
4688 event.ime.length = 0;
4689 event.ime.position = 0;
4690 event.ime.text = NULL;
4691 event.ime.counter = ++edit_counter;
4692
4693 android_write_event (&event);
4694 }
4695
4696 JNIEXPORT void JNICALL
4697 NATIVE_NAME (endBatchEdit) (JNIEnv *env, jobject object, jshort window)
4698 {
4699 JNI_STACK_ALIGNMENT_PROLOGUE;
4700
4701 union android_event event;
4702
4703 event.ime.type = ANDROID_INPUT_METHOD;
4704 event.ime.serial = ++event_serial;
4705 event.ime.window = window;
4706 event.ime.operation = ANDROID_IME_END_BATCH_EDIT;
4707 event.ime.start = 0;
4708 event.ime.end = 0;
4709 event.ime.length = 0;
4710 event.ime.position = 0;
4711 event.ime.text = NULL;
4712 event.ime.counter = ++edit_counter;
4713
4714 android_write_event (&event);
4715 }
4716
4717 JNIEXPORT void JNICALL
4718 NATIVE_NAME (commitCompletion) (JNIEnv *env, jobject object, jshort window,
4719 jstring completion_text, jint position)
4720 {
4721 JNI_STACK_ALIGNMENT_PROLOGUE;
4722
4723 union android_event event;
4724 unsigned short *text;
4725 size_t length;
4726
4727
4728 text = android_copy_java_string (env, completion_text, &length);
4729
4730 if (!text)
4731 return;
4732
4733
4734
4735
4736
4737 event.ime.type = ANDROID_INPUT_METHOD;
4738 event.ime.serial = ++event_serial;
4739 event.ime.window = window;
4740 event.ime.operation = ANDROID_IME_COMMIT_TEXT;
4741 event.ime.start = 0;
4742 event.ime.end = 0;
4743 event.ime.length = min (length, PTRDIFF_MAX);
4744 event.ime.position = position;
4745 event.ime.text = text;
4746 event.ime.counter = ++edit_counter;
4747
4748 android_write_event (&event);
4749 }
4750
4751 JNIEXPORT void JNICALL
4752 NATIVE_NAME (commitText) (JNIEnv *env, jobject object, jshort window,
4753 jstring commit_text, jint position)
4754 {
4755 JNI_STACK_ALIGNMENT_PROLOGUE;
4756
4757 union android_event event;
4758 unsigned short *text;
4759 size_t length;
4760
4761
4762 text = android_copy_java_string (env, commit_text, &length);
4763
4764 if (!text)
4765 return;
4766
4767
4768
4769
4770
4771 event.ime.type = ANDROID_INPUT_METHOD;
4772 event.ime.serial = ++event_serial;
4773 event.ime.window = window;
4774 event.ime.operation = ANDROID_IME_COMMIT_TEXT;
4775 event.ime.start = 0;
4776 event.ime.end = 0;
4777 event.ime.length = min (length, PTRDIFF_MAX);
4778 event.ime.position = position;
4779 event.ime.text = text;
4780 event.ime.counter = ++edit_counter;
4781
4782 android_write_event (&event);
4783 }
4784
4785 JNIEXPORT void JNICALL
4786 NATIVE_NAME (deleteSurroundingText) (JNIEnv *env, jobject object,
4787 jshort window, jint left_length,
4788 jint right_length)
4789 {
4790 JNI_STACK_ALIGNMENT_PROLOGUE;
4791
4792 union android_event event;
4793
4794 event.ime.type = ANDROID_INPUT_METHOD;
4795 event.ime.serial = ++event_serial;
4796 event.ime.window = window;
4797 event.ime.operation = ANDROID_IME_DELETE_SURROUNDING_TEXT;
4798 event.ime.start = left_length;
4799 event.ime.end = right_length;
4800 event.ime.length = 0;
4801 event.ime.position = 0;
4802 event.ime.text = NULL;
4803 event.ime.counter = ++edit_counter;
4804
4805 android_write_event (&event);
4806 }
4807
4808 JNIEXPORT void JNICALL
4809 NATIVE_NAME (finishComposingText) (JNIEnv *env, jobject object,
4810 jshort window)
4811 {
4812 JNI_STACK_ALIGNMENT_PROLOGUE;
4813
4814 union android_event event;
4815
4816 event.ime.type = ANDROID_INPUT_METHOD;
4817 event.ime.serial = ++event_serial;
4818 event.ime.window = window;
4819 event.ime.operation = ANDROID_IME_FINISH_COMPOSING_TEXT;
4820 event.ime.start = 0;
4821 event.ime.end = 0;
4822 event.ime.length = 0;
4823 event.ime.position = 0;
4824 event.ime.text = NULL;
4825 event.ime.counter = ++edit_counter;
4826
4827 android_write_event (&event);
4828 }
4829
4830
4831
4832 struct android_conversion_query_context
4833 {
4834
4835 struct textconv_callback_struct query;
4836
4837
4838 android_window window;
4839
4840
4841 bool success;
4842 };
4843
4844
4845
4846
4847
4848
4849
4850 static void
4851 android_perform_conversion_query (void *data)
4852 {
4853 struct android_conversion_query_context *context;
4854 struct frame *f;
4855
4856 context = data;
4857
4858
4859 f = android_window_to_frame (NULL, context->window);
4860
4861 if (!f)
4862 return;
4863
4864 textconv_query (f, &context->query, 0);
4865
4866
4867
4868
4869 context->success = true;
4870 }
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885 static jstring
4886 android_text_to_string (JNIEnv *env, char *buffer, ptrdiff_t n,
4887 ptrdiff_t bytes)
4888 {
4889 jchar *utf16;
4890 size_t size, index;
4891 jstring string;
4892 int encoded;
4893
4894 if (n == bytes)
4895 {
4896
4897
4898 if (INT_MULTIPLY_WRAPV (n, sizeof *utf16, &size))
4899 return NULL;
4900
4901 utf16 = malloc (size);
4902 index = 0;
4903
4904 if (!utf16)
4905 return NULL;
4906
4907 while (n--)
4908 {
4909 utf16[index] = buffer[index];
4910 index++;
4911 }
4912
4913 string = (*env)->NewString (env, utf16, bytes);
4914 free (utf16);
4915
4916 return string;
4917 }
4918
4919
4920
4921 if (INT_MULTIPLY_WRAPV (n, sizeof *utf16, &size))
4922 return NULL;
4923
4924 utf16 = malloc (size);
4925 index = 0;
4926
4927 if (!utf16)
4928 return NULL;
4929
4930 while (n--)
4931 {
4932 eassert (CHAR_HEAD_P (*buffer));
4933 encoded = STRING_CHAR ((unsigned char *) buffer);
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950 if (encoded >= 65536)
4951 encoded = 0;
4952
4953 utf16[index++] = encoded;
4954 buffer += BYTES_BY_CHAR_HEAD (*buffer);
4955 }
4956
4957
4958 string = (*env)->NewString (env, utf16, index);
4959 free (utf16);
4960 return string;
4961 }
4962
4963 JNIEXPORT jstring JNICALL
4964 NATIVE_NAME (getTextAfterCursor) (JNIEnv *env, jobject object, jshort window,
4965 jint length, jint flags)
4966 {
4967 JNI_STACK_ALIGNMENT_PROLOGUE;
4968
4969 struct android_conversion_query_context context;
4970 jstring string;
4971
4972
4973 context.query.position = EMACS_INT_MAX;
4974 context.query.direction = TEXTCONV_FORWARD_CHAR;
4975 context.query.factor = min (length, 65535);
4976 context.query.operation = TEXTCONV_RETRIEVAL;
4977
4978
4979 context.window = window;
4980 context.success = false;
4981
4982
4983 android_sync_edit ();
4984 if (android_run_in_emacs_thread (android_perform_conversion_query,
4985 &context))
4986 return NULL;
4987
4988 if (!context.success)
4989 return NULL;
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999 string = android_text_to_string (env, context.query.text.text,
5000 context.query.text.length,
5001 context.query.text.bytes);
5002 free (context.query.text.text);
5003
5004 return string;
5005 }
5006
5007 JNIEXPORT jstring JNICALL
5008 NATIVE_NAME (getTextBeforeCursor) (JNIEnv *env, jobject object, jshort window,
5009 jint length, jint flags)
5010 {
5011 JNI_STACK_ALIGNMENT_PROLOGUE;
5012
5013 struct android_conversion_query_context context;
5014 jstring string;
5015
5016
5017 context.query.position = TYPE_MINIMUM (EMACS_INT);
5018 context.query.direction = TEXTCONV_BACKWARD_CHAR;
5019 context.query.factor = min (length, 65535);
5020 context.query.operation = TEXTCONV_RETRIEVAL;
5021
5022
5023 context.window = window;
5024 context.success = false;
5025
5026
5027 android_sync_edit ();
5028 if (android_run_in_emacs_thread (android_perform_conversion_query,
5029 &context))
5030 return NULL;
5031
5032 if (!context.success)
5033 return NULL;
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043 string = android_text_to_string (env, context.query.text.text,
5044 context.query.text.length,
5045 context.query.text.bytes);
5046 free (context.query.text.text);
5047
5048 return string;
5049 }
5050
5051 JNIEXPORT void JNICALL
5052 NATIVE_NAME (setComposingText) (JNIEnv *env, jobject object, jshort window,
5053 jstring composing_text,
5054 jint new_cursor_position)
5055 {
5056 JNI_STACK_ALIGNMENT_PROLOGUE;
5057
5058 union android_event event;
5059 unsigned short *text;
5060 size_t length;
5061
5062
5063 text = android_copy_java_string (env, composing_text, &length);
5064
5065 if (!text)
5066 return;
5067
5068
5069
5070
5071
5072 event.ime.type = ANDROID_INPUT_METHOD;
5073 event.ime.serial = ++event_serial;
5074 event.ime.window = window;
5075 event.ime.operation = ANDROID_IME_SET_COMPOSING_TEXT;
5076 event.ime.start = 0;
5077 event.ime.end = 0;
5078 event.ime.length = min (length, PTRDIFF_MAX);
5079 event.ime.position = new_cursor_position;
5080 event.ime.text = text;
5081 event.ime.counter = ++edit_counter;
5082
5083 android_write_event (&event);
5084 }
5085
5086 JNIEXPORT void JNICALL
5087 NATIVE_NAME (setComposingRegion) (JNIEnv *env, jobject object, jshort window,
5088 jint start, jint end)
5089 {
5090 JNI_STACK_ALIGNMENT_PROLOGUE;
5091
5092 union android_event event;
5093
5094 event.ime.type = ANDROID_INPUT_METHOD;
5095 event.ime.serial = ++event_serial;
5096 event.ime.window = window;
5097 event.ime.operation = ANDROID_IME_SET_COMPOSING_REGION;
5098 event.ime.start = start + 1;
5099 event.ime.end = end + 1;
5100 event.ime.length = 0;
5101 event.ime.position = 0;
5102 event.ime.text = NULL;
5103 event.ime.counter = ++edit_counter;
5104
5105 android_write_event (&event);
5106 }
5107
5108 JNIEXPORT void JNICALL
5109 NATIVE_NAME (setSelection) (JNIEnv *env, jobject object, jshort window,
5110 jint start, jint end)
5111 {
5112 JNI_STACK_ALIGNMENT_PROLOGUE;
5113
5114 union android_event event;
5115
5116
5117
5118
5119 event.ime.type = ANDROID_INPUT_METHOD;
5120 event.ime.serial = ++event_serial;
5121 event.ime.window = window;
5122 event.ime.operation = ANDROID_IME_SET_POINT;
5123 event.ime.start = start + 1;
5124 event.ime.end = end + 1;
5125 event.ime.length = 0;
5126 event.ime.position = start;
5127 event.ime.text = NULL;
5128 event.ime.counter = ++edit_counter;
5129
5130 android_write_event (&event);
5131 }
5132
5133
5134
5135 struct android_get_selection_context
5136 {
5137
5138 android_window window;
5139
5140
5141
5142 ptrdiff_t point, mark;
5143 };
5144
5145
5146
5147
5148 static void
5149 android_get_selection (void *data)
5150 {
5151 struct android_get_selection_context *context;
5152 struct frame *f;
5153 struct window *w;
5154 struct buffer *b;
5155
5156 context = data;
5157
5158
5159 f = android_window_to_frame (NULL, context->window);
5160
5161 if (!f)
5162 context->point = -1;
5163 else
5164 {
5165 w = XWINDOW (f->selected_window);
5166
5167
5168
5169 context->point = window_point (w);
5170 w->ephemeral_last_point = context->point;
5171
5172
5173 context->mark = context->point;
5174
5175
5176
5177 b = XBUFFER (w->contents);
5178 if (!NILP (BVAR (b, mark_active)))
5179 {
5180 context->mark = marker_position (BVAR (b, mark));
5181 w->last_mark = context->mark;
5182 }
5183 }
5184 }
5185
5186 JNIEXPORT jintArray JNICALL
5187 NATIVE_NAME (getSelection) (JNIEnv *env, jobject object, jshort window)
5188 {
5189 JNI_STACK_ALIGNMENT_PROLOGUE;
5190
5191 struct android_get_selection_context context;
5192 jintArray array;
5193 jint contents[2];
5194
5195 context.window = window;
5196
5197 android_sync_edit ();
5198 if (android_run_in_emacs_thread (android_get_selection,
5199 &context))
5200 return NULL;
5201
5202 if (context.point == -1)
5203 return NULL;
5204
5205
5206
5207
5208 contents[0] = (unsigned int) min (context.point,
5209 context.mark) - 1;
5210 contents[1] = (unsigned int) max (context.point,
5211 context.mark) - 1;
5212
5213
5214 array = (*env)->NewIntArray (env, 2);
5215
5216 if (!array)
5217 return NULL;
5218
5219
5220 (*env)->SetIntArrayRegion (env, array, 0, 2, contents);
5221 return array;
5222 }
5223
5224 JNIEXPORT void JNICALL
5225 NATIVE_NAME (performEditorAction) (JNIEnv *env, jobject object,
5226 jshort window, int action)
5227 {
5228 JNI_STACK_ALIGNMENT_PROLOGUE;
5229
5230 union android_event event;
5231
5232
5233
5234
5235
5236
5237 android_sync_edit ();
5238
5239
5240
5241
5242 event.ime.type = ANDROID_INPUT_METHOD;
5243 event.ime.serial = ++event_serial;
5244 event.ime.window = window;
5245 event.ime.operation = ANDROID_IME_FINISH_COMPOSING_TEXT;
5246 event.ime.start = 0;
5247 event.ime.end = 0;
5248
5249
5250
5251
5252 event.ime.length = 1;
5253 event.ime.position = 0;
5254 event.ime.text = NULL;
5255 event.ime.counter = ++edit_counter;
5256
5257 android_write_event (&event);
5258
5259
5260
5261
5262
5263
5264 event.xkey.type = ANDROID_KEY_PRESS;
5265 event.xkey.serial = ++event_serial;
5266 event.xkey.window = window;
5267 event.xkey.time = 0;
5268 event.xkey.state = 0;
5269 event.xkey.keycode = 66;
5270 event.xkey.unicode_char = 0;
5271 event.xkey.counter = ++edit_counter;
5272
5273 android_write_event (&event);
5274 }
5275
5276 JNIEXPORT void JNICALL
5277 NATIVE_NAME (performContextMenuAction) (JNIEnv *env, jobject object,
5278 jshort window, int action)
5279 {
5280 JNI_STACK_ALIGNMENT_PROLOGUE;
5281
5282 union android_event event;
5283 int key;
5284
5285
5286
5287
5288 switch (action)
5289 {
5290 case 0:
5291 case 1:
5292 case 2:
5293 default:
5294
5295 return;
5296
5297 case 3:
5298 key = 277;
5299 break;
5300
5301 case 4:
5302 key = 278;
5303 break;
5304
5305 case 5:
5306 key = 279;
5307 break;
5308 }
5309
5310 event.xkey.type = ANDROID_KEY_PRESS;
5311 event.xkey.serial = ++event_serial;
5312 event.xkey.window = window;
5313 event.xkey.time = 0;
5314 event.xkey.state = 0;
5315 event.xkey.keycode = key;
5316 event.xkey.unicode_char = 0;
5317 event.xkey.counter = ++edit_counter;
5318
5319 android_write_event (&event);
5320 }
5321
5322
5323
5324
5325
5326 struct android_get_extracted_text_context
5327 {
5328
5329 int hint_max_chars;
5330
5331
5332 int token;
5333
5334
5335 int flags;
5336
5337
5338 char *text;
5339
5340
5341 ptrdiff_t length, bytes;
5342
5343
5344 ptrdiff_t start, start_offset, end_offset;
5345
5346
5347 android_window window;
5348
5349
5350 bool mark_active;
5351 };
5352
5353
5354
5355
5356 static void
5357 android_get_extracted_text (void *data)
5358 {
5359 struct android_get_extracted_text_context *request;
5360 struct frame *f;
5361
5362 request = data;
5363
5364
5365 f = android_window_to_frame (NULL, request->window);
5366
5367 if (!f)
5368 return;
5369
5370
5371 request->text
5372 = get_extracted_text (f, min (request->hint_max_chars, 600),
5373 &request->start, &request->start_offset,
5374 &request->end_offset, &request->length,
5375 &request->bytes, &request->mark_active);
5376
5377
5378
5379
5380
5381 FRAME_ANDROID_OUTPUT (f)->extracted_text_flags = request->flags;
5382 FRAME_ANDROID_OUTPUT (f)->extracted_text_token = request->token;
5383 FRAME_ANDROID_OUTPUT (f)->extracted_text_hint = request->hint_max_chars;
5384 }
5385
5386
5387
5388
5389 struct android_extracted_text_request_class
5390 {
5391 bool initialized;
5392 jfieldID hint_max_chars;
5393 jfieldID token;
5394 };
5395
5396
5397
5398
5399 struct android_extracted_text_class
5400 {
5401 jclass class;
5402 jmethodID constructor;
5403 jfieldID flags;
5404 jfieldID partial_start_offset;
5405 jfieldID partial_end_offset;
5406 jfieldID selection_start;
5407 jfieldID selection_end;
5408 jfieldID start_offset;
5409 jfieldID text;
5410 };
5411
5412
5413
5414 struct android_extracted_text_request_class request_class;
5415
5416
5417 struct android_extracted_text_class text_class;
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432 static jobject
5433 android_build_extracted_text (jstring text, ptrdiff_t start,
5434 ptrdiff_t start_offset,
5435 ptrdiff_t end_offset, bool mark_active)
5436 {
5437 JNIEnv *env;
5438 jobject object;
5439
5440 env = android_java_env;
5441
5442
5443 if (!text_class.class)
5444 return NULL;
5445
5446
5447 object = (*env)->NewObject (env, text_class.class,
5448 text_class.constructor);
5449 if (!object)
5450 return NULL;
5451
5452 (*env)->SetIntField (env, object, text_class.flags,
5453
5454 mark_active ? 2 : 0);
5455 (*env)->SetIntField (env, object, text_class.partial_start_offset, -1);
5456 (*env)->SetIntField (env, object, text_class.partial_end_offset, -1);
5457 (*env)->SetIntField (env, object, text_class.selection_start,
5458 min (start_offset, TYPE_MAXIMUM (jint)));
5459 (*env)->SetIntField (env, object, text_class.selection_end,
5460 min (end_offset, TYPE_MAXIMUM (jint)));
5461
5462
5463
5464 (*env)->SetIntField (env, object, text_class.start_offset,
5465 min (start - 1, TYPE_MAXIMUM (jint)));
5466 (*env)->SetObjectField (env, object, text_class.text, text);
5467 return object;
5468 }
5469
5470 JNIEXPORT jobject JNICALL
5471 NATIVE_NAME (getExtractedText) (JNIEnv *env, jobject ignored_object,
5472 jshort window, jobject request,
5473 jint flags)
5474 {
5475 JNI_STACK_ALIGNMENT_PROLOGUE;
5476
5477 struct android_get_extracted_text_context context;
5478 jstring string;
5479 jclass class;
5480 jobject object;
5481
5482
5483
5484 if (!request_class.initialized)
5485 {
5486 class
5487 = (*env)->FindClass (env, ("android/view/inputmethod"
5488 "/ExtractedTextRequest"));
5489 assert (class);
5490
5491 request_class.hint_max_chars
5492 = (*env)->GetFieldID (env, class, "hintMaxChars", "I");
5493 assert (request_class.hint_max_chars);
5494
5495 request_class.token
5496 = (*env)->GetFieldID (env, class, "token", "I");
5497 assert (request_class.token);
5498
5499 request_class.initialized = true;
5500 }
5501
5502 if (!text_class.class)
5503 {
5504 text_class.class
5505 = (*env)->FindClass (env, ("android/view/inputmethod"
5506 "/ExtractedText"));
5507 assert (text_class.class);
5508
5509 class
5510 = text_class.class
5511 = (*env)->NewGlobalRef (env, text_class.class);
5512 assert (text_class.class);
5513
5514 text_class.flags
5515 = (*env)->GetFieldID (env, class, "flags", "I");
5516 text_class.partial_start_offset
5517 = (*env)->GetFieldID (env, class, "partialStartOffset", "I");
5518 text_class.partial_end_offset
5519 = (*env)->GetFieldID (env, class, "partialEndOffset", "I");
5520 text_class.selection_start
5521 = (*env)->GetFieldID (env, class, "selectionStart", "I");
5522 text_class.selection_end
5523 = (*env)->GetFieldID (env, class, "selectionEnd", "I");
5524 text_class.start_offset
5525 = (*env)->GetFieldID (env, class, "startOffset", "I");
5526 text_class.text
5527 = (*env)->GetFieldID (env, class, "text", "Ljava/lang/CharSequence;");
5528 text_class.constructor
5529 = (*env)->GetMethodID (env, class, "<init>", "()V");
5530 }
5531
5532 context.hint_max_chars
5533 = (*env)->GetIntField (env, request, request_class.hint_max_chars);
5534 context.token
5535 = (*env)->GetIntField (env, request, request_class.token);
5536 context.flags = flags;
5537 context.text = NULL;
5538 context.window = window;
5539
5540 android_sync_edit ();
5541 if (android_run_in_emacs_thread (android_get_extracted_text,
5542 &context))
5543 return NULL;
5544
5545 if (!context.text)
5546 return NULL;
5547
5548
5549 string = android_text_to_string (env, context.text, context.length,
5550 context.bytes);
5551 free (context.text);
5552
5553 if (!string)
5554 return NULL;
5555
5556
5557 object = (*env)->NewObject (env, text_class.class,
5558 text_class.constructor);
5559 if (!object)
5560 return NULL;
5561
5562 (*env)->SetIntField (env, object, text_class.flags,
5563
5564 context.mark_active ? 2 : 0);
5565 (*env)->SetIntField (env, object, text_class.partial_start_offset, -1);
5566 (*env)->SetIntField (env, object, text_class.partial_end_offset, -1);
5567 (*env)->SetIntField (env, object, text_class.selection_start,
5568 min (context.start_offset, TYPE_MAXIMUM (jint)));
5569 (*env)->SetIntField (env, object, text_class.selection_end,
5570 min (context.end_offset, TYPE_MAXIMUM (jint)));
5571
5572
5573
5574 (*env)->SetIntField (env, object, text_class.start_offset,
5575 min (context.start - 1, TYPE_MAXIMUM (jint)));
5576 (*env)->SetObjectField (env, object, text_class.text, string);
5577 return object;
5578 }
5579
5580
5581
5582 JNIEXPORT jstring JNICALL
5583 NATIVE_NAME (getSelectedText) (JNIEnv *env, jobject object,
5584 jshort window)
5585 {
5586 JNI_STACK_ALIGNMENT_PROLOGUE;
5587
5588 struct android_get_extracted_text_context context;
5589 jstring string;
5590
5591 context.hint_max_chars = -1;
5592 context.token = 0;
5593 context.text = NULL;
5594 context.window = window;
5595
5596 android_sync_edit ();
5597 if (android_run_in_emacs_thread (android_get_extracted_text,
5598 &context))
5599 return NULL;
5600
5601 if (!context.text)
5602 return NULL;
5603
5604
5605 string = android_text_to_string (env, context.text, context.length,
5606 context.bytes);
5607 free (context.text);
5608
5609 return string;
5610 }
5611
5612 JNIEXPORT void JNICALL
5613 NATIVE_NAME (requestSelectionUpdate) (JNIEnv *env, jobject object,
5614 jshort window)
5615 {
5616 JNI_STACK_ALIGNMENT_PROLOGUE;
5617
5618 union android_event event;
5619
5620 event.ime.type = ANDROID_INPUT_METHOD;
5621 event.ime.serial = ++event_serial;
5622 event.ime.window = window;
5623 event.ime.operation = ANDROID_IME_REQUEST_SELECTION_UPDATE;
5624 event.ime.start = 0;
5625 event.ime.end = 0;
5626 event.ime.length = 0;
5627 event.ime.position = 0;
5628 event.ime.text = NULL;
5629 event.ime.counter = ++edit_counter;
5630
5631 android_write_event (&event);
5632 }
5633
5634 JNIEXPORT void JNICALL
5635 NATIVE_NAME (requestCursorUpdates) (JNIEnv *env, jobject object,
5636 jshort window, jint mode)
5637 {
5638 JNI_STACK_ALIGNMENT_PROLOGUE;
5639
5640 union android_event event;
5641
5642 event.ime.type = ANDROID_INPUT_METHOD;
5643 event.ime.serial = ++event_serial;
5644 event.ime.window = window;
5645 event.ime.operation = ANDROID_IME_REQUEST_CURSOR_UPDATES;
5646 event.ime.start = 0;
5647 event.ime.end = 0;
5648 event.ime.length = mode;
5649 event.ime.position = 0;
5650 event.ime.text = NULL;
5651
5652
5653
5654 event.ime.counter = 0;
5655
5656 android_write_event (&event);
5657 }
5658
5659
5660
5661
5662
5663 JNIEXPORT void JNICALL
5664 NATIVE_NAME (clearInputFlags) (JNIEnv *env, jobject object,
5665 jshort window)
5666 {
5667 JNI_STACK_ALIGNMENT_PROLOGUE;
5668
5669 union android_event event;
5670
5671 event.ime.type = ANDROID_INPUT_METHOD;
5672 event.ime.serial = ++event_serial;
5673 event.ime.window = window;
5674 event.ime.operation = ANDROID_IME_FINISH_COMPOSING_TEXT;
5675 event.ime.start = 0;
5676 event.ime.end = 0;
5677
5678
5679
5680
5681 event.ime.length = 2;
5682 event.ime.position = 0;
5683 event.ime.text = NULL;
5684 event.ime.counter = ++edit_counter;
5685
5686 android_write_event (&event);
5687 }
5688
5689
5690
5691
5692
5693 struct android_get_surrounding_text_context
5694 {
5695
5696 int before_length;
5697
5698
5699 int after_length;
5700
5701
5702 char *text;
5703
5704
5705 ptrdiff_t length, bytes;
5706
5707
5708 ptrdiff_t offset, start, end;
5709
5710
5711
5712 ptrdiff_t conversion_start, conversion_end;
5713
5714
5715 android_window window;
5716 };
5717
5718
5719
5720
5721 static void
5722 android_get_surrounding_text (void *data)
5723 {
5724 struct android_get_surrounding_text_context *request;
5725 struct frame *f;
5726 ptrdiff_t temp;
5727
5728 request = data;
5729
5730
5731 f = android_window_to_frame (NULL, request->window);
5732
5733 if (!f)
5734 return;
5735
5736
5737 request->text
5738 = get_surrounding_text (f, request->before_length,
5739 request->after_length, &request->length,
5740 &request->bytes, &request->offset,
5741 &request->start, &request->end);
5742
5743
5744
5745
5746 if (request->end < request->start)
5747 {
5748 temp = request->start;
5749 request->start = request->end;
5750 request->end = temp;
5751 }
5752
5753
5754
5755 request->conversion_start = -1;
5756 request->conversion_end = -1;
5757
5758 if (MARKERP (f->conversion.compose_region_start))
5759 {
5760 request->conversion_start
5761 = marker_position (f->conversion.compose_region_start) - 1;
5762 request->conversion_end
5763 = marker_position (f->conversion.compose_region_end) - 1;
5764 }
5765 }
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779 static jobject
5780 android_get_surrounding_text_internal (JNIEnv *env, jshort window,
5781 jint before_length,
5782 jint after_length,
5783 ptrdiff_t *conversion_start,
5784 ptrdiff_t *conversion_end)
5785 {
5786 struct android_get_surrounding_text_context context;
5787 jstring string;
5788 jobject object;
5789
5790 static jclass class;
5791 static jmethodID constructor;
5792
5793
5794
5795 if (!class)
5796 {
5797 class
5798 = (*env)->FindClass (env, ("android/view/inputmethod"
5799 "/SurroundingText"));
5800
5801 #if __ANDROID_API__ < 31
5802
5803
5804
5805 if (!class)
5806 {
5807 (*env)->ExceptionClear (env);
5808 return NULL;
5809 }
5810 #else
5811 assert (class);
5812 #endif
5813
5814 class = (*env)->NewGlobalRef (env, class);
5815 if (!class)
5816
5817
5818 return (class = NULL);
5819
5820
5821 constructor = (*env)->GetMethodID (env, class, "<init>",
5822 "(Ljava/lang/CharSequence;III)V");
5823 assert (constructor);
5824 }
5825
5826 context.before_length = before_length;
5827 context.after_length = after_length;
5828 context.window = window;
5829 context.text = NULL;
5830
5831 android_sync_edit ();
5832 if (android_run_in_emacs_thread (android_get_surrounding_text,
5833 &context))
5834 return NULL;
5835
5836 if (!context.text)
5837 return NULL;
5838
5839
5840 string = android_text_to_string (env, context.text, context.length,
5841 context.bytes);
5842 free (context.text);
5843
5844 if (!string)
5845 return NULL;
5846
5847
5848 object = (*env)->NewObject (env, class, constructor, string,
5849 (jint) min (context.start,
5850 TYPE_MAXIMUM (jint)),
5851 (jint) min (context.end,
5852 TYPE_MAXIMUM (jint)),
5853
5854
5855 (jint) min (context.offset - 1,
5856 TYPE_MAXIMUM (jint)));
5857 if (!object)
5858 return NULL;
5859
5860
5861
5862 if (conversion_start)
5863 {
5864 *conversion_start = context.conversion_start;
5865 *conversion_end = context.conversion_start;
5866 }
5867
5868 return object;
5869 }
5870
5871 JNIEXPORT jobject JNICALL
5872 NATIVE_NAME (getSurroundingText) (JNIEnv *env, jobject object,
5873 jshort window, jint before_length,
5874 jint after_length, jint flags)
5875 {
5876 JNI_STACK_ALIGNMENT_PROLOGUE;
5877
5878 return android_get_surrounding_text_internal (env, window, before_length,
5879 after_length, NULL, NULL);
5880 }
5881
5882 JNIEXPORT jobject JNICALL
5883 NATIVE_NAME (takeSnapshot) (JNIEnv *env, jobject object, jshort window)
5884 {
5885 JNI_STACK_ALIGNMENT_PROLOGUE;
5886
5887 jobject text;
5888 ptrdiff_t start, end;
5889
5890 static jclass class;
5891 static jmethodID constructor;
5892
5893
5894 text = android_get_surrounding_text_internal (env, window, 600, 600,
5895 &start, &end);
5896
5897
5898
5899 if (!text)
5900 return NULL;
5901
5902
5903
5904 if (!class)
5905 {
5906 class
5907 = (*env)->FindClass (env, ("android/view/inputmethod"
5908 "/TextSnapshot"));
5909 #if __ANDROID_API__ < 33
5910
5911
5912
5913 if (!class)
5914 {
5915 (*env)->ExceptionClear (env);
5916 return NULL;
5917 }
5918 #else
5919 assert (class);
5920 #endif
5921
5922 class = (*env)->NewGlobalRef (env, class);
5923 if (!class)
5924
5925
5926 return (class = NULL);
5927
5928 constructor = (*env)->GetMethodID (env, class, "<init>",
5929 "(Landroid/view/inputmethod"
5930 "/SurroundingText;III)V");
5931 assert (constructor);
5932 }
5933
5934
5935 eassert (start <= end);
5936 object = (*env)->NewObject (env, class, constructor, text,
5937 (jint) min (start, TYPE_MAXIMUM (jint)),
5938 (jint) min (end, TYPE_MAXIMUM (jint)),
5939 (jint) 0);
5940 return object;
5941 }
5942
5943 #ifdef __clang__
5944 #pragma clang diagnostic pop
5945 #else
5946 #pragma GCC diagnostic pop
5947 #endif
5948
5949
5950
5951
5952
5953
5954
5955 static void
5956 android_update_selection (struct frame *f, struct window *w)
5957 {
5958 ptrdiff_t start, end, point, mark, start_offset, end_offset;
5959 ptrdiff_t length, bytes;
5960 struct buffer *b;
5961 int hint, token;
5962 char *text;
5963 jobject extracted;
5964 jstring string;
5965 bool mark_active;
5966
5967 if (MARKERP (f->conversion.compose_region_start))
5968 {
5969 eassert (MARKERP (f->conversion.compose_region_end));
5970
5971
5972 start = marker_position (f->conversion.compose_region_start) - 1;
5973 end = marker_position (f->conversion.compose_region_end) - 1;
5974 }
5975 else
5976 start = -1, end = -1;
5977
5978
5979
5980 start = min (start, TYPE_MAXIMUM (jint));
5981 end = min (end, TYPE_MAXIMUM (jint));
5982
5983 if (!w)
5984 w = XWINDOW (f->selected_window);
5985
5986
5987
5988 b = XBUFFER (w->contents);
5989 point = min (w->ephemeral_last_point,
5990 TYPE_MAXIMUM (jint));
5991 mark = ((!NILP (BVAR (b, mark_active))
5992 && w->last_mark != -1)
5993 ? min (w->last_mark, TYPE_MAXIMUM (jint))
5994 : point);
5995
5996
5997
5998
5999
6000
6001 android_update_ic (FRAME_ANDROID_WINDOW (f), min (point, mark) - 1,
6002 max (point, mark) - 1, start, end);
6003
6004
6005
6006
6007
6008 if (FRAME_ANDROID_OUTPUT (f)->extracted_text_flags & 1)
6009 {
6010 hint = FRAME_ANDROID_OUTPUT (f)->extracted_text_hint;
6011 token = FRAME_ANDROID_OUTPUT (f)->extracted_text_token;
6012 text = get_extracted_text (f, min (hint, 600), &start,
6013 &start_offset, &end_offset,
6014 &length, &bytes, &mark_active);
6015
6016 if (text)
6017 {
6018
6019 string = android_text_to_string (android_java_env,
6020 text, length, bytes);
6021 xfree (text);
6022 android_exception_check ();
6023
6024
6025 extracted = android_build_extracted_text (string, start,
6026 start_offset,
6027 end_offset,
6028 mark_active);
6029 android_exception_check_1 (string);
6030 ANDROID_DELETE_LOCAL_REF (string);
6031
6032 if (extracted)
6033 {
6034
6035
6036 android_update_extracted_text (FRAME_ANDROID_WINDOW (f),
6037 extracted, token);
6038 ANDROID_DELETE_LOCAL_REF (extracted);
6039 }
6040 }
6041 }
6042 }
6043
6044
6045
6046
6047 static bool
6048 android_event_is_for_frame (union android_event *event, void *arg)
6049 {
6050 struct frame *f;
6051
6052 f = arg;
6053 return (event->type == ANDROID_INPUT_METHOD
6054 && event->ime.window == FRAME_ANDROID_WINDOW (f));
6055 }
6056
6057
6058
6059
6060 static void
6061 android_reset_conversion (struct frame *f)
6062 {
6063 enum android_ic_mode mode;
6064 struct window *w;
6065 struct buffer *buffer;
6066 Lisp_Object style;
6067 union android_event event;
6068
6069
6070
6071
6072
6073
6074
6075
6076 w = XWINDOW (f->selected_window);
6077 buffer = XBUFFER (WINDOW_BUFFER (w));
6078
6079 style = (EQ (find_symbol_value (Qoverriding_text_conversion_style),
6080 Qlambda)
6081 ? BVAR (buffer, text_conversion_style)
6082 : find_symbol_value (Qoverriding_text_conversion_style));
6083
6084 if (NILP (style) || conversion_disabled_p ())
6085 mode = ANDROID_IC_MODE_NULL;
6086 else if (EQ (style, Qaction) || EQ (f->selected_window,
6087 f->minibuffer_window))
6088 mode = ANDROID_IC_MODE_ACTION;
6089 else
6090 mode = ANDROID_IC_MODE_TEXT;
6091
6092
6093
6094
6095
6096
6097
6098 while (android_check_if_event (&event, android_event_is_for_frame, f))
6099 {
6100 switch (event.ime.operation)
6101 {
6102 case ANDROID_IME_COMMIT_TEXT:
6103 case ANDROID_IME_FINISH_COMPOSING_TEXT:
6104 case ANDROID_IME_SET_COMPOSING_TEXT:
6105 xfree (event.ime.text);
6106 break;
6107
6108 default:
6109 break;
6110 }
6111 }
6112
6113 android_reset_ic (FRAME_ANDROID_WINDOW (f), mode);
6114
6115
6116
6117 FRAME_ANDROID_OUTPUT (f)->extracted_text_flags = 0;
6118
6119
6120 android_update_selection (f, NULL);
6121 }
6122
6123
6124
6125
6126 static void
6127 android_set_point (struct frame *f, struct window *w,
6128 struct buffer *buffer)
6129 {
6130 android_update_selection (f, w);
6131 }
6132
6133
6134
6135
6136 static void
6137 android_compose_region_changed (struct frame *f)
6138 {
6139 android_update_selection (f, XWINDOW (f->old_selected_window));
6140 }
6141
6142
6143
6144 static void
6145 android_notify_conversion (unsigned long counter)
6146 {
6147 int sval;
6148
6149 if (last_edit_counter < counter)
6150 __atomic_store_n (&last_edit_counter, counter,
6151 __ATOMIC_SEQ_CST);
6152
6153 sem_getvalue (&edit_sem, &sval);
6154
6155 if (sval <= 0)
6156 sem_post (&edit_sem);
6157 }
6158
6159
6160
6161 static struct textconv_interface text_conversion_interface =
6162 {
6163 android_reset_conversion,
6164 android_set_point,
6165 android_compose_region_changed,
6166 android_notify_conversion,
6167 };
6168
6169
6170
6171 extern frame_parm_handler android_frame_parm_handlers[];
6172
6173 #endif
6174
6175 static struct redisplay_interface android_redisplay_interface =
6176 {
6177 #ifndef ANDROID_STUBIFY
6178 android_frame_parm_handlers,
6179 gui_produce_glyphs,
6180 gui_write_glyphs,
6181 gui_insert_glyphs,
6182 gui_clear_end_of_line,
6183 android_scroll_run,
6184 android_after_update_window_line,
6185 NULL,
6186 NULL,
6187 android_flip_and_flush,
6188 gui_clear_window_mouse_face,
6189 gui_get_glyph_overhangs,
6190 gui_fix_overlapping_area,
6191 android_draw_fringe_bitmap,
6192 NULL,
6193 NULL,
6194 android_compute_glyph_string_overhangs,
6195 android_draw_glyph_string,
6196 android_define_frame_cursor,
6197 android_clear_frame_area,
6198 android_clear_under_internal_border,
6199 android_draw_window_cursor,
6200 android_draw_vertical_window_border,
6201 android_draw_window_divider,
6202 NULL,
6203 android_show_hourglass,
6204 android_hide_hourglass,
6205 android_default_font_parameter,
6206 #endif
6207 };
6208
6209
6210
6211 void
6212 frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
6213 {
6214
6215
6216 }
6217
6218 char *
6219 get_keysym_name (int keysym)
6220 {
6221 static char buffer[64];
6222
6223 #ifndef ANDROID_STUBIFY
6224 android_get_keysym_name (keysym, buffer, 64);
6225 #else
6226 emacs_abort ();
6227 #endif
6228 return buffer;
6229 }
6230
6231
6232
6233
6234
6235
6236 static struct terminal *
6237 android_create_terminal (struct android_display_info *dpyinfo)
6238 {
6239 struct terminal *terminal;
6240
6241 terminal = create_terminal (output_android,
6242 &android_redisplay_interface);
6243 terminal->display_info.android = dpyinfo;
6244 dpyinfo->terminal = terminal;
6245
6246
6247
6248 #ifndef ANDROID_STUBIFY
6249
6250 terminal->clear_frame_hook = android_clear_frame;
6251 terminal->ring_bell_hook = android_ring_bell;
6252 terminal->toggle_invisible_pointer_hook
6253 = android_toggle_invisible_pointer;
6254 terminal->update_begin_hook = android_update_begin;
6255 terminal->update_end_hook = android_update_end;
6256 terminal->read_socket_hook = android_read_socket;
6257 terminal->frame_up_to_date_hook = android_frame_up_to_date;
6258 terminal->buffer_flipping_unblocked_hook
6259 = android_buffer_flipping_unblocked_hook;
6260 terminal->defined_color_hook = android_defined_color;
6261 terminal->query_frame_background_color
6262 = android_query_frame_background_color;
6263 terminal->query_colors = android_query_colors;
6264 terminal->mouse_position_hook = android_mouse_position;
6265 terminal->get_focus_frame = android_get_focus_frame;
6266 terminal->focus_frame_hook = android_focus_frame;
6267 terminal->frame_rehighlight_hook = android_frame_rehighlight_hook;
6268 terminal->frame_raise_lower_hook = android_frame_raise_lower;
6269 terminal->frame_visible_invisible_hook
6270 = android_make_frame_visible_invisible;
6271 terminal->fullscreen_hook = android_fullscreen_hook;
6272 terminal->iconify_frame_hook = android_iconify_frame;
6273 terminal->set_window_size_hook = android_set_window_size;
6274 terminal->set_frame_offset_hook = android_set_offset;
6275 terminal->set_frame_alpha_hook = android_set_alpha;
6276 terminal->set_new_font_hook = android_new_font;
6277 terminal->set_bitmap_icon_hook = android_bitmap_icon;
6278 terminal->implicit_set_name_hook = android_implicitly_set_name;
6279 terminal->menu_show_hook = android_menu_show;
6280 terminal->popup_dialog_hook = android_popup_dialog;
6281 terminal->change_tab_bar_height_hook = android_change_tab_bar_height;
6282 terminal->change_tool_bar_height_hook = android_change_tool_bar_height;
6283 terminal->set_scroll_bar_default_width_hook
6284 = android_set_scroll_bar_default_width;
6285 terminal->set_scroll_bar_default_height_hook
6286 = android_set_scroll_bar_default_height;
6287 terminal->free_pixmap = android_free_pixmap_hook;
6288 terminal->delete_frame_hook = android_delete_frame;
6289 terminal->delete_terminal_hook = android_delete_terminal;
6290
6291 #else
6292 emacs_abort ();
6293 #endif
6294
6295 return terminal;
6296 }
6297
6298
6299
6300
6301 void
6302 android_term_init (void)
6303 {
6304 struct terminal *terminal;
6305 struct android_display_info *dpyinfo;
6306 Lisp_Object color_file, color_map;
6307
6308 dpyinfo = xzalloc (sizeof *dpyinfo);
6309 terminal = android_create_terminal (dpyinfo);
6310 terminal->kboard = allocate_kboard (Qandroid);
6311 terminal->kboard->reference_count++;
6312
6313 dpyinfo->n_planes = 24;
6314
6315
6316 eassert (!x_display_list);
6317 x_display_list = dpyinfo;
6318
6319 dpyinfo->name_list_element
6320 = Fcons (build_pure_c_string ("android"), Qnil);
6321
6322 color_file = Fexpand_file_name (build_string ("rgb.txt"),
6323 Vdata_directory);
6324 color_map = Fx_load_color_file (color_file);
6325
6326 if (NILP (color_map))
6327 fatal ("Could not read %s.\n", SDATA (color_file));
6328
6329 dpyinfo->color_map = color_map;
6330
6331 #ifndef ANDROID_STUBIFY
6332 dpyinfo->resx = android_pixel_density_x;
6333 dpyinfo->resy = android_pixel_density_y;
6334 dpyinfo->font_resolution = android_scaled_pixel_density;
6335 #endif
6336
6337
6338 dpyinfo->smallest_font_height = 1;
6339 dpyinfo->smallest_char_width = 1;
6340
6341 terminal->name = xstrdup ("android");
6342
6343
6344
6345 terminal->reference_count = 30000;
6346
6347
6348 baud_rate = 19200;
6349
6350 #ifndef ANDROID_STUBIFY
6351 sem_init (&edit_sem, false, 0);
6352 register_textconv_interface (&text_conversion_interface);
6353 #endif
6354 }
6355
6356
6357
6358
6359
6360
6361 static void
6362 android_set_build_fingerprint (void)
6363 {
6364 #ifdef ANDROID_STUBIFY
6365 Vandroid_build_fingerprint = Qnil;
6366 #else
6367 jclass class;
6368 jfieldID field;
6369 jobject string;
6370 const char *data;
6371
6372
6373
6374 class = NULL;
6375
6376
6377 string = NULL;
6378
6379 if (!android_init_gui)
6380 goto fail;
6381 else
6382 {
6383
6384
6385
6386 class = (*android_java_env)->FindClass (android_java_env,
6387 "android/os/Build");
6388 (*android_java_env)->ExceptionClear (android_java_env);
6389
6390 if (!class)
6391 goto fail;
6392
6393 field = (*android_java_env)->GetStaticFieldID (android_java_env,
6394 class,
6395 "FINGERPRINT",
6396 "Ljava/lang/String;");
6397 (*android_java_env)->ExceptionClear (android_java_env);
6398
6399 if (!field)
6400 goto fail;
6401
6402 string
6403 = (*android_java_env)->GetStaticObjectField (android_java_env,
6404 class, field);
6405 (*android_java_env)->ExceptionClear (android_java_env);
6406
6407 if (!string)
6408 goto fail;
6409
6410 data = (*android_java_env)->GetStringUTFChars (android_java_env,
6411 string, NULL);
6412 (*android_java_env)->ExceptionClear (android_java_env);
6413
6414 if (!data)
6415 goto fail;
6416
6417 Vandroid_build_fingerprint = build_string_from_utf8 (data);
6418 (*android_java_env)->ReleaseStringUTFChars (android_java_env,
6419 string, data);
6420
6421
6422
6423 ANDROID_DELETE_LOCAL_REF (string);
6424 string = NULL;
6425
6426 field = (*android_java_env)->GetStaticFieldID (android_java_env,
6427 class,
6428 "MANUFACTURER",
6429 "Ljava/lang/String;");
6430 (*android_java_env)->ExceptionClear (android_java_env);
6431
6432 if (!field)
6433 goto fail;
6434
6435 string
6436 = (*android_java_env)->GetStaticObjectField (android_java_env,
6437 class, field);
6438 (*android_java_env)->ExceptionClear (android_java_env);
6439
6440 if (!string)
6441 goto fail;
6442
6443 data = (*android_java_env)->GetStringUTFChars (android_java_env,
6444 string, NULL);
6445 (*android_java_env)->ExceptionClear (android_java_env);
6446
6447 if (!data)
6448 goto fail;
6449
6450 Vandroid_build_manufacturer = build_string_from_utf8 (data);
6451 (*android_java_env)->ReleaseStringUTFChars (android_java_env,
6452 string, data);
6453 }
6454
6455 if (string)
6456 ANDROID_DELETE_LOCAL_REF (string);
6457
6458 ANDROID_DELETE_LOCAL_REF (class);
6459
6460 return;
6461
6462 fail:
6463 if (class)
6464 ANDROID_DELETE_LOCAL_REF (class);
6465
6466 Vandroid_build_fingerprint = Qnil;
6467 Vandroid_build_manufacturer = Qnil;
6468 #endif
6469 }
6470
6471 void
6472 syms_of_androidterm (void)
6473 {
6474 Fprovide (Qandroid, Qnil);
6475
6476 DEFVAR_LISP ("android-wait-for-event-timeout",
6477 Vandroid_wait_for_event_timeout,
6478 doc:
6479
6480
6481
6482
6483
6484
6485 );
6486 Vandroid_wait_for_event_timeout = make_float (0.1);
6487
6488 DEFVAR_BOOL ("x-use-underline-position-properties",
6489 x_use_underline_position_properties,
6490 doc: );
6491 x_use_underline_position_properties = true;
6492 DEFSYM (Qx_use_underline_position_properties,
6493 "x-use-underline-position-properties");
6494
6495 DEFVAR_BOOL ("x-underline-at-descent-line",
6496 x_underline_at_descent_line,
6497 doc: );
6498 x_underline_at_descent_line = false;
6499
6500 DEFVAR_LISP ("android-build-fingerprint", Vandroid_build_fingerprint,
6501 doc:
6502
6503 );
6504 Vandroid_build_fingerprint = Qnil;
6505
6506 DEFVAR_LISP ("android-build-manufacturer", Vandroid_build_manufacturer,
6507 doc: );
6508 Vandroid_build_manufacturer = Qnil;
6509
6510
6511 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
6512 doc: );
6513 Vx_toolkit_scroll_bars = Qnil;
6514
6515
6516 pdumper_do_now_and_after_load (android_set_build_fingerprint);
6517
6518 DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
6519 }
6520
6521 void
6522 mark_androidterm (void)
6523 {
6524 if (x_display_list)
6525 mark_object (x_display_list->color_map);
6526 }