diff options
| author | Po Lu | 2023-01-02 21:38:19 +0800 |
|---|---|---|
| committer | Po Lu | 2023-01-02 21:38:19 +0800 |
| commit | a32963e11f9f8e5d22b0d754d34a867f3b178ed2 (patch) | |
| tree | 898f12248beb2feb63ed4295f9de40c89053ae19 /src/androidterm.c | |
| parent | fd074f3133a348dd1d3b7ee569f0fc046223efb9 (diff) | |
| download | emacs-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.c | 544 |
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 | |||
| 42 | enum | 44 | enum |
| 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 | |||
| 149 | static int | ||
| 150 | android_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 | |||
| 158 | static int | ||
| 159 | android_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 | |||
| 167 | static void android_frame_rehighlight (struct android_display_info *); | ||
| 168 | |||
| 169 | static void | ||
| 170 | android_lower_frame (struct frame *f) | ||
| 171 | { | ||
| 172 | /* TODO. */ | ||
| 173 | } | ||
| 174 | |||
| 175 | static void | ||
| 176 | android_raise_frame (struct frame *f) | ||
| 177 | { | ||
| 178 | /* TODO. */ | ||
| 179 | } | ||
| 180 | |||
| 181 | static void | ||
| 182 | android_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 | |||
| 207 | static void | ||
| 208 | android_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 | |||
| 242 | static void | ||
| 243 | android_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 | |||
| 144 | static int | 264 | static int |
| 145 | handle_one_android_event (struct android_display_info *dpyinfo, | 265 | handle_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 | ||
| 220 | static int | 429 | static int |
| @@ -378,15 +587,52 @@ android_focus_frame (struct frame *f, bool noactivate) | |||
| 378 | } | 587 | } |
| 379 | 588 | ||
| 380 | static void | 589 | static void |
| 381 | android_frame_rehighlight (struct frame *f) | 590 | android_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 | |||
| 623 | static void | ||
| 624 | android_frame_rehighlight_hook (struct frame *f) | ||
| 625 | { | ||
| 626 | android_frame_rehighlight (FRAME_DISPLAY_INFO (f)); | ||
| 384 | } | 627 | } |
| 385 | 628 | ||
| 386 | static void | 629 | static void |
| 387 | android_frame_raise_lower (struct frame *f, bool raise_flag) | 630 | android_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 | ||
| 392 | void | 638 | void |
| @@ -401,6 +647,10 @@ android_make_frame_visible (struct frame *f) | |||
| 401 | void | 647 | void |
| 402 | android_make_frame_invisible (struct frame *f) | 648 | android_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 | |||
| 1688 | static void | ||
| 1689 | android_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 | ||