aboutsummaryrefslogtreecommitdiffstats
path: root/src/androidterm.c
diff options
context:
space:
mode:
authorPo Lu2023-01-02 21:38:19 +0800
committerPo Lu2023-01-02 21:38:19 +0800
commita32963e11f9f8e5d22b0d754d34a867f3b178ed2 (patch)
tree898f12248beb2feb63ed4295f9de40c89053ae19 /src/androidterm.c
parentfd074f3133a348dd1d3b7ee569f0fc046223efb9 (diff)
downloademacs-a32963e11f9f8e5d22b0d754d34a867f3b178ed2.tar.gz
emacs-a32963e11f9f8e5d22b0d754d34a867f3b178ed2.zip
Update Android port
* Makefile.in (java): Depend on info. (MAKEFILE_NAME): (config.status): Remove unneeded changes. * configure.ac (BUILD_DETAILS, ANDROID_STUBIFY): Don't require a C++ compiler on Android. * java/AndroidManifest.xml: <EmacsActivity>: Set launchMode appropriately. <EmacsMultitaskActivity>: New activity. * java/Makefile.in (CROSS_BINS): Add EmacsClient. * java/org/gnu/emacs/EmacsActivity.java (EmacsActivity) (onCreate): Use the window attachment manager. * java/org/gnu/emacs/EmacsCopyArea.java (EmacsCopyArea) (paintTo): Implement clip masks correctly. * java/org/gnu/emacs/EmacsDrawRectangle.java (getRect, paintTo): Fix damage tracking rectangles. * java/org/gnu/emacs/EmacsFontDriver.java (FontSpec, toString): New function. (FontMetrics, EmacsFontDriver): Fix signature of textExtents. * java/org/gnu/emacs/EmacsMultitaskActivity.java (EmacsMultitaskActivity): New file. * java/org/gnu/emacs/EmacsNative.java (EmacsNative): New functions sendFocusIn, sendFocusOut, sendWindowAction. * java/org/gnu/emacs/EmacsPaintQueue.java (run): Fix clipping handling. * java/org/gnu/emacs/EmacsPixmap.java (EmacsPixmap): Add constructor for mutable pixmaps. * java/org/gnu/emacs/EmacsSdk23FontDriver.java (EmacsSdk23FontDriver): New file. * java/org/gnu/emacs/EmacsSdk7FontDriver.java (EmacsSdk7FontDriver, Sdk7Typeface, Sdk7FontEntity, Sdk7FontObject) (checkMatch, hasChar, encodeChar): Implement text display and fix font metrics semantics. * java/org/gnu/emacs/EmacsService.java (EmacsService): Remove availableChildren. (getLibraryDirectory, onCreate): Pass pixel density to Emacs. (clearArea): Fix arguments. Switch to using the window attachment manager. * java/org/gnu/emacs/EmacsSurfaceView.java (surfaceChanged) (surfaceCreated): Flip buffers on surface attachment. * java/org/gnu/emacs/EmacsView.java (EmacsView, swapBuffers): New argument FORCE. Always swap if it is true. (onKeyMultiple, onFocusChanged): New functions. * java/org/gnu/emacs/EmacsWindow.java (EmacsWindow, destroyHandle) (run): Switch to using the window attachment manager. * java/org/gnu/emacs/EmacsWindowAttachmentManager.java (EmacsWindowAttachmentManager): New file. * lisp/cus-edit.el (custom-button, custom-button-mouse) (custom-button-pressed): * lisp/faces.el (tool-bar): Define faces correctly on Android. * src/android.c (struct android_emacs_pixmap): Add mutable constructor. (struct android_emacs_drawable): New structure. (android_write_event): Check if event queue hasn't yet been initialized. (android_select): Set errno to EINTR if pselect fails. (android_close): Remove unused debugging code. (android_get_home_directory): New function. (Java_org_gnu_emacs_EmacsNative_setEmacsParams): Set pixel density and compute game path. (android_init_emacs_drawable): New function. (Java_org_gnu_emacs_EmacsNative_sendKeyPress): New argument `unicode_char'. Pass it in events. (Java_org_gnu_emacs_EmacsNative_sendKeyRelease): Likewise. (Java_org_gnu_emacs_EmacsNative_sendFocusIn) (Java_org_gnu_emacs_EmacsNative_sendFocusOut) (Java_org_gnu_emacs_EmacsNative_sendWindowAction): New functions. (android_resolve_handle): Export function. (android_change_gc): Clear clip rects under the right circumstances. Set right clip mask field. (android_create_pixmap_from_bitmap_data): Use correct alpha channels. (android_create_pixmap): Create mutable pixmap and avoid redundant color array allocation. (android_create_bitmap_from_data, android_create_image) (android_destroy_image, android_put_pixel, android_get_pixel) (android_get_image, android_put_image, faccessat): New functions. * src/android.h: Update prototypes. * src/androidfns.c (android_default_font_parameter): Prefer monospace to Droid Sans Mono. * src/androidfont.c (struct android_emacs_font_driver): New method `draw'. (struct android_emacs_font_spec): New field `dpi'. (struct androidfont_info): Add font metrics cache. (android_init_font_driver, android_init_font_spec): Adjust accordingly. (androidfont_from_lisp, androidfont_from_java): Handle new fields. (androidfont_draw): Implement function. (androidfont_open_font): Set pixel size correctly. (androidfont_close_font): Free metrics cache. (androidfont_cache_text_extents) (androidfont_check_cached_extents): New functions. (androidfont_text_extents): Cache glyph metrics somewhere for future use. (androidfont_list_family): Implement function. * src/androidgui.h (enum android_event_type): New focus and window action events. (enum android_modifier_mask): New masks. (struct android_key_event): New field `unicode_char'. (ANDROID_IS_MODIFIER_KEY): Newmacro. (struct android_focus_event, struct android_window_action_event): New structs. (union android_event): Add new fields. (enum android_image_format, struct android_image): New enums and structs. * src/androidterm.c (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): New functions. (handle_one_android_event): Implement focus and key event handling. (android_frame_rehighlight): New function. (android_frame_raise_lower): Implement accordingly. (android_make_frame_invisible): Clear highlight_frame if required. (android_free_frame_resources): Clear x_focus_event_frame if required. (android_draw_fringe_bitmap, android_draw_image_foreground) (android_draw_image_foreground_1) (android_draw_image_glyph_string): Remove unnecessary code. (android_create_terminal, android_term_init): Set the baud rate to something sensible. * src/androidterm.h (struct android_bitmap_record): Make structure the same as on X. (struct android_display_info): New focus tracking fields. (struct android_output): Likewise. * src/dispextern.h (struct image): Add ximg and mask_img on Android. * src/emacs.c (android_emacs_init): Fix argc sorting iteration. * src/fileio.c (user_homedir): (get_homedir): Implement correctly on Android. * src/font.h (PT_PER_INCH): Define correctly on Android. * src/fringe.c (X, swap_nibble, init_fringe_bitmap): Swap fringe bitmaps correctly on Android. * src/image.c (GET_PIXEL, image_create_bitmap_from_data) (image_create_bitmap_from_file, free_bitmap_record) (image_unget_x_image_or_dc, struct image_type) (prepare_image_for_display, image_clear_image_1) (image_size_in_bytes, x_check_image_size) (x_create_x_image_and_pixmap, x_destroy_x_image) (image_check_image_size, image_create_x_image_and_pixmap_1) (image_destroy_x_image, gui_put_x_image, image_put_x_image) (image_get_x_image, image_unget_x_image) (Create_Pixmap_From_Bitmap_Data, image_pixmap_draw_cross) (MaskForeground, image_types, syms_of_image): Implement all of the above on Android in terms of an API very similar to X. * src/keyboard.c (FUNCTION_KEY_OFFSET, lispy_function_keys): Define on Android to something sensible. * src/lread.c (build_load_history): Fix problem.
Diffstat (limited to 'src/androidterm.c')
-rw-r--r--src/androidterm.c544
1 files changed, 319 insertions, 225 deletions
diff --git a/src/androidterm.c b/src/androidterm.c
index bb3c2a29737..0279da4f58d 100644
--- a/src/androidterm.c
+++ b/src/androidterm.c
@@ -39,6 +39,8 @@ struct android_display_info *x_display_list;
39 39
40#ifndef ANDROID_STUBIFY 40#ifndef ANDROID_STUBIFY
41 41
42#include <android/log.h>
43
42enum 44enum
43 { 45 {
44 ANDROID_EVENT_NORMAL, 46 ANDROID_EVENT_NORMAL,
@@ -141,6 +143,124 @@ android_flush_dirty_back_buffer_on (struct frame *f)
141 show_back_buffer (f); 143 show_back_buffer (f);
142} 144}
143 145
146/* Convert between the modifier bits Android uses and the modifier
147 bits Emacs uses. */
148
149static int
150android_android_to_emacs_modifiers (struct android_display_info *dpyinfo,
151 int state)
152{
153 return ((state & ANDROID_CONTROL_MASK) ? ctrl_modifier : 0
154 | (state & ANDROID_SHIFT_MASK) ? shift_modifier : 0
155 | (state & ANDROID_ALT_MASK) ? meta_modifier : 0);
156}
157
158static int
159android_emacs_to_android_modifiers (struct android_display_info *dpyinfo,
160 intmax_t state)
161{
162 return ((state & ctrl_modifier) ? ANDROID_CONTROL_MASK : 0
163 | (state & shift_modifier) ? ANDROID_SHIFT_MASK : 0
164 | (state & meta_modifier) ? ANDROID_ALT_MASK : 0);
165}
166
167static void android_frame_rehighlight (struct android_display_info *);
168
169static void
170android_lower_frame (struct frame *f)
171{
172 /* TODO. */
173}
174
175static void
176android_raise_frame (struct frame *f)
177{
178 /* TODO. */
179}
180
181static void
182android_new_focus_frame (struct android_display_info *dpyinfo,
183 struct frame *frame)
184{
185 struct frame *old_focus;
186
187 old_focus = dpyinfo->focus_frame;
188
189 if (frame != dpyinfo->focus_frame)
190 {
191 /* Set this before calling other routines, so that they see
192 the correct value of x_focus_frame. */
193 dpyinfo->focus_frame = frame;
194
195 if (old_focus && old_focus->auto_lower)
196 android_lower_frame (old_focus);
197
198 if (dpyinfo->focus_frame && dpyinfo->focus_frame->auto_raise)
199 dpyinfo->pending_autoraise_frame = dpyinfo->focus_frame;
200 else
201 dpyinfo->pending_autoraise_frame = NULL;
202 }
203
204 android_frame_rehighlight (dpyinfo);
205}
206
207static void
208android_focus_changed (int type, int state,
209 struct android_display_info *dpyinfo,
210 struct frame *frame, struct input_event *bufp)
211{
212 if (type == ANDROID_FOCUS_IN)
213 {
214 if (dpyinfo->x_focus_event_frame != frame)
215 {
216 android_new_focus_frame (dpyinfo, frame);
217 dpyinfo->x_focus_event_frame = frame;
218 bufp->kind = FOCUS_IN_EVENT;
219 XSETFRAME (bufp->frame_or_window, frame);
220 }
221
222 frame->output_data.android->focus_state |= state;
223 }
224 else if (type == ANDROID_FOCUS_OUT)
225 {
226 frame->output_data.android->focus_state &= ~state;
227
228 if (dpyinfo->x_focus_event_frame == frame)
229 {
230 dpyinfo->x_focus_event_frame = 0;
231 android_new_focus_frame (dpyinfo, 0);
232
233 bufp->kind = FOCUS_OUT_EVENT;
234 XSETFRAME (bufp->frame_or_window, frame);
235 }
236
237 if (frame->pointer_invisible)
238 android_toggle_invisible_pointer (frame, false);
239 }
240}
241
242static void
243android_detect_focus_change (struct android_display_info *dpyinfo,
244 struct frame *frame,
245 union android_event *event,
246 struct input_event *bufp)
247{
248 if (!frame)
249 return;
250
251 switch (event->type)
252 {
253 case ANDROID_FOCUS_IN:
254 case ANDROID_FOCUS_OUT:
255 android_focus_changed (event->type, FOCUS_EXPLICIT,
256 dpyinfo, frame, bufp);
257 break;
258
259 default:
260 break;
261 }
262}
263
144static int 264static int
145handle_one_android_event (struct android_display_info *dpyinfo, 265handle_one_android_event (struct android_display_info *dpyinfo,
146 union android_event *event, int *finish, 266 union android_event *event, int *finish,
@@ -149,11 +269,20 @@ handle_one_android_event (struct android_display_info *dpyinfo,
149 union android_event configureEvent; 269 union android_event configureEvent;
150 struct frame *f, *any, *mouse_frame; 270 struct frame *f, *any, *mouse_frame;
151 Mouse_HLInfo *hlinfo; 271 Mouse_HLInfo *hlinfo;
272 union buffered_input_event inev;
273 int modifiers, count;
274
275 /* It is okay for this to not resemble handle_one_xevent so much.
276 Differences in event handling code are much less nasty than
277 stuble differences in the graphics code. */
152 278
279 count = 0;
153 hlinfo = &dpyinfo->mouse_highlight; 280 hlinfo = &dpyinfo->mouse_highlight;
154 *finish = ANDROID_EVENT_NORMAL; 281 *finish = ANDROID_EVENT_NORMAL;
155 any = android_window_to_frame (dpyinfo, event->xany.window); 282 any = android_window_to_frame (dpyinfo, event->xany.window);
156 283
284 EVENT_INIT (inev.ie);
285
157 switch (event->type) 286 switch (event->type)
158 { 287 {
159 case ANDROID_CONFIGURE_NOTIFY: 288 case ANDROID_CONFIGURE_NOTIFY:
@@ -192,12 +321,15 @@ handle_one_android_event (struct android_display_info *dpyinfo,
192 321
193 case ANDROID_KEY_PRESS: 322 case ANDROID_KEY_PRESS:
194 323
324 /* Set f to any. There are no ``outer windows'' on Android. */
325 f = any;
326
195 /* If mouse-highlight is an integer, input clears out 327 /* If mouse-highlight is an integer, input clears out
196 mouse highlighting. */ 328 mouse highlighting. */
197 if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight) 329 if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
198 && (any == 0 330 && (any == 0
199 || !EQ (f->tool_bar_window, hlinfo->mouse_face_window) 331 || !EQ (any->tool_bar_window, hlinfo->mouse_face_window)
200 || !EQ (f->tab_bar_window, hlinfo->mouse_face_window))) 332 || !EQ (any->tab_bar_window, hlinfo->mouse_face_window)))
201 { 333 {
202 mouse_frame = hlinfo->mouse_face_mouse_frame; 334 mouse_frame = hlinfo->mouse_face_mouse_frame;
203 335
@@ -208,13 +340,90 @@ handle_one_android_event (struct android_display_info *dpyinfo,
208 android_flush_dirty_back_buffer_on (mouse_frame); 340 android_flush_dirty_back_buffer_on (mouse_frame);
209 } 341 }
210 342
343 event->xkey.state
344 |= android_emacs_to_android_modifiers (dpyinfo,
345 extra_keyboard_modifiers);
346 modifiers = event->xkey.state;
347
348 /* Common for all keysym input events. */
349 XSETFRAME (inev.ie.frame_or_window, any);
350 inev.ie.modifiers
351 = android_android_to_emacs_modifiers (dpyinfo, modifiers);
352 inev.ie.timestamp = event->xkey.time;
353
354 /* First deal with keysyms which have defined translations to
355 characters. */
356
357 if (event->xkey.unicode_char >= 32
358 && event->xkey.unicode_char < 128)
359 {
360 inev.ie.kind = ASCII_KEYSTROKE_EVENT;
361 inev.ie.code = event->xkey.unicode_char;
362 }
363 else if (event->xkey.unicode_char < 32)
364 {
365 /* If the key is a modifier key, just return. */
366 if (ANDROID_IS_MODIFIER_KEY (event->xkey.keycode))
367 goto done_keysym;
368
369 /* Next, deal with special ``characters'' by giving the
370 keycode to keyboard.c. */
371 inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
372 inev.ie.code = event->xkey.keycode;
373 }
374 else
375 {
376 /* Finally, deal with Unicode characters. */
377 inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
378 inev.ie.code = event->xkey.unicode_char;
379 }
380
381 goto done_keysym;
382
383 done_keysym:
384 goto OTHER;
385
386 case ANDROID_FOCUS_IN:
387 case ANDROID_FOCUS_OUT:
388 android_detect_focus_change (dpyinfo, any, event, &inev.ie);
389 goto OTHER;
390
391 case ANDROID_WINDOW_ACTION:
392
393 f = any;
394
395 if (event->xaction.action == 0)
396 {
397 /* Action 0 either means to destroy a frame or to create a
398 new frame, depending on whether or not
399 event->xaction.window exists. */
400
401 if (event->xaction.window)
402 {
403 if (!f)
404 goto OTHER;
405
406 inev.ie.kind = DELETE_WINDOW_EVENT;
407 XSETFRAME (inev.ie.frame_or_window, f);
408 }
409 else
410 /* A new frame must be created. */;
411 }
412
413 goto OTHER;
414
211 default: 415 default:
212 goto OTHER; 416 goto OTHER;
213 } 417 }
214 418
215 OTHER: 419 OTHER:
420 if (inev.ie.kind != NO_EVENT)
421 {
422 kbd_buffer_store_buffered_event (&inev, hold_quit);
423 count++;
424 }
216 425
217 return 0; 426 return count;
218} 427}
219 428
220static int 429static int
@@ -378,15 +587,52 @@ android_focus_frame (struct frame *f, bool noactivate)
378} 587}
379 588
380static void 589static void
381android_frame_rehighlight (struct frame *f) 590android_frame_rehighlight (struct android_display_info *dpyinfo)
382{ 591{
383 /* TODO */ 592 struct frame *old_highlight;
593
594 old_highlight = dpyinfo->highlight_frame;
595
596 if (dpyinfo->focus_frame)
597 {
598 dpyinfo->highlight_frame
599 = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->focus_frame)))
600 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->focus_frame))
601 : dpyinfo->focus_frame);
602 if (!FRAME_LIVE_P (dpyinfo->highlight_frame))
603 {
604 fset_focus_frame (dpyinfo->focus_frame, Qnil);
605 dpyinfo->highlight_frame = dpyinfo->focus_frame;
606 }
607 }
608 else
609 dpyinfo->highlight_frame = 0;
610
611 if (dpyinfo->highlight_frame != old_highlight)
612 {
613 /* This is not yet required on Android. */
614#if 0
615 if (old_highlight)
616 android_frame_unhighlight (old_highlight);
617 if (dpyinfo->highlight_frame)
618 android_frame_highlight (dpyinfo->highlight_frame);
619#endif
620 }
621}
622
623static void
624android_frame_rehighlight_hook (struct frame *f)
625{
626 android_frame_rehighlight (FRAME_DISPLAY_INFO (f));
384} 627}
385 628
386static void 629static void
387android_frame_raise_lower (struct frame *f, bool raise_flag) 630android_frame_raise_lower (struct frame *f, bool raise_flag)
388{ 631{
389 /* TODO */ 632 if (raise_flag)
633 android_raise_frame (f);
634 else
635 android_lower_frame (f);
390} 636}
391 637
392void 638void
@@ -401,6 +647,10 @@ android_make_frame_visible (struct frame *f)
401void 647void
402android_make_frame_invisible (struct frame *f) 648android_make_frame_invisible (struct frame *f)
403{ 649{
650 /* Don't keep the highlight on an invisible frame. */
651 if (FRAME_DISPLAY_INFO (f)->highlight_frame == f)
652 FRAME_DISPLAY_INFO (f)->highlight_frame = 0;
653
404 android_unmap_window (FRAME_ANDROID_WINDOW (f)); 654 android_unmap_window (FRAME_ANDROID_WINDOW (f));
405 655
406 SET_FRAME_VISIBLE (f, false); 656 SET_FRAME_VISIBLE (f, false);
@@ -584,6 +834,8 @@ android_free_frame_resources (struct frame *f)
584 834
585 if (f == dpyinfo->focus_frame) 835 if (f == dpyinfo->focus_frame)
586 dpyinfo->focus_frame = 0; 836 dpyinfo->focus_frame = 0;
837 if (f == dpyinfo->x_focus_event_frame)
838 dpyinfo->x_focus_event_frame = 0;
587 if (f == dpyinfo->highlight_frame) 839 if (f == dpyinfo->highlight_frame)
588 dpyinfo->highlight_frame = 0; 840 dpyinfo->highlight_frame = 0;
589 if (f == hlinfo->mouse_face_mouse_frame) 841 if (f == hlinfo->mouse_face_mouse_frame)
@@ -783,7 +1035,7 @@ android_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
783 if (p->overlay_p) 1035 if (p->overlay_p)
784 { 1036 {
785 clipmask = android_create_pixmap_from_bitmap_data (bits, p->wd, p->h, 1037 clipmask = android_create_pixmap_from_bitmap_data (bits, p->wd, p->h,
786 1, 0, 0); 1038 1, 0, 1);
787 1039
788 gcv.clip_mask = clipmask; 1040 gcv.clip_mask = clipmask;
789 gcv.clip_x_origin = p->x; 1041 gcv.clip_x_origin = p->x;
@@ -1606,158 +1858,47 @@ android_draw_image_foreground (struct glyph_string *s)
1606 1858
1607 if (s->img->pixmap) 1859 if (s->img->pixmap)
1608 { 1860 {
1609 if (s->img->mask) 1861 unsigned long mask = (ANDROID_GC_CLIP_MASK
1610 { 1862 | ANDROID_GC_CLIP_X_ORIGIN
1611 unsigned long mask = (ANDROID_GC_CLIP_MASK 1863 | ANDROID_GC_CLIP_Y_ORIGIN
1612 | ANDROID_GC_CLIP_X_ORIGIN 1864 | ANDROID_GC_FUNCTION);
1613 | ANDROID_GC_CLIP_Y_ORIGIN 1865 struct android_gc_values xgcv;
1614 | ANDROID_GC_FUNCTION); 1866 struct android_rectangle clip_rect, image_rect, r;
1615 struct android_gc_values xgcv; 1867
1616 struct android_rectangle clip_rect, image_rect, r; 1868 xgcv.clip_mask = s->img->mask;
1617 1869 xgcv.clip_x_origin = x - s->slice.x;
1618 xgcv.clip_mask = s->img->mask; 1870 xgcv.clip_y_origin = y - s->slice.y;
1619 xgcv.clip_x_origin = x - s->slice.x; 1871 xgcv.function = ANDROID_GC_COPY;
1620 xgcv.clip_y_origin = y - s->slice.y; 1872 android_change_gc (s->gc, mask, &xgcv);
1621 xgcv.function = ANDROID_GC_COPY; 1873
1622 android_change_gc (s->gc, mask, &xgcv); 1874 get_glyph_string_clip_rect (s, &clip_rect);
1623 1875 image_rect.x = x;
1624 get_glyph_string_clip_rect (s, &clip_rect); 1876 image_rect.y = y;
1625 image_rect.x = x; 1877 image_rect.width = s->slice.width;
1626 image_rect.y = y; 1878 image_rect.height = s->slice.height;
1627 image_rect.width = s->slice.width; 1879
1628 image_rect.height = s->slice.height; 1880 if (gui_intersect_rectangles (&clip_rect, &image_rect, &r))
1629 1881 android_copy_area (s->img->pixmap,
1630 if (gui_intersect_rectangles (&clip_rect, &image_rect, &r)) 1882 FRAME_ANDROID_WINDOW (s->f),
1631 android_copy_area (s->img->pixmap, FRAME_ANDROID_WINDOW (s->f), 1883 s->gc, s->slice.x + r.x - x,
1632 s->gc, s->slice.x + r.x - x, 1884 s->slice.y + r.y - y,
1633 s->slice.y + r.y - y, 1885 r.width, r.height, r.x, r.y);
1634 r.x, r.y, r.width, r.height); 1886
1635 } 1887 /* When the image has a mask, we can expect that at least part
1636 else 1888 of a mouse highlight or a block cursor will be visible. If
1889 the image doesn't have a mask, make a block cursor visible by
1890 drawing a rectangle around the image. I believe it's looking
1891 better if we do nothing here for mouse-face. */
1892 if (s->hl == DRAW_CURSOR && !s->img->mask)
1637 { 1893 {
1638 unsigned long mask = (ANDROID_GC_CLIP_MASK 1894 int relief = eabs (s->img->relief);
1639 | ANDROID_GC_CLIP_X_ORIGIN 1895 android_draw_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc,
1640 | ANDROID_GC_CLIP_Y_ORIGIN 1896 x - relief, y - relief,
1641 | ANDROID_GC_FUNCTION); 1897 s->slice.width + relief*2 - 1,
1642 struct android_gc_values xgcv; 1898 s->slice.height + relief*2 - 1);
1643 struct android_rectangle clip_rect, image_rect, r;
1644
1645 xgcv.clip_mask = s->img->mask;
1646 xgcv.clip_x_origin = x - s->slice.x;
1647 xgcv.clip_y_origin = y - s->slice.y;
1648 xgcv.function = ANDROID_GC_COPY;
1649 android_change_gc (s->gc, mask, &xgcv);
1650
1651 get_glyph_string_clip_rect (s, &clip_rect);
1652 image_rect.x = x;
1653 image_rect.y = y;
1654 image_rect.width = s->slice.width;
1655 image_rect.height = s->slice.height;
1656
1657 if (gui_intersect_rectangles (&clip_rect, &image_rect, &r))
1658 android_copy_area (s->img->pixmap,
1659 FRAME_ANDROID_WINDOW (s->f),
1660 s->gc, s->slice.x + r.x - x,
1661 s->slice.y + r.y - y,
1662 r.x, r.y, r.width, r.height);
1663
1664 /* When the image has a mask, we can expect that at
1665 least part of a mouse highlight or a block cursor will
1666 be visible. If the image doesn't have a mask, make
1667 a block cursor visible by drawing a rectangle around
1668 the image. I believe it's looking better if we do
1669 nothing here for mouse-face. */
1670 if (s->hl == DRAW_CURSOR)
1671 {
1672 int relief = eabs (s->img->relief);
1673 android_draw_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc,
1674 x - relief, y - relief,
1675 s->slice.width + relief*2 - 1,
1676 s->slice.height + relief*2 - 1);
1677 }
1678 } 1899 }
1679 }
1680 else
1681 /* Draw a rectangle if image could not be loaded. */
1682 android_draw_rectangle (FRAME_ANDROID_WINDOW (s->f), s->gc, x, y,
1683 s->slice.width - 1, s->slice.height - 1);
1684}
1685
1686/* Draw the foreground of image glyph string S to PIXMAP. */
1687
1688static void
1689android_draw_image_foreground_1 (struct glyph_string *s,
1690 android_pixmap pixmap)
1691{
1692 int x = 0;
1693 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
1694
1695 /* If first glyph of S has a left box line, start drawing it to the
1696 right of that line. */
1697 if (s->face->box != FACE_NO_BOX
1698 && s->first_glyph->left_box_line_p
1699 && s->slice.x == 0)
1700 x += max (s->face->box_vertical_line_width, 0);
1701
1702 /* If there is a margin around the image, adjust x- and y-position
1703 by that margin. */
1704 if (s->slice.x == 0)
1705 x += s->img->hmargin;
1706 if (s->slice.y == 0)
1707 y += s->img->vmargin;
1708 1900
1709 if (s->img->pixmap) 1901 android_set_clip_mask (s->gc, ANDROID_NONE);
1710 {
1711 if (s->img->mask)
1712 {
1713 unsigned long mask = (ANDROID_GC_CLIP_MASK
1714 | ANDROID_GC_CLIP_X_ORIGIN
1715 | ANDROID_GC_CLIP_Y_ORIGIN
1716 | ANDROID_GC_FUNCTION);
1717 struct android_gc_values xgcv;
1718 struct android_rectangle clip_rect, image_rect, r;
1719
1720 xgcv.clip_mask = s->img->mask;
1721 xgcv.clip_x_origin = x - s->slice.x;
1722 xgcv.clip_y_origin = y - s->slice.y;
1723 xgcv.function = ANDROID_GC_COPY;
1724 android_change_gc (s->gc, mask, &xgcv);
1725
1726 get_glyph_string_clip_rect (s, &clip_rect);
1727 image_rect.x = x;
1728 image_rect.y = y;
1729 image_rect.width = s->slice.width;
1730 image_rect.height = s->slice.height;
1731
1732 if (gui_intersect_rectangles (&clip_rect, &image_rect, &r))
1733 android_copy_area (s->img->pixmap, pixmap, s->gc,
1734 s->slice.x + r.x - x,
1735 s->slice.y + r.y - y,
1736 r.x, r.y, r.width, r.height);
1737
1738 android_set_clip_mask (s->gc, ANDROID_NONE);
1739 }
1740 else
1741 {
1742 android_copy_area (s->img->pixmap, pixmap, s->gc,
1743 s->slice.x, s->slice.y,
1744 s->slice.width, s->slice.height, x, y);
1745
1746 /* When the image has a mask, we can expect that at
1747 least part of a mouse highlight or a block cursor will
1748 be visible. If the image doesn't have a mask, make
1749 a block cursor visible by drawing a rectangle around
1750 the image. I believe it's looking better if we do
1751 nothing here for mouse-face. */
1752 if (s->hl == DRAW_CURSOR)
1753 {
1754 int r = eabs (s->img->relief);
1755 android_draw_rectangle (FRAME_ANDROID_WINDOW (s->f),
1756 s->gc, x - r, y - r,
1757 s->slice.width + r*2 - 1,
1758 s->slice.height + r*2 - 1);
1759 }
1760 }
1761 } 1902 }
1762 else 1903 else
1763 /* Draw a rectangle if image could not be loaded. */ 1904 /* Draw a rectangle if image could not be loaded. */
@@ -1771,7 +1912,6 @@ android_draw_image_glyph_string (struct glyph_string *s)
1771 int box_line_hwidth = max (s->face->box_vertical_line_width, 0); 1912 int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
1772 int box_line_vwidth = max (s->face->box_horizontal_line_width, 0); 1913 int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
1773 int height; 1914 int height;
1774 android_pixmap pixmap = ANDROID_NONE;
1775 1915
1776 height = s->height; 1916 height = s->height;
1777 if (s->slice.y == 0) 1917 if (s->slice.y == 0)
@@ -1793,79 +1933,27 @@ android_draw_image_glyph_string (struct glyph_string *s)
1793 if (s->stippled_p) 1933 if (s->stippled_p)
1794 s->row->stipple_p = true; 1934 s->row->stipple_p = true;
1795 1935
1796 if (s->img->mask) 1936 int x = s->x;
1797 { 1937 int y = s->y;
1798 /* Create a pixmap as large as the glyph string. Fill it 1938 int width = s->background_width;
1799 with the background color. Copy the image to it, using
1800 its mask. Copy the temporary pixmap to the display. */
1801 int depth = FRAME_DISPLAY_INFO (s->f)->n_planes;
1802
1803 /* Create a pixmap as large as the glyph string. */
1804 pixmap = android_create_pixmap (s->background_width,
1805 s->height, depth);
1806
1807 /* Don't clip in the following because we're working on the
1808 pixmap. */
1809 android_set_clip_mask (s->gc, ANDROID_NONE);
1810
1811 /* Fill the pixmap with the background color/stipple. */
1812 if (s->stippled_p)
1813 {
1814 /* Fill background with a stipple pattern. */
1815 android_set_fill_style (s->gc, ANDROID_FILL_OPAQUE_STIPPLED);
1816 android_set_ts_origin (s->gc, - s->x, - s->y);
1817 android_fill_rectangle (pixmap, s->gc,
1818 0, 0, s->background_width, s->height);
1819 android_set_fill_style (s->gc, ANDROID_FILL_OPAQUE_STIPPLED);
1820 android_set_ts_origin (s->gc, 0, 0);
1821 }
1822 else
1823 {
1824 struct android_gc_values xgcv;
1825 1939
1826 android_get_gc_values (s->gc, (ANDROID_GC_FOREGROUND 1940 if (s->first_glyph->left_box_line_p
1827 | ANDROID_GC_BACKGROUND), 1941 && s->slice.x == 0)
1828 &xgcv);
1829 android_set_foreground (s->gc, xgcv.background);
1830 android_fill_rectangle (pixmap, s->gc,
1831 0, 0, s->background_width, s->height);
1832 android_set_background (s->gc, xgcv.foreground);
1833 }
1834 }
1835 else
1836 { 1942 {
1837 int x = s->x; 1943 x += box_line_hwidth;
1838 int y = s->y; 1944 width -= box_line_hwidth;
1839 int width = s->background_width; 1945 }
1840 1946
1841 if (s->first_glyph->left_box_line_p 1947 if (s->slice.y == 0)
1842 && s->slice.x == 0) 1948 y += box_line_vwidth;
1843 {
1844 x += box_line_hwidth;
1845 width -= box_line_hwidth;
1846 }
1847 1949
1848 if (s->slice.y == 0) 1950 android_draw_glyph_string_bg_rect (s, x, y, width, height);
1849 y += box_line_vwidth;
1850
1851 android_draw_glyph_string_bg_rect (s, x, y, width, height);
1852 }
1853 1951
1854 s->background_filled_p = true; 1952 s->background_filled_p = true;
1855 } 1953 }
1856 1954
1857 /* Draw the foreground. */ 1955 /* Draw the foreground. */
1858 if (pixmap != ANDROID_NONE) 1956 android_draw_image_foreground (s);
1859 {
1860 android_draw_image_foreground_1 (s, pixmap);
1861 android_set_glyph_string_clipping (s);
1862 android_copy_area (pixmap, FRAME_ANDROID_WINDOW (s->f), s->gc,
1863 0, 0, s->background_width, s->height, s->x,
1864 s->y);
1865 android_free_pixmap (pixmap);
1866 }
1867 else
1868 android_draw_image_foreground (s);
1869 1957
1870 /* If we must draw a relief around the image, do it. */ 1958 /* If we must draw a relief around the image, do it. */
1871 if (s->img->relief 1959 if (s->img->relief
@@ -3047,7 +3135,7 @@ android_create_terminal (struct android_display_info *dpyinfo)
3047 terminal->mouse_position_hook = android_mouse_position; 3135 terminal->mouse_position_hook = android_mouse_position;
3048 terminal->get_focus_frame = android_get_focus_frame; 3136 terminal->get_focus_frame = android_get_focus_frame;
3049 terminal->focus_frame_hook = android_focus_frame; 3137 terminal->focus_frame_hook = android_focus_frame;
3050 terminal->frame_rehighlight_hook = android_frame_rehighlight; 3138 terminal->frame_rehighlight_hook = android_frame_rehighlight_hook;
3051 terminal->frame_raise_lower_hook = android_frame_raise_lower; 3139 terminal->frame_raise_lower_hook = android_frame_raise_lower;
3052 terminal->frame_visible_invisible_hook 3140 terminal->frame_visible_invisible_hook
3053 = android_make_frame_visible_invisible; 3141 = android_make_frame_visible_invisible;
@@ -3117,9 +3205,12 @@ android_term_init (void)
3117 3205
3118 dpyinfo->color_map = color_map; 3206 dpyinfo->color_map = color_map;
3119 3207
3120 /* TODO! */ 3208#ifndef ANDROID_STUBIFY
3121 dpyinfo->resx = 96.0; 3209
3122 dpyinfo->resy = 96.0; 3210 dpyinfo->resx = android_pixel_density_x;
3211 dpyinfo->resy = android_pixel_density_y;
3212
3213#endif
3123 3214
3124 /* https://lists.gnu.org/r/emacs-devel/2015-11/msg00194.html */ 3215 /* https://lists.gnu.org/r/emacs-devel/2015-11/msg00194.html */
3125 dpyinfo->smallest_font_height = 1; 3216 dpyinfo->smallest_font_height = 1;
@@ -3130,6 +3221,9 @@ android_term_init (void)
3130 /* The display "connection" is now set up, and it must never go 3221 /* The display "connection" is now set up, and it must never go
3131 away. */ 3222 away. */
3132 terminal->reference_count = 30000; 3223 terminal->reference_count = 30000;
3224
3225 /* Set the baud rate to the same value it gets set to on X. */
3226 baud_rate = 19200;
3133} 3227}
3134 3228
3135 3229