diff options
author | Alan Mackenzie <acm@muc.de> | 2022-01-22 11:02:50 +0000 |
---|---|---|
committer | Alan Mackenzie <acm@muc.de> | 2022-01-22 11:02:50 +0000 |
commit | 14d64a8adcc866deecd758b898e8ef2d836b354a (patch) | |
tree | 83cff9669e266f8e283ccb8cd7518e909240f1e1 /src | |
parent | bdd9b5b8a0d37dd09ee530c1dab3a44bee09e0f8 (diff) | |
parent | ebe334cdc234de2897263aed4c05ac7088c11857 (diff) | |
download | emacs-scratch/correct-warning-pos.tar.gz |
Merge branch 'master' into scratch/correct-warning-posscratch/correct-warning-pos
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.in | 5 | ||||
-rw-r--r-- | src/bidi.c | 8 | ||||
-rw-r--r-- | src/buffer.c | 13 | ||||
-rw-r--r-- | src/bytecode.c | 8 | ||||
-rw-r--r-- | src/emacsgtkfixed.c | 6 | ||||
-rw-r--r-- | src/frame.c | 8 | ||||
-rw-r--r-- | src/gtkutil.c | 20 | ||||
-rw-r--r-- | src/haiku_select.cc | 27 | ||||
-rw-r--r-- | src/haiku_support.cc | 36 | ||||
-rw-r--r-- | src/haiku_support.h | 8 | ||||
-rw-r--r-- | src/haikufns.c | 498 | ||||
-rw-r--r-- | src/haikumenu.c | 12 | ||||
-rw-r--r-- | src/haikuselect.c | 31 | ||||
-rw-r--r-- | src/haikuselect.h | 9 | ||||
-rw-r--r-- | src/haikuterm.c | 90 | ||||
-rw-r--r-- | src/haikuterm.h | 2 | ||||
-rw-r--r-- | src/image.c | 6 | ||||
-rw-r--r-- | src/keyboard.c | 47 | ||||
-rw-r--r-- | src/nsterm.m | 11 | ||||
-rw-r--r-- | src/pgtkfns.c | 14 | ||||
-rw-r--r-- | src/pgtkterm.c | 38 | ||||
-rw-r--r-- | src/syntax.c | 5 | ||||
-rw-r--r-- | src/verbose.mk.in | 31 | ||||
-rw-r--r-- | src/w32font.c | 3 | ||||
-rw-r--r-- | src/xdisp.c | 3 | ||||
-rw-r--r-- | src/xfaces.c | 13 | ||||
-rw-r--r-- | src/xfns.c | 98 | ||||
-rw-r--r-- | src/xsettings.h | 5 | ||||
-rw-r--r-- | src/xterm.c | 374 | ||||
-rw-r--r-- | src/xterm.h | 15 | ||||
-rw-r--r-- | src/xwidget.c | 3 |
31 files changed, 1015 insertions, 432 deletions
diff --git a/src/Makefile.in b/src/Makefile.in index 04fabd5f424..706beb453b6 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -616,7 +616,7 @@ endif ## icon set. ifeq ($(HAVE_BE_APP),yes) -Emacs: emacs$(EXEEXT) +Emacs: emacs$(EXEEXT) $(libsrc)/be-resources $(AM_V_GEN) cp -f emacs$(EXEEXT) $@ $(AM_V_at) $(libsrc)/be-resources \ $(etc)/images/icons/hicolor/32x32/apps/emacs.png $@ @@ -914,6 +914,9 @@ $(bootstrap_pdmp): bootstrap-emacs$(EXEEXT) $(RUN_TEMACS) --batch $(BUILD_DETAILS) -l loadup --temacs=pbootstrap \ --bin-dest $(BIN_DESTDIR) --eln-dest $(ELN_DESTDIR) @: Compile some files earlier to speed up further compilation. + @: First, byte compile these files, .... + ANCIENT=yes $(MAKE) -C ../lisp compile-first EMACS="$(bootstrap_exe)" + @: .... then use their .elcs in native compiling these and other files. $(MAKE) -C ../lisp compile-first EMACS="$(bootstrap_exe)" endif diff --git a/src/bidi.c b/src/bidi.c index c5d524f0493..d6ed607f14c 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -3569,7 +3569,9 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it) ptrdiff_t bidi_find_first_overridden (struct bidi_it *bidi_it) { - ptrdiff_t found_pos = ZV; + ptrdiff_t eob + = STRINGP (bidi_it->string.lstring) ? bidi_it->string.schars : ZV; + ptrdiff_t found_pos = eob; /* Maximum bidi levels we allow for L2R and R2L characters. Note that these are levels after resolving explicit embeddings, overrides, and isolates, i.e. before resolving implicit levels. */ @@ -3607,8 +3609,8 @@ bidi_find_first_overridden (struct bidi_it *bidi_it) || ((category == WEAK || bidi_it->orig_type == NEUTRAL_ON) && level > max_weak)) found_pos = bidi_it->charpos; - } while (found_pos == ZV - && bidi_it->charpos < ZV + } while (found_pos == eob + && bidi_it->charpos < eob && bidi_it->ch != BIDI_EOB && bidi_it->ch != '\n'); diff --git a/src/buffer.c b/src/buffer.c index a3091015d9b..0bdad086ddd 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -912,6 +912,10 @@ does not run the hooks `kill-buffer-hook', Fset (intern ("buffer-save-without-query"), Qnil); Fset (intern ("buffer-file-number"), Qnil); Fset (intern ("buffer-stale-function"), Qnil); + /* Cloned buffers need extra setup, to do things such as deep + variable copies for list variables that might be mangled due + to destructive operations in the indirect buffer. */ + run_hook (Qclone_indirect_buffer_hook); set_buffer_internal_1 (old_b); } @@ -5569,6 +5573,8 @@ syms_of_buffer (void) Fput (Qprotected_field, Qerror_message, build_pure_c_string ("Attempt to modify a protected field")); + DEFSYM (Qclone_indirect_buffer_hook, "clone-indirect-buffer-hook"); + DEFVAR_PER_BUFFER ("tab-line-format", &BVAR (current_buffer, tab_line_format), Qnil, @@ -6392,6 +6398,13 @@ If `delete-auto-save-files' is nil, any autosave deletion is inhibited. */); This is the default. If nil, auto-save file deletion is inhibited. */); delete_auto_save_files = 1; + DEFVAR_LISP ("clone-indirect-buffer-hook", Vclone_indirect_buffer_hook, + doc: /* Normal hook to run in the new buffer at the end of `make-indirect-buffer'. + +Since `clone-indirect-buffer' calls `make-indirect-buffer', this hook +will run for `clone-indirect-buffer' calls as well. */); + Vclone_indirect_buffer_hook = Qnil; + defsubr (&Sbuffer_live_p); defsubr (&Sbuffer_list); defsubr (&Sget_buffer); diff --git a/src/bytecode.c b/src/bytecode.c index 472992be180..b7e65d05aef 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -1167,13 +1167,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, NEXT; CASE (Bchar_syntax): - { - CHECK_CHARACTER (TOP); - int c = XFIXNAT (TOP); - if (NILP (BVAR (current_buffer, enable_multibyte_characters))) - c = make_char_multibyte (c); - XSETFASTINT (TOP, syntax_code_spec[SYNTAX (c)]); - } + TOP = Fchar_syntax (TOP); NEXT; CASE (Bbuffer_substring): diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c index da56031e2a4..a38ba35ad80 100644 --- a/src/emacsgtkfixed.c +++ b/src/emacsgtkfixed.c @@ -164,13 +164,9 @@ XSetWMSizeHints (Display *d, if ((hints->flags & PMinSize) && f) { -#ifdef HAVE_PGTK - int w = f->output_data.pgtk->size_hints.min_width; - int h = f->output_data.pgtk->size_hints.min_height; -#else int w = f->output_data.x->size_hints.min_width; int h = f->output_data.x->size_hints.min_height; -#endif + data[5] = w; data[6] = h; } diff --git a/src/frame.c b/src/frame.c index e5d74edc168..8aaff949ba2 100644 --- a/src/frame.c +++ b/src/frame.c @@ -6472,6 +6472,14 @@ This variable is effective only with the X toolkit (and there only when Gtk+ tooltips are not used) and on Windows. */); tooltip_reuse_hidden_frame = false; + DEFVAR_BOOL ("use-system-tooltips", use_system_tooltips, + doc: /* Use the toolkit to display tooltips. +This option is only meaningful when Emacs is built with GTK+ or Haiku +windowing support, and results in tooltips that look like those +displayed by other GTK+ or Haiku programs, but will not be able to +display text properties inside tooltip text. */); + use_system_tooltips = true; + DEFVAR_LISP ("iconify-child-frame", iconify_child_frame, doc: /* How to handle iconification of child frames. This variable tells Emacs how to proceed when it is asked to iconify a diff --git a/src/gtkutil.c b/src/gtkutil.c index 36ed55bc039..eb148560620 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -4534,6 +4534,12 @@ xg_update_scrollbar_pos (struct frame *f, gtk_widget_show_all (wparent); gtk_widget_set_size_request (wscroll, width, height); } + +#if !defined HAVE_PGTK && GTK_CHECK_VERSION (2, 18, 0) + if (!gdk_window_ensure_native (gtk_widget_get_window (wscroll))) + emacs_abort (); +#endif + if (oldx != -1 && oldw > 0 && oldh > 0) { /* Clear under old scroll bar position. */ @@ -4587,7 +4593,6 @@ xg_update_horizontal_scrollbar_pos (struct frame *f, int width, int height) { - GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id); if (wscroll) @@ -4634,6 +4639,11 @@ xg_update_horizontal_scrollbar_pos (struct frame *f, pgtk_clear_area (f, oldx, oldy, oldw, oldh); #endif +#if !defined HAVE_PGTK && GTK_CHECK_VERSION (2, 18, 0) + if (!gdk_window_ensure_native (gtk_widget_get_window (wscroll))) + emacs_abort (); +#endif + /* GTK does not redraw until the main loop is entered again, but if there are no X events pending we will not enter it. So we sync here to get some events. */ @@ -6151,6 +6161,7 @@ xg_widget_key_press_event_cb (GtkWidget *widget, GdkEvent *event, inev.ie.modifiers |= x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), xstate); + inev.ie.timestamp = event->key.time; if (event->key.is_modifier) goto done; @@ -6256,13 +6267,16 @@ xg_widget_key_press_event_cb (GtkWidget *widget, GdkEvent *event, } XNoOp (FRAME_X_DISPLAY (f)); +#ifdef USABLE_SIGIO + raise (SIGIO); +#endif return true; } bool xg_filter_key (struct frame *frame, XEvent *xkey) { - GdkEvent *xg_event = gdk_event_new ((xkey->type == ButtonPress + GdkEvent *xg_event = gdk_event_new ((xkey->type == KeyPress #ifdef HAVE_XINPUT2 || (xkey->type == GenericEvent && xkey->xgeneric.evtype == XI_KeyPress) @@ -6321,6 +6335,7 @@ xg_filter_key (struct frame *frame, XEvent *xkey) NULL, NULL, &consumed); xg_add_virtual_mods (dpyinfo, &xg_event->key); xg_event->key.state &= ~consumed; + xg_event->key.time = xkey->xkey.time; #if GTK_CHECK_VERSION (3, 6, 0) xg_event->key.is_modifier = gdk_x11_keymap_key_is_modifier (keymap, xg_event->key.hardware_keycode); @@ -6334,6 +6349,7 @@ xg_filter_key (struct frame *frame, XEvent *xkey) xg_event->key.hardware_keycode = xev->detail; xg_event->key.group = xev->group.effective; xg_event->key.state = xev->mods.effective; + xg_event->key.time = xev->time; gdk_keymap_translate_keyboard_state (keymap, xev->detail, xev->mods.effective, diff --git a/src/haiku_select.cc b/src/haiku_select.cc index 041e244f3ea..d39000d8bbe 100644 --- a/src/haiku_select.cc +++ b/src/haiku_select.cc @@ -29,6 +29,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ static BClipboard *primary = NULL; static BClipboard *secondary = NULL; static BClipboard *system_clipboard = NULL; +static unsigned long count_clipboard = 0; +static unsigned long count_primary = 0; +static unsigned long count_secondary = 0; int selection_state_flag; @@ -174,6 +177,7 @@ BClipboard_set_system_data (const char *type, const char *data, return; BClipboard_set_data (system_clipboard, type, data, len, clear); + count_clipboard = system_clipboard->SystemCount (); } void @@ -184,6 +188,7 @@ BClipboard_set_primary_selection_data (const char *type, const char *data, return; BClipboard_set_data (primary, type, data, len, clear); + count_primary = primary->SystemCount (); } void @@ -194,6 +199,7 @@ BClipboard_set_secondary_selection_data (const char *type, const char *data, return; BClipboard_set_data (secondary, type, data, len, clear); + count_secondary = secondary->SystemCount (); } void @@ -220,6 +226,27 @@ BClipboard_secondary_targets (char **buf, int len) BClipboard_get_targets (secondary, buf, len); } +bool +BClipboard_owns_clipboard (void) +{ + return (count_clipboard + == system_clipboard->SystemCount ()); +} + +bool +BClipboard_owns_primary (void) +{ + return (count_primary + == primary->SystemCount ()); +} + +bool +BClipboard_owns_secondary (void) +{ + return (count_secondary + == secondary->SystemCount ()); +} + void init_haiku_select (void) { diff --git a/src/haiku_support.cc b/src/haiku_support.cc index d49e319b98c..ae2736110ec 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -36,6 +36,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <interface/MenuBar.h> #include <interface/Alert.h> #include <interface/Button.h> +#include <interface/ControlLook.h> #include <locale/UnicodeChar.h> @@ -406,6 +407,7 @@ public: bool menu_bar_active_p = false; window_look pre_override_redirect_style; window_feel pre_override_redirect_feel; + uint32 pre_override_redirect_workspaces; EmacsWindow () : BWindow (BRect (0, 0, 0, 0), "", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS) @@ -718,6 +720,7 @@ public: int ret; msg->FindInt32 ("raw_char", &raw); msg->FindInt32 ("key", &key); + msg->FindInt64 ("when", &rq.time); rq.modifiers = 0; uint32_t mods = modifiers (); @@ -1318,7 +1321,6 @@ public: if (!offscreen_draw_view) gui_abort ("Failed to lock offscreen view during buffer flip"); - offscreen_draw_view->Flush (); offscreen_draw_view->Sync (); EmacsWindow *w = (EmacsWindow *) Window (); @@ -1381,8 +1383,8 @@ public: rq.just_exited_p = transit == B_EXITED_VIEW; rq.x = point.x; rq.y = point.y; - rq.be_code = transit; rq.window = this->Window (); + rq.time = system_time (); if (ToolTip ()) ToolTip ()->SetMouseRelativeLocation (BPoint (-(point.x - tt_absl_pos.x), @@ -1437,6 +1439,7 @@ public: SetMouseEventMask (B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); + rq.time = system_time (); haiku_write (BUTTON_DOWN, &rq); } @@ -1483,6 +1486,7 @@ public: if (!buttons) SetMouseEventMask (0, 0); + rq.time = system_time (); haiku_write (BUTTON_UP, &rq); } }; @@ -1632,17 +1636,17 @@ public: { struct haiku_menu_bar_help_event rq; - if (menu_bar_id >= 0) + if (help) + { + Menu ()->SetToolTip (highlight_p ? help : NULL); + } + else if (menu_bar_id >= 0) { rq.window = wind_ptr; rq.mb_idx = highlight_p ? menu_bar_id : -1; haiku_write (MENU_BAR_HELP_EVENT, &rq); } - else if (help) - { - Menu ()->SetToolTip (highlight_p ? help : NULL); - } BMenuItem::Highlight (highlight_p); } @@ -1997,8 +2001,6 @@ BView_move_frame (void *view, int x, int y, int x1, int y1) gui_abort ("Failed to lock view moving frame"); vw->MoveTo (x, y); vw->ResizeTo (x1 - x, y1 - y); - vw->Flush (); - vw->Sync (); vw->UnlockLooper (); } @@ -2018,7 +2020,9 @@ BView_scroll_bar_update (void *sb, int portion, int whole, int position) int BScrollBar_default_size (int horizontal_p) { - return horizontal_p ? B_H_SCROLL_BAR_HEIGHT : B_V_SCROLL_BAR_WIDTH; + return be_control_look->GetScrollBarWidth (horizontal_p + ? B_HORIZONTAL + : B_VERTICAL); } /* Invalidate VIEW, causing it to be drawn again. */ @@ -2224,7 +2228,11 @@ BWindow_set_tooltip_decoration (void *window) if (!w->LockLooper ()) gui_abort ("Failed to lock window while setting ttip decoration"); w->SetLook (B_BORDERED_WINDOW_LOOK); - w->SetFeel (B_FLOATING_APP_WINDOW_FEEL); + w->SetFeel (kMenuWindowFeel); + w->SetFlags (B_NOT_ZOOMABLE + | B_NOT_MINIMIZABLE + | B_AVOID_FRONT + | B_AVOID_FOCUS); w->UnlockLooper (); } @@ -2241,7 +2249,6 @@ BWindow_set_avoid_focus (void *window, int avoid_focus_p) w->SetFlags (w->Flags () & ~B_AVOID_FOCUS); else w->SetFlags (w->Flags () | B_AVOID_FOCUS); - w->Sync (); w->UnlockLooper (); } @@ -2818,7 +2825,7 @@ be_popup_file_dialog (int open_p, const char *default_dir, int must_match_p, int enum haiku_event_type type; char *ptr = NULL; - if (!haiku_read_with_timeout (&type, buf, 200, 100000)) + if (!haiku_read_with_timeout (&type, buf, 200, 1000000)) { block_input_function (); if (type != FILE_PANEL_EVENT) @@ -3166,11 +3173,14 @@ BWindow_set_override_redirect (void *window, bool override_redirect_p) w->pre_override_redirect_style = w->Look (); w->SetFeel (kMenuWindowFeel); w->SetLook (B_NO_BORDER_WINDOW_LOOK); + w->pre_override_redirect_workspaces = w->Workspaces (); + w->SetWorkspaces (B_ALL_WORKSPACES); } else { w->SetFeel (w->pre_override_redirect_feel); w->SetLook (w->pre_override_redirect_style); + w->SetWorkspaces (w->pre_override_redirect_workspaces); } w->UnlockLooper (); diff --git a/src/haiku_support.h b/src/haiku_support.h index 83f22972ce2..6ddc28759b5 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -34,6 +34,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <math.h> +#include <kernel/OS.h> + enum haiku_cursor { CURSOR_ID_NO_CURSOR = 12, @@ -132,6 +134,9 @@ struct haiku_key_event int modifiers; unsigned keysym; uint32_t multibyte_char; + + /* Time the keypress occurred, in microseconds. */ + bigtime_t time; }; struct haiku_activation_event @@ -146,7 +151,7 @@ struct haiku_mouse_motion_event bool just_exited_p; int x; int y; - uint32_t be_code; + bigtime_t time; }; struct haiku_button_event @@ -156,6 +161,7 @@ struct haiku_button_event int modifiers; int x; int y; + bigtime_t time; }; struct haiku_iconification_event diff --git a/src/haikufns.c b/src/haikufns.c index 52bb13bc89b..58a2e1d4642 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -45,7 +45,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #define BLUE_FROM_ULONG(color) ((color) & 0xff) /* The frame of the currently visible tooltip. */ -static Lisp_Object tip_frame; +Lisp_Object tip_frame; /* The window-system window corresponding to the frame of the currently visible tooltip. */ @@ -452,6 +452,15 @@ haiku_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object o } static void +initial_setup_back_buffer (struct frame *f) +{ + block_input (); + if (NILP (CDR (Fassq (Qinhibit_double_buffering, f->param_alist)))) + EmacsView_set_up_double_buffering (FRAME_HAIKU_VIEW (f)); + unblock_input (); +} + +static void unwind_create_frame (Lisp_Object frame) { struct frame *f = XFRAME (frame); @@ -547,13 +556,12 @@ unwind_popup (void) } static Lisp_Object -haiku_create_frame (Lisp_Object parms, int ttip_p) +haiku_create_frame (Lisp_Object parms) { struct frame *f; Lisp_Object frame, tem; Lisp_Object name; bool minibuffer_only = false; - bool face_change_before = face_change; long window_prompting = 0; ptrdiff_t count = SPECPDL_INDEX (); Lisp_Object display; @@ -593,10 +601,8 @@ haiku_create_frame (Lisp_Object parms, int ttip_p) tem = gui_display_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer", RES_TYPE_SYMBOL); - if (ttip_p) - f = make_frame (0); - else if (EQ (tem, Qnone) || NILP (tem)) - f = make_frame_without_minibuffer (Qnil, kb, display); + if (EQ (tem, Qnone) || NILP (tem)) + f = make_frame_without_minibuffer (Qnil, kb, display); else if (EQ (tem, Qonly)) { f = make_minibuffer_frame (); @@ -618,22 +624,16 @@ haiku_create_frame (Lisp_Object parms, int ttip_p) f->output_data.haiku->pending_zoom_width = INT_MIN; f->output_data.haiku->pending_zoom_height = INT_MIN; - if (ttip_p) - f->wants_modeline = false; - fset_icon_name (f, gui_display_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING)); - if (! STRINGP (f->icon_name) || ttip_p) + if (! STRINGP (f->icon_name)) fset_icon_name (f, Qnil); FRAME_DISPLAY_INFO (f) = dpyinfo; /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe. */ - if (!ttip_p) - record_unwind_protect (unwind_create_frame, frame); - else - record_unwind_protect (unwind_create_tip_frame, frame); + record_unwind_protect (unwind_create_frame, frame); FRAME_OUTPUT_DATA (f)->parent_desc = NULL; FRAME_OUTPUT_DATA (f)->explicit_parent = 0; @@ -660,8 +660,6 @@ haiku_create_frame (Lisp_Object parms, int ttip_p) #endif register_font_driver (&haikufont_driver, f); - f->tooltip = ttip_p; - image_cache_refcount = FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0; @@ -674,7 +672,7 @@ haiku_create_frame (Lisp_Object parms, int ttip_p) gui_default_parameter (f, parms, Qborder_width, make_fixnum (0), "borderwidth", "BorderWidth", RES_TYPE_NUMBER); - gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (ttip_p ? 1 : 2), + gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (2), "internalBorderWidth", "InternalBorderWidth", RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qchild_frame_border_width, Qnil, @@ -684,7 +682,7 @@ haiku_create_frame (Lisp_Object parms, int ttip_p) NULL, NULL, RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0), NULL, NULL, RES_TYPE_NUMBER); - gui_default_parameter (f, parms, Qvertical_scroll_bars, !ttip_p ? Qt : Qnil, + gui_default_parameter (f, parms, Qvertical_scroll_bars, Qt, "verticalScrollBars", "VerticalScrollBars", RES_TYPE_SYMBOL); gui_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil, @@ -700,7 +698,7 @@ haiku_create_frame (Lisp_Object parms, int ttip_p) "leftFringe", "LeftFringe", RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qright_fringe, Qnil, "rightFringe", "RightFringe", RES_TYPE_NUMBER); - gui_default_parameter (f, parms, Qno_special_glyphs, ttip_p ? Qnil : Qt, + gui_default_parameter (f, parms, Qno_special_glyphs, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); init_frame_faces (f); @@ -718,57 +716,39 @@ haiku_create_frame (Lisp_Object parms, int ttip_p) FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1, Qx_create_frame_1); - if (!ttip_p) - { - gui_default_parameter (f, parms, Qz_group, Qnil, NULL, NULL, RES_TYPE_SYMBOL); - gui_default_parameter (f, parms, Qno_focus_on_map, Qnil, - NULL, NULL, RES_TYPE_BOOLEAN); - gui_default_parameter (f, parms, Qno_accept_focus, Qnil, - NULL, NULL, RES_TYPE_BOOLEAN); - - /* The resources controlling the menu-bar, tool-bar, and tab-bar are - processed specially at startup, and reflected in the mode - variables; ignore them here. */ - gui_default_parameter (f, parms, Qmenu_bar_lines, - NILP (Vmenu_bar_mode) - ? make_fixnum (0) : make_fixnum (1), - NULL, NULL, RES_TYPE_NUMBER); - gui_default_parameter (f, parms, Qtab_bar_lines, - NILP (Vtab_bar_mode) - ? make_fixnum (0) : make_fixnum (1), - NULL, NULL, RES_TYPE_NUMBER); - gui_default_parameter (f, parms, Qtool_bar_lines, - NILP (Vtool_bar_mode) - ? make_fixnum (0) : make_fixnum (1), - NULL, NULL, RES_TYPE_NUMBER); - gui_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate", - "BufferPredicate", RES_TYPE_SYMBOL); - gui_default_parameter (f, parms, Qtitle, Qnil, "title", "Title", - RES_TYPE_STRING); - } + gui_default_parameter (f, parms, Qz_group, Qnil, NULL, NULL, RES_TYPE_SYMBOL); + gui_default_parameter (f, parms, Qno_focus_on_map, Qnil, + NULL, NULL, RES_TYPE_BOOLEAN); + gui_default_parameter (f, parms, Qno_accept_focus, Qnil, + NULL, NULL, RES_TYPE_BOOLEAN); + + /* The resources controlling the menu-bar, tool-bar, and tab-bar are + processed specially at startup, and reflected in the mode + variables; ignore them here. */ + gui_default_parameter (f, parms, Qmenu_bar_lines, + NILP (Vmenu_bar_mode) + ? make_fixnum (0) : make_fixnum (1), + NULL, NULL, RES_TYPE_NUMBER); + gui_default_parameter (f, parms, Qtab_bar_lines, + NILP (Vtab_bar_mode) + ? make_fixnum (0) : make_fixnum (1), + NULL, NULL, RES_TYPE_NUMBER); + gui_default_parameter (f, parms, Qtool_bar_lines, + NILP (Vtool_bar_mode) + ? make_fixnum (0) : make_fixnum (1), + NULL, NULL, RES_TYPE_NUMBER); + gui_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate", + "BufferPredicate", RES_TYPE_SYMBOL); + gui_default_parameter (f, parms, Qtitle, Qnil, "title", "Title", + RES_TYPE_STRING); parms = get_geometry_from_preferences (dpyinfo, parms); window_prompting = gui_figure_window_size (f, parms, false, true); - if (ttip_p) - { - /* No fringes on tip frame. */ - f->fringe_cols = 0; - f->left_fringe_width = 0; - f->right_fringe_width = 0; - /* No dividers on tip frame. */ - f->right_divider_width = 0; - f->bottom_divider_width = 0; - } - tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN); f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !NILP (tem)); - /* Add `tooltip' frame parameter's default value. */ - if (NILP (Fframe_parameter (frame, Qtooltip)) && ttip_p) - Fmodify_frame_parameters (frame, Fcons (Fcons (Qtooltip, Qt), Qnil)); - #define ASSIGN_CURSOR(cursor, be_cursor) \ (FRAME_OUTPUT_DATA (f)->cursor = be_cursor) @@ -803,16 +783,13 @@ haiku_create_frame (Lisp_Object parms, int ttip_p) ASSIGN_CURSOR (current_cursor, FRAME_OUTPUT_DATA (f)->text_cursor); #undef ASSIGN_CURSOR - - if (ttip_p) - f->no_split = true; f->terminal->reference_count++; FRAME_OUTPUT_DATA (f)->window = BWindow_new (&FRAME_OUTPUT_DATA (f)->view); if (!FRAME_OUTPUT_DATA (f)->window) xsignal1 (Qerror, build_unibyte_string ("Could not create window")); - if (!minibuffer_only && !ttip_p && FRAME_EXTERNAL_MENU_BAR (f)) + if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)) initialize_frame_menubar (f); FRAME_OUTPUT_DATA (f)->window_desc = FRAME_OUTPUT_DATA (f)->window; @@ -839,58 +816,33 @@ haiku_create_frame (Lisp_Object parms, int ttip_p) gui_default_parameter (f, parms, Qicon_type, Qnil, "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL); - if (ttip_p) - { - gui_default_parameter (f, parms, Qundecorated, Qt, NULL, NULL, RES_TYPE_BOOLEAN); - gui_default_parameter (f, parms, Qno_accept_focus, Qt, NULL, NULL, - RES_TYPE_BOOLEAN); - } - else - { - gui_default_parameter (f, parms, Qauto_raise, Qnil, - "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN); - gui_default_parameter (f, parms, Qauto_lower, Qnil, - "autoLower", "AutoLower", RES_TYPE_BOOLEAN); - gui_default_parameter (f, parms, Qcursor_type, Qbox, - "cursorType", "CursorType", RES_TYPE_SYMBOL); - gui_default_parameter (f, parms, Qscroll_bar_width, Qnil, - "scrollBarWidth", "ScrollBarWidth", - RES_TYPE_NUMBER); - gui_default_parameter (f, parms, Qscroll_bar_height, Qnil, - "scrollBarHeight", "ScrollBarHeight", - RES_TYPE_NUMBER); - gui_default_parameter (f, parms, Qalpha, Qnil, - "alpha", "Alpha", RES_TYPE_NUMBER); - gui_default_parameter (f, parms, Qfullscreen, Qnil, - "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); - } + gui_default_parameter (f, parms, Qauto_raise, Qnil, + "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN); + gui_default_parameter (f, parms, Qauto_lower, Qnil, + "autoLower", "AutoLower", RES_TYPE_BOOLEAN); + gui_default_parameter (f, parms, Qcursor_type, Qbox, + "cursorType", "CursorType", RES_TYPE_SYMBOL); + gui_default_parameter (f, parms, Qscroll_bar_width, Qnil, + "scrollBarWidth", "ScrollBarWidth", + RES_TYPE_NUMBER); + gui_default_parameter (f, parms, Qscroll_bar_height, Qnil, + "scrollBarHeight", "ScrollBarHeight", + RES_TYPE_NUMBER); + gui_default_parameter (f, parms, Qalpha, Qnil, + "alpha", "Alpha", RES_TYPE_NUMBER); + gui_default_parameter (f, parms, Qfullscreen, Qnil, + "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil, "inhibitDoubleBuffering", "InhibitDoubleBuffering", RES_TYPE_BOOLEAN); - if (ttip_p) - { - Lisp_Object bg = Fframe_parameter (frame, Qbackground_color); - - call2 (Qface_set_after_frame_default, frame, Qnil); - - if (!EQ (bg, Fframe_parameter (frame, Qbackground_color))) - { - AUTO_FRAME_ARG (arg, Qbackground_color, bg); - Fmodify_frame_parameters (frame, arg); - } - } - - if (ttip_p) - face_change = face_change_before; - f->can_set_window_size = true; adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), - 0, true, ttip_p ? Qtip_frame : Qx_create_frame_2); + 0, true, Qx_create_frame_2); - if (!FRAME_OUTPUT_DATA (f)->explicit_parent && !ttip_p) + if (!FRAME_OUTPUT_DATA (f)->explicit_parent) { Lisp_Object visibility; @@ -908,13 +860,10 @@ haiku_create_frame (Lisp_Object parms, int ttip_p) } } - if (!ttip_p) - { - if (FRAME_HAS_MINIBUF_P (f) - && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame)) - || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))) - kset_default_minibuffer_frame (kb, frame); - } + if (FRAME_HAS_MINIBUF_P (f) + && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame)) + || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))) + kset_default_minibuffer_frame (kb, frame); for (tem = parms; CONSP (tem); tem = XCDR (tem)) if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem)))) @@ -929,13 +878,230 @@ haiku_create_frame (Lisp_Object parms, int ttip_p) and similar functions. */ Vwindow_list = Qnil; - if (ttip_p) - adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), - 0, true, Qtip_frame); + return unbind_to (count, frame); +} + +/* Create a frame for a tooltip. PARMS is a list of frame parameters. + TEXT is the string to display in the tip frame. Value is the + frame. + + Note that functions called here, esp. gui_default_parameter can + signal errors, for instance when a specified color name is + undefined. We have to make sure that we're in a consistent state + when this happens. */ +static Lisp_Object +haiku_create_tip_frame (Lisp_Object parms) +{ + struct frame *f; + Lisp_Object frame; + Lisp_Object name; + ptrdiff_t count = SPECPDL_INDEX (); + bool face_change_before = face_change; + struct haiku_display_info *dpyinfo = x_display_list; + + if (!dpyinfo->terminal->name) + error ("Terminal is not live, can't create new frames on it"); + + parms = Fcopy_alist (parms); + + /* Get the name of the frame to use for resource lookup. */ + name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", + RES_TYPE_STRING); + if (!STRINGP (name) + && !EQ (name, Qunbound) + && !NILP (name)) + error ("Invalid frame name--not a string or nil"); + + frame = Qnil; + f = make_frame (false); + f->wants_modeline = false; + XSETFRAME (frame, f); + record_unwind_protect (unwind_create_tip_frame, frame); + + f->terminal = dpyinfo->terminal; + + /* By setting the output method, we're essentially saying that + the frame is live, as per FRAME_LIVE_P. If we get a signal + from this point on, x_destroy_window might screw up reference + counts etc. */ + f->output_method = output_haiku; + f->output_data.haiku = xzalloc (sizeof *f->output_data.haiku); + + f->output_data.haiku->pending_zoom_x = INT_MIN; + f->output_data.haiku->pending_zoom_y = INT_MIN; + f->output_data.haiku->pending_zoom_width = INT_MIN; + f->output_data.haiku->pending_zoom_height = INT_MIN; + + f->tooltip = true; + fset_icon_name (f, Qnil); + FRAME_DISPLAY_INFO (f) = dpyinfo; + + FRAME_OUTPUT_DATA (f)->parent_desc = NULL; + FRAME_OUTPUT_DATA (f)->explicit_parent = 0; + + /* Set the name; the functions to which we pass f expect the name to + be set. */ + if (EQ (name, Qunbound) || NILP (name)) + f->explicit_name = false; + else + { + fset_name (f, name); + f->explicit_name = true; + /* use the frame's title when getting resources for this frame. */ + specbind (Qx_resource_name, name); + } + +#ifdef USE_BE_CAIRO + register_font_driver (&ftcrfont_driver, f); +#ifdef HAVE_HARFBUZZ + register_font_driver (&ftcrhbfont_driver, f); +#endif +#endif + register_font_driver (&haikufont_driver, f); + + image_cache_refcount = + FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0; + + gui_default_parameter (f, parms, Qfont_backend, Qnil, + "fontBackend", "FontBackend", RES_TYPE_STRING); + + /* Extract the window parameters from the supplied values that are + needed to determine window geometry. */ + FRAME_RIF (f)->default_font_parameter (f, parms); + + /* This defaults to 1 in order to match xterm. We recognize either + internalBorderWidth or internalBorder (which is what xterm calls + it). */ + if (NILP (Fassq (Qinternal_border_width, parms))) + { + Lisp_Object value; + + value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, + "internalBorder", "internalBorder", + RES_TYPE_NUMBER); + if (! EQ (value, Qunbound)) + parms = Fcons (Fcons (Qinternal_border_width, value), + parms); + } + + gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (1), + "internalBorderWidth", "internalBorderWidth", + RES_TYPE_NUMBER); + + gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0), + NULL, NULL, RES_TYPE_NUMBER); + gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0), + NULL, NULL, RES_TYPE_NUMBER); + + /* Also do the stuff which must be set before the window exists. */ + gui_default_parameter (f, parms, Qforeground_color, build_string ("black"), + "foreground", "Foreground", RES_TYPE_STRING); + + gui_default_parameter (f, parms, Qbackground_color, build_string ("white"), + "background", "Background", RES_TYPE_STRING); + gui_default_parameter (f, parms, Qmouse_color, build_string ("black"), + "pointerColor", "Foreground", RES_TYPE_STRING); + gui_default_parameter (f, parms, Qcursor_color, build_string ("black"), + "cursorColor", "Foreground", RES_TYPE_STRING); + gui_default_parameter (f, parms, Qborder_color, build_string ("black"), + "borderColor", "BorderColor", RES_TYPE_STRING); + gui_default_parameter (f, parms, Qno_special_glyphs, Qnil, + NULL, NULL, RES_TYPE_BOOLEAN); + + /* Init faces before gui_default_parameter is called for the + scroll-bar-width parameter because otherwise we end up in + init_iterator with a null face cache, which should not happen. */ + init_frame_faces (f); + + gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil, + "inhibitDoubleBuffering", "InhibitDoubleBuffering", + RES_TYPE_BOOLEAN); + + gui_figure_window_size (f, parms, false, false); + + { + void *window; + + block_input (); + window = BWindow_new (&FRAME_OUTPUT_DATA (f)->view); + + FRAME_OUTPUT_DATA (f)->window = window; + if (!window) + emacs_abort (); + + FRAME_OUTPUT_DATA (f)->window_desc = window; + BWindow_set_tooltip_decoration (window); + unblock_input (); + } + + gui_default_parameter (f, parms, Qauto_raise, Qnil, + "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN); + gui_default_parameter (f, parms, Qauto_lower, Qnil, + "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN); + gui_default_parameter (f, parms, Qcursor_type, Qbox, + "cursorType", "CursorType", RES_TYPE_SYMBOL); + gui_default_parameter (f, parms, Qalpha, Qnil, + "alpha", "Alpha", RES_TYPE_NUMBER); + + initial_setup_back_buffer (f); + + /* Add `tooltip' frame parameter's default value. */ + if (NILP (Fframe_parameter (frame, Qtooltip))) + { + AUTO_FRAME_ARG (arg, Qtooltip, Qt); + Fmodify_frame_parameters (frame, arg); + } + + /* FIXME - can this be done in a similar way to normal frames? + https://lists.gnu.org/r/emacs-devel/2007-10/msg00641.html */ + + /* Set up faces after all frame parameters are known. This call + also merges in face attributes specified for new frames. + + Frame parameters may be changed if .Xdefaults contains + specifications for the default font. For example, if there is an + `Emacs.default.attributeBackground: pink', the `background-color' + attribute of the frame gets set, which let's the internal border + of the tooltip frame appear in pink. Prevent this. */ + { + Lisp_Object bg = Fframe_parameter (frame, Qbackground_color); + + call2 (Qface_set_after_frame_default, frame, Qnil); + + if (!EQ (bg, Fframe_parameter (frame, Qbackground_color))) + { + AUTO_FRAME_ARG (arg, Qbackground_color, bg); + Fmodify_frame_parameters (frame, arg); + } + } + + f->no_split = true; + + /* Now that the frame will be official, it counts as a reference to + its display and terminal. */ + f->terminal->reference_count++; + + /* It is now ok to make the frame official even if we get an error + below. And the frame needs to be on Vframe_list or making it + visible won't work. */ + Vframe_list = Fcons (frame, Vframe_list); + f->can_set_window_size = true; + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), + 0, true, Qtip_frame); + + /* Setting attributes of faces of the tooltip frame from resources + and similar will set face_change, which leads to the clearing of + all current matrices. Since this isn't necessary here, avoid it + by resetting face_change to the value it had before we created + the tip frame. */ + face_change = face_change_before; + + /* Discard the unwind_protect. */ return unbind_to (count, frame); } + static void compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object dy, @@ -1440,6 +1606,7 @@ haiku_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object o if (new_width == old_width) return; + f->internal_border_width = new_width; if (FRAME_HAIKU_WINDOW (f)) @@ -1527,9 +1694,9 @@ haiku_set_inhibit_double_buffering (struct frame *f, Lisp_Object old_value) { block_input (); -#ifndef USE_BE_CAIRO if (FRAME_HAIKU_WINDOW (f)) { +#ifndef USE_BE_CAIRO if (NILP (new_value)) { #endif @@ -1543,8 +1710,8 @@ haiku_set_inhibit_double_buffering (struct frame *f, } else EmacsView_disable_double_buffering (FRAME_HAIKU_VIEW (f)); - } #endif + } unblock_input (); } @@ -1709,7 +1876,7 @@ DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0, int width, height; BScreen_px_dim (&width, &height); - return make_fixnum (height / (dpyinfo->resy / 25.4)); + return make_fixnum (width / (dpyinfo->resx / 25.4)); } DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, @@ -1717,7 +1884,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, doc: /* SKIP: real doc in xfns.c. */) (Lisp_Object parms) { - return haiku_create_frame (parms, 0); + return haiku_create_frame (parms); } DEFUN ("x-display-visual-class", Fx_display_visual_class, @@ -1752,12 +1919,13 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, ptrdiff_t count = SPECPDL_INDEX (); ptrdiff_t count_1; Lisp_Object window, size, tip_buf; - AUTO_STRING (tip, " *tip*"); specbind (Qinhibit_redisplay, Qt); CHECK_STRING (string); + if (SCHARS (string) == 0) + string = make_unibyte_string (" ", 1); if (NILP (frame)) frame = selected_frame; @@ -1778,7 +1946,7 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, else CHECK_FIXNUM (dy); - if (haiku_use_system_tooltips) + if (use_system_tooltips) { int root_x, root_y; CHECK_STRING (string); @@ -1821,24 +1989,21 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, { if (FRAME_VISIBLE_P (XFRAME (tip_frame)) && EQ (frame, tip_last_frame) - && !NILP (Fequal_including_properties (string, tip_last_string)) - && !NILP (Fequal (parms, tip_last_parms))) + && !NILP (Fequal_including_properties (tip_last_string, string)) + && !NILP (Fequal (tip_last_parms, parms))) { /* Only DX and DY have changed. */ tip_f = XFRAME (tip_frame); if (!NILP (tip_timer)) { - Lisp_Object timer = tip_timer; - + call1 (Qcancel_timer, tip_timer); tip_timer = Qnil; - call1 (Qcancel_timer, timer); } block_input (); compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f), FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y); - haiku_set_offset (tip_f, root_x, root_y, 1); - haiku_visualize_frame (tip_f); + BWindow_set_offset (FRAME_HAIKU_WINDOW (tip_f), root_x, root_y); unblock_input (); goto start_timer; @@ -1849,8 +2014,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, Lisp_Object tail, elt, parm, last; /* Check if every parameter in PARMS has the same value in - tip_last_parms. This may destruct tip_last_parms - which, however, will be recreated below. */ + tip_last_parms. This may destruct tip_last_parms which, + however, will be recreated below. */ for (tail = parms; CONSP (tail); tail = XCDR (tail)) { elt = XCAR (tail); @@ -1876,8 +2041,9 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, call2 (Qassq_delete_all, parm, tip_last_parms); } - /* Now check if there's a parameter left in tip_last_parms with a - non-nil value. */ + /* Now check if every parameter in what is left of + tip_last_parms with a non-nil value has an association in + PARMS. */ for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail)) { elt = XCAR (tail); @@ -1903,10 +2069,6 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, tip_last_string = string; tip_last_parms = parms; - /* Block input until the tip has been fully drawn, to avoid crashes - when drawing tips in menus. */ - block_input (); - if (NILP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame))) { /* Add default values to frame parameters. */ @@ -1917,21 +2079,16 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, if (NILP (Fassq (Qborder_width, parms))) parms = Fcons (Fcons (Qborder_width, make_fixnum (1)), parms); if (NILP (Fassq (Qborder_color, parms))) - parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), - parms); + parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms); if (NILP (Fassq (Qbackground_color, parms))) parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")), parms); - /* Create a frame for the tooltip and record it in the global + /* Create a frame for the tooltip, and record it in the global variable tip_frame. */ - - if (NILP (tip_frame = haiku_create_frame (parms, 1))) - { - /* Creating the tip frame failed. */ - unblock_input (); - return unbind_to (count, Qnil); - } + if (NILP (tip_frame = haiku_create_tip_frame (parms))) + /* Creating the tip frame failed. */ + return unbind_to (count, Qnil); } tip_f = XFRAME (tip_frame); @@ -1971,11 +2128,11 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f); w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f); - FRAME_TOTAL_COLS (tip_f) = WINDOW_TOTAL_COLS (w); + FRAME_TOTAL_COLS (tip_f) = w->total_cols; adjust_frame_glyphs (tip_f); - /* Insert STRING into the root window's buffer and fit the frame to - the buffer. */ + /* Insert STRING into root window's buffer and fit the frame to the + buffer. */ count_1 = SPECPDL_INDEX (); old_buffer = current_buffer; set_buffer_internal_1 (XBUFFER (w->contents)); @@ -1996,22 +2153,28 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, /* Add the frame's internal border to calculated size. */ width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); + /* Calculate position of tooltip frame. */ compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y); - BWindow_resize (FRAME_HAIKU_WINDOW (tip_f), width, height); - haiku_set_offset (tip_f, root_x, root_y, 1); - BWindow_set_tooltip_decoration (FRAME_HAIKU_WINDOW (tip_f)); - BView_set_view_cursor (FRAME_HAIKU_VIEW (tip_f), - FRAME_OUTPUT_DATA (XFRAME (frame))->current_cursor); - SET_FRAME_VISIBLE (tip_f, 1); - BWindow_set_visible (FRAME_HAIKU_WINDOW (tip_f), 1); + + /* Show tooltip frame. */ + block_input (); + void *wnd = FRAME_HAIKU_WINDOW (tip_f); + BWindow_resize (wnd, width, height); + BView_resize_to (FRAME_HAIKU_VIEW (tip_f), width, height); + BWindow_set_offset (wnd, root_x, root_y); + BWindow_set_visible (wnd, true); + SET_FRAME_VISIBLE (tip_f, true); + FRAME_PIXEL_WIDTH (tip_f) = width; + FRAME_PIXEL_HEIGHT (tip_f) = height; + BWindow_sync (wnd); + unblock_input (); w->must_be_updated_p = true; - flush_frame (tip_f); update_single_window (w); + flush_frame (tip_f); set_buffer_internal_1 (old_buffer); unbind_to (count_1, Qnil); - unblock_input (); windows_or_buffers_changed = old_windows_or_buffers_changed; start_timer: @@ -2459,6 +2622,7 @@ syms_of_haikufns (void) DEFSYM (Qalways, "always"); DEFSYM (Qnot_useful, "not-useful"); DEFSYM (Qwhen_mapped, "when-mapped"); + DEFSYM (Qtooltip_reuse_hidden_frame, "tooltip-reuse-hidden-frame"); defsubr (&Sx_hide_tip); defsubr (&Sxw_display_color_p); @@ -2508,14 +2672,6 @@ syms_of_haikufns (void) doc: /* SKIP: real doc in xfns.c. */); Vx_max_tooltip_size = Fcons (make_fixnum (80), make_fixnum (40)); - DEFVAR_BOOL ("haiku-use-system-tooltips", haiku_use_system_tooltips, - doc: /* When non-nil, Emacs will display tooltips using the App Kit. -This can avoid a great deal of consing that does not play -well with the Haiku memory allocator, but comes with the -disadvantage of not being able to use special display properties -within tooltips. */); - haiku_use_system_tooltips = 1; - #ifdef USE_BE_CAIRO DEFVAR_LISP ("cairo-version-string", Vcairo_version_string, doc: /* Version info for cairo. */); diff --git a/src/haikumenu.c b/src/haikumenu.c index f335bdacb40..2922981cb3b 100644 --- a/src/haikumenu.c +++ b/src/haikumenu.c @@ -142,10 +142,7 @@ digest_menu_items (void *first_menu, int start, int menu_items_used, } if (STRINGP (help) && STRING_MULTIBYTE (help)) - { - help = ENCODE_UTF_8 (help); - ASET (menu_items, i + MENU_ITEMS_ITEM_HELP, help); - } + help = ENCODE_UTF_8 (help); if (i + MENU_ITEMS_ITEM_LENGTH < menu_items_used && NILP (AREF (menu_items, i + MENU_ITEMS_ITEM_LENGTH))) @@ -158,6 +155,12 @@ digest_menu_items (void *first_menu, int start, int menu_items_used, !NILP (enable), !NILP (selected), 0, window, !NILP (descrip) ? SSDATA (descrip) : NULL, STRINGP (help) ? SSDATA (help) : NULL); + else if (!use_system_tooltips || NILP (Fsymbol_value (Qtooltip_mode))) + BMenu_add_item (menu, SSDATA (item_name), + !NILP (def) ? (void *) (intptr_t) i : NULL, + !NILP (enable), !NILP (selected), 1, window, + !NILP (descrip) ? SSDATA (descrip) : NULL, + NULL); else BMenu_add_item (menu, SSDATA (item_name), !NILP (def) ? (void *) (intptr_t) i : NULL, @@ -664,6 +667,7 @@ syms_of_haikumenu (void) DEFSYM (Qdebug_on_next_call, "debug-on-next-call"); DEFSYM (Qpopup_menu, "popup-menu"); DEFSYM (Qmouse_menu_bar_map, "mouse-menu-bar-map"); + DEFSYM (Qtooltip_mode, "tooltip-mode"); defsubr (&Smenu_or_popup_active_p); defsubr (&Shaiku_menu_bar_open); diff --git a/src/haikuselect.c b/src/haikuselect.c index 2e619c69f7a..e65ab827c51 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c @@ -166,6 +166,36 @@ clipboard. */) return Qnil; } +DEFUN ("haiku-selection-owner-p", Fhaiku_selection_owner_p, Shaiku_selection_owner_p, + 0, 1, 0, + doc: /* Whether the current Emacs process owns the given SELECTION. +The arg should be the name of the selection in question, typically one +of the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. For +convenience, the symbol nil is the same as `PRIMARY', and t is the +same as `SECONDARY'. */) + (Lisp_Object selection) +{ + bool value; + + if (NILP (selection)) + selection = QPRIMARY; + else if (EQ (selection, Qt)) + selection = QSECONDARY; + + block_input (); + if (EQ (selection, QPRIMARY)) + value = BClipboard_owns_primary (); + else if (EQ (selection, QSECONDARY)) + value = BClipboard_owns_secondary (); + else if (EQ (selection, QCLIPBOARD)) + value = BClipboard_owns_clipboard (); + else + value = false; + unblock_input (); + + return value ? Qt : Qnil; +} + void syms_of_haikuselect (void) { @@ -179,4 +209,5 @@ syms_of_haikuselect (void) defsubr (&Shaiku_selection_data); defsubr (&Shaiku_selection_put); defsubr (&Shaiku_selection_targets); + defsubr (&Shaiku_selection_owner_p); } diff --git a/src/haikuselect.h b/src/haikuselect.h index 80f33c6ed25..566aae596f6 100644 --- a/src/haikuselect.h +++ b/src/haikuselect.h @@ -66,6 +66,15 @@ extern "C" extern void BClipboard_secondary_targets (char **buf, int len); + extern bool + BClipboard_owns_clipboard (void); + + extern bool + BClipboard_owns_primary (void); + + extern bool + BClipboard_owns_secondary (void); + /* Free the returned data. */ extern void BClipboard_free_data (void *ptr); #ifdef __cplusplus diff --git a/src/haikuterm.c b/src/haikuterm.c index 3e99cc1c8d9..93ba088f5b1 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -55,6 +55,8 @@ struct unhandled_event uint8_t buffer[200]; }; +static bool any_help_event_p = false; + char * get_keysym_name (int keysym) { @@ -281,7 +283,7 @@ haiku_new_font (struct frame *f, Lisp_Object font_object, int fontset) else FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit; - if (FRAME_HAIKU_WINDOW (f)) + if (FRAME_HAIKU_WINDOW (f) && !FRAME_TOOLTIP_P (f)) { adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), @@ -370,6 +372,13 @@ haiku_frame_raise_lower (struct frame *f, bool raise_p) BWindow_sync (FRAME_HAIKU_WINDOW (f)); unblock_input (); } + else + { + block_input (); + BWindow_send_behind (FRAME_HAIKU_WINDOW (f), NULL); + BWindow_sync (FRAME_HAIKU_WINDOW (f)); + unblock_input (); + } } /* Unfortunately, NOACTIVATE is not implementable on Haiku. */ @@ -2472,10 +2481,7 @@ haiku_default_font_parameter (struct frame *f, Lisp_Object parms) struct haiku_font_pattern ptn; ptn.specified = 0; - if (f->tooltip) - BFont_populate_plain_family (&ptn); - else - BFont_populate_fixed_family (&ptn); + BFont_populate_fixed_family (&ptn); if (ptn.specified & FSPEC_FAMILY) font = font_open_by_name (f, build_unibyte_string (ptn.family)); @@ -2590,6 +2596,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) struct unhandled_event *unhandled_events = NULL; int button_or_motion_p; int need_flush = 0; + int do_help = 0; if (!buf) buf = xmalloc (200); @@ -2638,9 +2645,19 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) int width = lrint (b->px_widthf); int height = lrint (b->px_heightf); + if (FRAME_TOOLTIP_P (f)) + { + FRAME_PIXEL_WIDTH (f) = width; + FRAME_PIXEL_HEIGHT (f) = height; + + haiku_clear_under_internal_border (f); + continue; + } + BView_draw_lock (FRAME_HAIKU_VIEW (f)); BView_resize_to (FRAME_HAIKU_VIEW (f), width, height); BView_draw_unlock (FRAME_HAIKU_VIEW (f)); + if (width != FRAME_PIXEL_WIDTH (f) || height != FRAME_PIXEL_HEIGHT (f) || (f->new_size_p @@ -2708,6 +2725,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) inev.kind = inev.code > 127 ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT; + inev.timestamp = b->time / 1000; inev.modifiers = haiku_modifiers_to_emacs (b->modifiers); XSETFRAME (inev.frame_or_window, f); break; @@ -2746,7 +2764,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) Lisp_Object frame; XSETFRAME (frame, f); - x_display_list->last_mouse_movement_time = time (NULL); + x_display_list->last_mouse_movement_time = b->time / 1000; button_or_motion_p = 1; if (hlinfo->mouse_face_hidden) @@ -2770,14 +2788,25 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) } haiku_new_focus_frame (x_display_list->focused_frame); - help_echo_string = Qnil; - gen_help_event (Qnil, frame, Qnil, Qnil, 0); + + if (any_help_event_p) + do_help = -1; } else { struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); struct haiku_rect r = dpyinfo->last_mouse_glyph; + /* For an unknown reason Haiku sends phantom motion events when a + tooltip frame is visible. FIXME */ + if (FRAMEP (tip_frame) + && FRAME_LIVE_P (XFRAME (tip_frame)) + && FRAME_VISIBLE_P (XFRAME (tip_frame)) + && f == dpyinfo->last_mouse_motion_frame + && b->x == dpyinfo->last_mouse_motion_x + && b->y == dpyinfo->last_mouse_motion_y) + continue; + dpyinfo->last_mouse_motion_x = b->x; dpyinfo->last_mouse_motion_y = b->y; dpyinfo->last_mouse_motion_frame = f; @@ -2816,9 +2845,9 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) remember_mouse_glyph (f, b->x, b->y, &FRAME_DISPLAY_INFO (f)->last_mouse_glyph); dpyinfo->last_mouse_glyph_frame = f; - gen_help_event (help_echo_string, frame, help_echo_window, - help_echo_object, help_echo_pos); } + else + help_echo_string = previous_help_echo_string; if (!NILP (Vmouse_autoselect_window)) { @@ -2838,6 +2867,10 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) last_mouse_window = window; } + + if (!NILP (help_echo_string) + || !NILP (previous_help_echo_string)) + do_help = 1; } break; } @@ -2857,7 +2890,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) inev.modifiers = haiku_modifiers_to_emacs (b->modifiers); x_display_list->last_mouse_glyph_frame = 0; - x_display_list->last_mouse_movement_time = time (NULL); + x_display_list->last_mouse_movement_time = b->time / 1000; button_or_motion_p = 1; /* Is this in the tab-bar? */ @@ -3262,20 +3295,20 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) if (inev.kind != NO_EVENT) { - if (inev.kind != HELP_EVENT) + if (inev.kind != HELP_EVENT && !inev.timestamp) inev.timestamp = (button_or_motion_p ? x_display_list->last_mouse_movement_time - : time (NULL)); + : system_time () / 1000); kbd_buffer_store_event_hold (&inev, hold_quit); ++message_count; } if (inev2.kind != NO_EVENT) { - if (inev2.kind != HELP_EVENT) + if (inev2.kind != HELP_EVENT && !inev.timestamp) inev2.timestamp = (button_or_motion_p ? x_display_list->last_mouse_movement_time - : time (NULL)); + : system_time () / 1000); kbd_buffer_store_event_hold (&inev2, hold_quit); ++message_count; } @@ -3289,6 +3322,28 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) xfree (old); } + if (do_help && !(hold_quit && hold_quit->kind != NO_EVENT)) + { + Lisp_Object help_frame = Qnil; + + if (x_display_list->last_mouse_frame) + XSETFRAME (help_frame, + x_display_list->last_mouse_frame); + + if (do_help > 0) + { + any_help_event_p = true; + gen_help_event (help_echo_string, help_frame, + help_echo_window, help_echo_object, + help_echo_pos); + } + else + { + help_echo_string = Qnil; + gen_help_event (Qnil, help_frame, Qnil, Qnil, 0); + } + } + if (need_flush) flush_dirty_back_buffers (); @@ -3507,7 +3562,10 @@ put_xrm_resource (Lisp_Object name, Lisp_Object val) void haiku_clear_under_internal_border (struct frame *f) { - if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0) + if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0 + /* This is needed because tooltip frames set up the internal + border before init_frame_faces. */ + && FRAME_FACE_CACHE (f)) { int border = FRAME_INTERNAL_BORDER_WIDTH (f); int width = FRAME_PIXEL_WIDTH (f); diff --git a/src/haikuterm.h b/src/haikuterm.h index 3e39403ab4d..de302883e48 100644 --- a/src/haikuterm.h +++ b/src/haikuterm.h @@ -178,6 +178,8 @@ struct x_output extern struct haiku_display_info *x_display_list; extern struct font_driver const haikufont_driver; +extern Lisp_Object tip_frame; + struct scroll_bar { /* These fields are shared by all vectors. */ diff --git a/src/image.c b/src/image.c index a4976caba86..ce9af2dd677 100644 --- a/src/image.c +++ b/src/image.c @@ -2906,9 +2906,8 @@ x_create_xrender_picture (struct frame *f, Emacs_Pixmap pixmap, int depth) { Picture p; Display *display = FRAME_X_DISPLAY (f); - int event_basep, error_basep; - if (XRenderQueryExtension (display, &event_basep, &error_basep)) + if (FRAME_DISPLAY_INFO (f)->xrender_supported_p) { if (depth <= 0) depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f)); @@ -11198,8 +11197,7 @@ The list of capabilities can include one or more of the following: # elif defined (HAVE_X_WINDOWS) && defined (HAVE_XRENDER) int event_basep, error_basep; - if (XRenderQueryExtension (FRAME_X_DISPLAY (f), - &event_basep, &error_basep)) + if (FRAME_DISPLAY_INFO (f)->xrender_supported_p) return list2 (Qscale, Qrotate90); # elif defined (HAVE_NTGUI) return (w32_image_rotations_p () diff --git a/src/keyboard.c b/src/keyboard.c index d2ab3a80249..441c23e10c7 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1897,6 +1897,9 @@ int poll_suppress_count; static struct atimer *poll_timer; +/* The poll period that constructed this timer. */ +static Lisp_Object poll_timer_time; + #if defined CYGWIN || defined DOS_NT /* Poll for input, so that we catch a C-g if it comes in. */ void @@ -1938,17 +1941,18 @@ start_polling (void) /* If poll timer doesn't exist, or we need one with a different interval, start a new one. */ - if (poll_timer == NULL - || poll_timer->interval.tv_sec != polling_period) + if (NUMBERP (Vpolling_period) + && (poll_timer == NULL + || NILP (Fequal (Vpolling_period, poll_timer_time)))) { - time_t period = max (1, min (polling_period, TYPE_MAXIMUM (time_t))); - struct timespec interval = make_timespec (period, 0); + struct timespec interval = dtotimespec (XFLOATINT (Vpolling_period)); if (poll_timer) cancel_atimer (poll_timer); poll_timer = start_atimer (ATIMER_CONTINUOUS, interval, poll_for_input, NULL); + poll_timer_time = Vpolling_period; } /* Let the timer's callback function poll for input @@ -2016,14 +2020,28 @@ void bind_polling_period (int n) { #ifdef POLL_FOR_INPUT - intmax_t new = polling_period; + if (FIXNUMP (Vpolling_period)) + { + intmax_t new = XFIXNUM (Vpolling_period); + + if (n > new) + new = n; + + stop_other_atimers (poll_timer); + stop_polling (); + specbind (Qpolling_period, make_int (new)); + } + else if (FLOATP (Vpolling_period)) + { + double new = XFLOAT_DATA (Vpolling_period); - if (n > new) - new = n; + stop_other_atimers (poll_timer); + stop_polling (); + specbind (Qpolling_period, (n > new + ? make_int (n) + : Vpolling_period)); + } - stop_other_atimers (poll_timer); - stop_polling (); - specbind (Qpolling_period, make_int (new)); /* Start a new alarm with the new period. */ start_polling (); #endif @@ -12066,6 +12084,11 @@ syms_of_keyboard (void) help_form_saved_window_configs = Qnil; staticpro (&help_form_saved_window_configs); +#ifdef POLL_FOR_INPUT + poll_timer_time = Qnil; + staticpro (&poll_timer_time); +#endif + defsubr (&Scurrent_idle_time); defsubr (&Sevent_symbol_parse_modifiers); defsubr (&Sevent_convert_list); @@ -12223,12 +12246,12 @@ The value may be integer or floating point. If the value is zero, don't echo at all. */); Vecho_keystrokes = make_fixnum (1); - DEFVAR_INT ("polling-period", polling_period, + DEFVAR_LISP ("polling-period", Vpolling_period, doc: /* Interval between polling for input during Lisp execution. The reason for polling is to make C-g work to stop a running program. Polling is needed only when using X windows and SIGIO does not work. Polling is automatically disabled in all other cases. */); - polling_period = 2; + Vpolling_period = make_float (2.0); DEFVAR_LISP ("double-click-time", Vdouble_click_time, doc: /* Maximum time between mouse clicks to make a double-click. diff --git a/src/nsterm.m b/src/nsterm.m index 4f60cc737da..a3c7b55218c 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -7071,6 +7071,9 @@ not_in_argv (NSString *arg) { struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe); struct frame *old_focus = dpyinfo->ns_focus_frame; + struct input_event event; + + EVENT_INIT (event); NSTRACE ("[EmacsView windowDidBecomeKey]"); @@ -7079,11 +7082,9 @@ not_in_argv (NSString *arg) ns_frame_rehighlight (emacsframe); - if (emacs_event) - { - emacs_event->kind = FOCUS_IN_EVENT; - EV_TRAILER ((id)nil); - } + event.kind = FOCUS_IN_EVENT; + XSETFRAME (event.frame_or_window, emacsframe); + kbd_buffer_store_event (&event); } diff --git a/src/pgtkfns.c b/src/pgtkfns.c index c604e2f1002..9c37c04810c 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -3128,7 +3128,7 @@ x_hide_tip (bool delete) value of x_gtk_use_system_tooltips might not be the same as used for the tooltip we have to hide, see Bug#30399. */ if ((NILP (tip_last_frame) && NILP (tip_frame)) - || (!x_gtk_use_system_tooltips + || (!use_system_tooltips && !delete && FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)) @@ -3161,7 +3161,7 @@ x_hide_tip (bool delete) /* When using GTK+ system tooltips (compare Bug#41200) reset tip_last_frame. It will be reassigned when showing the next GTK+ system tooltip. */ - if (x_gtk_use_system_tooltips) + if (use_system_tooltips) tip_last_frame = Qnil; /* Now look whether there's an Emacs tip around. */ @@ -3171,7 +3171,7 @@ x_hide_tip (bool delete) if (FRAME_LIVE_P (f)) { - if (delete || x_gtk_use_system_tooltips) + if (delete || use_system_tooltips) { /* Delete the Emacs tooltip frame when DELETE is true or we change the tooltip type from an Emacs one to @@ -3267,7 +3267,7 @@ Text larger than the specified size is clipped. */) else CHECK_FIXNUM (dy); - if (x_gtk_use_system_tooltips) + if (use_system_tooltips) { bool ok; @@ -4068,12 +4068,6 @@ If more space for files in the file chooser dialog is wanted, set this to nil to turn the additional text off. */); x_gtk_file_dialog_help_text = true; - DEFVAR_BOOL ("x-gtk-use-system-tooltips", x_gtk_use_system_tooltips, - doc: /* If non-nil with a Gtk+ built Emacs, the Gtk+ tooltip is used. -Otherwise use Emacs own tooltip implementation. -When using Gtk+ tooltips, the tooltip face is not used. */); - x_gtk_use_system_tooltips = true; - DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size, doc: /* Maximum size for tooltips. Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 0155ae991d3..8073f51c610 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -153,10 +153,24 @@ static int evq_flush (struct input_event *hold_quit) { struct event_queue_t *evq = &event_q; - int i, n = evq->nr; - for (i = 0; i < n; i++) - kbd_buffer_store_buffered_event (&evq->q[i], hold_quit); - evq->nr = 0; + int n = 0; + + while (evq->nr > 0) + { + /* kbd_buffer_store_buffered_event may do longjmp, so + we need to shift event queue first and pass the event + to kbd_buffer_store_buffered_event so that events in + queue are not processed twice. Bug#52941 */ + union buffered_input_event ev = evq->q[0]; + int i; + for (i = 1; i < evq->nr; i++) + evq->q[i - 1] = evq->q[i]; + evq->nr--; + + kbd_buffer_store_buffered_event (&ev, hold_quit); + n++; + } + return n; } @@ -3720,6 +3734,9 @@ pgtk_flash (struct frame *f) block_input (); { + if (!FRAME_CR_CONTEXT (f)) + return; + cairo_surface_t *surface_orig = FRAME_CR_SURFACE (f); int width = FRAME_CR_SURFACE_DESIRED_WIDTH (f); @@ -7027,13 +7044,12 @@ If set to a non-float value, there will be no wait at all. */); } /* Cairo does not allow resizing a surface/context after it is - * created, so we need to trash the old context, create a new context - * on the next cr_clip_begin with the new dimensions and request a - * re-draw. - * - * This Will leave the active context available to present on screen - * until a redrawn frame is completed. - */ + created, so we need to trash the old context, create a new context + on the next cr_clip_begin with the new dimensions and request a + re-draw. + + This will leave the active context available to present on screen + until a redrawn frame is completed. */ void pgtk_cr_update_surface_desired_size (struct frame *f, int width, int height, bool force) { diff --git a/src/syntax.c b/src/syntax.c index 9df878b8edf..13c36fdf3cd 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -1101,10 +1101,11 @@ this is probably the wrong function to use, because it can't take `syntax-after' instead. */) (Lisp_Object character) { - int char_int; CHECK_CHARACTER (character); - char_int = XFIXNUM (character); + int char_int = XFIXNAT (character); SETUP_BUFFER_SYNTAX_TABLE (); + if (NILP (BVAR (current_buffer, enable_multibyte_characters))) + char_int = make_char_multibyte (char_int); return make_fixnum (syntax_code_spec[SYNTAX (char_int)]); } diff --git a/src/verbose.mk.in b/src/verbose.mk.in index e3f56783031..eb99e426958 100644 --- a/src/verbose.mk.in +++ b/src/verbose.mk.in @@ -33,24 +33,45 @@ AM_V_GLOBALS = AM_V_NO_PD = AM_V_RC = else + +# Whether $(info ...) works. This is to work around a bug in GNU Make +# 4.3 and earlier, which implements $(info MSG) via two system calls +# { write (..., "MSG", 3); write (..., "\n", 1); } +# which looks bad when make -j interleaves two of these at about the same time. +# +# Later versions of GNU Make have the 'notintermediate' feature, +# so assume that $(info ...) works if this feature is present. +# +have_working_info = $(filter notintermediate,$(value .FEATURES)) +# +# The workaround is to use the shell and 'echo' rather than $(info ...). +# The workaround is done only for AM_V_ELC and AM_V_ELN, +# since the bug is not annoying elsewhere. + AM_V_AR = @$(info $ AR $@) AM_V_at = @ AM_V_CC = @$(info $ CC $@) AM_V_CXX = @$(info $ CXX $@) AM_V_CCLD = @$(info $ CCLD $@) AM_V_CXXLD = @$(info $ CXXLD $@) -ifeq ($(HAVE_NATIVE_COMP),yes) -ifeq ($(NATIVE_DISABLED),1) -AM_V_ELC = @$(info $ ELC $@) -AM_V_ELN = -else + +ifeq ($(HAVE_NATIVE_COMP)-$(NATIVE_DISABLED)-$(ANCIENT),yes--) +ifdef have_working_info AM_V_ELC = @$(info $ ELC+ELN $@) AM_V_ELN = @$(info $ ELN $@) +else +AM_V_ELC = @echo " ELC+ELN " $@; +AM_V_ELN = @echo " ELN " $@; endif else +ifdef have_working_info AM_V_ELC = @$(info $ ELC $@) +else +AM_V_ELC = @echo " ELC " $@; +endif AM_V_ELN = endif + AM_V_GEN = @$(info $ GEN $@) AM_V_GLOBALS = @$(info $ GEN globals.h) AM_V_NO_PD = --no-print-directory diff --git a/src/w32font.c b/src/w32font.c index 0495099db5c..c4a89446b98 100644 --- a/src/w32font.c +++ b/src/w32font.c @@ -2385,7 +2385,6 @@ font_supported_scripts (FONTSIGNATURE * sig) SUBRANGE (108, Qkharoshthi); SUBRANGE (109, Qtai_xuan_jing_symbol); SUBRANGE (110, Qcuneiform); - SUBRANGE (111, Qcuneiform_numbers_and_punctuation); SUBRANGE (111, Qcounting_rod_numeral); SUBRANGE (112, Qsundanese); SUBRANGE (113, Qlepcha); @@ -2828,8 +2827,6 @@ syms_of_w32font (void) DEFSYM (Qbuginese, "buginese"); DEFSYM (Qbuhid, "buhid"); DEFSYM (Qcuneiform, "cuneiform"); - DEFSYM (Qcuneiform_numbers_and_punctuation, - "cuneiform-numbers-and-punctuation"); DEFSYM (Qcypriot, "cypriot"); DEFSYM (Qdeseret, "deseret"); DEFSYM (Qglagolitic, "glagolitic"); diff --git a/src/xdisp.c b/src/xdisp.c index 977d31703fb..c695e466e78 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -19157,7 +19157,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) struct glyph_row *row; row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix); - while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos) + while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos + && !row->ends_at_zv_p) ++row; TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row), diff --git a/src/xfaces.c b/src/xfaces.c index 8064d47c947..6a279f87192 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -3165,14 +3165,15 @@ FRAME 0 means change the face on all frames, and change the default */ valid_p = true; - while (!NILP (CAR_SAFE(list))) + while (!NILP (CAR_SAFE (list))) { key = CAR_SAFE (list); list = CDR_SAFE (list); val = CAR_SAFE (list); list = CDR_SAFE (list); - if (NILP (key) || NILP (val)) + if (NILP (key) || (NILP (val) + && !EQ (key, QCposition))) { valid_p = false; break; @@ -6423,8 +6424,12 @@ face_at_buffer_position (struct window *w, ptrdiff_t pos, cached faces since we've looked up these faces, we need to look them up again. */ if (!default_face) - default_face = FACE_FROM_ID (f, - lookup_basic_face (w, f, DEFAULT_FACE_ID)); + { + if (FRAME_FACE_CACHE (f)->used == 0) + recompute_basic_faces (f); + default_face = FACE_FROM_ID (f, + lookup_basic_face (w, f, DEFAULT_FACE_ID)); + } } /* Optimize common cases where we can use the default face. */ diff --git a/src/xfns.c b/src/xfns.c index ffad0bc3d1a..7123198724a 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -40,6 +40,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <sys/types.h> #include <sys/stat.h> +#ifdef USE_XCB +#include <xcb/xcb.h> +#include <xcb/xproto.h> +#include <xcb/xcb_aux.h> +#endif + #include "bitmaps/gray.xbm" #include "xsettings.h" @@ -2643,11 +2649,7 @@ best_xim_style (struct x_display_info *dpyinfo, int nr_supported = ARRAYELTS (supported_xim_styles); if (dpyinfo->preferred_xim_style) - { - for (j = 0; j < xim->count_styles; ++j) - if (dpyinfo->preferred_xim_style == xim->supported_styles[j]) - return dpyinfo->preferred_xim_style; - } + return dpyinfo->preferred_xim_style; for (i = 0; i < nr_supported; ++i) for (j = 0; j < xim->count_styles; ++j) @@ -3049,7 +3051,7 @@ x_xim_text_to_utf8_unix (XIMText *text, ptrdiff_t *length) } nbytes = strlen (text->string.multi_byte); - setup_coding_system (Qutf_8_unix, &coding); + setup_coding_system (Vlocale_coding_system, &coding); coding.mode |= (CODING_MODE_LAST_BLOCK | CODING_MODE_SAFE_ENCODING); coding.source = (const unsigned char *) text->string.multi_byte; @@ -6486,7 +6488,11 @@ void x_sync (struct frame *f) { block_input (); +#ifndef USE_XCB XSync (FRAME_X_DISPLAY (f), False); +#else + xcb_aux_sync (FRAME_DISPLAY_INFO (f)->xcb_connection); +#endif unblock_input (); } @@ -7107,6 +7113,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) gui_figure_window_size (f, parms, false, false); { +#ifndef USE_XCB XSetWindowAttributes attrs; unsigned long mask; Atom type = FRAME_DISPLAY_INFO (f)->Xatom_net_window_type_tooltip; @@ -7143,6 +7150,47 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) XA_ATOM, 32, PropModeReplace, (unsigned char *)&type, 1); unblock_input (); +#else + uint32_t value_list[4]; + xcb_atom_t net_wm_window_type_tooltip + = (xcb_atom_t) dpyinfo->Xatom_net_window_type_tooltip; + + f->output_data.x->current_cursor = f->output_data.x->text_cursor; + /* Values are set in the order of their enumeration in `enum + xcb_cw_t'. */ + value_list[0] = FRAME_BACKGROUND_PIXEL (f); + value_list[1] = true; + value_list[2] = XCB_EVENT_MASK_STRUCTURE_NOTIFY; + value_list[3] = (xcb_cursor_t) f->output_data.x->text_cursor; + + block_input (); + tip_window + = FRAME_X_WINDOW (f) + = (Window) xcb_generate_id (dpyinfo->xcb_connection); + + xcb_create_window (dpyinfo->xcb_connection, + XCB_COPY_FROM_PARENT, + (xcb_window_t) tip_window, + (xcb_window_t) dpyinfo->root_window, + 0, 0, 1, 1, f->border_width, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + XCB_COPY_FROM_PARENT, + (XCB_CW_BACK_PIXEL + | XCB_CW_OVERRIDE_REDIRECT + | XCB_CW_EVENT_MASK + | XCB_CW_CURSOR), + &value_list); + + xcb_change_property (dpyinfo->xcb_connection, + XCB_PROP_MODE_REPLACE, + (xcb_window_t) tip_window, + (xcb_atom_t) dpyinfo->Xatom_net_window_type, + (xcb_atom_t) dpyinfo->Xatom_ATOM, + 32, 1, &net_wm_window_type_tooltip); + + initial_set_up_x_back_buffer (f); + unblock_input (); +#endif } x_make_gc (f); @@ -7361,13 +7409,13 @@ x_hide_tip (bool delete) } #ifdef USE_GTK - /* Any GTK+ system tooltip can be found via the x_output structure of - tip_last_frame, provided that frame is still live. Any Emacs - tooltip is found via the tip_frame variable. Note that the current - value of x_gtk_use_system_tooltips might not be the same as used - for the tooltip we have to hide, see Bug#30399. */ + /* Any GTK+ system tooltip can be found via the x_output structure + of tip_last_frame, provided that frame is still live. Any Emacs + tooltip is found via the tip_frame variable. Note that the + current value of use_system_tooltips might not be the same as + used for the tooltip we have to hide, see Bug#30399. */ if ((NILP (tip_last_frame) && NILP (tip_frame)) - || (!x_gtk_use_system_tooltips + || (!use_system_tooltips && !delete && !NILP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)) @@ -7400,7 +7448,7 @@ x_hide_tip (bool delete) /* When using GTK+ system tooltips (compare Bug#41200) reset tip_last_frame. It will be reassigned when showing the next GTK+ system tooltip. */ - if (x_gtk_use_system_tooltips) + if (use_system_tooltips) tip_last_frame = Qnil; /* Now look whether there's an Emacs tip around. */ @@ -7410,7 +7458,7 @@ x_hide_tip (bool delete) if (FRAME_LIVE_P (f)) { - if (delete || x_gtk_use_system_tooltips) + if (delete || use_system_tooltips) { /* Delete the Emacs tooltip frame when DELETE is true or we change the tooltip type from an Emacs one to @@ -7569,7 +7617,7 @@ Text larger than the specified size is clipped. */) CHECK_FIXNUM (dy); #ifdef USE_GTK - if (x_gtk_use_system_tooltips) + if (use_system_tooltips) { bool ok; @@ -7765,9 +7813,23 @@ Text larger than the specified size is clipped. */) /* Show tooltip frame. */ block_input (); +#ifndef USE_XCB XMoveResizeWindow (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f), root_x, root_y, width, height); XMapRaised (FRAME_X_DISPLAY (tip_f), FRAME_X_WINDOW (tip_f)); +#else + uint32_t values[] = { root_x, root_y, width, height, XCB_STACK_MODE_ABOVE }; + + xcb_configure_window (FRAME_DISPLAY_INFO (tip_f)->xcb_connection, + (xcb_window_t) FRAME_X_WINDOW (tip_f), + (XCB_CONFIG_WINDOW_X + | XCB_CONFIG_WINDOW_Y + | XCB_CONFIG_WINDOW_WIDTH + | XCB_CONFIG_WINDOW_HEIGHT + | XCB_CONFIG_WINDOW_STACK_MODE), &values); + xcb_map_window (FRAME_DISPLAY_INFO (tip_f)->xcb_connection, + (xcb_window_t) FRAME_X_WINDOW (tip_f)); +#endif unblock_input (); #ifdef USE_CAIRO @@ -8651,12 +8713,6 @@ If more space for files in the file chooser dialog is wanted, set this to nil to turn the additional text off. */); x_gtk_file_dialog_help_text = true; - DEFVAR_BOOL ("x-gtk-use-system-tooltips", x_gtk_use_system_tooltips, - doc: /* If non-nil with a Gtk+ built Emacs, the Gtk+ tooltip is used. -Otherwise use Emacs own tooltip implementation. -When using Gtk+ tooltips, the tooltip face is not used. */); - x_gtk_use_system_tooltips = true; - DEFVAR_LISP ("x-gtk-resize-child-frames", x_gtk_resize_child_frames, doc: /* If non-nil, resize child frames specially with GTK builds. If this is nil, resize child frames like any other frames. This is the diff --git a/src/xsettings.h b/src/xsettings.h index 266526df101..ccaa36489d0 100644 --- a/src/xsettings.h +++ b/src/xsettings.h @@ -21,15 +21,14 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #define XSETTINGS_H #ifndef HAVE_PGTK +#include "dispextern.h" #include <X11/Xlib.h> #endif struct x_display_info; struct pgtk_display_info; -#ifndef HAVE_PGTK -typedef struct x_display_info Display_Info; -#else +#ifdef HAVE_PGTK typedef struct pgtk_display_info Display_Info; #endif diff --git a/src/xterm.c b/src/xterm.c index ec415f5ffaf..36e0045d2ed 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -99,6 +99,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include "xterm.h" #include <X11/cursorfont.h> +#ifdef USE_XCB +#include <xcb/xproto.h> +#include <xcb/xcb.h> +#include <xcb/xcb_aux.h> +#endif + /* If we have Xfixes extension, use it for pointer blanking. */ #ifdef HAVE_XFIXES #include <X11/extensions/Xfixes.h> @@ -167,6 +173,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include "../lwlib/xlwmenu.h" #endif +#ifdef HAVE_XWIDGETS +#include <cairo-xlib.h> +#endif + #ifdef USE_X_TOOLKIT /* Include toolkit specific headers for the scroll bar widget. */ @@ -206,6 +216,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <X11/XKBlib.h> #endif +#if defined USE_XCB && defined USE_CAIRO_XCB +#define USE_CAIRO_XCB_SURFACE +#endif + /* Default to using XIM if available. */ #ifdef USE_XIM bool use_xim = true; @@ -777,11 +791,19 @@ x_begin_cr_clip (struct frame *f, GC gc) { int width = FRAME_CR_SURFACE_DESIRED_WIDTH (f); int height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f); - cairo_surface_t *surface - = cairo_xlib_surface_create (FRAME_X_DISPLAY (f), - FRAME_X_RAW_DRAWABLE (f), - FRAME_X_VISUAL (f), - width, height); + cairo_surface_t *surface; +#ifdef USE_CAIRO_XCB_SURFACE + if (FRAME_DISPLAY_INFO (f)->xcb_visual) + surface = cairo_xcb_surface_create (FRAME_DISPLAY_INFO (f)->xcb_connection, + (xcb_drawable_t) FRAME_X_RAW_DRAWABLE (f), + FRAME_DISPLAY_INFO (f)->xcb_visual, + width, height); + else +#endif + surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f), + FRAME_X_RAW_DRAWABLE (f), + FRAME_X_VISUAL (f), + width, height); cr = FRAME_CR_CONTEXT (f) = cairo_create (surface); cairo_surface_destroy (surface); @@ -850,6 +872,9 @@ x_try_cr_xlib_drawable (struct frame *f, GC gc) switch (cairo_surface_get_type (surface)) { case CAIRO_SURFACE_TYPE_XLIB: +#ifdef USE_CAIRO_XCB_SURFACE + case CAIRO_SURFACE_TYPE_XCB: +#endif cairo_surface_flush (surface); return true; @@ -1262,11 +1287,15 @@ x_clear_window (struct frame *f) cairo_paint (cr); x_end_cr_clip (f); #else +#ifndef USE_GTK if (FRAME_X_DOUBLE_BUFFERED_P (f)) +#endif x_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); +#ifndef USE_GTK else XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); #endif +#endif } #ifdef USE_CAIRO @@ -2768,8 +2797,9 @@ x_query_frame_background_color (struct frame *f, XColor *bgcolor) and names we've actually looked up; list-colors-display is probably the most color-intensive case we're likely to hit. */ -Status x_parse_color (struct frame *f, const char *color_name, - XColor *color) +Status +x_parse_color (struct frame *f, const char *color_name, + XColor *color) { /* Don't pass #RGB strings directly to XParseColor, because that follows the X convention of zero-extending each channel @@ -2798,6 +2828,10 @@ Status x_parse_color (struct frame *f, const char *color_name, } } + /* Some X servers send BadValue on empty color names. */ + if (!strlen (color_name)) + return 0; + if (XParseColor (dpy, cmap, color_name, color) == 0) /* No caching of negative results, currently. */ return 0; @@ -4473,15 +4507,19 @@ x_clear_area (struct frame *f, int x, int y, int width, int height) cairo_fill (cr); x_end_cr_clip (f); #else +#ifndef USE_GTK if (FRAME_X_DOUBLE_BUFFERED_P (f)) +#endif XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), f->output_data.x->reverse_gc, x, y, width, height); +#ifndef USE_GTK else x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), x, y, width, height, False); #endif +#endif } @@ -4528,6 +4566,7 @@ x_show_hourglass (struct frame *f) if (!x->hourglass_window) { +#ifndef USE_XCB unsigned long mask = CWCursor; XSetWindowAttributes attrs; #ifdef USE_GTK @@ -4540,12 +4579,41 @@ x_show_hourglass (struct frame *f) x->hourglass_window = XCreateWindow (dpy, parent, 0, 0, 32000, 32000, 0, 0, InputOnly, CopyFromParent, mask, &attrs); +#else + uint32_t cursor = (uint32_t) x->hourglass_cursor; +#ifdef USE_GTK + xcb_window_t parent = (xcb_window_t) FRAME_X_WINDOW (f); +#else + xcb_window_t parent = (xcb_window_t) FRAME_OUTER_WINDOW (f); +#endif + x->hourglass_window + = (Window) xcb_generate_id (FRAME_DISPLAY_INFO (f)->xcb_connection); + + xcb_create_window (FRAME_DISPLAY_INFO (f)->xcb_connection, + XCB_COPY_FROM_PARENT, + (xcb_window_t) x->hourglass_window, + parent, 0, 0, FRAME_PIXEL_WIDTH (f), + FRAME_PIXEL_HEIGHT (f), 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + XCB_COPY_FROM_PARENT, XCB_CW_CURSOR, + &cursor); +#endif } +#ifndef USE_XCB XMapRaised (dpy, x->hourglass_window); - XFlush (dpy); /* Ensure that the spinning hourglass is shown. */ flush_frame (f); +#else + uint32_t value = XCB_STACK_MODE_ABOVE; + + xcb_configure_window (FRAME_DISPLAY_INFO (f)->xcb_connection, + (xcb_window_t) x->hourglass_window, + XCB_CONFIG_WINDOW_STACK_MODE, &value); + xcb_map_window (FRAME_DISPLAY_INFO (f)->xcb_connection, + (xcb_window_t) x->hourglass_window); + xcb_flush (FRAME_DISPLAY_INFO (f)->xcb_connection); +#endif } } } @@ -4560,10 +4628,16 @@ x_hide_hourglass (struct frame *f) /* Watch out for newly created frames. */ if (x->hourglass_window) { +#ifndef USE_XCB XUnmapWindow (FRAME_X_DISPLAY (f), x->hourglass_window); /* Sync here because XTread_socket looks at the hourglass_p flag that is reset to zero below. */ XSync (FRAME_X_DISPLAY (f), False); +#else + xcb_unmap_window (FRAME_DISPLAY_INFO (f)->xcb_connection, + (xcb_window_t) x->hourglass_window); + xcb_aux_sync (FRAME_DISPLAY_INFO (f)->xcb_connection); +#endif x->hourglass_p = false; } } @@ -4576,38 +4650,6 @@ XTflash (struct frame *f) block_input (); { -#ifdef USE_GTK - /* Use Gdk routines to draw. This way, we won't draw over scroll bars - when the scroll bars and the edit widget share the same X window. */ - GdkWindow *window = gtk_widget_get_window (FRAME_GTK_WIDGET (f)); -#ifdef HAVE_GTK3 -#if GTK_CHECK_VERSION (3, 22, 0) - cairo_region_t *region = gdk_window_get_visible_region (window); - GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region); - cairo_t *cr = gdk_drawing_context_get_cairo_context (context); -#else - cairo_t *cr = gdk_cairo_create (window); -#endif - cairo_set_source_rgb (cr, 1, 1, 1); - cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE); -#define XFillRectangle(d, win, gc, x, y, w, h) \ - do { \ - cairo_rectangle (cr, x, y, w, h); \ - cairo_fill (cr); \ - } \ - while (false) -#else /* ! HAVE_GTK3 */ - GdkGCValues vals; - GdkGC *gc; - vals.foreground.pixel = (FRAME_FOREGROUND_PIXEL (f) - ^ FRAME_BACKGROUND_PIXEL (f)); - vals.function = GDK_XOR; - gc = gdk_gc_new_with_values (window, - &vals, GDK_GC_FUNCTION | GDK_GC_FOREGROUND); -#define XFillRectangle(d, win, gc, x, y, w, h) \ - gdk_draw_rectangle (window, gc, true, x, y, w, h) -#endif /* ! HAVE_GTK3 */ -#else /* ! USE_GTK */ GC gc; /* Create a GC that will use the GXxor function to flip foreground @@ -4622,7 +4664,6 @@ XTflash (struct frame *f) gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), GCFunction | GCForeground, &values); } -#endif { /* Get the height not including a menu bar widget. */ int height = FRAME_PIXEL_HEIGHT (f); @@ -4698,22 +4739,7 @@ XTflash (struct frame *f) XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); - -#ifdef USE_GTK -#ifdef HAVE_GTK3 -#if GTK_CHECK_VERSION (3, 22, 0) - gdk_window_end_draw_frame (window, context); - cairo_region_destroy (region); -#else - cairo_destroy (cr); -#endif -#else - g_object_unref (G_OBJECT (gc)); -#endif -#undef XFillRectangle -#else XFreeGC (FRAME_X_DISPLAY (f), gc); -#endif x_flush (f); } } @@ -4921,6 +4947,18 @@ x_scroll_run (struct window *w, struct run *run) x, to_y); cairo_surface_mark_dirty_rectangle (surface, x, to_y, width, height); } +#ifdef USE_CAIRO_XCB_SURFACE + else if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XCB) + { + cairo_surface_flush (surface); + xcb_copy_area (FRAME_DISPLAY_INFO (f)->xcb_connection, + (xcb_drawable_t) FRAME_X_DRAWABLE (f), + (xcb_drawable_t) FRAME_X_DRAWABLE (f), + (xcb_gcontext_t) XGContextFromGC (f->output_data.x->normal_gc), + x, from_y, x, to_y, width, height); + cairo_surface_mark_dirty_rectangle (surface, x, to_y, width, height); + } +#endif else { cairo_surface_t *s @@ -5436,11 +5474,6 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo) int syms_per_code; XModifierKeymap *mods; #ifdef HAVE_XKB - Atom meta; - Atom super; - Atom hyper; - Atom shiftlock; - Atom alt; int i; int found_meta_p = false; #endif @@ -5454,28 +5487,22 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo) #ifdef HAVE_XKB if (dpyinfo->xkb_desc) { - meta = XInternAtom (dpyinfo->display, "Meta", False); - super = XInternAtom (dpyinfo->display, "Super", False); - hyper = XInternAtom (dpyinfo->display, "Hyper", False); - shiftlock = XInternAtom (dpyinfo->display, "ShiftLock", False); - alt = XInternAtom (dpyinfo->display, "Alt", False); - for (i = 0; i < XkbNumVirtualMods; i++) { uint vmodmask = dpyinfo->xkb_desc->server->vmods[i]; - if (dpyinfo->xkb_desc->names->vmods[i] == meta) + if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Meta) { dpyinfo->meta_mod_mask |= vmodmask; found_meta_p = vmodmask; } - else if (dpyinfo->xkb_desc->names->vmods[i] == alt) + else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Alt) dpyinfo->alt_mod_mask |= vmodmask; - else if (dpyinfo->xkb_desc->names->vmods[i] == super) + else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Super) dpyinfo->super_mod_mask |= vmodmask; - else if (dpyinfo->xkb_desc->names->vmods[i] == hyper) + else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_Hyper) dpyinfo->hyper_mod_mask |= vmodmask; - else if (dpyinfo->xkb_desc->names->vmods[i] == shiftlock) + else if (dpyinfo->xkb_desc->names->vmods[i] == dpyinfo->Xatom_ShiftLock) dpyinfo->shift_lock_mask |= vmodmask; } @@ -8373,6 +8400,7 @@ x_filter_event (struct x_display_info *dpyinfo, XEvent *event) #ifdef USE_GTK } else if (f1 && (event->type == KeyPress + || event->type == KeyRelease #ifdef HAVE_XINPUT2 || xinput_event #endif @@ -8384,6 +8412,11 @@ x_filter_event (struct x_display_info *dpyinfo, XEvent *event) result = xg_filter_key (f1, event); unblock_input (); + if (result && f1) + /* There will probably be a GDK event generated soon, so + exercise the wire to make pselect return. */ + XNoOp (FRAME_X_DISPLAY (f1)); + return result; } @@ -8434,8 +8467,10 @@ event_handler_gdk (GdkXEvent *gxev, GdkEvent *ev, gpointer data) && xev->type == GenericEvent && (xev->xgeneric.extension == dpyinfo->xi2_opcode) - && (xev->xgeneric.evtype - == XI_KeyPress)) + && ((xev->xgeneric.evtype + == XI_KeyPress) + || (xev->xgeneric.evtype + == XI_KeyRelease))) #endif )) { @@ -8947,12 +8982,17 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (!FRAME_VISIBLE_P (f)) { block_input (); - /* The following two are commented out to avoid that a - plain invisible frame gets reported as iconified. That - problem occurred first for Emacs 26 and is described in - https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00133.html. */ -/** SET_FRAME_VISIBLE (f, 1); **/ -/** SET_FRAME_ICONIFIED (f, false); **/ + /* By default, do not set the frame's visibility here, see + https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00133.html. + The default behavior can be overridden by setting + 'x-set-frame-visibility-more-laxly' (Bug#49955, + Bug#53298). */ + if (EQ (x_set_frame_visibility_more_laxly, Qexpose) + || EQ (x_set_frame_visibility_more_laxly, Qt)) + { + SET_FRAME_VISIBLE (f, 1); + SET_FRAME_ICONIFIED (f, false); + } if (FRAME_X_DOUBLE_BUFFERED_P (f)) font_drop_xrender_surfaces (f); @@ -9236,7 +9276,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, int modifiers; Lisp_Object coding_system = Qlatin_1; Lisp_Object c; - /* Event will be modified. */ + /* `xkey' will be modified, but it's not important to modify + `event' itself. */ XKeyEvent xkey = event->xkey; #ifdef USE_GTK @@ -9498,8 +9539,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (keysym == NoSymbol) break; } - /* FIXME: check side effects and remove this. */ - ((XEvent *) event)->xkey = xkey; } done_keysym: #ifdef HAVE_X_I18N @@ -9571,26 +9610,33 @@ handle_one_xevent (struct x_display_info *dpyinfo, goto OTHER; case FocusIn: -#ifndef USE_GTK +#ifdef USE_GTK /* Some WMs (e.g. Mutter in Gnome Shell), don't unmap minimized/iconified windows; thus, for those WMs we won't get - a MapNotify when unminimizing/deconifying. Check here if we + a MapNotify when unminimizing/deiconifying. Check here if we are deiconizing a window (Bug42655). - But don't do that on GTK since it may cause a plain invisible - frame get reported as iconified, compare + But don't do that by default on GTK since it may cause a plain + invisible frame get reported as iconified, compare https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00133.html. - That is fixed above but bites us here again. */ - f = any; - if (f && FRAME_ICONIFIED_P (f)) - { - SET_FRAME_VISIBLE (f, 1); - SET_FRAME_ICONIFIED (f, false); - f->output_data.x->has_been_visible = true; - inev.ie.kind = DEICONIFY_EVENT; - XSETFRAME (inev.ie.frame_or_window, f); - } + That is fixed above but bites us here again. + + The option x_set_frame_visibility_more_laxly allows to override + the default behavior (Bug#49955, Bug#53298). */ + if (EQ (x_set_frame_visibility_more_laxly, Qfocus_in) + || EQ (x_set_frame_visibility_more_laxly, Qt)) #endif /* USE_GTK */ + { + f = any; + if (f && FRAME_ICONIFIED_P (f)) + { + SET_FRAME_VISIBLE (f, 1); + SET_FRAME_ICONIFIED (f, false); + f->output_data.x->has_been_visible = true; + inev.ie.kind = DEICONIFY_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); + } + } x_detect_focus_change (dpyinfo, any, event, &inev.ie); goto OTHER; @@ -10194,26 +10240,33 @@ handle_one_xevent (struct x_display_info *dpyinfo, { case XI_FocusIn: any = x_any_window_to_frame (dpyinfo, focusin->event); -#ifndef USE_GTK +#ifdef USE_GTK /* Some WMs (e.g. Mutter in Gnome Shell), don't unmap minimized/iconified windows; thus, for those WMs we won't get - a MapNotify when unminimizing/deconifying. Check here if we + a MapNotify when unminimizing/deiconifying. Check here if we are deiconizing a window (Bug42655). - But don't do that on GTK since it may cause a plain invisible - frame get reported as iconified, compare + But don't do that by default on GTK since it may cause a plain + invisible frame get reported as iconified, compare https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00133.html. - That is fixed above but bites us here again. */ - f = any; - if (f && FRAME_ICONIFIED_P (f)) + That is fixed above but bites us here again. + + The option x_set_frame_visibility_more_laxly allows to override + the default behavior (Bug#49955, Bug#53298). */ + if (EQ (x_set_frame_visibility_more_laxly, Qfocus_in) + || EQ (x_set_frame_visibility_more_laxly, Qt)) +#endif /* USE_GTK */ { - SET_FRAME_VISIBLE (f, 1); - SET_FRAME_ICONIFIED (f, false); - f->output_data.x->has_been_visible = true; - inev.ie.kind = DEICONIFY_EVENT; - XSETFRAME (inev.ie.frame_or_window, f); + f = any; + if (f && FRAME_ICONIFIED_P (f)) + { + SET_FRAME_VISIBLE (f, 1); + SET_FRAME_ICONIFIED (f, false); + f->output_data.x->has_been_visible = true; + inev.ie.kind = DEICONIFY_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); + } } -#endif /* USE_GTK */ x_detect_focus_change (dpyinfo, any, event, &inev.ie); goto XI_OTHER; case XI_FocusOut: @@ -10708,7 +10761,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (f && xev->evtype == XI_ButtonPress && !popup_activated () - && !x_window_to_scroll_bar (xev->display, xev->event, 2) + && !x_window_to_scroll_bar (dpyinfo->display, xev->event, 2) && !FRAME_NO_ACCEPT_FOCUS (f)) { /* When clicking into a child frame or when clicking @@ -10881,7 +10934,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, xkey.type = KeyPress; xkey.serial = xev->serial; xkey.send_event = xev->send_event; - xkey.display = xev->display; + xkey.display = dpyinfo->display; xkey.window = xev->event; xkey.root = xev->root; xkey.subwindow = xev->child; @@ -11227,7 +11280,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, xkey.type = KeyRelease; xkey.serial = xev->serial; xkey.send_event = xev->send_event; - xkey.display = xev->display; + xkey.display = dpyinfo->display; xkey.window = xev->event; xkey.root = xev->root; xkey.subwindow = xev->child; @@ -11523,8 +11576,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, XkbFreeKeyboard (dpyinfo->xkb_desc, XkbAllComponentsMask, True); dpyinfo->xkb_desc = NULL; } - - x_find_modifier_meanings (dpyinfo); } else { @@ -11542,6 +11593,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, } XkbRefreshKeyboardMapping (&xkbevent->map); + x_find_modifier_meanings (dpyinfo); } } #endif @@ -12698,9 +12750,11 @@ xim_initialize (struct x_display_info *dpyinfo, char *resource_name) ret = XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->rdb, xim_inst->resource_name, emacs_class, xim_instantiate_callback, - /* This is XPointer in XFree86 but (XPointer *) - on Tru64, at least, hence the configure test. */ - (XRegisterIMInstantiateCallback_arg6) xim_inst); + /* This is XPointer in XFree86 but (XPointer *) on Tru64, at + least, but the configure test doesn't work because + xim_instantiate_callback can either be XIMProc or + XIDProc, so just cast to void *. */ + (void *) xim_inst); eassert (ret == True); #else /* not HAVE_X11R6_XIM */ xim_open_dpy (dpyinfo, resource_name); @@ -12725,8 +12779,7 @@ xim_close_dpy (struct x_display_info *dpyinfo) { Bool ret = XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->rdb, xim_inst->resource_name, - emacs_class, xim_instantiate_callback, - (XRegisterIMInstantiateCallback_arg6) xim_inst); + emacs_class, xim_instantiate_callback, (void *) xim_inst); eassert (ret == True); } xfree (xim_inst->resource_name); @@ -15261,6 +15314,40 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) dpyinfo->supports_xdbe = true; #endif +#ifdef USE_XCB + xcb_screen_t *xcb_screen = NULL; + xcb_screen_iterator_t iter; + xcb_visualid_t wanted = { XVisualIDFromVisual (dpyinfo->visual) }; + xcb_depth_iterator_t depth_iter; + xcb_visualtype_iterator_t visual_iter; + + int screen = DefaultScreen (dpyinfo->display); + + iter = xcb_setup_roots_iterator (xcb_get_setup (dpyinfo->xcb_connection)); + for (; iter.rem; --screen, xcb_screen_next (&iter)) + { + if (!screen) + xcb_screen = iter.data; + } + + if (xcb_screen) + { + depth_iter = xcb_screen_allowed_depths_iterator (xcb_screen); + for (; depth_iter.rem; xcb_depth_next (&depth_iter)) + { + visual_iter = xcb_depth_visuals_iterator (depth_iter.data); + for (; visual_iter.rem; xcb_visualtype_next (&visual_iter)) + { + if (wanted == visual_iter.data->visual_id) + { + dpyinfo->xcb_visual = visual_iter.data; + break; + } + } + } + } +#endif + #ifdef HAVE_XINPUT2 dpyinfo->supports_xi2 = false; int rc; @@ -15329,9 +15416,19 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) XkbNewKeyboardNotifyMask | XkbMapNotifyMask, XkbNewKeyboardNotifyMask | XkbMapNotifyMask); } +#endif - /* Figure out which modifier bits mean what. */ - x_find_modifier_meanings (dpyinfo); +#ifdef HAVE_XRENDER + int event_base, error_base; + dpyinfo->xrender_supported_p + = XRenderQueryExtension (dpyinfo->display, &event_base, &error_base); + + if (dpyinfo->xrender_supported_p) + { + if (!XRenderQueryVersion (dpyinfo->display, &dpyinfo->xrender_major, + &dpyinfo->xrender_minor)) + dpyinfo->xrender_supported_p = false; + } #endif #if defined USE_CAIRO || defined HAVE_XFT @@ -15350,11 +15447,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) or larger than other for other applications, even if it is the same font name (monospace-10 for example). */ -# ifdef HAVE_XRENDER - int event_base, error_base; - XRenderQueryExtension (dpyinfo->display, &event_base, &error_base); -# endif - char *v = XGetDefault (dpyinfo->display, "Xft", "dpi"); double d; if (v != NULL && sscanf (v, "%lf", &d) == 1) @@ -15447,6 +15539,13 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) ATOM_REFS_INIT ("_NET_WM_STATE_SKIP_TASKBAR", Xatom_net_wm_state_skip_taskbar) ATOM_REFS_INIT ("_NET_WM_STATE_ABOVE", Xatom_net_wm_state_above) ATOM_REFS_INIT ("_NET_WM_STATE_BELOW", Xatom_net_wm_state_below) +#ifdef HAVE_XKB + ATOM_REFS_INIT ("Meta", Xatom_Meta) + ATOM_REFS_INIT ("Super", Xatom_Super) + ATOM_REFS_INIT ("Hyper", Xatom_Hyper) + ATOM_REFS_INIT ("ShiftLock", Xatom_ShiftLock) + ATOM_REFS_INIT ("Alt", Xatom_Alt) +#endif }; int i; @@ -15477,6 +15576,11 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) dpyinfo->Xatom_xsettings_sel = atoms_return[i]; } +#ifdef HAVE_XKB + /* Figure out which modifier bits mean what. */ + x_find_modifier_meanings (dpyinfo); +#endif + dpyinfo->x_dnd_atoms_size = 8; dpyinfo->x_dnd_atoms = xmalloc (sizeof *dpyinfo->x_dnd_atoms * dpyinfo->x_dnd_atoms_size); @@ -16128,6 +16232,7 @@ always uses gtk_window_move and ignores the value of this variable. */); This option is only effective when Emacs is built with XInput 2 support. */); Vx_scroll_event_delta_factor = make_float (1.0); + DEFSYM (Qexpose, "expose"); DEFVAR_BOOL ("x-gtk-use-native-input", x_gtk_use_native_input, doc: /* Non-nil means to use GTK for input method support. @@ -16135,6 +16240,21 @@ This provides better support for some modern input methods, and is only effective when Emacs is built with GTK. */); x_gtk_use_native_input = false; + DEFVAR_LISP ("x-set-frame-visibility-more-laxly", + x_set_frame_visibility_more_laxly, + doc: /* Non-nil means set frame visibility more laxly. +If this is nil, Emacs is more strict when marking a frame as visible. +Since this may cause problems on some window managers, this variable can +be also set as follows: The value `focus-in' means to mark a frame as +visible also when a FocusIn event is received for it on GTK builds. The +value `expose' means to mark a frame as visible also when an Expose +event is received for it on any X build. The value `t' means to mark a +frame as visible in either of these two cases. + +Note that any non-nil setting may cause invisible frames get erroneously +reported as iconified. */); + x_set_frame_visibility_more_laxly = Qnil; + DEFVAR_BOOL ("x-input-grab-touch-events", x_input_grab_touch_events, doc: /* Non-nil means to actively grab touch events. This means touch sequences that started on an Emacs frame will diff --git a/src/xterm.h b/src/xterm.h index 664db48392d..26b2851590d 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -78,6 +78,9 @@ typedef GtkWidget *xt_or_gtk_widget; #ifdef CAIRO_HAS_SVG_SURFACE #include <cairo-svg.h> #endif +#ifdef USE_CAIRO_XCB +#include <cairo-xcb.h> +#endif #endif #ifdef HAVE_X_I18N @@ -496,6 +499,11 @@ struct x_display_info /* SM */ Atom Xatom_SM_CLIENT_ID; +#ifdef HAVE_XKB + /* Virtual modifiers */ + Atom Xatom_Meta, Xatom_Super, Xatom_Hyper, Xatom_ShiftLock, Xatom_Alt; +#endif + #ifdef HAVE_XRANDR int xrandr_major_version; int xrandr_minor_version; @@ -507,6 +515,7 @@ struct x_display_info #ifdef USE_XCB xcb_connection_t *xcb_connection; + xcb_visualtype_t *xcb_visual; #endif #ifdef HAVE_XDBE @@ -531,6 +540,12 @@ struct x_display_info #ifdef USE_GTK bool prefer_native_input; #endif + +#ifdef HAVE_XRENDER + bool xrender_supported_p; + int xrender_major; + int xrender_minor; +#endif }; #ifdef HAVE_X_I18N diff --git a/src/xwidget.c b/src/xwidget.c index 45879b15cbe..fb66a17acd8 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -39,6 +39,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <webkit2/webkit2.h> #include <JavaScriptCore/JavaScript.h> #include <cairo.h> +#include <cairo-xlib.h> #ifndef HAVE_PGTK #include <X11/Xlib.h> #else @@ -1855,7 +1856,7 @@ webkit_js_to_lisp (JSCValue *value) const gint32 dlen = jsc_value_to_int32 (len); Lisp_Object obj; - if (! (0 <= dlen && dlen < PTRDIFF_MAX + 1.0)) + if (! (0 <= dlen && dlen < G_MAXINT32)) memory_full (SIZE_MAX); ptrdiff_t n = dlen; |