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 if (encoded >= 65536)
4949 encoded = 0;
4950
4951 utf16[index++] = encoded;
4952 buffer += BYTES_BY_CHAR_HEAD (*buffer);
4953 }
4954
4955
4956 string = (*env)->NewString (env, utf16, index);
4957 free (utf16);
4958 return string;
4959 }
4960
4961 JNIEXPORT jstring JNICALL
4962 NATIVE_NAME (getTextAfterCursor) (JNIEnv *env, jobject object, jshort window,
4963 jint length, jint flags)
4964 {
4965 JNI_STACK_ALIGNMENT_PROLOGUE;
4966
4967 struct android_conversion_query_context context;
4968 jstring string;
4969
4970
4971 context.query.position = EMACS_INT_MAX;
4972 context.query.direction = TEXTCONV_FORWARD_CHAR;
4973 context.query.factor = min (length, 65535);
4974 context.query.operation = TEXTCONV_RETRIEVAL;
4975
4976
4977 context.window = window;
4978 context.success = false;
4979
4980
4981 android_sync_edit ();
4982 if (android_run_in_emacs_thread (android_perform_conversion_query,
4983 &context))
4984 return NULL;
4985
4986 if (!context.success)
4987 return NULL;
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997 string = android_text_to_string (env, context.query.text.text,
4998 context.query.text.length,
4999 context.query.text.bytes);
5000 free (context.query.text.text);
5001
5002 return string;
5003 }
5004
5005 JNIEXPORT jstring JNICALL
5006 NATIVE_NAME (getTextBeforeCursor) (JNIEnv *env, jobject object, jshort window,
5007 jint length, jint flags)
5008 {
5009 JNI_STACK_ALIGNMENT_PROLOGUE;
5010
5011 struct android_conversion_query_context context;
5012 jstring string;
5013
5014
5015 context.query.position = TYPE_MINIMUM (EMACS_INT);
5016 context.query.direction = TEXTCONV_BACKWARD_CHAR;
5017 context.query.factor = min (length, 65535);
5018 context.query.operation = TEXTCONV_RETRIEVAL;
5019
5020
5021 context.window = window;
5022 context.success = false;
5023
5024
5025 android_sync_edit ();
5026 if (android_run_in_emacs_thread (android_perform_conversion_query,
5027 &context))
5028 return NULL;
5029
5030 if (!context.success)
5031 return NULL;
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041 string = android_text_to_string (env, context.query.text.text,
5042 context.query.text.length,
5043 context.query.text.bytes);
5044 free (context.query.text.text);
5045
5046 return string;
5047 }
5048
5049 JNIEXPORT void JNICALL
5050 NATIVE_NAME (setComposingText) (JNIEnv *env, jobject object, jshort window,
5051 jstring composing_text,
5052 jint new_cursor_position)
5053 {
5054 JNI_STACK_ALIGNMENT_PROLOGUE;
5055
5056 union android_event event;
5057 unsigned short *text;
5058 size_t length;
5059
5060
5061 text = android_copy_java_string (env, composing_text, &length);
5062
5063 if (!text)
5064 return;
5065
5066
5067
5068
5069
5070 event.ime.type = ANDROID_INPUT_METHOD;
5071 event.ime.serial = ++event_serial;
5072 event.ime.window = window;
5073 event.ime.operation = ANDROID_IME_SET_COMPOSING_TEXT;
5074 event.ime.start = 0;
5075 event.ime.end = 0;
5076 event.ime.length = min (length, PTRDIFF_MAX);
5077 event.ime.position = new_cursor_position;
5078 event.ime.text = text;
5079 event.ime.counter = ++edit_counter;
5080
5081 android_write_event (&event);
5082 }
5083
5084 JNIEXPORT void JNICALL
5085 NATIVE_NAME (setComposingRegion) (JNIEnv *env, jobject object, jshort window,
5086 jint start, jint end)
5087 {
5088 JNI_STACK_ALIGNMENT_PROLOGUE;
5089
5090 union android_event event;
5091
5092 event.ime.type = ANDROID_INPUT_METHOD;
5093 event.ime.serial = ++event_serial;
5094 event.ime.window = window;
5095 event.ime.operation = ANDROID_IME_SET_COMPOSING_REGION;
5096 event.ime.start = start + 1;
5097 event.ime.end = end + 1;
5098 event.ime.length = 0;
5099 event.ime.position = 0;
5100 event.ime.text = NULL;
5101 event.ime.counter = ++edit_counter;
5102
5103 android_write_event (&event);
5104 }
5105
5106 JNIEXPORT void JNICALL
5107 NATIVE_NAME (setSelection) (JNIEnv *env, jobject object, jshort window,
5108 jint start, jint end)
5109 {
5110 JNI_STACK_ALIGNMENT_PROLOGUE;
5111
5112 union android_event event;
5113
5114
5115
5116
5117 event.ime.type = ANDROID_INPUT_METHOD;
5118 event.ime.serial = ++event_serial;
5119 event.ime.window = window;
5120 event.ime.operation = ANDROID_IME_SET_POINT;
5121 event.ime.start = start + 1;
5122 event.ime.end = end + 1;
5123 event.ime.length = 0;
5124 event.ime.position = start;
5125 event.ime.text = NULL;
5126 event.ime.counter = ++edit_counter;
5127
5128 android_write_event (&event);
5129 }
5130
5131
5132
5133 struct android_get_selection_context
5134 {
5135
5136 android_window window;
5137
5138
5139
5140 ptrdiff_t point, mark;
5141 };
5142
5143
5144
5145
5146 static void
5147 android_get_selection (void *data)
5148 {
5149 struct android_get_selection_context *context;
5150 struct frame *f;
5151 struct window *w;
5152 struct buffer *b;
5153
5154 context = data;
5155
5156
5157 f = android_window_to_frame (NULL, context->window);
5158
5159 if (!f)
5160 context->point = -1;
5161 else
5162 {
5163 w = XWINDOW (f->selected_window);
5164
5165
5166
5167 context->point = window_point (w);
5168 w->ephemeral_last_point = context->point;
5169
5170
5171 context->mark = context->point;
5172
5173
5174
5175 b = XBUFFER (w->contents);
5176 if (!NILP (BVAR (b, mark_active)))
5177 {
5178 context->mark = marker_position (BVAR (b, mark));
5179 w->last_mark = context->mark;
5180 }
5181 }
5182 }
5183
5184 JNIEXPORT jintArray JNICALL
5185 NATIVE_NAME (getSelection) (JNIEnv *env, jobject object, jshort window)
5186 {
5187 JNI_STACK_ALIGNMENT_PROLOGUE;
5188
5189 struct android_get_selection_context context;
5190 jintArray array;
5191 jint contents[2];
5192
5193 context.window = window;
5194
5195 android_sync_edit ();
5196 if (android_run_in_emacs_thread (android_get_selection,
5197 &context))
5198 return NULL;
5199
5200 if (context.point == -1)
5201 return NULL;
5202
5203
5204
5205
5206 contents[0] = (unsigned int) min (context.point,
5207 context.mark) - 1;
5208 contents[1] = (unsigned int) max (context.point,
5209 context.mark) - 1;
5210
5211
5212 array = (*env)->NewIntArray (env, 2);
5213
5214 if (!array)
5215 return NULL;
5216
5217
5218 (*env)->SetIntArrayRegion (env, array, 0, 2, contents);
5219 return array;
5220 }
5221
5222 JNIEXPORT void JNICALL
5223 NATIVE_NAME (performEditorAction) (JNIEnv *env, jobject object,
5224 jshort window, int action)
5225 {
5226 JNI_STACK_ALIGNMENT_PROLOGUE;
5227
5228 union android_event event;
5229
5230
5231
5232
5233
5234
5235 android_sync_edit ();
5236
5237
5238
5239
5240 event.ime.type = ANDROID_INPUT_METHOD;
5241 event.ime.serial = ++event_serial;
5242 event.ime.window = window;
5243 event.ime.operation = ANDROID_IME_FINISH_COMPOSING_TEXT;
5244 event.ime.start = 0;
5245 event.ime.end = 0;
5246
5247
5248
5249
5250 event.ime.length = 1;
5251 event.ime.position = 0;
5252 event.ime.text = NULL;
5253 event.ime.counter = ++edit_counter;
5254
5255 android_write_event (&event);
5256
5257
5258
5259
5260
5261
5262 event.xkey.type = ANDROID_KEY_PRESS;
5263 event.xkey.serial = ++event_serial;
5264 event.xkey.window = window;
5265 event.xkey.time = 0;
5266 event.xkey.state = 0;
5267 event.xkey.keycode = 66;
5268 event.xkey.unicode_char = 0;
5269 event.xkey.counter = ++edit_counter;
5270
5271 android_write_event (&event);
5272 }
5273
5274 JNIEXPORT void JNICALL
5275 NATIVE_NAME (performContextMenuAction) (JNIEnv *env, jobject object,
5276 jshort window, int action)
5277 {
5278 JNI_STACK_ALIGNMENT_PROLOGUE;
5279
5280 union android_event event;
5281 int key;
5282
5283
5284
5285
5286 switch (action)
5287 {
5288 case 0:
5289 case 1:
5290 case 2:
5291 default:
5292
5293 return;
5294
5295 case 3:
5296 key = 277;
5297 break;
5298
5299 case 4:
5300 key = 278;
5301 break;
5302
5303 case 5:
5304 key = 279;
5305 break;
5306 }
5307
5308 event.xkey.type = ANDROID_KEY_PRESS;
5309 event.xkey.serial = ++event_serial;
5310 event.xkey.window = window;
5311 event.xkey.time = 0;
5312 event.xkey.state = 0;
5313 event.xkey.keycode = key;
5314 event.xkey.unicode_char = 0;
5315 event.xkey.counter = ++edit_counter;
5316
5317 android_write_event (&event);
5318 }
5319
5320
5321
5322
5323
5324 struct android_get_extracted_text_context
5325 {
5326
5327 int hint_max_chars;
5328
5329
5330 int token;
5331
5332
5333 int flags;
5334
5335
5336 char *text;
5337
5338
5339 ptrdiff_t length, bytes;
5340
5341
5342 ptrdiff_t start, start_offset, end_offset;
5343
5344
5345 android_window window;
5346
5347
5348 bool mark_active;
5349 };
5350
5351
5352
5353
5354 static void
5355 android_get_extracted_text (void *data)
5356 {
5357 struct android_get_extracted_text_context *request;
5358 struct frame *f;
5359
5360 request = data;
5361
5362
5363 f = android_window_to_frame (NULL, request->window);
5364
5365 if (!f)
5366 return;
5367
5368
5369 request->text
5370 = get_extracted_text (f, min (request->hint_max_chars, 600),
5371 &request->start, &request->start_offset,
5372 &request->end_offset, &request->length,
5373 &request->bytes, &request->mark_active);
5374
5375
5376
5377
5378
5379 FRAME_ANDROID_OUTPUT (f)->extracted_text_flags = request->flags;
5380 FRAME_ANDROID_OUTPUT (f)->extracted_text_token = request->token;
5381 FRAME_ANDROID_OUTPUT (f)->extracted_text_hint = request->hint_max_chars;
5382 }
5383
5384
5385
5386
5387 struct android_extracted_text_request_class
5388 {
5389 bool initialized;
5390 jfieldID hint_max_chars;
5391 jfieldID token;
5392 };
5393
5394
5395
5396
5397 struct android_extracted_text_class
5398 {
5399 jclass class;
5400 jmethodID constructor;
5401 jfieldID flags;
5402 jfieldID partial_start_offset;
5403 jfieldID partial_end_offset;
5404 jfieldID selection_start;
5405 jfieldID selection_end;
5406 jfieldID start_offset;
5407 jfieldID text;
5408 };
5409
5410
5411
5412 struct android_extracted_text_request_class request_class;
5413
5414
5415 struct android_extracted_text_class text_class;
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430 static jobject
5431 android_build_extracted_text (jstring text, ptrdiff_t start,
5432 ptrdiff_t start_offset,
5433 ptrdiff_t end_offset, bool mark_active)
5434 {
5435 JNIEnv *env;
5436 jobject object;
5437
5438 env = android_java_env;
5439
5440
5441 if (!text_class.class)
5442 return NULL;
5443
5444
5445 object = (*env)->NewObject (env, text_class.class,
5446 text_class.constructor);
5447 if (!object)
5448 return NULL;
5449
5450 (*env)->SetIntField (env, object, text_class.flags,
5451
5452 mark_active ? 2 : 0);
5453 (*env)->SetIntField (env, object, text_class.partial_start_offset, -1);
5454 (*env)->SetIntField (env, object, text_class.partial_end_offset, -1);
5455 (*env)->SetIntField (env, object, text_class.selection_start,
5456 min (start_offset, TYPE_MAXIMUM (jint)));
5457 (*env)->SetIntField (env, object, text_class.selection_end,
5458 min (end_offset, TYPE_MAXIMUM (jint)));
5459
5460
5461
5462 (*env)->SetIntField (env, object, text_class.start_offset,
5463 min (start - 1, TYPE_MAXIMUM (jint)));
5464 (*env)->SetObjectField (env, object, text_class.text, text);
5465 return object;
5466 }
5467
5468 JNIEXPORT jobject JNICALL
5469 NATIVE_NAME (getExtractedText) (JNIEnv *env, jobject ignored_object,
5470 jshort window, jobject request,
5471 jint flags)
5472 {
5473 JNI_STACK_ALIGNMENT_PROLOGUE;
5474
5475 struct android_get_extracted_text_context context;
5476 jstring string;
5477 jclass class;
5478 jobject object;
5479
5480
5481
5482 if (!request_class.initialized)
5483 {
5484 class
5485 = (*env)->FindClass (env, ("android/view/inputmethod"
5486 "/ExtractedTextRequest"));
5487 assert (class);
5488
5489 request_class.hint_max_chars
5490 = (*env)->GetFieldID (env, class, "hintMaxChars", "I");
5491 assert (request_class.hint_max_chars);
5492
5493 request_class.token
5494 = (*env)->GetFieldID (env, class, "token", "I");
5495 assert (request_class.token);
5496
5497 request_class.initialized = true;
5498 }
5499
5500 if (!text_class.class)
5501 {
5502 text_class.class
5503 = (*env)->FindClass (env, ("android/view/inputmethod"
5504 "/ExtractedText"));
5505 assert (text_class.class);
5506
5507 class
5508 = text_class.class
5509 = (*env)->NewGlobalRef (env, text_class.class);
5510 assert (text_class.class);
5511
5512 text_class.flags
5513 = (*env)->GetFieldID (env, class, "flags", "I");
5514 text_class.partial_start_offset
5515 = (*env)->GetFieldID (env, class, "partialStartOffset", "I");
5516 text_class.partial_end_offset
5517 = (*env)->GetFieldID (env, class, "partialEndOffset", "I");
5518 text_class.selection_start
5519 = (*env)->GetFieldID (env, class, "selectionStart", "I");
5520 text_class.selection_end
5521 = (*env)->GetFieldID (env, class, "selectionEnd", "I");
5522 text_class.start_offset
5523 = (*env)->GetFieldID (env, class, "startOffset", "I");
5524 text_class.text
5525 = (*env)->GetFieldID (env, class, "text", "Ljava/lang/CharSequence;");
5526 text_class.constructor
5527 = (*env)->GetMethodID (env, class, "<init>", "()V");
5528 }
5529
5530 context.hint_max_chars
5531 = (*env)->GetIntField (env, request, request_class.hint_max_chars);
5532 context.token
5533 = (*env)->GetIntField (env, request, request_class.token);
5534 context.flags = flags;
5535 context.text = NULL;
5536 context.window = window;
5537
5538 android_sync_edit ();
5539 if (android_run_in_emacs_thread (android_get_extracted_text,
5540 &context))
5541 return NULL;
5542
5543 if (!context.text)
5544 return NULL;
5545
5546
5547 string = android_text_to_string (env, context.text, context.length,
5548 context.bytes);
5549 free (context.text);
5550
5551 if (!string)
5552 return NULL;
5553
5554
5555 object = (*env)->NewObject (env, text_class.class,
5556 text_class.constructor);
5557 if (!object)
5558 return NULL;
5559
5560 (*env)->SetIntField (env, object, text_class.flags,
5561
5562 context.mark_active ? 2 : 0);
5563 (*env)->SetIntField (env, object, text_class.partial_start_offset, -1);
5564 (*env)->SetIntField (env, object, text_class.partial_end_offset, -1);
5565 (*env)->SetIntField (env, object, text_class.selection_start,
5566 min (context.start_offset, TYPE_MAXIMUM (jint)));
5567 (*env)->SetIntField (env, object, text_class.selection_end,
5568 min (context.end_offset, TYPE_MAXIMUM (jint)));
5569
5570
5571
5572 (*env)->SetIntField (env, object, text_class.start_offset,
5573 min (context.start - 1, TYPE_MAXIMUM (jint)));
5574 (*env)->SetObjectField (env, object, text_class.text, string);
5575 return object;
5576 }
5577
5578
5579
5580 JNIEXPORT jstring JNICALL
5581 NATIVE_NAME (getSelectedText) (JNIEnv *env, jobject object,
5582 jshort window)
5583 {
5584 JNI_STACK_ALIGNMENT_PROLOGUE;
5585
5586 struct android_get_extracted_text_context context;
5587 jstring string;
5588
5589 context.hint_max_chars = -1;
5590 context.token = 0;
5591 context.text = NULL;
5592 context.window = window;
5593
5594 android_sync_edit ();
5595 if (android_run_in_emacs_thread (android_get_extracted_text,
5596 &context))
5597 return NULL;
5598
5599 if (!context.text)
5600 return NULL;
5601
5602
5603 string = android_text_to_string (env, context.text, context.length,
5604 context.bytes);
5605 free (context.text);
5606
5607 return string;
5608 }
5609
5610 JNIEXPORT void JNICALL
5611 NATIVE_NAME (requestSelectionUpdate) (JNIEnv *env, jobject object,
5612 jshort window)
5613 {
5614 JNI_STACK_ALIGNMENT_PROLOGUE;
5615
5616 union android_event event;
5617
5618 event.ime.type = ANDROID_INPUT_METHOD;
5619 event.ime.serial = ++event_serial;
5620 event.ime.window = window;
5621 event.ime.operation = ANDROID_IME_REQUEST_SELECTION_UPDATE;
5622 event.ime.start = 0;
5623 event.ime.end = 0;
5624 event.ime.length = 0;
5625 event.ime.position = 0;
5626 event.ime.text = NULL;
5627 event.ime.counter = ++edit_counter;
5628
5629 android_write_event (&event);
5630 }
5631
5632 JNIEXPORT void JNICALL
5633 NATIVE_NAME (requestCursorUpdates) (JNIEnv *env, jobject object,
5634 jshort window, jint mode)
5635 {
5636 JNI_STACK_ALIGNMENT_PROLOGUE;
5637
5638 union android_event event;
5639
5640 event.ime.type = ANDROID_INPUT_METHOD;
5641 event.ime.serial = ++event_serial;
5642 event.ime.window = window;
5643 event.ime.operation = ANDROID_IME_REQUEST_CURSOR_UPDATES;
5644 event.ime.start = 0;
5645 event.ime.end = 0;
5646 event.ime.length = mode;
5647 event.ime.position = 0;
5648 event.ime.text = NULL;
5649
5650
5651
5652 event.ime.counter = 0;
5653
5654 android_write_event (&event);
5655 }
5656
5657
5658
5659
5660
5661 JNIEXPORT void JNICALL
5662 NATIVE_NAME (clearInputFlags) (JNIEnv *env, jobject object,
5663 jshort window)
5664 {
5665 JNI_STACK_ALIGNMENT_PROLOGUE;
5666
5667 union android_event event;
5668
5669 event.ime.type = ANDROID_INPUT_METHOD;
5670 event.ime.serial = ++event_serial;
5671 event.ime.window = window;
5672 event.ime.operation = ANDROID_IME_FINISH_COMPOSING_TEXT;
5673 event.ime.start = 0;
5674 event.ime.end = 0;
5675
5676
5677
5678
5679 event.ime.length = 2;
5680 event.ime.position = 0;
5681 event.ime.text = NULL;
5682 event.ime.counter = ++edit_counter;
5683
5684 android_write_event (&event);
5685 }
5686
5687
5688
5689
5690
5691 struct android_get_surrounding_text_context
5692 {
5693
5694 int before_length;
5695
5696
5697 int after_length;
5698
5699
5700 char *text;
5701
5702
5703 ptrdiff_t length, bytes;
5704
5705
5706 ptrdiff_t offset, start, end;
5707
5708
5709
5710 ptrdiff_t conversion_start, conversion_end;
5711
5712
5713 android_window window;
5714 };
5715
5716
5717
5718
5719 static void
5720 android_get_surrounding_text (void *data)
5721 {
5722 struct android_get_surrounding_text_context *request;
5723 struct frame *f;
5724 ptrdiff_t temp;
5725
5726 request = data;
5727
5728
5729 f = android_window_to_frame (NULL, request->window);
5730
5731 if (!f)
5732 return;
5733
5734
5735 request->text
5736 = get_surrounding_text (f, request->before_length,
5737 request->after_length, &request->length,
5738 &request->bytes, &request->offset,
5739 &request->start, &request->end);
5740
5741
5742
5743
5744 if (request->end < request->start)
5745 {
5746 temp = request->start;
5747 request->start = request->end;
5748 request->end = temp;
5749 }
5750
5751
5752
5753 request->conversion_start = -1;
5754 request->conversion_end = -1;
5755
5756 if (MARKERP (f->conversion.compose_region_start))
5757 {
5758 request->conversion_start
5759 = marker_position (f->conversion.compose_region_start) - 1;
5760 request->conversion_end
5761 = marker_position (f->conversion.compose_region_end) - 1;
5762 }
5763 }
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777 static jobject
5778 android_get_surrounding_text_internal (JNIEnv *env, jshort window,
5779 jint before_length,
5780 jint after_length,
5781 ptrdiff_t *conversion_start,
5782 ptrdiff_t *conversion_end)
5783 {
5784 struct android_get_surrounding_text_context context;
5785 jstring string;
5786 jobject object;
5787
5788 static jclass class;
5789 static jmethodID constructor;
5790
5791
5792
5793 if (!class)
5794 {
5795 class
5796 = (*env)->FindClass (env, ("android/view/inputmethod"
5797 "/SurroundingText"));
5798
5799 #if __ANDROID_API__ < 31
5800
5801
5802
5803 if (!class)
5804 {
5805 (*env)->ExceptionClear (env);
5806 return NULL;
5807 }
5808 #else
5809 assert (class);
5810 #endif
5811
5812 class = (*env)->NewGlobalRef (env, class);
5813 if (!class)
5814
5815
5816 return (class = NULL);
5817
5818
5819 constructor = (*env)->GetMethodID (env, class, "<init>",
5820 "(Ljava/lang/CharSequence;III)V");
5821 assert (constructor);
5822 }
5823
5824 context.before_length = before_length;
5825 context.after_length = after_length;
5826 context.window = window;
5827 context.text = NULL;
5828
5829 android_sync_edit ();
5830 if (android_run_in_emacs_thread (android_get_surrounding_text,
5831 &context))
5832 return NULL;
5833
5834 if (!context.text)
5835 return NULL;
5836
5837
5838 string = android_text_to_string (env, context.text, context.length,
5839 context.bytes);
5840 free (context.text);
5841
5842 if (!string)
5843 return NULL;
5844
5845
5846 object = (*env)->NewObject (env, class, constructor, string,
5847 (jint) min (context.start,
5848 TYPE_MAXIMUM (jint)),
5849 (jint) min (context.end,
5850 TYPE_MAXIMUM (jint)),
5851
5852
5853 (jint) min (context.offset - 1,
5854 TYPE_MAXIMUM (jint)));
5855 if (!object)
5856 return NULL;
5857
5858
5859
5860 if (conversion_start)
5861 {
5862 *conversion_start = context.conversion_start;
5863 *conversion_end = context.conversion_start;
5864 }
5865
5866 return object;
5867 }
5868
5869 JNIEXPORT jobject JNICALL
5870 NATIVE_NAME (getSurroundingText) (JNIEnv *env, jobject object,
5871 jshort window, jint before_length,
5872 jint after_length, jint flags)
5873 {
5874 JNI_STACK_ALIGNMENT_PROLOGUE;
5875
5876 return android_get_surrounding_text_internal (env, window, before_length,
5877 after_length, NULL, NULL);
5878 }
5879
5880 JNIEXPORT jobject JNICALL
5881 NATIVE_NAME (takeSnapshot) (JNIEnv *env, jobject object, jshort window)
5882 {
5883 JNI_STACK_ALIGNMENT_PROLOGUE;
5884
5885 jobject text;
5886 ptrdiff_t start, end;
5887
5888 static jclass class;
5889 static jmethodID constructor;
5890
5891
5892 text = android_get_surrounding_text_internal (env, window, 600, 600,
5893 &start, &end);
5894
5895
5896
5897 if (!text)
5898 return NULL;
5899
5900
5901
5902 if (!class)
5903 {
5904 class
5905 = (*env)->FindClass (env, ("android/view/inputmethod"
5906 "/TextSnapshot"));
5907 #if __ANDROID_API__ < 33
5908
5909
5910
5911 if (!class)
5912 {
5913 (*env)->ExceptionClear (env);
5914 return NULL;
5915 }
5916 #else
5917 assert (class);
5918 #endif
5919
5920 class = (*env)->NewGlobalRef (env, class);
5921 if (!class)
5922
5923
5924 return (class = NULL);
5925
5926 constructor = (*env)->GetMethodID (env, class, "<init>",
5927 "(Landroid/view/inputmethod"
5928 "/SurroundingText;III)V");
5929 assert (constructor);
5930 }
5931
5932
5933 eassert (start <= end);
5934 object = (*env)->NewObject (env, class, constructor, text,
5935 (jint) min (start, TYPE_MAXIMUM (jint)),
5936 (jint) min (end, TYPE_MAXIMUM (jint)),
5937 (jint) 0);
5938 return object;
5939 }
5940
5941 #ifdef __clang__
5942 #pragma clang diagnostic pop
5943 #else
5944 #pragma GCC diagnostic pop
5945 #endif
5946
5947
5948
5949
5950
5951
5952
5953 static void
5954 android_update_selection (struct frame *f, struct window *w)
5955 {
5956 ptrdiff_t start, end, point, mark, start_offset, end_offset;
5957 ptrdiff_t length, bytes;
5958 struct buffer *b;
5959 int hint, token;
5960 char *text;
5961 jobject extracted;
5962 jstring string;
5963 bool mark_active;
5964
5965 if (MARKERP (f->conversion.compose_region_start))
5966 {
5967 eassert (MARKERP (f->conversion.compose_region_end));
5968
5969
5970 start = marker_position (f->conversion.compose_region_start) - 1;
5971 end = marker_position (f->conversion.compose_region_end) - 1;
5972 }
5973 else
5974 start = -1, end = -1;
5975
5976
5977
5978 start = min (start, TYPE_MAXIMUM (jint));
5979 end = min (end, TYPE_MAXIMUM (jint));
5980
5981 if (!w)
5982 w = XWINDOW (f->selected_window);
5983
5984
5985
5986 b = XBUFFER (w->contents);
5987 point = min (w->ephemeral_last_point,
5988 TYPE_MAXIMUM (jint));
5989 mark = ((!NILP (BVAR (b, mark_active))
5990 && w->last_mark != -1)
5991 ? min (w->last_mark, TYPE_MAXIMUM (jint))
5992 : point);
5993
5994
5995
5996
5997
5998
5999 android_update_ic (FRAME_ANDROID_WINDOW (f), min (point, mark) - 1,
6000 max (point, mark) - 1, start, end);
6001
6002
6003
6004
6005
6006 if (FRAME_ANDROID_OUTPUT (f)->extracted_text_flags & 1)
6007 {
6008 hint = FRAME_ANDROID_OUTPUT (f)->extracted_text_hint;
6009 token = FRAME_ANDROID_OUTPUT (f)->extracted_text_token;
6010 text = get_extracted_text (f, min (hint, 600), &start,
6011 &start_offset, &end_offset,
6012 &length, &bytes, &mark_active);
6013
6014 if (text)
6015 {
6016
6017 string = android_text_to_string (android_java_env,
6018 text, length, bytes);
6019 xfree (text);
6020 android_exception_check ();
6021
6022
6023 extracted = android_build_extracted_text (string, start,
6024 start_offset,
6025 end_offset,
6026 mark_active);
6027 android_exception_check_1 (string);
6028 ANDROID_DELETE_LOCAL_REF (string);
6029
6030 if (extracted)
6031 {
6032
6033
6034 android_update_extracted_text (FRAME_ANDROID_WINDOW (f),
6035 extracted, token);
6036 ANDROID_DELETE_LOCAL_REF (extracted);
6037 }
6038 }
6039 }
6040 }
6041
6042
6043
6044
6045 static bool
6046 android_event_is_for_frame (union android_event *event, void *arg)
6047 {
6048 struct frame *f;
6049
6050 f = arg;
6051 return (event->type == ANDROID_INPUT_METHOD
6052 && event->ime.window == FRAME_ANDROID_WINDOW (f));
6053 }
6054
6055
6056
6057
6058 static void
6059 android_reset_conversion (struct frame *f)
6060 {
6061 enum android_ic_mode mode;
6062 struct window *w;
6063 struct buffer *buffer;
6064 Lisp_Object style;
6065 union android_event event;
6066
6067
6068
6069
6070
6071
6072
6073 w = XWINDOW (f->selected_window);
6074 buffer = XBUFFER (WINDOW_BUFFER (w));
6075
6076 style = (EQ (find_symbol_value (Qoverriding_text_conversion_style),
6077 Qlambda)
6078 ? BVAR (buffer, text_conversion_style)
6079 : find_symbol_value (Qoverriding_text_conversion_style));
6080
6081 if (NILP (style) || conversion_disabled_p ())
6082 mode = ANDROID_IC_MODE_NULL;
6083 else if (EQ (style, Qaction) || EQ (f->selected_window,
6084 f->minibuffer_window))
6085 mode = ANDROID_IC_MODE_ACTION;
6086 else
6087 mode = ANDROID_IC_MODE_TEXT;
6088
6089
6090
6091
6092
6093
6094
6095 while (android_check_if_event (&event, android_event_is_for_frame, f))
6096 {
6097 switch (event.ime.operation)
6098 {
6099 case ANDROID_IME_COMMIT_TEXT:
6100 case ANDROID_IME_FINISH_COMPOSING_TEXT:
6101 case ANDROID_IME_SET_COMPOSING_TEXT:
6102 xfree (event.ime.text);
6103 break;
6104
6105 default:
6106 break;
6107 }
6108 }
6109
6110 android_reset_ic (FRAME_ANDROID_WINDOW (f), mode);
6111
6112
6113
6114 FRAME_ANDROID_OUTPUT (f)->extracted_text_flags = 0;
6115
6116
6117 android_update_selection (f, NULL);
6118 }
6119
6120
6121
6122
6123 static void
6124 android_set_point (struct frame *f, struct window *w,
6125 struct buffer *buffer)
6126 {
6127 android_update_selection (f, w);
6128 }
6129
6130
6131
6132
6133 static void
6134 android_compose_region_changed (struct frame *f)
6135 {
6136 android_update_selection (f, XWINDOW (f->old_selected_window));
6137 }
6138
6139
6140
6141 static void
6142 android_notify_conversion (unsigned long counter)
6143 {
6144 int sval;
6145
6146 if (last_edit_counter < counter)
6147 __atomic_store_n (&last_edit_counter, counter,
6148 __ATOMIC_SEQ_CST);
6149
6150 sem_getvalue (&edit_sem, &sval);
6151
6152 if (sval <= 0)
6153 sem_post (&edit_sem);
6154 }
6155
6156
6157
6158 static struct textconv_interface text_conversion_interface =
6159 {
6160 android_reset_conversion,
6161 android_set_point,
6162 android_compose_region_changed,
6163 android_notify_conversion,
6164 };
6165
6166
6167
6168 extern frame_parm_handler android_frame_parm_handlers[];
6169
6170 #endif
6171
6172 static struct redisplay_interface android_redisplay_interface =
6173 {
6174 #ifndef ANDROID_STUBIFY
6175 android_frame_parm_handlers,
6176 gui_produce_glyphs,
6177 gui_write_glyphs,
6178 gui_insert_glyphs,
6179 gui_clear_end_of_line,
6180 android_scroll_run,
6181 android_after_update_window_line,
6182 NULL,
6183 NULL,
6184 android_flip_and_flush,
6185 gui_clear_window_mouse_face,
6186 gui_get_glyph_overhangs,
6187 gui_fix_overlapping_area,
6188 android_draw_fringe_bitmap,
6189 NULL,
6190 NULL,
6191 android_compute_glyph_string_overhangs,
6192 android_draw_glyph_string,
6193 android_define_frame_cursor,
6194 android_clear_frame_area,
6195 android_clear_under_internal_border,
6196 android_draw_window_cursor,
6197 android_draw_vertical_window_border,
6198 android_draw_window_divider,
6199 NULL,
6200 android_show_hourglass,
6201 android_hide_hourglass,
6202 android_default_font_parameter,
6203 #endif
6204 };
6205
6206
6207
6208 void
6209 frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
6210 {
6211
6212
6213 }
6214
6215 char *
6216 get_keysym_name (int keysym)
6217 {
6218 static char buffer[64];
6219
6220 #ifndef ANDROID_STUBIFY
6221 android_get_keysym_name (keysym, buffer, 64);
6222 #else
6223 emacs_abort ();
6224 #endif
6225 return buffer;
6226 }
6227
6228
6229
6230
6231
6232
6233 static struct terminal *
6234 android_create_terminal (struct android_display_info *dpyinfo)
6235 {
6236 struct terminal *terminal;
6237
6238 terminal = create_terminal (output_android,
6239 &android_redisplay_interface);
6240 terminal->display_info.android = dpyinfo;
6241 dpyinfo->terminal = terminal;
6242
6243
6244
6245 #ifndef ANDROID_STUBIFY
6246
6247 terminal->clear_frame_hook = android_clear_frame;
6248 terminal->ring_bell_hook = android_ring_bell;
6249 terminal->toggle_invisible_pointer_hook
6250 = android_toggle_invisible_pointer;
6251 terminal->update_begin_hook = android_update_begin;
6252 terminal->update_end_hook = android_update_end;
6253 terminal->read_socket_hook = android_read_socket;
6254 terminal->frame_up_to_date_hook = android_frame_up_to_date;
6255 terminal->buffer_flipping_unblocked_hook
6256 = android_buffer_flipping_unblocked_hook;
6257 terminal->defined_color_hook = android_defined_color;
6258 terminal->query_frame_background_color
6259 = android_query_frame_background_color;
6260 terminal->query_colors = android_query_colors;
6261 terminal->mouse_position_hook = android_mouse_position;
6262 terminal->get_focus_frame = android_get_focus_frame;
6263 terminal->focus_frame_hook = android_focus_frame;
6264 terminal->frame_rehighlight_hook = android_frame_rehighlight_hook;
6265 terminal->frame_raise_lower_hook = android_frame_raise_lower;
6266 terminal->frame_visible_invisible_hook
6267 = android_make_frame_visible_invisible;
6268 terminal->fullscreen_hook = android_fullscreen_hook;
6269 terminal->iconify_frame_hook = android_iconify_frame;
6270 terminal->set_window_size_hook = android_set_window_size;
6271 terminal->set_frame_offset_hook = android_set_offset;
6272 terminal->set_frame_alpha_hook = android_set_alpha;
6273 terminal->set_new_font_hook = android_new_font;
6274 terminal->set_bitmap_icon_hook = android_bitmap_icon;
6275 terminal->implicit_set_name_hook = android_implicitly_set_name;
6276 terminal->menu_show_hook = android_menu_show;
6277 terminal->popup_dialog_hook = android_popup_dialog;
6278 terminal->change_tab_bar_height_hook = android_change_tab_bar_height;
6279 terminal->change_tool_bar_height_hook = android_change_tool_bar_height;
6280 terminal->set_scroll_bar_default_width_hook
6281 = android_set_scroll_bar_default_width;
6282 terminal->set_scroll_bar_default_height_hook
6283 = android_set_scroll_bar_default_height;
6284 terminal->free_pixmap = android_free_pixmap_hook;
6285 terminal->delete_frame_hook = android_delete_frame;
6286 terminal->delete_terminal_hook = android_delete_terminal;
6287
6288 #else
6289 emacs_abort ();
6290 #endif
6291
6292 return terminal;
6293 }
6294
6295
6296
6297
6298 void
6299 android_term_init (void)
6300 {
6301 struct terminal *terminal;
6302 struct android_display_info *dpyinfo;
6303 Lisp_Object color_file, color_map;
6304
6305 dpyinfo = xzalloc (sizeof *dpyinfo);
6306 terminal = android_create_terminal (dpyinfo);
6307 terminal->kboard = allocate_kboard (Qandroid);
6308 terminal->kboard->reference_count++;
6309
6310 dpyinfo->n_planes = 24;
6311
6312
6313 eassert (!x_display_list);
6314 x_display_list = dpyinfo;
6315
6316 dpyinfo->name_list_element
6317 = Fcons (build_pure_c_string ("android"), Qnil);
6318
6319 color_file = Fexpand_file_name (build_string ("rgb.txt"),
6320 Vdata_directory);
6321 color_map = Fx_load_color_file (color_file);
6322
6323 if (NILP (color_map))
6324 fatal ("Could not read %s.\n", SDATA (color_file));
6325
6326 dpyinfo->color_map = color_map;
6327
6328 #ifndef ANDROID_STUBIFY
6329 dpyinfo->resx = android_pixel_density_x;
6330 dpyinfo->resy = android_pixel_density_y;
6331 dpyinfo->font_resolution = android_scaled_pixel_density;
6332 #endif
6333
6334
6335 dpyinfo->smallest_font_height = 1;
6336 dpyinfo->smallest_char_width = 1;
6337
6338 terminal->name = xstrdup ("android");
6339
6340
6341
6342 terminal->reference_count = 30000;
6343
6344
6345 baud_rate = 19200;
6346
6347 #ifndef ANDROID_STUBIFY
6348 sem_init (&edit_sem, false, 0);
6349 register_textconv_interface (&text_conversion_interface);
6350 #endif
6351 }
6352
6353
6354
6355
6356
6357
6358 static void
6359 android_set_build_fingerprint (void)
6360 {
6361 #ifdef ANDROID_STUBIFY
6362 Vandroid_build_fingerprint = Qnil;
6363 #else
6364 jclass class;
6365 jfieldID field;
6366 jobject string;
6367 const char *data;
6368
6369
6370
6371 class = NULL;
6372
6373
6374 string = NULL;
6375
6376 if (!android_init_gui)
6377 goto fail;
6378 else
6379 {
6380
6381
6382
6383 class = (*android_java_env)->FindClass (android_java_env,
6384 "android/os/Build");
6385 (*android_java_env)->ExceptionClear (android_java_env);
6386
6387 if (!class)
6388 goto fail;
6389
6390 field = (*android_java_env)->GetStaticFieldID (android_java_env,
6391 class,
6392 "FINGERPRINT",
6393 "Ljava/lang/String;");
6394 (*android_java_env)->ExceptionClear (android_java_env);
6395
6396 if (!field)
6397 goto fail;
6398
6399 string
6400 = (*android_java_env)->GetStaticObjectField (android_java_env,
6401 class, field);
6402 (*android_java_env)->ExceptionClear (android_java_env);
6403
6404 if (!string)
6405 goto fail;
6406
6407 data = (*android_java_env)->GetStringUTFChars (android_java_env,
6408 string, NULL);
6409 (*android_java_env)->ExceptionClear (android_java_env);
6410
6411 if (!data)
6412 goto fail;
6413
6414 Vandroid_build_fingerprint = build_string_from_utf8 (data);
6415 (*android_java_env)->ReleaseStringUTFChars (android_java_env,
6416 string, data);
6417
6418
6419
6420 ANDROID_DELETE_LOCAL_REF (string);
6421 string = NULL;
6422
6423 field = (*android_java_env)->GetStaticFieldID (android_java_env,
6424 class,
6425 "MANUFACTURER",
6426 "Ljava/lang/String;");
6427 (*android_java_env)->ExceptionClear (android_java_env);
6428
6429 if (!field)
6430 goto fail;
6431
6432 string
6433 = (*android_java_env)->GetStaticObjectField (android_java_env,
6434 class, field);
6435 (*android_java_env)->ExceptionClear (android_java_env);
6436
6437 if (!string)
6438 goto fail;
6439
6440 data = (*android_java_env)->GetStringUTFChars (android_java_env,
6441 string, NULL);
6442 (*android_java_env)->ExceptionClear (android_java_env);
6443
6444 if (!data)
6445 goto fail;
6446
6447 Vandroid_build_manufacturer = build_string_from_utf8 (data);
6448 (*android_java_env)->ReleaseStringUTFChars (android_java_env,
6449 string, data);
6450 }
6451
6452 if (string)
6453 ANDROID_DELETE_LOCAL_REF (string);
6454
6455 ANDROID_DELETE_LOCAL_REF (class);
6456
6457 return;
6458
6459 fail:
6460 if (class)
6461 ANDROID_DELETE_LOCAL_REF (class);
6462
6463 Vandroid_build_fingerprint = Qnil;
6464 Vandroid_build_manufacturer = Qnil;
6465 #endif
6466 }
6467
6468 void
6469 syms_of_androidterm (void)
6470 {
6471 Fprovide (Qandroid, Qnil);
6472
6473 DEFVAR_LISP ("android-wait-for-event-timeout",
6474 Vandroid_wait_for_event_timeout,
6475 doc:
6476
6477
6478
6479
6480
6481
6482 );
6483 Vandroid_wait_for_event_timeout = make_float (0.1);
6484
6485 DEFVAR_BOOL ("x-use-underline-position-properties",
6486 x_use_underline_position_properties,
6487 doc: );
6488 x_use_underline_position_properties = true;
6489 DEFSYM (Qx_use_underline_position_properties,
6490 "x-use-underline-position-properties");
6491
6492 DEFVAR_BOOL ("x-underline-at-descent-line",
6493 x_underline_at_descent_line,
6494 doc: );
6495 x_underline_at_descent_line = false;
6496
6497 DEFVAR_LISP ("android-build-fingerprint", Vandroid_build_fingerprint,
6498 doc:
6499
6500 );
6501 Vandroid_build_fingerprint = Qnil;
6502
6503 DEFVAR_LISP ("android-build-manufacturer", Vandroid_build_manufacturer,
6504 doc: );
6505 Vandroid_build_manufacturer = Qnil;
6506
6507
6508 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
6509 doc: );
6510 Vx_toolkit_scroll_bars = Qnil;
6511
6512
6513 pdumper_do_now_and_after_load (android_set_build_fingerprint);
6514
6515 DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
6516 }
6517
6518 void
6519 mark_androidterm (void)
6520 {
6521 if (x_display_list)
6522 mark_object (x_display_list->color_map);
6523 }