root/src/pgtkterm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pgtk_device_added_or_removal_cb
  2. pgtk_seat_added_cb
  3. pgtk_seat_removed_cb
  4. pgtk_enumerate_devices
  5. pgtk_free_devices
  6. pgtk_regenerate_devices
  7. pgtk_toolkit_position
  8. pgtk_get_device_for_event
  9. flip_cr_context
  10. evq_enqueue
  11. evq_flush
  12. mark_pgtkterm
  13. get_keysym_name
  14. frame_set_mouse_pixel_position
  15. pgtk_raise_frame
  16. pgtk_lower_frame
  17. pgtk_frame_raise_lower
  18. pgtk_free_frame_resources
  19. pgtk_destroy_window
  20. pgtk_calc_absolute_position
  21. pgtk_set_offset
  22. pgtk_set_window_size
  23. pgtk_iconify_frame
  24. pgtk_make_frame_visible_wait_for_map_event_cb
  25. pgtk_make_frame_visible_wait_for_map_event_timeout
  26. pgtk_wait_for_map_event
  27. pgtk_make_frame_visible
  28. pgtk_make_frame_invisible
  29. pgtk_make_frame_visible_invisible
  30. pgtk_new_font
  31. pgtk_display_pixel_height
  32. pgtk_display_pixel_width
  33. pgtk_set_parent_frame
  34. pgtk_set_no_focus_on_map
  35. pgtk_set_no_accept_focus
  36. pgtk_set_z_group
  37. pgtk_initialize_display_info
  38. pgtk_set_cursor_gc
  39. pgtk_set_mouse_face_gc
  40. pgtk_set_mode_line_face_gc
  41. pgtk_set_glyph_string_gc
  42. pgtk_set_glyph_string_clipping
  43. pgtk_set_glyph_string_clipping_exactly
  44. pgtk_compute_glyph_string_overhangs
  45. pgtk_clear_glyph_string_rect
  46. fill_background_by_face
  47. fill_background
  48. pgtk_draw_glyph_string_background
  49. pgtk_draw_rectangle
  50. pgtk_draw_glyph_string_foreground
  51. pgtk_draw_composite_glyph_string_foreground
  52. pgtk_draw_glyphless_glyph_string_foreground
  53. pgtk_compute_lighter_color
  54. pgtk_fill_trapezoid_for_relief
  55. pgtk_erase_corners_for_relief
  56. pgtk_setup_relief_color
  57. pgtk_setup_relief_colors
  58. pgtk_set_clip_rectangles
  59. pgtk_draw_relief_rect
  60. pgtk_draw_box_rect
  61. pgtk_draw_glyph_string_box
  62. pgtk_draw_horizontal_wave
  63. pgtk_draw_underwave
  64. pgtk_draw_image_relief
  65. pgtk_draw_glyph_string_bg_rect
  66. pgtk_cr_draw_image
  67. pgtk_draw_image_foreground
  68. pgtk_draw_image_glyph_string
  69. pgtk_draw_stretch_glyph_string
  70. pgtk_draw_glyph_string
  71. pgtk_define_frame_cursor
  72. pgtk_after_update_window_line
  73. pgtk_clear_frame_area
  74. pgtk_draw_hollow_cursor
  75. pgtk_draw_bar_cursor
  76. pgtk_draw_window_cursor
  77. pgtk_copy_bits
  78. pgtk_scroll_run
  79. pgtk_bitmap_icon
  80. pgtk_text_icon
  81. pgtk_update_begin
  82. pgtk_draw_vertical_window_border
  83. pgtk_draw_window_divider
  84. pgtk_update_end
  85. pgtk_frame_up_to_date
  86. pgtk_mouse_position
  87. pgtk_define_fringe_bitmap
  88. pgtk_destroy_fringe_bitmap
  89. pgtk_clip_to_row
  90. pgtk_draw_fringe_bitmap
  91. hourglass_cb
  92. pgtk_show_hourglass
  93. pgtk_hide_hourglass
  94. pgtk_flush_display
  95. pgtk_clear_frame
  96. recover_from_visible_bell
  97. pgtk_flash
  98. pgtk_ring_bell
  99. pgtk_read_socket
  100. pgtk_send_scroll_bar_event
  101. xg_scroll_callback
  102. xg_end_scroll_callback
  103. pgtk_create_toolkit_scroll_bar
  104. pgtk_create_horizontal_toolkit_scroll_bar
  105. pgtk_set_toolkit_scroll_bar_thumb
  106. pgtk_set_toolkit_horizontal_scroll_bar_thumb
  107. pgtk_scroll_bar_create
  108. pgtk_scroll_bar_remove
  109. pgtk_set_vertical_scroll_bar
  110. pgtk_set_horizontal_scroll_bar
  111. pgtk_condemn_scroll_bars
  112. pgtk_redeem_scroll_bar
  113. pgtk_judge_scroll_bars
  114. set_fullscreen_state
  115. pgtk_fullscreen_hook
  116. pgtk_delete_terminal
  117. pgtk_query_frame_background_color
  118. pgtk_free_pixmap
  119. pgtk_focus_frame
  120. set_opacity_recursively
  121. pgtk_set_frame_alpha
  122. frame_highlight
  123. frame_unhighlight
  124. pgtk_frame_rehighlight
  125. pgtk_frame_rehighlight_hook
  126. pgtk_toggle_invisible_pointer
  127. pgtk_new_focus_frame
  128. pgtk_buffer_flipping_unblocked_hook
  129. pgtk_create_terminal
  130. pgtk_window_is_of_frame_recursive
  131. pgtk_window_is_of_frame
  132. pgtk_any_window_to_frame
  133. pgtk_handle_event
  134. pgtk_fill_rectangle
  135. pgtk_clear_under_internal_border
  136. pgtk_handle_draw
  137. size_allocate
  138. get_modifier_values
  139. pgtk_gtk_to_emacs_modifiers
  140. pgtk_emacs_to_gtk_modifiers
  141. pgtk_enqueue_string
  142. pgtk_enqueue_preedit
  143. key_press_event
  144. pgtk_display_info_for_display
  145. key_release_event
  146. configure_event
  147. map_event
  148. window_state_event
  149. delete_event
  150. pgtk_focus_changed
  151. enter_notify_event
  152. leave_notify_event
  153. focus_in_event
  154. focus_out_event
  155. note_mouse_movement
  156. motion_notify_event
  157. construct_mouse_click
  158. button_event
  159. scroll_event
  160. symbol_to_drag_action
  161. drag_action_to_symbol
  162. pgtk_update_drop_status
  163. pgtk_finish_drop
  164. drag_leave
  165. drag_motion
  166. drag_drop
  167. pgtk_monitors_changed_cb
  168. pgtk_set_event_handler
  169. my_log_handler
  170. same_x_server
  171. pgtk_find_selection_owner
  172. pgtk_selection_event
  173. pgtk_display_x_warning
  174. pgtk_term_init
  175. pgtk_delete_display
  176. pgtk_xlfd_to_fontname
  177. pgtk_defined_color
  178. pgtk_parse_color
  179. pgtk_query_colors
  180. pgtk_query_color
  181. pgtk_clear_area
  182. syms_of_pgtkterm
  183. pgtk_cr_update_surface_desired_size
  184. pgtk_begin_cr_clip
  185. pgtk_end_cr_clip
  186. pgtk_set_cr_source_with_gc_foreground
  187. pgtk_set_cr_source_with_gc_background
  188. pgtk_set_cr_source_with_color
  189. pgtk_cr_draw_frame
  190. pgtk_cr_accumulate_data
  191. pgtk_cr_destroy_frame_context
  192. pgtk_cr_destroy
  193. pgtk_cr_export_frames

     1 /* Communication module for window systems using GTK.
     2 
     3 Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2023 Free Software
     4 Foundation, Inc.
     5 
     6 This file is part of GNU Emacs.
     7 
     8 GNU Emacs is free software: you can redistribute it and/or modify
     9 it under the terms of the GNU General Public License as published by
    10 the Free Software Foundation, either version 3 of the License, or (at
    11 your option) any later version.
    12 
    13 GNU Emacs is distributed in the hope that it will be useful,
    14 but WITHOUT ANY WARRANTY; without even the implied warranty of
    15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16 GNU General Public License for more details.
    17 
    18 You should have received a copy of the GNU General Public License
    19 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    20 
    21 /* This should be the first include, as it may set up #defines affecting
    22    interpretation of even the system includes. */
    23 #include <config.h>
    24 
    25 #include <cairo.h>
    26 #include <fcntl.h>
    27 #include <math.h>
    28 #include <pthread.h>
    29 #include <sys/types.h>
    30 #include <time.h>
    31 #include <signal.h>
    32 #include <unistd.h>
    33 #include <errno.h>
    34 
    35 #include <c-ctype.h>
    36 #include <c-strcase.h>
    37 #include <ftoastr.h>
    38 
    39 #include <dlfcn.h>
    40 
    41 #include "lisp.h"
    42 #include "blockinput.h"
    43 #include "frame.h"
    44 #include "sysselect.h"
    45 #include "gtkutil.h"
    46 #include "systime.h"
    47 #include "character.h"
    48 #include "xwidget.h"
    49 #include "fontset.h"
    50 #include "composite.h"
    51 #include "ccl.h"
    52 
    53 #include "termhooks.h"
    54 #include "termopts.h"
    55 #include "termchar.h"
    56 #include "emacs-icon.h"
    57 #include "menu.h"
    58 #include "window.h"
    59 #include "keyboard.h"
    60 #include "atimer.h"
    61 #include "buffer.h"
    62 #include "font.h"
    63 #include "xsettings.h"
    64 #include "emacsgtkfixed.h"
    65 
    66 #ifdef GDK_WINDOWING_WAYLAND
    67 #include <gdk/gdkwayland.h>
    68 #endif
    69 
    70 #define FRAME_CR_CONTEXT(f)             ((f)->output_data.pgtk->cr_context)
    71 #define FRAME_CR_ACTIVE_CONTEXT(f)      ((f)->output_data.pgtk->cr_active)
    72 #define FRAME_CR_SURFACE(f)             (cairo_get_target (FRAME_CR_CONTEXT (f)))
    73 
    74 /* Non-zero means that a HELP_EVENT has been generated since Emacs
    75    start.  */
    76 
    77 static bool any_help_event_p;
    78 
    79 /* Chain of existing displays */
    80 struct pgtk_display_info *x_display_list;
    81 
    82 struct event_queue_t
    83 {
    84   union buffered_input_event *q;
    85   int nr, cap;
    86 };
    87 
    88 /* A queue of events that will be read by the read_socket_hook.  */
    89 static struct event_queue_t event_q;
    90 
    91 /* Non-zero timeout value means ignore next mouse click if it arrives
    92    before that timeout elapses (i.e. as part of the same sequence of
    93    events resulting from clicking on a frame to select it).  */
    94 static Time ignore_next_mouse_click_timeout;
    95 
    96 /* The default Emacs icon .  */
    97 static Lisp_Object xg_default_icon_file;
    98 
    99 /* The current GdkDragContext of a drop.  */
   100 static GdkDragContext *current_drop_context;
   101 
   102 /* Whether or not current_drop_context was set from a drop
   103    handler.  */
   104 static bool current_drop_context_drop;
   105 
   106 /* The time of the last drop.  */
   107 static guint32 current_drop_time;
   108 
   109 static void pgtk_delete_display (struct pgtk_display_info *);
   110 static void pgtk_clear_frame_area (struct frame *, int, int, int, int);
   111 static void pgtk_fill_rectangle (struct frame *, unsigned long, int, int,
   112                                  int, int, bool);
   113 static void pgtk_clip_to_row (struct window *, struct glyph_row *,
   114                               enum glyph_row_area, cairo_t *);
   115 static struct frame *pgtk_any_window_to_frame (GdkWindow *);
   116 static void pgtk_regenerate_devices (struct pgtk_display_info *);
   117 
   118 static void
   119 pgtk_device_added_or_removal_cb (GdkSeat *seat, GdkDevice *device,
   120                                  gpointer user_data)
   121 {
   122   pgtk_regenerate_devices (user_data);
   123 }
   124 
   125 static void
   126 pgtk_seat_added_cb (GdkDisplay *dpy, GdkSeat *seat,
   127                     gpointer user_data)
   128 {
   129   pgtk_regenerate_devices (user_data);
   130 
   131   g_signal_connect (G_OBJECT (seat), "device-added",
   132                     G_CALLBACK (pgtk_device_added_or_removal_cb),
   133                     user_data);
   134   g_signal_connect (G_OBJECT (seat), "device-removed",
   135                     G_CALLBACK (pgtk_device_added_or_removal_cb),
   136                     user_data);
   137 }
   138 
   139 static void
   140 pgtk_seat_removed_cb (GdkDisplay *dpy, GdkSeat *seat,
   141                       gpointer user_data)
   142 {
   143   pgtk_regenerate_devices (user_data);
   144 
   145   g_signal_handlers_disconnect_by_func (G_OBJECT (seat),
   146                                         G_CALLBACK (pgtk_device_added_or_removal_cb),
   147                                         user_data);
   148 }
   149 
   150 static void
   151 pgtk_enumerate_devices (struct pgtk_display_info *dpyinfo,
   152                         bool initial_p)
   153 {
   154   struct pgtk_device_t *rec;
   155   GList *all_seats, *devices_on_seat, *tem, *t1;
   156   GdkSeat *seat;
   157   char printbuf[1026]; /* Believe it or not, some device names are
   158                           actually almost this long.  */
   159 
   160   block_input ();
   161   all_seats = gdk_display_list_seats (dpyinfo->gdpy);
   162 
   163   for (tem = all_seats; tem; tem = tem->next)
   164     {
   165       seat = GDK_SEAT (tem->data);
   166 
   167       if (initial_p)
   168         {
   169           g_signal_connect (G_OBJECT (seat), "device-added",
   170                             G_CALLBACK (pgtk_device_added_or_removal_cb),
   171                             dpyinfo);
   172           g_signal_connect (G_OBJECT (seat), "device-removed",
   173                             G_CALLBACK (pgtk_device_added_or_removal_cb),
   174                             dpyinfo);
   175         }
   176 
   177       /* We only want slaves, not master devices.  */
   178       devices_on_seat = gdk_seat_get_slaves (seat,
   179                                              GDK_SEAT_CAPABILITY_ALL);
   180 
   181       for (t1 = devices_on_seat; t1; t1 = t1->next)
   182         {
   183           rec = xmalloc (sizeof *rec);
   184           rec->seat = g_object_ref (seat);
   185           rec->device = GDK_DEVICE (t1->data);
   186 
   187           snprintf (printbuf, 1026, "%u:%s",
   188                     gdk_device_get_source (rec->device),
   189                     gdk_device_get_name (rec->device));
   190 
   191           rec->name = build_string (printbuf);
   192           rec->next = dpyinfo->devices;
   193           dpyinfo->devices = rec;
   194         }
   195 
   196       g_list_free (devices_on_seat);
   197     }
   198 
   199   g_list_free (all_seats);
   200   unblock_input ();
   201 }
   202 
   203 static void
   204 pgtk_free_devices (struct pgtk_display_info *dpyinfo)
   205 {
   206   struct pgtk_device_t *last, *tem;
   207 
   208   tem = dpyinfo->devices;
   209   while (tem)
   210     {
   211       last = tem;
   212       tem = tem->next;
   213 
   214       g_object_unref (last->seat);
   215       xfree (last);
   216     }
   217 
   218   dpyinfo->devices = NULL;
   219 }
   220 
   221 static void
   222 pgtk_regenerate_devices (struct pgtk_display_info *dpyinfo)
   223 {
   224   pgtk_free_devices (dpyinfo);
   225   pgtk_enumerate_devices (dpyinfo, false);
   226 }
   227 
   228 static void
   229 pgtk_toolkit_position (struct frame *f, int x, int y,
   230                        bool *menu_bar_p, bool *tool_bar_p)
   231 {
   232   GdkRectangle test_rect;
   233   int scale;
   234 
   235   y += (FRAME_MENUBAR_HEIGHT (f)
   236         + FRAME_TOOLBAR_TOP_HEIGHT (f));
   237   x += FRAME_TOOLBAR_LEFT_WIDTH (f);
   238 
   239   if (FRAME_EXTERNAL_MENU_BAR (f))
   240     *menu_bar_p = (x >= 0 && x < FRAME_PIXEL_WIDTH (f)
   241                    && y >= 0 && y < FRAME_MENUBAR_HEIGHT (f));
   242 
   243   if (FRAME_X_OUTPUT (f)->toolbar_widget)
   244     {
   245       scale = xg_get_scale (f);
   246       test_rect.x = x / scale;
   247       test_rect.y = y / scale;
   248       test_rect.width = 1;
   249       test_rect.height = 1;
   250 
   251       *tool_bar_p = gtk_widget_intersect (FRAME_X_OUTPUT (f)->toolbar_widget,
   252                                           &test_rect, NULL);
   253     }
   254 }
   255 
   256 static Lisp_Object
   257 pgtk_get_device_for_event (struct pgtk_display_info *dpyinfo,
   258                            GdkEvent *event)
   259 {
   260   struct pgtk_device_t *tem;
   261   GdkDevice *device;
   262 
   263   device = gdk_event_get_source_device (event);
   264 
   265   if (!device)
   266     return Qt;
   267 
   268   for (tem = dpyinfo->devices; tem; tem = tem->next)
   269     {
   270       if (tem->device == device)
   271         return tem->name;
   272     }
   273 
   274   return Qt;
   275 }
   276 
   277 /* This is not a flip context in the same sense as gpu rendering
   278    scenes, it only occurs when a new context was required due to a
   279    resize or other fundamental change.  This is called when that
   280    context's surface has completed drawing.  */
   281 
   282 static void
   283 flip_cr_context (struct frame *f)
   284 {
   285   cairo_t *cr = FRAME_CR_ACTIVE_CONTEXT (f);
   286 
   287   block_input ();
   288   if (cr != FRAME_CR_CONTEXT (f))
   289     {
   290       cairo_destroy (cr);
   291 
   292       FRAME_CR_ACTIVE_CONTEXT (f)
   293         = cairo_reference (FRAME_CR_CONTEXT (f));
   294     }
   295   unblock_input ();
   296 }
   297 
   298 
   299 static void
   300 evq_enqueue (union buffered_input_event *ev)
   301 {
   302   struct event_queue_t *evq = &event_q;
   303   struct frame *frame;
   304   struct pgtk_display_info *dpyinfo;
   305 
   306   if (evq->cap == 0)
   307     {
   308       evq->cap = 4;
   309       evq->q = xmalloc (sizeof *evq->q * evq->cap);
   310     }
   311 
   312   if (evq->nr >= evq->cap)
   313     {
   314       evq->cap += evq->cap / 2;
   315       evq->q = xrealloc (evq->q, sizeof *evq->q * evq->cap);
   316     }
   317 
   318   evq->q[evq->nr++] = *ev;
   319 
   320   if (ev->ie.kind != SELECTION_REQUEST_EVENT
   321       && ev->ie.kind != SELECTION_CLEAR_EVENT)
   322     {
   323       frame = NULL;
   324 
   325       if (WINDOWP (ev->ie.frame_or_window))
   326         frame = WINDOW_XFRAME (XWINDOW (ev->ie.frame_or_window));
   327 
   328       if (FRAMEP (ev->ie.frame_or_window))
   329         frame = XFRAME (ev->ie.frame_or_window);
   330 
   331       if (frame)
   332         {
   333           dpyinfo = FRAME_DISPLAY_INFO (frame);
   334 
   335           if (dpyinfo->last_user_time < ev->ie.timestamp)
   336             dpyinfo->last_user_time = ev->ie.timestamp;
   337         }
   338     }
   339 
   340   raise (SIGIO);
   341 }
   342 
   343 static int
   344 evq_flush (struct input_event *hold_quit)
   345 {
   346   struct event_queue_t *evq = &event_q;
   347   int n = 0;
   348 
   349   while (evq->nr > 0)
   350     {
   351       /* kbd_buffer_store_buffered_event may do longjmp, so
   352          we need to shift event queue first and pass the event
   353          to kbd_buffer_store_buffered_event so that events in
   354          queue are not processed twice.  Bug#52941 */
   355       union buffered_input_event ev = evq->q[0];
   356       int i;
   357       for (i = 1; i < evq->nr; i++)
   358         evq->q[i - 1] = evq->q[i];
   359       evq->nr--;
   360 
   361       kbd_buffer_store_buffered_event (&ev, hold_quit);
   362       n++;
   363     }
   364 
   365   return n;
   366 }
   367 
   368 void
   369 mark_pgtkterm (void)
   370 {
   371   struct pgtk_display_info *dpyinfo;
   372   struct pgtk_device_t *device;
   373   struct event_queue_t *evq = &event_q;
   374   int i, n = evq->nr;
   375 
   376   for (i = 0; i < n; i++)
   377     {
   378       union buffered_input_event *ev = &evq->q[i];
   379 
   380       /* Selection requests don't have Lisp object members.  */
   381 
   382       if (ev->ie.kind == SELECTION_REQUEST_EVENT
   383           || ev->ie.kind == SELECTION_CLEAR_EVENT)
   384         continue;
   385 
   386       mark_object (ev->ie.x);
   387       mark_object (ev->ie.y);
   388       mark_object (ev->ie.frame_or_window);
   389       mark_object (ev->ie.arg);
   390       mark_object (ev->ie.device);
   391     }
   392 
   393   for (dpyinfo = x_display_list; dpyinfo;
   394        dpyinfo = dpyinfo->next)
   395     {
   396       for (device = dpyinfo->devices; device;
   397            device = device->next)
   398         mark_object (device->name);
   399     }
   400 }
   401 
   402 char *
   403 get_keysym_name (int keysym)
   404 {
   405   return gdk_keyval_name (keysym);
   406 }
   407 
   408 void
   409 frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
   410 /* --------------------------------------------------------------------------
   411      Programmatically reposition mouse pointer in pixel coordinates
   412    -------------------------------------------------------------------------- */
   413 {
   414 }
   415 
   416 /* Raise frame F.  */
   417 
   418 static void
   419 pgtk_raise_frame (struct frame *f)
   420 {
   421   /* This works only for non-child frames on X.
   422      It does not work for child frames on X, and it does not work
   423      on Wayland too. */
   424   block_input ();
   425   if (FRAME_VISIBLE_P (f))
   426     gdk_window_raise (gtk_widget_get_window (FRAME_WIDGET (f)));
   427   unblock_input ();
   428 }
   429 
   430 /* Lower frame F.  */
   431 
   432 static void
   433 pgtk_lower_frame (struct frame *f)
   434 {
   435   if (FRAME_VISIBLE_P (f))
   436     {
   437       block_input ();
   438       gdk_window_lower (gtk_widget_get_window (FRAME_WIDGET (f)));
   439       unblock_input ();
   440     }
   441 }
   442 
   443 static void
   444 pgtk_frame_raise_lower (struct frame *f, bool raise_flag)
   445 {
   446   if (raise_flag)
   447     pgtk_raise_frame (f);
   448   else
   449     pgtk_lower_frame (f);
   450 }
   451 
   452 /* Free X resources of frame F.  */
   453 
   454 void
   455 pgtk_free_frame_resources (struct frame *f)
   456 {
   457   struct pgtk_display_info *dpyinfo;
   458   Mouse_HLInfo *hlinfo;
   459 
   460   check_window_system (f);
   461   dpyinfo = FRAME_DISPLAY_INFO (f);
   462   hlinfo = MOUSE_HL_INFO (f);
   463 
   464   block_input ();
   465 
   466 #ifdef HAVE_XWIDGETS
   467   kill_frame_xwidget_views (f);
   468 #endif
   469   free_frame_faces (f);
   470 
   471   if (FRAME_X_OUTPUT (f)->scale_factor_atimer != NULL)
   472     {
   473       cancel_atimer (FRAME_X_OUTPUT (f)->scale_factor_atimer);
   474       FRAME_X_OUTPUT (f)->scale_factor_atimer = NULL;
   475     }
   476 
   477 #define CLEAR_IF_EQ(FIELD)      \
   478   do { if (f == dpyinfo->FIELD) dpyinfo->FIELD = 0; } while (false)
   479 
   480   CLEAR_IF_EQ (x_focus_frame);
   481   CLEAR_IF_EQ (highlight_frame);
   482   CLEAR_IF_EQ (x_focus_event_frame);
   483   CLEAR_IF_EQ (last_mouse_frame);
   484   CLEAR_IF_EQ (last_mouse_motion_frame);
   485   CLEAR_IF_EQ (last_mouse_glyph_frame);
   486   CLEAR_IF_EQ (im.focused_frame);
   487 
   488 #undef CLEAR_IF_EQ
   489 
   490   if (f == hlinfo->mouse_face_mouse_frame)
   491     reset_mouse_highlight (hlinfo);
   492 
   493   g_clear_object (&FRAME_X_OUTPUT (f)->text_cursor);
   494   g_clear_object (&FRAME_X_OUTPUT (f)->nontext_cursor);
   495   g_clear_object (&FRAME_X_OUTPUT (f)->modeline_cursor);
   496   g_clear_object (&FRAME_X_OUTPUT (f)->hand_cursor);
   497   g_clear_object (&FRAME_X_OUTPUT (f)->hourglass_cursor);
   498   g_clear_object (&FRAME_X_OUTPUT (f)->horizontal_drag_cursor);
   499   g_clear_object (&FRAME_X_OUTPUT (f)->vertical_drag_cursor);
   500   g_clear_object (&FRAME_X_OUTPUT (f)->left_edge_cursor);
   501   g_clear_object (&FRAME_X_OUTPUT (f)->right_edge_cursor);
   502   g_clear_object (&FRAME_X_OUTPUT (f)->top_edge_cursor);
   503   g_clear_object (&FRAME_X_OUTPUT (f)->bottom_edge_cursor);
   504   g_clear_object (&FRAME_X_OUTPUT (f)->top_left_corner_cursor);
   505   g_clear_object (&FRAME_X_OUTPUT (f)->top_right_corner_cursor);
   506   g_clear_object (&FRAME_X_OUTPUT (f)->bottom_right_corner_cursor);
   507   g_clear_object (&FRAME_X_OUTPUT (f)->bottom_left_corner_cursor);
   508 
   509 
   510   if (FRAME_X_OUTPUT (f)->border_color_css_provider != NULL)
   511     {
   512       GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f));
   513       GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider;
   514       gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old));
   515       g_object_unref (old);
   516       FRAME_X_OUTPUT (f)->border_color_css_provider = NULL;
   517     }
   518 
   519   if (FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider != NULL)
   520     {
   521       GtkCssProvider *old
   522         = FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider;
   523       g_object_unref (old);
   524       FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider = NULL;
   525     }
   526 
   527   if (FRAME_X_OUTPUT (f)->scrollbar_background_css_provider != NULL)
   528     {
   529       GtkCssProvider *old
   530         = FRAME_X_OUTPUT (f)->scrollbar_background_css_provider;
   531       g_object_unref (old);
   532       FRAME_X_OUTPUT (f)->scrollbar_background_css_provider = NULL;
   533     }
   534 
   535   gtk_widget_destroy (FRAME_WIDGET (f));
   536 
   537   if (FRAME_X_OUTPUT (f)->cr_surface_visible_bell != NULL)
   538     {
   539       cairo_surface_destroy (FRAME_X_OUTPUT (f)->cr_surface_visible_bell);
   540       FRAME_X_OUTPUT (f)->cr_surface_visible_bell = NULL;
   541     }
   542 
   543   if (FRAME_X_OUTPUT (f)->atimer_visible_bell != NULL)
   544     {
   545       cancel_atimer (FRAME_X_OUTPUT (f)->atimer_visible_bell);
   546       FRAME_X_OUTPUT (f)->atimer_visible_bell = NULL;
   547     }
   548 
   549   xfree (f->output_data.pgtk);
   550   f->output_data.pgtk = NULL;
   551 
   552   unblock_input ();
   553 }
   554 
   555 void
   556 pgtk_destroy_window (struct frame *f)
   557 /* --------------------------------------------------------------------------
   558      External: Delete the window
   559    -------------------------------------------------------------------------- */
   560 {
   561   struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   562 
   563   check_window_system (f);
   564   if (dpyinfo->gdpy != NULL)
   565     pgtk_free_frame_resources (f);
   566 
   567   dpyinfo->reference_count--;
   568 }
   569 
   570 /* Calculate the absolute position in frame F
   571    from its current recorded position values and gravity.  */
   572 
   573 static void
   574 pgtk_calc_absolute_position (struct frame *f)
   575 {
   576   int flags = f->size_hint_flags;
   577   struct frame *p = FRAME_PARENT_FRAME (f);
   578 
   579   /* We have nothing to do if the current position
   580      is already for the top-left corner.  */
   581   if (! ((flags & XNegative) || (flags & YNegative)))
   582     return;
   583 
   584   /* Treat negative positions as relative to the leftmost bottommost
   585      position that fits on the screen.  */
   586   if ((flags & XNegative) && (f->left_pos <= 0))
   587     {
   588       int width = FRAME_PIXEL_WIDTH (f);
   589 
   590       /* A frame that has been visible at least once should have outer
   591          edges.  */
   592       if (f->output_data.pgtk->has_been_visible && !p)
   593         {
   594           Lisp_Object frame;
   595           Lisp_Object edges = Qnil;
   596 
   597           XSETFRAME (frame, f);
   598           edges = Fpgtk_frame_edges (frame, Qouter_edges);
   599           if (!NILP (edges))
   600             width = (XFIXNUM (Fnth (make_fixnum (2), edges))
   601                      - XFIXNUM (Fnth (make_fixnum (0), edges)));
   602         }
   603 
   604       if (p)
   605         f->left_pos = (FRAME_PIXEL_WIDTH (p) - width - 2 * f->border_width
   606                        + f->left_pos);
   607       else
   608         f->left_pos = (pgtk_display_pixel_width (FRAME_DISPLAY_INFO (f))
   609                        - width + f->left_pos);
   610 
   611     }
   612 
   613   if ((flags & YNegative) && (f->top_pos <= 0))
   614     {
   615       int height = FRAME_PIXEL_HEIGHT (f);
   616 
   617       if (f->output_data.pgtk->has_been_visible && !p)
   618         {
   619           Lisp_Object frame;
   620           Lisp_Object edges = Qnil;
   621 
   622           XSETFRAME (frame, f);
   623           if (NILP (edges))
   624             edges = Fpgtk_frame_edges (frame, Qouter_edges);
   625           if (!NILP (edges))
   626             height = (XFIXNUM (Fnth (make_fixnum (3), edges))
   627                       - XFIXNUM (Fnth (make_fixnum (1), edges)));
   628         }
   629 
   630       if (p)
   631         f->top_pos = (FRAME_PIXEL_HEIGHT (p) - height - 2 * f->border_width
   632                        + f->top_pos);
   633       else
   634         f->top_pos = (pgtk_display_pixel_height (FRAME_DISPLAY_INFO (f))
   635                       - height + f->top_pos);
   636   }
   637 
   638   /* The left_pos and top_pos
   639      are now relative to the top and left screen edges,
   640      so the flags should correspond.  */
   641   f->size_hint_flags &= ~ (XNegative | YNegative);
   642 }
   643 
   644 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
   645    to really change the position, and 0 when calling from
   646    x_make_frame_visible (in that case, XOFF and YOFF are the current
   647    position values).  It is -1 when calling from x_set_frame_parameters,
   648    which means, do adjust for borders but don't change the gravity.  */
   649 
   650 static void
   651 pgtk_set_offset (struct frame *f, int xoff, int yoff, int change_gravity)
   652 {
   653   if (change_gravity > 0)
   654     {
   655       f->top_pos = yoff;
   656       f->left_pos = xoff;
   657       f->size_hint_flags &= ~ (XNegative | YNegative);
   658       if (xoff < 0)
   659         f->size_hint_flags |= XNegative;
   660       if (yoff < 0)
   661         f->size_hint_flags |= YNegative;
   662       f->win_gravity = NorthWestGravity;
   663     }
   664 
   665   pgtk_calc_absolute_position (f);
   666 
   667   block_input ();
   668   xg_wm_set_size_hint (f, 0, false);
   669 
   670   if (change_gravity != 0)
   671     {
   672       if (FRAME_GTK_OUTER_WIDGET (f))
   673         gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
   674                          f->left_pos, f->top_pos);
   675       else
   676         {
   677           GtkWidget *fixed = FRAME_GTK_WIDGET (f);
   678           GtkWidget *parent = gtk_widget_get_parent (fixed);
   679           gtk_fixed_move (GTK_FIXED (parent), fixed,
   680                           f->left_pos, f->top_pos);
   681         }
   682     }
   683   unblock_input ();
   684   return;
   685 }
   686 
   687 static void
   688 pgtk_set_window_size (struct frame *f, bool change_gravity,
   689                       int width, int height)
   690 /* --------------------------------------------------------------------------
   691      Adjust window pixel size based on given character grid size
   692      Impl is a bit more complex than other terms, need to do some
   693      internal clipping.
   694    -------------------------------------------------------------------------- */
   695 {
   696   int pixelwidth, pixelheight;
   697 
   698   block_input ();
   699 
   700   gtk_widget_get_size_request (FRAME_GTK_WIDGET (f), &pixelwidth,
   701                                &pixelheight);
   702 
   703   pixelwidth = width;
   704   pixelheight = height;
   705 
   706   for (GtkWidget * w = FRAME_GTK_WIDGET (f); w != NULL;
   707        w = gtk_widget_get_parent (w))
   708     {
   709       gint wd, hi;
   710       gtk_widget_get_size_request (w, &wd, &hi);
   711     }
   712 
   713   f->output_data.pgtk->preferred_width = pixelwidth;
   714   f->output_data.pgtk->preferred_height = pixelheight;
   715   xg_wm_set_size_hint (f, 0, 0);
   716   xg_frame_set_char_size (f, pixelwidth, pixelheight);
   717   gtk_widget_queue_resize (FRAME_WIDGET (f));
   718 
   719   unblock_input ();
   720 }
   721 
   722 void
   723 pgtk_iconify_frame (struct frame *f)
   724 {
   725   GtkWindow *window;
   726 
   727   /* Don't keep the highlight on an invisible frame.  */
   728 
   729   if (FRAME_DISPLAY_INFO (f)->highlight_frame == f)
   730     FRAME_DISPLAY_INFO (f)->highlight_frame = NULL;
   731 
   732   /* If the frame is already iconified, return.  */
   733 
   734   if (FRAME_ICONIFIED_P (f))
   735     return;
   736 
   737   /* Child frames on PGTK have no outer widgets.  In that case, simply
   738      refuse to iconify the frame.  */
   739 
   740   if (FRAME_GTK_OUTER_WIDGET (f))
   741     {
   742       if (!FRAME_VISIBLE_P (f))
   743         gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
   744 
   745       window = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
   746 
   747       gtk_window_iconify (window);
   748 
   749       /* Don't make the frame iconified here.  Doing so will cause it
   750          to be skipped by redisplay, until GDK says it is deiconified
   751          (see window_state_event for more details).  However, if the
   752          window server rejects the iconification request, GDK will
   753          never tell Emacs about the iconification not happening,
   754          leading to the frame not being redisplayed until the next
   755          window state change.  */
   756 
   757       /* SET_FRAME_VISIBLE (f, 0);
   758          SET_FRAME_ICONIFIED (f, true); */
   759     }
   760 }
   761 
   762 static gboolean
   763 pgtk_make_frame_visible_wait_for_map_event_cb (GtkWidget *widget,
   764                                                GdkEventAny *event,
   765                                                gpointer user_data)
   766 {
   767   int *foundptr = user_data;
   768   *foundptr = 1;
   769   return FALSE;
   770 }
   771 
   772 static gboolean
   773 pgtk_make_frame_visible_wait_for_map_event_timeout (gpointer user_data)
   774 {
   775   int *timedoutptr = user_data;
   776   *timedoutptr = 1;
   777   return FALSE;
   778 }
   779 
   780 static void
   781 pgtk_wait_for_map_event (struct frame *f, bool multiple_times)
   782 {
   783   if (FLOATP (Vpgtk_wait_for_event_timeout))
   784     {
   785       guint msec
   786         = (guint) (XFLOAT_DATA (Vpgtk_wait_for_event_timeout) * 1000);
   787       int found = 0;
   788       int timed_out = 0;
   789       gulong id
   790         = g_signal_connect (FRAME_WIDGET (f), "map-event",
   791                             G_CALLBACK
   792                             (pgtk_make_frame_visible_wait_for_map_event_cb),
   793                             &found);
   794       guint src
   795         = g_timeout_add (msec,
   796                          pgtk_make_frame_visible_wait_for_map_event_timeout,
   797                          &timed_out);
   798 
   799       if (!multiple_times)
   800         {
   801           while (!found && !timed_out)
   802             gtk_main_iteration ();
   803         }
   804       else
   805         {
   806           while (!timed_out)
   807             gtk_main_iteration ();
   808         }
   809 
   810       g_signal_handler_disconnect (FRAME_WIDGET (f), id);
   811 
   812       if (!timed_out)
   813         g_source_remove (src);
   814     }
   815 }
   816 
   817 void
   818 pgtk_make_frame_visible (struct frame *f)
   819 {
   820   GtkWidget *win = FRAME_GTK_OUTER_WIDGET (f);
   821 
   822   if (!FRAME_VISIBLE_P (f))
   823     {
   824       gtk_widget_show (FRAME_WIDGET (f));
   825       if (win)
   826         gtk_window_deiconify (GTK_WINDOW (win));
   827 
   828       pgtk_wait_for_map_event (f, false);
   829     }
   830 }
   831 
   832 
   833 void
   834 pgtk_make_frame_invisible (struct frame *f)
   835 {
   836   gtk_widget_hide (FRAME_WIDGET (f));
   837 
   838   /* Handle any pending map event(s), then make the frame visible
   839      manually, to avoid race conditions.  */
   840   pgtk_wait_for_map_event (f, true);
   841 
   842   SET_FRAME_VISIBLE (f, 0);
   843   SET_FRAME_ICONIFIED (f, false);
   844 }
   845 
   846 static void
   847 pgtk_make_frame_visible_invisible (struct frame *f, bool visible)
   848 {
   849   if (visible)
   850     pgtk_make_frame_visible (f);
   851   else
   852     pgtk_make_frame_invisible (f);
   853 }
   854 
   855 static Lisp_Object
   856 pgtk_new_font (struct frame *f, Lisp_Object font_object, int fontset)
   857 {
   858   struct font *font = XFONT_OBJECT (font_object);
   859   int font_ascent, font_descent;
   860 
   861   if (fontset < 0)
   862     fontset = fontset_from_font (font_object);
   863   FRAME_FONTSET (f) = fontset;
   864 
   865   if (FRAME_FONT (f) == font)
   866     {
   867       /* This font is already set in frame F.  There's nothing more to
   868          do.  */
   869       return font_object;
   870     }
   871 
   872   FRAME_FONT (f) = font;
   873 
   874   FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
   875   FRAME_COLUMN_WIDTH (f) = font->average_width;
   876   get_font_ascent_descent (font, &font_ascent, &font_descent);
   877   FRAME_LINE_HEIGHT (f) = font_ascent + font_descent;
   878 
   879   /* We could use a more elaborate calculation here.  */
   880   FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
   881 
   882   /* Compute the scroll bar width in character columns.  */
   883   if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
   884     {
   885       int wid = FRAME_COLUMN_WIDTH (f);
   886       FRAME_CONFIG_SCROLL_BAR_COLS (f)
   887         = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
   888     }
   889   else
   890     {
   891       int wid = FRAME_COLUMN_WIDTH (f);
   892       FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
   893     }
   894 
   895   /* Compute the scroll bar height in character lines.  */
   896   if (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0)
   897     {
   898       int height = FRAME_LINE_HEIGHT (f);
   899       FRAME_CONFIG_SCROLL_BAR_LINES (f)
   900         = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + height - 1) / height;
   901     }
   902   else
   903     {
   904       int height = FRAME_LINE_HEIGHT (f);
   905       FRAME_CONFIG_SCROLL_BAR_LINES (f) = (14 + height - 1) / height;
   906     }
   907 
   908   /* Now make the frame display the given font.  */
   909   if (FRAME_GTK_WIDGET (f) != NULL)
   910     adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
   911                        FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3,
   912                        false, Qfont);
   913 
   914   return font_object;
   915 }
   916 
   917 int
   918 pgtk_display_pixel_height (struct pgtk_display_info *dpyinfo)
   919 {
   920   GdkDisplay *gdpy = dpyinfo->gdpy;
   921   GdkScreen *gscr = gdk_display_get_default_screen (gdpy);
   922 
   923   return gdk_screen_get_height (gscr);
   924 }
   925 
   926 int
   927 pgtk_display_pixel_width (struct pgtk_display_info *dpyinfo)
   928 {
   929   GdkDisplay *gdpy = dpyinfo->gdpy;
   930   GdkScreen *gscr = gdk_display_get_default_screen (gdpy);
   931 
   932   return gdk_screen_get_width (gscr);
   933 }
   934 
   935 void
   936 pgtk_set_parent_frame (struct frame *f, Lisp_Object new_value,
   937                        Lisp_Object old_value)
   938 {
   939   struct frame *p = NULL;
   940 
   941   if (!NILP (new_value)
   942       && (!FRAMEP (new_value)
   943           || !FRAME_LIVE_P (p = XFRAME (new_value))
   944           || !FRAME_PGTK_P (p)))
   945     {
   946       store_frame_param (f, Qparent_frame, old_value);
   947       error ("Invalid specification of `parent-frame'");
   948     }
   949 
   950   if (p != FRAME_PARENT_FRAME (f))
   951     {
   952       block_input ();
   953 
   954       if (p != NULL)
   955         {
   956           if (FRAME_DISPLAY_INFO (f) != FRAME_DISPLAY_INFO (p))
   957             error ("Cross display reparent.");
   958         }
   959 
   960       GtkWidget *fixed = FRAME_GTK_WIDGET (f);
   961 
   962       GtkAllocation alloc;
   963       gtk_widget_get_allocation (fixed, &alloc);
   964       g_object_ref (fixed);
   965 
   966       /* Remember the css provider, and restore it later. */
   967       GtkCssProvider *provider = FRAME_X_OUTPUT (f)->border_color_css_provider;
   968       FRAME_X_OUTPUT (f)->border_color_css_provider = NULL;
   969       {
   970         GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f));
   971         if (provider != NULL)
   972           gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (provider));
   973       }
   974 
   975       {
   976         GtkWidget *whbox_of_f = gtk_widget_get_parent (fixed);
   977         /* Here, unhighlight can be called and may change
   978            border_color_css_provider.  */
   979         gtk_container_remove (GTK_CONTAINER (whbox_of_f), fixed);
   980 
   981         if (FRAME_GTK_OUTER_WIDGET (f))
   982           {
   983             gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
   984             FRAME_GTK_OUTER_WIDGET (f) = NULL;
   985             FRAME_OUTPUT_DATA (f)->vbox_widget = NULL;
   986             FRAME_OUTPUT_DATA (f)->hbox_widget = NULL;
   987             FRAME_OUTPUT_DATA (f)->menubar_widget = NULL;
   988             FRAME_OUTPUT_DATA (f)->toolbar_widget = NULL;
   989             FRAME_OUTPUT_DATA (f)->ttip_widget = NULL;
   990             FRAME_OUTPUT_DATA (f)->ttip_lbl = NULL;
   991             FRAME_OUTPUT_DATA (f)->ttip_window = NULL;
   992           }
   993       }
   994 
   995       if (p == NULL)
   996         {
   997           xg_create_frame_outer_widgets (f);
   998           pgtk_set_event_handler (f);
   999           gtk_box_pack_start (GTK_BOX (f->output_data.pgtk->hbox_widget),
  1000                               fixed, TRUE, TRUE, 0);
  1001           f->output_data.pgtk->preferred_width = alloc.width;
  1002           f->output_data.pgtk->preferred_height = alloc.height;
  1003           xg_wm_set_size_hint (f, 0, 0);
  1004           xg_frame_set_char_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, alloc.width),
  1005                                   FRAME_PIXEL_TO_TEXT_HEIGHT (f, alloc.height));
  1006           gtk_widget_queue_resize (FRAME_WIDGET (f));
  1007           gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
  1008         }
  1009       else
  1010         {
  1011           GtkWidget *fixed_of_p = FRAME_GTK_WIDGET (p);
  1012           gtk_fixed_put (GTK_FIXED (fixed_of_p), fixed, f->left_pos, f->top_pos);
  1013           gtk_widget_set_size_request (fixed, alloc.width, alloc.height);
  1014           gtk_widget_show_all (fixed);
  1015         }
  1016 
  1017       /* Restore css provider. */
  1018       GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f));
  1019       GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider;
  1020       FRAME_X_OUTPUT (f)->border_color_css_provider = provider;
  1021       if (provider != NULL)
  1022         {
  1023           gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (provider),
  1024                                           GTK_STYLE_PROVIDER_PRIORITY_USER);
  1025         }
  1026       if (old != NULL)
  1027         {
  1028           gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old));
  1029           g_object_unref(old);
  1030         }
  1031 
  1032       g_object_unref (fixed);
  1033 
  1034       unblock_input ();
  1035 
  1036       fset_parent_frame (f, new_value);
  1037     }
  1038 }
  1039 
  1040 /* Doesn't work on wayland.  */
  1041 void
  1042 pgtk_set_no_focus_on_map (struct frame *f, Lisp_Object new_value,
  1043                           Lisp_Object old_value)
  1044 {
  1045   if (!EQ (new_value, old_value))
  1046     {
  1047       xg_set_no_focus_on_map (f, new_value);
  1048       FRAME_NO_FOCUS_ON_MAP (f) = !NILP (new_value);
  1049     }
  1050 }
  1051 
  1052 void
  1053 pgtk_set_no_accept_focus (struct frame *f, Lisp_Object new_value,
  1054                           Lisp_Object old_value)
  1055 {
  1056   xg_set_no_accept_focus (f, new_value);
  1057   FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
  1058 }
  1059 
  1060 void
  1061 pgtk_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
  1062 {
  1063   if (!FRAME_GTK_OUTER_WIDGET (f))
  1064     return;
  1065 
  1066   if (NILP (new_value))
  1067     {
  1068       gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
  1069                                  FALSE);
  1070       gtk_window_set_keep_below (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
  1071                                  FALSE);
  1072       FRAME_Z_GROUP (f) = z_group_none;
  1073     }
  1074   else if (EQ (new_value, Qabove))
  1075     {
  1076       gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
  1077                                  TRUE);
  1078       gtk_window_set_keep_below (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
  1079                                  FALSE);
  1080       FRAME_Z_GROUP (f) = z_group_above;
  1081     }
  1082   else if (EQ (new_value, Qabove_suspended))
  1083     {
  1084       gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
  1085                                  FALSE);
  1086       FRAME_Z_GROUP (f) = z_group_above_suspended;
  1087     }
  1088   else if (EQ (new_value, Qbelow))
  1089     {
  1090       gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
  1091                                  FALSE);
  1092       gtk_window_set_keep_below (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
  1093                                  TRUE);
  1094       FRAME_Z_GROUP (f) = z_group_below;
  1095     }
  1096   else
  1097     error ("Invalid z-group specification");
  1098 }
  1099 
  1100 static void
  1101 pgtk_initialize_display_info (struct pgtk_display_info *dpyinfo)
  1102 /* --------------------------------------------------------------------------
  1103       Initialize global info and storage for display.
  1104    -------------------------------------------------------------------------- */
  1105 {
  1106   dpyinfo->resx = 96;
  1107   dpyinfo->resy = 96;
  1108   dpyinfo->color_p = 1;
  1109   dpyinfo->n_planes = 32;
  1110   dpyinfo->root_window = 42;    /* a placeholder.. */
  1111   dpyinfo->highlight_frame = dpyinfo->x_focus_frame = NULL;
  1112   dpyinfo->n_fonts = 0;
  1113   dpyinfo->smallest_font_height = 1;
  1114   dpyinfo->smallest_char_width = 1;
  1115 
  1116   reset_mouse_highlight (&dpyinfo->mouse_highlight);
  1117 }
  1118 
  1119 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
  1120    face.  */
  1121 
  1122 static void
  1123 pgtk_set_cursor_gc (struct glyph_string *s)
  1124 {
  1125   if (s->font == FRAME_FONT (s->f)
  1126       && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
  1127       && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f) && !s->cmp)
  1128       s->xgcv = FRAME_X_OUTPUT (s->f)->cursor_xgcv;
  1129   else
  1130     {
  1131       /* Cursor on non-default face: must merge.  */
  1132       Emacs_GC xgcv;
  1133 
  1134       xgcv.background = FRAME_X_OUTPUT (s->f)->cursor_color;
  1135       xgcv.foreground = s->face->background;
  1136 
  1137       /* If the glyph would be invisible, try a different foreground.  */
  1138       if (xgcv.foreground == xgcv.background)
  1139         xgcv.foreground = s->face->foreground;
  1140       if (xgcv.foreground == xgcv.background)
  1141         xgcv.foreground = FRAME_X_OUTPUT (s->f)->cursor_foreground_color;
  1142       if (xgcv.foreground == xgcv.background)
  1143         xgcv.foreground = s->face->foreground;
  1144 
  1145       /* Make sure the cursor is distinct from text in this face.  */
  1146       if (xgcv.background == s->face->background
  1147           && xgcv.foreground == s->face->foreground)
  1148         {
  1149           xgcv.background = s->face->foreground;
  1150           xgcv.foreground = s->face->background;
  1151         }
  1152 
  1153       s->xgcv = xgcv;
  1154     }
  1155 }
  1156 
  1157 
  1158 /* Set up S->gc of glyph string S for drawing text in mouse face.  */
  1159 
  1160 static void
  1161 pgtk_set_mouse_face_gc (struct glyph_string *s)
  1162 {
  1163   prepare_face_for_display (s->f, s->face);
  1164 
  1165   if (s->font == s->face->font)
  1166     {
  1167       s->xgcv.foreground = s->face->foreground;
  1168       s->xgcv.background = s->face->background;
  1169     }
  1170   else
  1171     {
  1172       /* Otherwise construct scratch_cursor_gc with values from FACE
  1173          except for FONT.  */
  1174       Emacs_GC xgcv;
  1175 
  1176       xgcv.background = s->face->background;
  1177       xgcv.foreground = s->face->foreground;
  1178 
  1179       s->xgcv = xgcv;
  1180 
  1181     }
  1182 }
  1183 
  1184 
  1185 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
  1186    Faces to use in the mode line have already been computed when the
  1187    matrix was built, so there isn't much to do, here.  */
  1188 
  1189 static void
  1190 pgtk_set_mode_line_face_gc (struct glyph_string *s)
  1191 {
  1192   s->xgcv.foreground = s->face->foreground;
  1193   s->xgcv.background = s->face->background;
  1194 }
  1195 
  1196 
  1197 /* Set S->gc of glyph string S for drawing that glyph string.  Set
  1198    S->stippled_p to a non-zero value if the face of S has a stipple
  1199    pattern.  */
  1200 
  1201 static void
  1202 pgtk_set_glyph_string_gc (struct glyph_string *s)
  1203 {
  1204   prepare_face_for_display (s->f, s->face);
  1205 
  1206   if (s->hl == DRAW_NORMAL_TEXT)
  1207     {
  1208       s->xgcv.foreground = s->face->foreground;
  1209       s->xgcv.background = s->face->background;
  1210       s->stippled_p = s->face->stipple != 0;
  1211     }
  1212   else if (s->hl == DRAW_INVERSE_VIDEO)
  1213     {
  1214       pgtk_set_mode_line_face_gc (s);
  1215       s->stippled_p = s->face->stipple != 0;
  1216     }
  1217   else if (s->hl == DRAW_CURSOR)
  1218     {
  1219       pgtk_set_cursor_gc (s);
  1220       s->stippled_p = false;
  1221     }
  1222   else if (s->hl == DRAW_MOUSE_FACE)
  1223     {
  1224       pgtk_set_mouse_face_gc (s);
  1225       s->stippled_p = s->face->stipple != 0;
  1226     }
  1227   else if (s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
  1228     {
  1229       s->xgcv.foreground = s->face->foreground;
  1230       s->xgcv.background = s->face->background;
  1231       s->stippled_p = s->face->stipple != 0;
  1232     }
  1233   else
  1234     emacs_abort ();
  1235 }
  1236 
  1237 
  1238 /* Set clipping for output of glyph string S.  S may be part of a mode
  1239    line or menu if we don't have X toolkit support.  */
  1240 
  1241 static void
  1242 pgtk_set_glyph_string_clipping (struct glyph_string *s, cairo_t * cr)
  1243 {
  1244   XRectangle r[2];
  1245   int n = get_glyph_string_clip_rects (s, r, 2);
  1246 
  1247   if (n > 0)
  1248     {
  1249       for (int i = 0; i < n; i++)
  1250         {
  1251           cairo_rectangle (cr, r[i].x, r[i].y, r[i].width, r[i].height);
  1252         }
  1253       cairo_clip (cr);
  1254     }
  1255 }
  1256 
  1257 /* Set SRC's clipping for output of glyph string DST.  This is called
  1258    when we are drawing DST's left_overhang or right_overhang only in
  1259    the area of SRC.  */
  1260 
  1261 static void
  1262 pgtk_set_glyph_string_clipping_exactly (struct glyph_string *src,
  1263                                         struct glyph_string *dst, cairo_t * cr)
  1264 {
  1265   dst->clip[0].x = src->x;
  1266   dst->clip[0].y = src->y;
  1267   dst->clip[0].width = src->width;
  1268   dst->clip[0].height = src->height;
  1269   dst->num_clips = 1;
  1270 
  1271   cairo_rectangle (cr, src->x, src->y, src->width, src->height);
  1272   cairo_clip (cr);
  1273 }
  1274 
  1275 /* RIF:
  1276    Compute left and right overhang of glyph string S.  */
  1277 
  1278 static void
  1279 pgtk_compute_glyph_string_overhangs (struct glyph_string *s)
  1280 {
  1281   if (s->cmp == NULL
  1282       && (s->first_glyph->type == CHAR_GLYPH
  1283           || s->first_glyph->type == COMPOSITE_GLYPH))
  1284     {
  1285       struct font_metrics metrics;
  1286 
  1287       if (s->first_glyph->type == CHAR_GLYPH)
  1288         {
  1289           unsigned *code = alloca (sizeof (unsigned) * s->nchars);
  1290           struct font *font = s->font;
  1291           int i;
  1292 
  1293           for (i = 0; i < s->nchars; i++)
  1294             code[i] = s->char2b[i];
  1295           font->driver->text_extents (font, code, s->nchars, &metrics);
  1296         }
  1297       else
  1298         {
  1299           Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
  1300 
  1301           composition_gstring_width (gstring, s->cmp_from, s->cmp_to,
  1302                                      &metrics);
  1303         }
  1304       s->right_overhang = (metrics.rbearing > metrics.width
  1305                            ? metrics.rbearing - metrics.width : 0);
  1306       s->left_overhang = metrics.lbearing < 0 ? -metrics.lbearing : 0;
  1307     }
  1308   else if (s->cmp)
  1309     {
  1310       s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width;
  1311       s->left_overhang = -s->cmp->lbearing;
  1312     }
  1313 }
  1314 
  1315 /* Fill rectangle X, Y, W, H with background color of glyph string
  1316    S.  */
  1317 static void
  1318 pgtk_clear_glyph_string_rect (struct glyph_string *s, int x, int y,
  1319                               int w, int h)
  1320 {
  1321   pgtk_fill_rectangle (s->f, s->xgcv.background, x, y, w, h,
  1322                        (s->first_glyph->type != STRETCH_GLYPH
  1323                         || s->hl != DRAW_CURSOR));
  1324 }
  1325 
  1326 static void
  1327 fill_background_by_face (struct frame *f, struct face *face, int x, int y,
  1328                          int width, int height)
  1329 {
  1330   cairo_t *cr = pgtk_begin_cr_clip (f);
  1331   double r, g, b, a;
  1332 
  1333   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
  1334   cairo_rectangle (cr, x, y, width, height);
  1335   cairo_clip (cr);
  1336 
  1337   r = ((face->background >> 16) & 0xff) / 255.0;
  1338   g = ((face->background >> 8) & 0xff) / 255.0;
  1339   b = ((face->background >> 0) & 0xff) / 255.0;
  1340   a = f->alpha_background;
  1341   cairo_set_source_rgba (cr, r, g, b, a);
  1342   cairo_paint (cr);
  1343 
  1344   if (face->stipple != 0)
  1345     {
  1346       cairo_pattern_t *mask
  1347         = FRAME_DISPLAY_INFO (f)->bitmaps[face->stipple - 1].pattern;
  1348 
  1349       r = ((face->foreground >> 16) & 0xff) / 255.0;
  1350       g = ((face->foreground >> 8) & 0xff) / 255.0;
  1351       b = ((face->foreground >> 0) & 0xff) / 255.0;
  1352       cairo_set_source_rgba (cr, r, g, b, a);
  1353       cairo_mask (cr, mask);
  1354     }
  1355 
  1356   pgtk_end_cr_clip (f);
  1357 }
  1358 
  1359 static void
  1360 fill_background (struct glyph_string *s, int x, int y, int width, int height)
  1361 {
  1362   fill_background_by_face (s->f, s->face, x, y, width, height);
  1363 }
  1364 
  1365 /* Draw the background of glyph_string S.  If S->background_filled_p
  1366    is non-zero don't draw it.  FORCE_P non-zero means draw the
  1367    background even if it wouldn't be drawn normally.  This is used
  1368    when a string preceding S draws into the background of S, or S
  1369    contains the first component of a composition.  */
  1370 static void
  1371 pgtk_draw_glyph_string_background (struct glyph_string *s, bool force_p)
  1372 {
  1373   /* Nothing to do if background has already been drawn or if it
  1374      shouldn't be drawn in the first place.  */
  1375   if (!s->background_filled_p)
  1376     {
  1377       int box_line_width = max (s->face->box_horizontal_line_width, 0);
  1378 
  1379       if (s->stippled_p)
  1380         {
  1381           /* Fill background with a stipple pattern.  */
  1382           fill_background (s, s->x, s->y + box_line_width,
  1383                            s->background_width,
  1384                            s->height - 2 * box_line_width);
  1385           s->background_filled_p = true;
  1386         }
  1387       else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
  1388                /* When xdisp.c ignores FONT_HEIGHT, we cannot trust
  1389                   font dimensions, since the actual glyphs might be
  1390                   much smaller.  So in that case we always clear the
  1391                   rectangle with background color.  */
  1392                || FONT_TOO_HIGH (s->font)
  1393                || s->font_not_found_p
  1394                || s->extends_to_end_of_line_p || force_p)
  1395         {
  1396           pgtk_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
  1397                                         s->background_width,
  1398                                         s->height - 2 * box_line_width);
  1399           s->background_filled_p = true;
  1400         }
  1401     }
  1402 }
  1403 
  1404 
  1405 static void
  1406 pgtk_draw_rectangle (struct frame *f, unsigned long color, int x, int y,
  1407                      int width, int height, bool respect_alpha_background)
  1408 {
  1409   cairo_t *cr;
  1410 
  1411   cr = pgtk_begin_cr_clip (f);
  1412   pgtk_set_cr_source_with_color (f, color, respect_alpha_background);
  1413   cairo_rectangle (cr, x + 0.5, y + 0.5, width, height);
  1414   cairo_set_line_width (cr, 1);
  1415   cairo_stroke (cr);
  1416   pgtk_end_cr_clip (f);
  1417 }
  1418 
  1419 /* Draw the foreground of glyph string S.  */
  1420 static void
  1421 pgtk_draw_glyph_string_foreground (struct glyph_string *s)
  1422 {
  1423   int i, x;
  1424 
  1425   /* If first glyph of S has a left box line, start drawing the text
  1426      of S to the right of that box line.  */
  1427   if (s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p)
  1428     x = s->x + max (s->face->box_vertical_line_width, 0);
  1429   else
  1430     x = s->x;
  1431 
  1432   /* Draw characters of S as rectangles if S's font could not be
  1433      loaded.  */
  1434   if (s->font_not_found_p)
  1435     {
  1436       for (i = 0; i < s->nchars; ++i)
  1437         {
  1438           struct glyph *g = s->first_glyph + i;
  1439           pgtk_draw_rectangle (s->f,
  1440                                s->face->foreground, x, s->y,
  1441                                g->pixel_width - 1, s->height - 1,
  1442                                false);
  1443           x += g->pixel_width;
  1444         }
  1445     }
  1446   else
  1447     {
  1448       struct font *font = s->font;
  1449       int boff = font->baseline_offset;
  1450       int y;
  1451 
  1452       if (font->vertical_centering)
  1453         boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
  1454 
  1455       y = s->ybase - boff;
  1456       if (s->for_overlaps || (s->background_filled_p && s->hl != DRAW_CURSOR))
  1457         font->driver->draw (s, 0, s->nchars, x, y, false);
  1458       else
  1459         font->driver->draw (s, 0, s->nchars, x, y, true);
  1460       if (s->face->overstrike)
  1461         font->driver->draw (s, 0, s->nchars, x + 1, y, false);
  1462     }
  1463 }
  1464 
  1465 /* Draw the foreground of composite glyph string S.  */
  1466 static void
  1467 pgtk_draw_composite_glyph_string_foreground (struct glyph_string *s)
  1468 {
  1469   int i, j, x;
  1470   struct font *font = s->font;
  1471 
  1472   /* If first glyph of S has a left box line, start drawing the text
  1473      of S to the right of that box line.  */
  1474   if (s->face && s->face->box != FACE_NO_BOX
  1475       && s->first_glyph->left_box_line_p)
  1476     x = s->x + max (s->face->box_vertical_line_width, 0);
  1477   else
  1478     x = s->x;
  1479 
  1480   /* S is a glyph string for a composition.  S->cmp_from is the index
  1481      of the first character drawn for glyphs of this composition.
  1482      S->cmp_from == 0 means we are drawing the very first character of
  1483      this composition.  */
  1484 
  1485   /* Draw a rectangle for the composition if the font for the very
  1486      first character of the composition could not be loaded.  */
  1487   if (s->font_not_found_p)
  1488     {
  1489       if (s->cmp_from == 0)
  1490         pgtk_draw_rectangle (s->f, s->face->foreground, x, s->y,
  1491                              s->width - 1, s->height - 1, false);
  1492     }
  1493   else if (!s->first_glyph->u.cmp.automatic)
  1494     {
  1495       int y = s->ybase;
  1496 
  1497       for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
  1498         /* TAB in a composition means display glyphs with padding
  1499            space on the left or right.  */
  1500         if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
  1501           {
  1502             int xx = x + s->cmp->offsets[j * 2];
  1503             int yy = y - s->cmp->offsets[j * 2 + 1];
  1504 
  1505             font->driver->draw (s, j, j + 1, xx, yy, false);
  1506             if (s->face->overstrike)
  1507               font->driver->draw (s, j, j + 1, xx + 1, yy, false);
  1508           }
  1509     }
  1510   else
  1511     {
  1512       Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
  1513       Lisp_Object glyph;
  1514       int y = s->ybase;
  1515       int width = 0;
  1516 
  1517       for (i = j = s->cmp_from; i < s->cmp_to; i++)
  1518         {
  1519           glyph = LGSTRING_GLYPH (gstring, i);
  1520           if (NILP (LGLYPH_ADJUSTMENT (glyph)))
  1521             width += LGLYPH_WIDTH (glyph);
  1522           else
  1523             {
  1524               int xoff, yoff, wadjust;
  1525 
  1526               if (j < i)
  1527                 {
  1528                   font->driver->draw (s, j, i, x, y, false);
  1529                   if (s->face->overstrike)
  1530                     font->driver->draw (s, j, i, x + 1, y, false);
  1531                   x += width;
  1532                 }
  1533               xoff = LGLYPH_XOFF (glyph);
  1534               yoff = LGLYPH_YOFF (glyph);
  1535               wadjust = LGLYPH_WADJUST (glyph);
  1536               font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
  1537               if (s->face->overstrike)
  1538                 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
  1539                                     false);
  1540               x += wadjust;
  1541               j = i + 1;
  1542               width = 0;
  1543             }
  1544         }
  1545       if (j < i)
  1546         {
  1547           font->driver->draw (s, j, i, x, y, false);
  1548           if (s->face->overstrike)
  1549             font->driver->draw (s, j, i, x + 1, y, false);
  1550         }
  1551     }
  1552 }
  1553 
  1554 
  1555 /* Draw the foreground of glyph string S for glyphless characters.  */
  1556 static void
  1557 pgtk_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
  1558 {
  1559   struct glyph *glyph = s->first_glyph;
  1560   unsigned char2b[8];
  1561   int x, i, j;
  1562 
  1563   /* If first glyph of S has a left box line, start drawing the text
  1564      of S to the right of that box line.  */
  1565   if (s->face && s->face->box != FACE_NO_BOX
  1566       && s->first_glyph->left_box_line_p)
  1567     x = s->x + max (s->face->box_vertical_line_width, 0);
  1568   else
  1569     x = s->x;
  1570 
  1571   s->char2b = char2b;
  1572 
  1573   for (i = 0; i < s->nchars; i++, glyph++)
  1574     {
  1575 #ifdef GCC_LINT
  1576       enum
  1577       { PACIFY_GCC_BUG_81401 = 1 };
  1578 #else
  1579       enum
  1580       { PACIFY_GCC_BUG_81401 = 0 };
  1581 #endif
  1582       char buf[7 + PACIFY_GCC_BUG_81401];
  1583       char *str = NULL;
  1584       int len = glyph->u.glyphless.len;
  1585 
  1586       if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
  1587         {
  1588           if (len > 0
  1589               && CHAR_TABLE_P (Vglyphless_char_display)
  1590               &&
  1591               (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
  1592                >= 1))
  1593             {
  1594               Lisp_Object acronym
  1595                 = (!glyph->u.glyphless.for_no_font
  1596                    ? CHAR_TABLE_REF (Vglyphless_char_display,
  1597                                      glyph->u.glyphless.ch)
  1598                    : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
  1599               if (CONSP (acronym))
  1600                 acronym = XCAR (acronym);
  1601               if (STRINGP (acronym))
  1602                 str = SSDATA (acronym);
  1603             }
  1604         }
  1605       else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
  1606         {
  1607           unsigned int ch = glyph->u.glyphless.ch;
  1608           eassume (ch <= MAX_CHAR);
  1609           sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch);
  1610           str = buf;
  1611         }
  1612 
  1613       if (str)
  1614         {
  1615           int upper_len = (len + 1) / 2;
  1616 
  1617           /* It is assured that all LEN characters in STR is ASCII.  */
  1618           for (j = 0; j < len; j++)
  1619             char2b[j]
  1620               = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF;
  1621           s->font->driver->draw (s, 0, upper_len,
  1622                                  x + glyph->slice.glyphless.upper_xoff,
  1623                                  s->ybase + glyph->slice.glyphless.upper_yoff,
  1624                                  false);
  1625           s->font->driver->draw (s, upper_len, len,
  1626                                  x + glyph->slice.glyphless.lower_xoff,
  1627                                  s->ybase + glyph->slice.glyphless.lower_yoff,
  1628                                  false);
  1629         }
  1630       if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
  1631         pgtk_draw_rectangle (s->f, s->face->foreground,
  1632                              x, s->ybase - glyph->ascent,
  1633                              glyph->pixel_width - 1,
  1634                              glyph->ascent + glyph->descent - 1,
  1635                              false);
  1636       x += glyph->pixel_width;
  1637     }
  1638 
  1639   /* Pacify GCC 12 even though s->char2b is not used after this
  1640      function returns.  */
  1641   s->char2b = NULL;
  1642 }
  1643 
  1644 /* Brightness beyond which a color won't have its highlight brightness
  1645    boosted.
  1646 
  1647    Nominally, highlight colors for `3d' faces are calculated by
  1648    brightening an object's color by a constant scale factor, but this
  1649    doesn't yield good results for dark colors, so for colors who's
  1650    brightness is less than this value (on a scale of 0-65535) have an
  1651    use an additional additive factor.
  1652 
  1653    The value here is set so that the default menu-bar/mode-line color
  1654    (grey75) will not have its highlights changed at all.  */
  1655 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
  1656 
  1657 
  1658 /* Compute a color which is lighter or darker than *PIXEL by FACTOR or
  1659    DELTA.  Try a color with RGB values multiplied by FACTOR first.  If
  1660    this produces the same color as PIXEL, try a color where all RGB
  1661    values have DELTA added.  Return the computed color in *PIXEL.  F
  1662    is the frame to act on.  */
  1663 
  1664 static void
  1665 pgtk_compute_lighter_color (struct frame *f, unsigned long *pixel,
  1666                             double factor, int delta)
  1667 {
  1668   Emacs_Color color, new;
  1669   long bright;
  1670 
  1671   /* Get RGB color values.  */
  1672   color.pixel = *pixel;
  1673   pgtk_query_color (f, &color);
  1674 
  1675   /* Change RGB values by specified FACTOR.  Avoid overflow!  */
  1676   eassert (factor >= 0);
  1677   new.red = min (0xffff, factor * color.red);
  1678   new.green = min (0xffff, factor * color.green);
  1679   new.blue = min (0xffff, factor * color.blue);
  1680 
  1681   /* Calculate brightness of COLOR.  */
  1682   bright = (2 * color.red + 3 * color.green + color.blue) / 6;
  1683 
  1684   /* We only boost colors that are darker than
  1685      HIGHLIGHT_COLOR_DARK_BOOST_LIMIT.  */
  1686   if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
  1687     /* Make an additive adjustment to NEW, because it's dark enough so
  1688        that scaling by FACTOR alone isn't enough.  */
  1689     {
  1690       /* How far below the limit this color is (0 - 1, 1 being darker).  */
  1691       double dimness = 1 - (double) bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
  1692       /* The additive adjustment.  */
  1693       int min_delta = delta * dimness * factor / 2;
  1694 
  1695       if (factor < 1)
  1696         {
  1697           new.red = max (0, new.red - min_delta);
  1698           new.green = max (0, new.green - min_delta);
  1699           new.blue = max (0, new.blue - min_delta);
  1700         }
  1701       else
  1702         {
  1703           new.red = min (0xffff, min_delta + new.red);
  1704           new.green = min (0xffff, min_delta + new.green);
  1705           new.blue = min (0xffff, min_delta + new.blue);
  1706         }
  1707     }
  1708 
  1709   new.pixel = (new.red >> 8 << 16
  1710                | new.green >> 8 << 8
  1711                | new.blue >> 8);
  1712 
  1713   if (new.pixel == *pixel)
  1714     {
  1715       /* If we end up with the same color as before, try adding
  1716          delta to the RGB values.  */
  1717       new.red = min (0xffff, delta + color.red);
  1718       new.green = min (0xffff, delta + color.green);
  1719       new.blue = min (0xffff, delta + color.blue);
  1720       new.pixel = (new.red >> 8 << 16
  1721                    | new.green >> 8 << 8
  1722                    | new.blue >> 8);
  1723     }
  1724 
  1725   *pixel = new.pixel;
  1726 }
  1727 
  1728 static void
  1729 pgtk_fill_trapezoid_for_relief (struct frame *f, unsigned long color, int x,
  1730                                 int y, int width, int height, int top_p)
  1731 {
  1732   cairo_t *cr;
  1733 
  1734   cr = pgtk_begin_cr_clip (f);
  1735   pgtk_set_cr_source_with_color (f, color, false);
  1736   cairo_move_to (cr, top_p ? x : x + height, y);
  1737   cairo_line_to (cr, x, y + height);
  1738   cairo_line_to (cr, top_p ? x + width - height : x + width, y + height);
  1739   cairo_line_to (cr, x + width, y);
  1740   cairo_fill (cr);
  1741   pgtk_end_cr_clip (f);
  1742 }
  1743 
  1744 enum corners
  1745 {
  1746   CORNER_BOTTOM_RIGHT,          /* 0 -> pi/2 */
  1747   CORNER_BOTTOM_LEFT,           /* pi/2 -> pi */
  1748   CORNER_TOP_LEFT,              /* pi -> 3pi/2 */
  1749   CORNER_TOP_RIGHT,             /* 3pi/2 -> 2pi */
  1750   CORNER_LAST
  1751 };
  1752 
  1753 static void
  1754 pgtk_erase_corners_for_relief (struct frame *f, unsigned long color, int x,
  1755                                int y, int width, int height, double radius,
  1756                                double margin, int corners)
  1757 {
  1758   cairo_t *cr;
  1759   int i;
  1760 
  1761   cr = pgtk_begin_cr_clip (f);
  1762   pgtk_set_cr_source_with_color (f, color, false);
  1763   for (i = 0; i < CORNER_LAST; i++)
  1764     if (corners & (1 << i))
  1765       {
  1766         double xm, ym, xc, yc;
  1767 
  1768         if (i == CORNER_TOP_LEFT || i == CORNER_BOTTOM_LEFT)
  1769           xm = x - margin, xc = xm + radius;
  1770         else
  1771           xm = x + width + margin, xc = xm - radius;
  1772         if (i == CORNER_TOP_LEFT || i == CORNER_TOP_RIGHT)
  1773           ym = y - margin, yc = ym + radius;
  1774         else
  1775           ym = y + height + margin, yc = ym - radius;
  1776 
  1777         cairo_move_to (cr, xm, ym);
  1778         cairo_arc (cr, xc, yc, radius, i * M_PI_2, (i + 1) * M_PI_2);
  1779       }
  1780   cairo_clip (cr);
  1781   cairo_rectangle (cr, x, y, width, height);
  1782   cairo_fill (cr);
  1783   pgtk_end_cr_clip (f);
  1784 }
  1785 
  1786 static void
  1787 pgtk_setup_relief_color (struct frame *f, struct relief *relief, double factor,
  1788                          int delta, unsigned long default_pixel)
  1789 {
  1790   Emacs_GC xgcv;
  1791   struct pgtk_output *di = FRAME_X_OUTPUT (f);
  1792   unsigned long pixel;
  1793   unsigned long background = di->relief_background;
  1794 
  1795   /* Allocate new color.  */
  1796   xgcv.foreground = default_pixel;
  1797   pixel = background;
  1798   pgtk_compute_lighter_color (f, &pixel, factor, delta);
  1799   xgcv.foreground = relief->pixel = pixel;
  1800 
  1801   relief->xgcv = xgcv;
  1802 }
  1803 
  1804 /* Set up colors for the relief lines around glyph string S.  */
  1805 static void
  1806 pgtk_setup_relief_colors (struct glyph_string *s)
  1807 {
  1808   struct pgtk_output *di = FRAME_X_OUTPUT (s->f);
  1809   unsigned long color;
  1810 
  1811   if (s->face->use_box_color_for_shadows_p)
  1812     color = s->face->box_color;
  1813   else if (s->first_glyph->type == IMAGE_GLYPH
  1814            && s->img->pixmap
  1815            && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
  1816     color = IMAGE_BACKGROUND (s->img, s->f, 0);
  1817   else
  1818     {
  1819       /* Get the background color of the face.  */
  1820       color = s->xgcv.background;
  1821     }
  1822 
  1823   if (!di->relief_background_valid_p
  1824       || di->relief_background != color)
  1825     {
  1826       di->relief_background_valid_p = true;
  1827       di->relief_background = color;
  1828       pgtk_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
  1829                                WHITE_PIX_DEFAULT (s->f));
  1830       pgtk_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
  1831                                BLACK_PIX_DEFAULT (s->f));
  1832     }
  1833 }
  1834 
  1835 static void
  1836 pgtk_set_clip_rectangles (struct frame *f, cairo_t *cr,
  1837                           XRectangle *rectangles, int n)
  1838 {
  1839   if (n > 0)
  1840     {
  1841       for (int i = 0; i < n; i++)
  1842         cairo_rectangle (cr, rectangles[i].x, rectangles[i].y,
  1843                          rectangles[i].width, rectangles[i].height);
  1844       cairo_clip (cr);
  1845     }
  1846 }
  1847 
  1848 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
  1849    TOP_Y, RIGHT_X, and BOTTOM_Y.  WIDTH is the thickness of the relief
  1850    to draw, it must be >= 0.  RAISED_P means draw a raised
  1851    relief.  LEFT_P means draw a relief on the left side of
  1852    the rectangle.  RIGHT_P means draw a relief on the right
  1853    side of the rectangle.  CLIP_RECT is the clipping rectangle to use
  1854    when drawing.  */
  1855 
  1856 static void
  1857 pgtk_draw_relief_rect (struct frame *f,
  1858                        int left_x, int top_y, int right_x, int bottom_y,
  1859                        int hwidth, int vwidth, bool raised_p, bool top_p,
  1860                        bool bot_p, bool left_p, bool right_p,
  1861                        XRectangle *clip_rect)
  1862 {
  1863   unsigned long top_left_color, bottom_right_color;
  1864   int corners = 0;
  1865 
  1866   cairo_t *cr = pgtk_begin_cr_clip (f);
  1867 
  1868   if (raised_p)
  1869     {
  1870       top_left_color = FRAME_X_OUTPUT (f)->white_relief.xgcv.foreground;
  1871       bottom_right_color = FRAME_X_OUTPUT (f)->black_relief.xgcv.foreground;
  1872     }
  1873   else
  1874     {
  1875       top_left_color = FRAME_X_OUTPUT (f)->black_relief.xgcv.foreground;
  1876       bottom_right_color = FRAME_X_OUTPUT (f)->white_relief.xgcv.foreground;
  1877     }
  1878 
  1879   pgtk_set_clip_rectangles (f, cr, clip_rect, 1);
  1880 
  1881   if (left_p)
  1882     {
  1883       pgtk_fill_rectangle (f, top_left_color, left_x, top_y,
  1884                            vwidth, bottom_y + 1 - top_y, false);
  1885       if (top_p)
  1886         corners |= 1 << CORNER_TOP_LEFT;
  1887       if (bot_p)
  1888         corners |= 1 << CORNER_BOTTOM_LEFT;
  1889     }
  1890   if (right_p)
  1891     {
  1892       pgtk_fill_rectangle (f, bottom_right_color, right_x + 1 - vwidth, top_y,
  1893                            vwidth, bottom_y + 1 - top_y, false);
  1894       if (top_p)
  1895         corners |= 1 << CORNER_TOP_RIGHT;
  1896       if (bot_p)
  1897         corners |= 1 << CORNER_BOTTOM_RIGHT;
  1898     }
  1899   if (top_p)
  1900     {
  1901       if (!right_p)
  1902         pgtk_fill_rectangle (f, top_left_color, left_x, top_y,
  1903                              right_x + 1 - left_x, hwidth, false);
  1904       else
  1905         pgtk_fill_trapezoid_for_relief (f, top_left_color, left_x, top_y,
  1906                                         right_x + 1 - left_x, hwidth, 1);
  1907     }
  1908   if (bot_p)
  1909     {
  1910       if (!left_p)
  1911         pgtk_fill_rectangle (f, bottom_right_color, left_x,
  1912                              bottom_y + 1 - hwidth, right_x + 1 - left_x,
  1913                              hwidth, false);
  1914       else
  1915         pgtk_fill_trapezoid_for_relief (f, bottom_right_color,
  1916                                         left_x, bottom_y + 1 - hwidth,
  1917                                         right_x + 1 - left_x, hwidth, 0);
  1918     }
  1919   if (left_p && vwidth > 1)
  1920     pgtk_fill_rectangle (f, bottom_right_color, left_x, top_y,
  1921                          1, bottom_y + 1 - top_y, false);
  1922   if (top_p && hwidth > 1)
  1923     pgtk_fill_rectangle (f, bottom_right_color, left_x, top_y,
  1924                          right_x + 1 - left_x, 1, false);
  1925   if (corners)
  1926     pgtk_erase_corners_for_relief (f, FRAME_BACKGROUND_PIXEL (f), left_x,
  1927                                    top_y, right_x - left_x + 1,
  1928                                    bottom_y - top_y + 1, 6, 1, corners);
  1929 
  1930   pgtk_end_cr_clip (f);
  1931 }
  1932 
  1933 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
  1934    RIGHT_X, and BOTTOM_Y.  WIDTH is the thickness of the lines to
  1935    draw, it must be >= 0.  LEFT_P means draw a line on the
  1936    left side of the rectangle.  RIGHT_P means draw a line
  1937    on the right side of the rectangle.  CLIP_RECT is the clipping
  1938    rectangle to use when drawing.  */
  1939 
  1940 static void
  1941 pgtk_draw_box_rect (struct glyph_string *s, int left_x,
  1942                     int top_y, int right_x, int bottom_y, int hwidth,
  1943                     int vwidth, bool left_p, bool right_p,
  1944                     XRectangle * clip_rect)
  1945 {
  1946   unsigned long foreground_backup;
  1947 
  1948   cairo_t *cr = pgtk_begin_cr_clip (s->f);
  1949 
  1950   foreground_backup = s->xgcv.foreground;
  1951   s->xgcv.foreground = s->face->box_color;
  1952 
  1953   pgtk_set_clip_rectangles (s->f, cr, clip_rect, 1);
  1954 
  1955   /* Top.  */
  1956   pgtk_fill_rectangle (s->f, s->xgcv.foreground,
  1957                        left_x, top_y, right_x - left_x + 1, hwidth,
  1958                        false);
  1959 
  1960   /* Left.  */
  1961   if (left_p)
  1962     pgtk_fill_rectangle (s->f, s->xgcv.foreground,
  1963                          left_x, top_y, vwidth, bottom_y - top_y + 1,
  1964                          false);
  1965 
  1966   /* Bottom.  */
  1967   pgtk_fill_rectangle (s->f, s->xgcv.foreground,
  1968                        left_x, bottom_y - hwidth + 1, right_x - left_x + 1,
  1969                        hwidth, false);
  1970 
  1971   /* Right.  */
  1972   if (right_p)
  1973     pgtk_fill_rectangle (s->f, s->xgcv.foreground,
  1974                          right_x - vwidth + 1, top_y, vwidth,
  1975                          bottom_y - top_y + 1, false);
  1976 
  1977   s->xgcv.foreground = foreground_backup;
  1978 
  1979   pgtk_end_cr_clip (s->f);
  1980 }
  1981 
  1982 
  1983 /* Draw a box around glyph string S.  */
  1984 
  1985 static void
  1986 pgtk_draw_glyph_string_box (struct glyph_string *s)
  1987 {
  1988   int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
  1989   bool raised_p, left_p, right_p;
  1990   struct glyph *last_glyph;
  1991   XRectangle clip_rect;
  1992 
  1993   last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
  1994             ? WINDOW_RIGHT_EDGE_X (s->w) : window_box_right (s->w, s->area));
  1995 
  1996   /* The glyph that may have a right box line.  */
  1997   last_glyph = (s->cmp || s->img
  1998                 ? s->first_glyph : s->first_glyph + s->nchars - 1);
  1999 
  2000   vwidth = eabs (s->face->box_vertical_line_width);
  2001   hwidth = eabs (s->face->box_horizontal_line_width);
  2002   raised_p = s->face->box == FACE_RAISED_BOX;
  2003   left_x = s->x;
  2004   right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
  2005              ? last_x - 1 : min (last_x, s->x + s->background_width) - 1);
  2006   top_y = s->y;
  2007   bottom_y = top_y + s->height - 1;
  2008 
  2009   left_p = (s->first_glyph->left_box_line_p
  2010             || (s->hl == DRAW_MOUSE_FACE
  2011                 && (s->prev == NULL || s->prev->hl != s->hl)));
  2012   right_p = (last_glyph->right_box_line_p
  2013              || (s->hl == DRAW_MOUSE_FACE
  2014                  && (s->next == NULL || s->next->hl != s->hl)));
  2015 
  2016   get_glyph_string_clip_rect (s, &clip_rect);
  2017 
  2018   if (s->face->box == FACE_SIMPLE_BOX)
  2019     pgtk_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
  2020                         vwidth, left_p, right_p, &clip_rect);
  2021   else
  2022     {
  2023       pgtk_setup_relief_colors (s);
  2024       pgtk_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, hwidth,
  2025                              vwidth, raised_p, true, true, left_p, right_p,
  2026                              &clip_rect);
  2027     }
  2028 }
  2029 
  2030 static void
  2031 pgtk_draw_horizontal_wave (struct frame *f, unsigned long color, int x, int y,
  2032                            int width, int height, int wave_length)
  2033 {
  2034   cairo_t *cr;
  2035   double dx = wave_length, dy = height - 1;
  2036   int xoffset, n;
  2037 
  2038   cr = pgtk_begin_cr_clip (f);
  2039   pgtk_set_cr_source_with_color (f, color, false);
  2040   cairo_rectangle (cr, x, y, width, height);
  2041   cairo_clip (cr);
  2042 
  2043   if (x >= 0)
  2044     {
  2045       xoffset = x % (wave_length * 2);
  2046       if (xoffset == 0)
  2047         xoffset = wave_length * 2;
  2048     }
  2049   else
  2050     xoffset = x % (wave_length * 2) + wave_length * 2;
  2051   n = (width + xoffset) / wave_length + 1;
  2052   if (xoffset > wave_length)
  2053     {
  2054       xoffset -= wave_length;
  2055       --n;
  2056       y += height - 1;
  2057       dy = -dy;
  2058     }
  2059 
  2060   cairo_move_to (cr, x - xoffset + 0.5, y + 0.5);
  2061   while (--n >= 0)
  2062     {
  2063       cairo_rel_line_to (cr, dx, dy);
  2064       dy = -dy;
  2065     }
  2066   cairo_set_line_width (cr, 1);
  2067   cairo_stroke (cr);
  2068   pgtk_end_cr_clip (f);
  2069 }
  2070 
  2071 static void
  2072 pgtk_draw_underwave (struct glyph_string *s, unsigned long color)
  2073 {
  2074   int wave_height = 3, wave_length = 2;
  2075 
  2076   pgtk_draw_horizontal_wave (s->f, color, s->x, s->ybase - wave_height + 3,
  2077                              s->width, wave_height, wave_length);
  2078 }
  2079 
  2080 /* Draw a relief around the image glyph string S.  */
  2081 
  2082 static void
  2083 pgtk_draw_image_relief (struct glyph_string *s)
  2084 {
  2085   int x1, y1, thick;
  2086   bool raised_p, top_p, bot_p, left_p, right_p;
  2087   int extra_x, extra_y;
  2088   XRectangle r;
  2089   int x = s->x;
  2090   int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
  2091 
  2092   /* If first glyph of S has a left box line, start drawing it to the
  2093      right of that line.  */
  2094   if (s->face->box != FACE_NO_BOX
  2095       && s->first_glyph->left_box_line_p
  2096       && s->slice.x == 0)
  2097     x += max (s->face->box_vertical_line_width, 0);
  2098 
  2099   /* If there is a margin around the image, adjust x- and y-position
  2100      by that margin.  */
  2101   if (s->slice.x == 0)
  2102     x += s->img->hmargin;
  2103   if (s->slice.y == 0)
  2104     y += s->img->vmargin;
  2105 
  2106   if (s->hl == DRAW_IMAGE_SUNKEN
  2107       || s->hl == DRAW_IMAGE_RAISED)
  2108     {
  2109       if (s->face->id == TAB_BAR_FACE_ID)
  2110         thick = (tab_bar_button_relief < 0
  2111                  ? DEFAULT_TAB_BAR_BUTTON_RELIEF
  2112                  : min (tab_bar_button_relief, 1000000));
  2113       else
  2114         thick = (tool_bar_button_relief < 0
  2115                  ? DEFAULT_TOOL_BAR_BUTTON_RELIEF
  2116                  : min (tool_bar_button_relief, 1000000));
  2117       raised_p = s->hl == DRAW_IMAGE_RAISED;
  2118     }
  2119   else
  2120     {
  2121       thick = eabs (s->img->relief);
  2122       raised_p = s->img->relief > 0;
  2123     }
  2124 
  2125   x1 = x + s->slice.width - 1;
  2126   y1 = y + s->slice.height - 1;
  2127 
  2128   extra_x = extra_y = 0;
  2129   if (s->face->id == TAB_BAR_FACE_ID)
  2130     {
  2131       if (CONSP (Vtab_bar_button_margin)
  2132           && FIXNUMP (XCAR (Vtab_bar_button_margin))
  2133           && FIXNUMP (XCDR (Vtab_bar_button_margin)))
  2134         {
  2135           extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)) - thick;
  2136           extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)) - thick;
  2137         }
  2138       else if (FIXNUMP (Vtab_bar_button_margin))
  2139         extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin) - thick;
  2140     }
  2141 
  2142   if (s->face->id == TOOL_BAR_FACE_ID)
  2143     {
  2144       if (CONSP (Vtool_bar_button_margin)
  2145           && FIXNUMP (XCAR (Vtool_bar_button_margin))
  2146           && FIXNUMP (XCDR (Vtool_bar_button_margin)))
  2147         {
  2148           extra_x = XFIXNUM (XCAR (Vtool_bar_button_margin));
  2149           extra_y = XFIXNUM (XCDR (Vtool_bar_button_margin));
  2150         }
  2151       else if (FIXNUMP (Vtool_bar_button_margin))
  2152         extra_x = extra_y = XFIXNUM (Vtool_bar_button_margin);
  2153     }
  2154 
  2155   top_p = bot_p = left_p = right_p = false;
  2156 
  2157   if (s->slice.x == 0)
  2158     x -= thick + extra_x, left_p = true;
  2159   if (s->slice.y == 0)
  2160     y -= thick + extra_y, top_p = true;
  2161   if (s->slice.x + s->slice.width == s->img->width)
  2162     x1 += thick + extra_x, right_p = true;
  2163   if (s->slice.y + s->slice.height == s->img->height)
  2164     y1 += thick + extra_y, bot_p = true;
  2165 
  2166   pgtk_setup_relief_colors (s);
  2167   get_glyph_string_clip_rect (s, &r);
  2168   pgtk_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
  2169                          top_p, bot_p, left_p, right_p, &r);
  2170 }
  2171 
  2172 /* Draw part of the background of glyph string S.  X, Y, W, and H
  2173    give the rectangle to draw.  */
  2174 
  2175 static void
  2176 pgtk_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w,
  2177                                 int h)
  2178 {
  2179   if (s->stippled_p)
  2180     fill_background (s, x, y, w, h);
  2181   else
  2182     pgtk_clear_glyph_string_rect (s, x, y, w, h);
  2183 }
  2184 
  2185 static void
  2186 pgtk_cr_draw_image (struct frame *f, Emacs_GC *gc, cairo_pattern_t *image,
  2187                     int src_x, int src_y, int width, int height,
  2188                     int dest_x, int dest_y, bool overlay_p)
  2189 {
  2190   cairo_t *cr = pgtk_begin_cr_clip (f);
  2191 
  2192   if (overlay_p)
  2193     cairo_rectangle (cr, dest_x, dest_y, width, height);
  2194   else
  2195     {
  2196       pgtk_set_cr_source_with_gc_background (f, gc, false);
  2197       cairo_rectangle (cr, dest_x, dest_y, width, height);
  2198       cairo_fill_preserve (cr);
  2199     }
  2200 
  2201   cairo_translate (cr, dest_x - src_x, dest_y - src_y);
  2202 
  2203   cairo_surface_t *surface;
  2204   cairo_pattern_get_surface (image, &surface);
  2205   cairo_format_t format = cairo_image_surface_get_format (surface);
  2206   if (format != CAIRO_FORMAT_A8 && format != CAIRO_FORMAT_A1)
  2207     {
  2208       cairo_set_source (cr, image);
  2209       cairo_fill (cr);
  2210     }
  2211   else
  2212     {
  2213       pgtk_set_cr_source_with_gc_foreground (f, gc, false);
  2214       cairo_clip (cr);
  2215       cairo_mask (cr, image);
  2216     }
  2217 
  2218   pgtk_end_cr_clip (f);
  2219 }
  2220 
  2221 /* Draw foreground of image glyph string S.  */
  2222 
  2223 static void
  2224 pgtk_draw_image_foreground (struct glyph_string *s)
  2225 {
  2226   int x = s->x;
  2227   int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
  2228 
  2229   /* If first glyph of S has a left box line, start drawing it to the
  2230      right of that line.  */
  2231   if (s->face->box != FACE_NO_BOX
  2232       && s->first_glyph->left_box_line_p
  2233       && s->slice.x == 0)
  2234     x += max (s->face->box_vertical_line_width, 0);
  2235 
  2236   /* If there is a margin around the image, adjust x- and y-position
  2237      by that margin.  */
  2238   if (s->slice.x == 0)
  2239     x += s->img->hmargin;
  2240   if (s->slice.y == 0)
  2241     y += s->img->vmargin;
  2242 
  2243   if (s->img->cr_data)
  2244     {
  2245       cairo_t *cr = pgtk_begin_cr_clip (s->f);
  2246       pgtk_set_glyph_string_clipping (s, cr);
  2247       pgtk_cr_draw_image (s->f, &s->xgcv, s->img->cr_data,
  2248                           s->slice.x, s->slice.y, s->slice.width, s->slice.height,
  2249                           x, y, true);
  2250       if (!s->img->mask)
  2251         {
  2252           /* When the image has a mask, we can expect that at
  2253              least part of a mouse highlight or a block cursor will
  2254              be visible.  If the image doesn't have a mask, make
  2255              a block cursor visible by drawing a rectangle around
  2256              the image.  I believe it's looking better if we do
  2257              nothing here for mouse-face.  */
  2258           if (s->hl == DRAW_CURSOR)
  2259             {
  2260               int relief = eabs (s->img->relief);
  2261               pgtk_draw_rectangle (s->f, s->xgcv.foreground, x - relief,
  2262                                    y - relief, s->slice.width + relief * 2 - 1,
  2263                                    s->slice.height + relief * 2 - 1, false);
  2264             }
  2265         }
  2266       pgtk_end_cr_clip (s->f);
  2267     }
  2268   else
  2269     /* Draw a rectangle if image could not be loaded.  */
  2270     pgtk_draw_rectangle (s->f, s->xgcv.foreground, x, y,
  2271                          s->slice.width - 1, s->slice.height - 1, false);
  2272 }
  2273 
  2274 /* Draw image glyph string S.
  2275 
  2276             s->y
  2277    s->x      +-------------------------
  2278              |   s->face->box
  2279              |
  2280              |     +-------------------------
  2281              |     |  s->img->margin
  2282              |     |
  2283              |     |       +-------------------
  2284              |     |       |  the image
  2285 
  2286  */
  2287 
  2288 static void
  2289 pgtk_draw_image_glyph_string (struct glyph_string *s)
  2290 {
  2291   int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
  2292   int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
  2293   int height;
  2294 
  2295   height = s->height;
  2296   if (s->slice.y == 0)
  2297     height -= box_line_vwidth;
  2298   if (s->slice.y + s->slice.height >= s->img->height)
  2299     height -= box_line_vwidth;
  2300 
  2301   /* Fill background with face under the image.  Do it only if row is
  2302      taller than image or if image has a clip mask to reduce
  2303      flickering.  */
  2304   s->stippled_p = s->face->stipple != 0;
  2305   if (height > s->slice.height
  2306       || s->img->hmargin
  2307       || s->img->vmargin
  2308       || s->img->mask
  2309       || s->img->pixmap == 0
  2310       || s->width != s->background_width)
  2311     {
  2312       int x = s->x;
  2313       int y = s->y;
  2314       int width = s->background_width;
  2315 
  2316       if (s->first_glyph->left_box_line_p
  2317           && s->slice.x == 0)
  2318         {
  2319           x += box_line_hwidth;
  2320           width -= box_line_hwidth;
  2321         }
  2322 
  2323       if (s->slice.y == 0)
  2324         y += box_line_vwidth;
  2325 
  2326       pgtk_draw_glyph_string_bg_rect (s, x, y, width, height);
  2327 
  2328       s->background_filled_p = true;
  2329     }
  2330 
  2331   /* Draw the foreground.  */
  2332   pgtk_draw_image_foreground (s);
  2333 
  2334   /* If we must draw a relief around the image, do it.  */
  2335   if (s->img->relief
  2336       || s->hl == DRAW_IMAGE_RAISED
  2337       || s->hl == DRAW_IMAGE_SUNKEN)
  2338     pgtk_draw_image_relief (s);
  2339 }
  2340 
  2341 /* Draw stretch glyph string S.  */
  2342 
  2343 static void
  2344 pgtk_draw_stretch_glyph_string (struct glyph_string *s)
  2345 {
  2346   eassert (s->first_glyph->type == STRETCH_GLYPH);
  2347 
  2348   if (s->hl == DRAW_CURSOR && !x_stretch_cursor_p)
  2349     {
  2350       /* If `x-stretch-cursor' is nil, don't draw a block cursor as
  2351          wide as the stretch glyph.  */
  2352       int width, background_width = s->background_width;
  2353       int x = s->x;
  2354 
  2355       if (!s->row->reversed_p)
  2356         {
  2357           int left_x = window_box_left_offset (s->w, TEXT_AREA);
  2358 
  2359           if (x < left_x)
  2360             {
  2361               background_width -= left_x - x;
  2362               x = left_x;
  2363             }
  2364         }
  2365       else
  2366         {
  2367           /* In R2L rows, draw the cursor on the right edge of the
  2368              stretch glyph.  */
  2369           int right_x = window_box_right (s->w, TEXT_AREA);
  2370 
  2371           if (x + background_width > right_x)
  2372             background_width -= x - right_x;
  2373           x += background_width;
  2374         }
  2375       width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
  2376       if (s->row->reversed_p)
  2377         x -= width;
  2378 
  2379       /* Draw cursor.  */
  2380       pgtk_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
  2381 
  2382       /* Clear rest using the GC of the original non-cursor face.  */
  2383       if (width < background_width)
  2384         {
  2385           int y = s->y;
  2386           int w = background_width - width, h = s->height;
  2387           XRectangle r;
  2388           unsigned long color;
  2389 
  2390           if (!s->row->reversed_p)
  2391             x += width;
  2392           else
  2393             x = s->x;
  2394           if (s->row->mouse_face_p && cursor_in_mouse_face_p (s->w))
  2395             {
  2396               pgtk_set_mouse_face_gc (s);
  2397               color = s->xgcv.foreground;
  2398             }
  2399           else
  2400             color = s->face->background;
  2401 
  2402           cairo_t *cr = pgtk_begin_cr_clip (s->f);
  2403 
  2404           get_glyph_string_clip_rect (s, &r);
  2405           pgtk_set_clip_rectangles (s->f, cr, &r, 1);
  2406 
  2407           if (s->face->stipple)
  2408             fill_background (s, x, y, w, h);
  2409           else
  2410             pgtk_fill_rectangle (s->f, color, x, y, w, h,
  2411                                  true);
  2412 
  2413           pgtk_end_cr_clip (s->f);
  2414         }
  2415     }
  2416   else if (!s->background_filled_p)
  2417     {
  2418       int background_width = s->background_width;
  2419       int x = s->x, text_left_x = window_box_left (s->w, TEXT_AREA);
  2420 
  2421       /* Don't draw into left fringe or scrollbar area except for
  2422          header line and mode line.  */
  2423       if (s->area == TEXT_AREA
  2424           && x < text_left_x && !s->row->mode_line_p)
  2425         {
  2426           background_width -= text_left_x - x;
  2427           x = text_left_x;
  2428         }
  2429 
  2430       if (background_width > 0)
  2431         pgtk_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
  2432     }
  2433 
  2434   s->background_filled_p = true;
  2435 }
  2436 
  2437 static void
  2438 pgtk_draw_glyph_string (struct glyph_string *s)
  2439 {
  2440   bool relief_drawn_p = false;
  2441 
  2442   /* If S draws into the background of its successors, draw the
  2443      background of the successors first so that S can draw into it.
  2444      This makes S->next use XDrawString instead of XDrawImageString.  */
  2445   if (s->next && s->right_overhang && !s->for_overlaps)
  2446     {
  2447       int width;
  2448       struct glyph_string *next;
  2449 
  2450       for (width = 0, next = s->next;
  2451            next && width < s->right_overhang;
  2452            width += next->width, next = next->next)
  2453         if (next->first_glyph->type != IMAGE_GLYPH)
  2454           {
  2455             cairo_t *cr = pgtk_begin_cr_clip (next->f);
  2456             pgtk_set_glyph_string_gc (next);
  2457             pgtk_set_glyph_string_clipping (next, cr);
  2458             if (next->first_glyph->type == STRETCH_GLYPH)
  2459               pgtk_draw_stretch_glyph_string (next);
  2460             else
  2461               pgtk_draw_glyph_string_background (next, true);
  2462             next->num_clips = 0;
  2463             pgtk_end_cr_clip (next->f);
  2464           }
  2465     }
  2466 
  2467   /* Set up S->gc, set clipping and draw S.  */
  2468   pgtk_set_glyph_string_gc (s);
  2469 
  2470   cairo_t *cr = pgtk_begin_cr_clip (s->f);
  2471 
  2472   /* Draw relief (if any) in advance for char/composition so that the
  2473      glyph string can be drawn over it.  */
  2474   if (!s->for_overlaps
  2475       && s->face->box != FACE_NO_BOX
  2476       && (s->first_glyph->type == CHAR_GLYPH
  2477           || s->first_glyph->type == COMPOSITE_GLYPH))
  2478 
  2479     {
  2480       pgtk_set_glyph_string_clipping (s, cr);
  2481       pgtk_draw_glyph_string_background (s, true);
  2482       pgtk_draw_glyph_string_box (s);
  2483       pgtk_set_glyph_string_clipping (s, cr);
  2484       relief_drawn_p = true;
  2485     }
  2486   else if (!s->clip_head        /* draw_glyphs didn't specify a clip mask. */
  2487            && !s->clip_tail
  2488            && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
  2489                || (s->next && s->next->hl != s->hl && s->right_overhang)))
  2490     /* We must clip just this glyph.  left_overhang part has already
  2491        drawn when s->prev was drawn, and right_overhang part will be
  2492        drawn later when s->next is drawn. */
  2493     pgtk_set_glyph_string_clipping_exactly (s, s, cr);
  2494   else
  2495     pgtk_set_glyph_string_clipping (s, cr);
  2496 
  2497   switch (s->first_glyph->type)
  2498     {
  2499     case IMAGE_GLYPH:
  2500       pgtk_draw_image_glyph_string (s);
  2501       break;
  2502 
  2503     case XWIDGET_GLYPH:
  2504       x_draw_xwidget_glyph_string (s);
  2505       break;
  2506 
  2507     case STRETCH_GLYPH:
  2508       pgtk_draw_stretch_glyph_string (s);
  2509       break;
  2510 
  2511     case CHAR_GLYPH:
  2512       if (s->for_overlaps)
  2513         s->background_filled_p = true;
  2514       else
  2515         pgtk_draw_glyph_string_background (s, false);
  2516       pgtk_draw_glyph_string_foreground (s);
  2517       break;
  2518 
  2519     case COMPOSITE_GLYPH:
  2520       if (s->for_overlaps || (s->cmp_from > 0
  2521                               && !s->first_glyph->u.cmp.automatic))
  2522         s->background_filled_p = true;
  2523       else
  2524         pgtk_draw_glyph_string_background (s, true);
  2525       pgtk_draw_composite_glyph_string_foreground (s);
  2526       break;
  2527 
  2528     case GLYPHLESS_GLYPH:
  2529       if (s->for_overlaps)
  2530         s->background_filled_p = true;
  2531       else
  2532         pgtk_draw_glyph_string_background (s, true);
  2533       pgtk_draw_glyphless_glyph_string_foreground (s);
  2534       break;
  2535 
  2536     default:
  2537       emacs_abort ();
  2538     }
  2539 
  2540   if (!s->for_overlaps)
  2541     {
  2542       /* Draw relief if not yet drawn.  */
  2543       if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
  2544         pgtk_draw_glyph_string_box (s);
  2545 
  2546       /* Draw underline.  */
  2547       if (s->face->underline)
  2548         {
  2549           if (s->face->underline == FACE_UNDER_WAVE)
  2550             {
  2551               if (s->face->underline_defaulted_p)
  2552                 pgtk_draw_underwave (s, s->xgcv.foreground);
  2553               else
  2554                 pgtk_draw_underwave (s, s->face->underline_color);
  2555             }
  2556           else if (s->face->underline == FACE_UNDER_LINE)
  2557             {
  2558               unsigned long thickness, position;
  2559               int y;
  2560 
  2561               if (s->prev
  2562                   && s->prev->face->underline == FACE_UNDER_LINE
  2563                   && (s->prev->face->underline_at_descent_line_p
  2564                       == s->face->underline_at_descent_line_p)
  2565                   && (s->prev->face->underline_pixels_above_descent_line
  2566                       == s->face->underline_pixels_above_descent_line))
  2567                 {
  2568                   /* We use the same underline style as the previous one.  */
  2569                   thickness = s->prev->underline_thickness;
  2570                   position = s->prev->underline_position;
  2571                 }
  2572               else
  2573                 {
  2574                   struct font *font = font_for_underline_metrics (s);
  2575 
  2576                   /* Get the underline thickness.  Default is 1 pixel.  */
  2577                   if (font && font->underline_thickness > 0)
  2578                     thickness = font->underline_thickness;
  2579                   else
  2580                     thickness = 1;
  2581                   if ((x_underline_at_descent_line
  2582                        || s->face->underline_at_descent_line_p))
  2583                     position = ((s->height - thickness)
  2584                                 - (s->ybase - s->y)
  2585                                 - s->face->underline_pixels_above_descent_line);
  2586                   else
  2587                     {
  2588                       /* Get the underline position.  This is the recommended
  2589                          vertical offset in pixels from the baseline to the top of
  2590                          the underline.  This is a signed value according to the
  2591                          specs, and its default is
  2592 
  2593                          ROUND ((maximum descent) / 2), with
  2594                          ROUND(x) = floor (x + 0.5)  */
  2595 
  2596                       if (x_use_underline_position_properties
  2597                           && font && font->underline_position >= 0)
  2598                         position = font->underline_position;
  2599                       else if (font)
  2600                         position = (font->descent + 1) / 2;
  2601                       else
  2602                         position = underline_minimum_offset;
  2603                     }
  2604 
  2605                   /* Ignore minimum_offset if the amount of pixels was
  2606                      explicitly specified.  */
  2607                   if (!s->face->underline_pixels_above_descent_line)
  2608                     position = max (position, underline_minimum_offset);
  2609                 }
  2610               /* Check the sanity of thickness and position.  We should
  2611                  avoid drawing underline out of the current line area.  */
  2612               if (s->y + s->height <= s->ybase + position)
  2613                 position = (s->height - 1) - (s->ybase - s->y);
  2614               if (s->y + s->height < s->ybase + position + thickness)
  2615                 thickness = (s->y + s->height) - (s->ybase + position);
  2616               s->underline_thickness = thickness;
  2617               s->underline_position = position;
  2618               y = s->ybase + position;
  2619               if (s->face->underline_defaulted_p)
  2620                 pgtk_fill_rectangle (s->f, s->xgcv.foreground,
  2621                                      s->x, y, s->width, thickness,
  2622                                      false);
  2623               else
  2624                 {
  2625                   pgtk_fill_rectangle (s->f, s->face->underline_color,
  2626                                        s->x, y, s->width, thickness,
  2627                                        false);
  2628                 }
  2629             }
  2630         }
  2631       /* Draw overline.  */
  2632       if (s->face->overline_p)
  2633         {
  2634           unsigned long dy = 0, h = 1;
  2635 
  2636           if (s->face->overline_color_defaulted_p)
  2637             pgtk_fill_rectangle (s->f, s->xgcv.foreground, s->x, s->y + dy,
  2638                                  s->width, h, false);
  2639           else
  2640             pgtk_fill_rectangle (s->f, s->face->overline_color, s->x,
  2641                                  s->y + dy, s->width, h, false);
  2642         }
  2643 
  2644       /* Draw strike-through.  */
  2645       if (s->face->strike_through_p)
  2646         {
  2647           /* Y-coordinate and height of the glyph string's first
  2648              glyph.  We cannot use s->y and s->height because those
  2649              could be larger if there are taller display elements
  2650              (e.g., characters displayed with a larger font) in the
  2651              same glyph row.  */
  2652           int glyph_y = s->ybase - s->first_glyph->ascent;
  2653           int glyph_height = s->first_glyph->ascent + s->first_glyph->descent;
  2654           /* Strike-through width and offset from the glyph string's
  2655              top edge.  */
  2656           unsigned long h = 1;
  2657           unsigned long dy = (glyph_height - h) / 2;
  2658 
  2659           if (s->face->strike_through_color_defaulted_p)
  2660             pgtk_fill_rectangle (s->f, s->xgcv.foreground, s->x, glyph_y + dy,
  2661                                  s->width, h, false);
  2662           else
  2663             pgtk_fill_rectangle (s->f, s->face->strike_through_color, s->x,
  2664                                  glyph_y + dy, s->width, h, false);
  2665         }
  2666 
  2667       if (s->prev)
  2668         {
  2669           struct glyph_string *prev;
  2670 
  2671           for (prev = s->prev; prev; prev = prev->prev)
  2672             if (prev->hl != s->hl
  2673                 && prev->x + prev->width + prev->right_overhang > s->x)
  2674               {
  2675                 /* As prev was drawn while clipped to its own area, we
  2676                    must draw the right_overhang part using s->hl now.  */
  2677                 enum draw_glyphs_face save = prev->hl;
  2678 
  2679                 prev->hl = s->hl;
  2680                 pgtk_set_glyph_string_gc (prev);
  2681                 cairo_save (cr);
  2682                 pgtk_set_glyph_string_clipping_exactly (s, prev, cr);
  2683                 if (prev->first_glyph->type == CHAR_GLYPH)
  2684                   pgtk_draw_glyph_string_foreground (prev);
  2685                 else
  2686                   pgtk_draw_composite_glyph_string_foreground (prev);
  2687                 prev->hl = save;
  2688                 prev->num_clips = 0;
  2689                 cairo_restore (cr);
  2690               }
  2691         }
  2692 
  2693       if (s->next)
  2694         {
  2695           struct glyph_string *next;
  2696 
  2697           for (next = s->next; next; next = next->next)
  2698             if (next->hl != s->hl
  2699                 && next->x - next->left_overhang < s->x + s->width)
  2700               {
  2701                 /* As next will be drawn while clipped to its own area,
  2702                    we must draw the left_overhang part using s->hl now.  */
  2703                 enum draw_glyphs_face save = next->hl;
  2704 
  2705                 next->hl = s->hl;
  2706                 pgtk_set_glyph_string_gc (next);
  2707                 cairo_save (cr);
  2708                 pgtk_set_glyph_string_clipping_exactly (s, next, cr);
  2709                 if (next->first_glyph->type == CHAR_GLYPH)
  2710                   pgtk_draw_glyph_string_foreground (next);
  2711                 else
  2712                   pgtk_draw_composite_glyph_string_foreground (next);
  2713                 cairo_restore (cr);
  2714                 next->hl = save;
  2715                 next->num_clips = 0;
  2716                 next->clip_head = s->next;
  2717               }
  2718         }
  2719     }
  2720 
  2721   /* TODO: figure out in which cases the stipple is actually drawn on
  2722      PGTK.  */
  2723   if (!s->row->stipple_p)
  2724     s->row->stipple_p = s->face->stipple;
  2725 
  2726   /* Reset clipping.  */
  2727   pgtk_end_cr_clip (s->f);
  2728   s->num_clips = 0;
  2729 }
  2730 
  2731 /* RIF: Define cursor CURSOR on frame F.  */
  2732 
  2733 static void
  2734 pgtk_define_frame_cursor (struct frame *f, Emacs_Cursor cursor)
  2735 {
  2736   if (!f->pointer_invisible && FRAME_X_OUTPUT (f)->current_cursor != cursor)
  2737     gdk_window_set_cursor (gtk_widget_get_window (FRAME_GTK_WIDGET (f)),
  2738                            cursor);
  2739   FRAME_X_OUTPUT (f)->current_cursor = cursor;
  2740 }
  2741 
  2742 static void
  2743 pgtk_after_update_window_line (struct window *w,
  2744                                struct glyph_row *desired_row)
  2745 {
  2746   struct frame *f;
  2747   int width, height;
  2748 
  2749   /* begin copy from other terms */
  2750   eassert (w);
  2751 
  2752   if (!desired_row->mode_line_p && !w->pseudo_window_p)
  2753     desired_row->redraw_fringe_bitmaps_p = 1;
  2754 
  2755   /* When a window has disappeared, make sure that no rest of
  2756      full-width rows stays visible in the internal border.  */
  2757   if (windows_or_buffers_changed
  2758       && desired_row->full_width_p
  2759       && (f = XFRAME (w->frame),
  2760           width = FRAME_INTERNAL_BORDER_WIDTH (f),
  2761           width != 0) && (height = desired_row->visible_height, height > 0))
  2762     {
  2763       int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
  2764 
  2765       block_input ();
  2766       pgtk_clear_frame_area (f, 0, y, width, height);
  2767       pgtk_clear_frame_area (f,
  2768                              FRAME_PIXEL_WIDTH (f) - width, y, width, height);
  2769       unblock_input ();
  2770     }
  2771 }
  2772 
  2773 static void
  2774 pgtk_clear_frame_area (struct frame *f, int x, int y, int width, int height)
  2775 {
  2776   pgtk_clear_area (f, x, y, width, height);
  2777 }
  2778 
  2779 /* Draw a hollow box cursor on window W in glyph row ROW.  */
  2780 
  2781 static void
  2782 pgtk_draw_hollow_cursor (struct window *w, struct glyph_row *row)
  2783 {
  2784   struct frame *f = XFRAME (WINDOW_FRAME (w));
  2785   int x, y, wd, h;
  2786   struct glyph *cursor_glyph;
  2787 
  2788   /* Get the glyph the cursor is on.  If we can't tell because
  2789      the current matrix is invalid or such, give up.  */
  2790   cursor_glyph = get_phys_cursor_glyph (w);
  2791   if (cursor_glyph == NULL)
  2792     return;
  2793 
  2794   /* Compute frame-relative coordinates for phys cursor.  */
  2795   get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
  2796   wd = w->phys_cursor_width - 1;
  2797 
  2798   /* The foreground of cursor_gc is typically the same as the normal
  2799      background color, which can cause the cursor box to be invisible.  */
  2800   cairo_t *cr = pgtk_begin_cr_clip (f);
  2801   pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT (f)->cursor_color, false);
  2802 
  2803   /* When on R2L character, show cursor at the right edge of the
  2804      glyph, unless the cursor box is as wide as the glyph or wider
  2805      (the latter happens when x-stretch-cursor is non-nil).  */
  2806   if ((cursor_glyph->resolved_level & 1) != 0
  2807       && cursor_glyph->pixel_width > wd)
  2808     {
  2809       x += cursor_glyph->pixel_width - wd;
  2810       if (wd > 0)
  2811         wd -= 1;
  2812     }
  2813   /* Set clipping, draw the rectangle, and reset clipping again.  */
  2814   pgtk_clip_to_row (w, row, TEXT_AREA, cr);
  2815   pgtk_draw_rectangle (f, FRAME_X_OUTPUT (f)->cursor_color,
  2816                        x, y, wd, h - 1, false);
  2817   pgtk_end_cr_clip (f);
  2818 }
  2819 
  2820 /* Draw a bar cursor on window W in glyph row ROW.
  2821 
  2822    Implementation note: One would like to draw a bar cursor with an
  2823    angle equal to the one given by the font property XA_ITALIC_ANGLE.
  2824    Unfortunately, I didn't find a font yet that has this property set.
  2825    --gerd.  */
  2826 
  2827 static void
  2828 pgtk_draw_bar_cursor (struct window *w, struct glyph_row *row, int width,
  2829                    enum text_cursor_kinds kind)
  2830 {
  2831   struct frame *f = XFRAME (w->frame);
  2832   struct glyph *cursor_glyph;
  2833 
  2834   /* If cursor is out of bounds, don't draw garbage.  This can happen
  2835      in mini-buffer windows when switching between echo area glyphs
  2836      and mini-buffer.  */
  2837   cursor_glyph = get_phys_cursor_glyph (w);
  2838   if (cursor_glyph == NULL)
  2839     return;
  2840 
  2841   /* Experimental avoidance of cursor on xwidget.  */
  2842   if (cursor_glyph->type == XWIDGET_GLYPH)
  2843     return;
  2844 
  2845   /* If on an image, draw like a normal cursor.  That's usually better
  2846      visible than drawing a bar, esp. if the image is large so that
  2847      the bar might not be in the window.  */
  2848   if (cursor_glyph->type == IMAGE_GLYPH)
  2849     {
  2850       struct glyph_row *r;
  2851       r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
  2852       draw_phys_cursor_glyph (w, r, DRAW_CURSOR);
  2853     }
  2854   else
  2855     {
  2856       struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
  2857       unsigned long color;
  2858 
  2859       cairo_t *cr = pgtk_begin_cr_clip (f);
  2860 
  2861       /* If the glyph's background equals the color we normally draw
  2862          the bars cursor in, the bar cursor in its normal color is
  2863          invisible.  Use the glyph's foreground color instead in this
  2864          case, on the assumption that the glyph's colors are chosen so
  2865          that the glyph is legible.  */
  2866       if (face->background == FRAME_X_OUTPUT (f)->cursor_color)
  2867         color = face->foreground;
  2868       else
  2869         color = FRAME_X_OUTPUT (f)->cursor_color;
  2870 
  2871       pgtk_clip_to_row (w, row, TEXT_AREA, cr);
  2872 
  2873       if (kind == BAR_CURSOR)
  2874         {
  2875           int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
  2876 
  2877           if (width < 0)
  2878             width = FRAME_CURSOR_WIDTH (f);
  2879           width = min (cursor_glyph->pixel_width, width);
  2880 
  2881           w->phys_cursor_width = width;
  2882 
  2883           /* If the character under cursor is R2L, draw the bar cursor
  2884              on the right of its glyph, rather than on the left.  */
  2885           if ((cursor_glyph->resolved_level & 1) != 0)
  2886             x += cursor_glyph->pixel_width - width;
  2887 
  2888           pgtk_fill_rectangle (f, color, x,
  2889                                WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
  2890                                width, row->height, false);
  2891         }
  2892       else                      /* HBAR_CURSOR */
  2893         {
  2894           int dummy_x, dummy_y, dummy_h;
  2895           int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
  2896 
  2897           if (width < 0)
  2898             width = row->height;
  2899 
  2900           width = min (row->height, width);
  2901 
  2902           get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
  2903                                     &dummy_y, &dummy_h);
  2904 
  2905           if ((cursor_glyph->resolved_level & 1) != 0
  2906               && cursor_glyph->pixel_width > w->phys_cursor_width - 1)
  2907             x += cursor_glyph->pixel_width - w->phys_cursor_width + 1;
  2908           pgtk_fill_rectangle (f, color, x,
  2909                                WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
  2910                                                         row->height - width),
  2911                                w->phys_cursor_width - 1, width, false);
  2912         }
  2913 
  2914       pgtk_end_cr_clip (f);
  2915     }
  2916 }
  2917 
  2918 /* RIF: Draw cursor on window W.  */
  2919 
  2920 static void
  2921 pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
  2922                          int y, enum text_cursor_kinds cursor_type,
  2923                          int cursor_width, bool on_p, bool active_p)
  2924 {
  2925   struct frame *f = XFRAME (w->frame);
  2926 
  2927   if (on_p)
  2928     {
  2929       w->phys_cursor_type = cursor_type;
  2930       w->phys_cursor_on_p = true;
  2931 
  2932       if (glyph_row->exact_window_width_line_p
  2933           && (glyph_row->reversed_p
  2934               ? (w->phys_cursor.hpos < 0)
  2935               : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
  2936         {
  2937           glyph_row->cursor_in_fringe_p = true;
  2938           draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
  2939         }
  2940       else
  2941         {
  2942           switch (cursor_type)
  2943             {
  2944             case HOLLOW_BOX_CURSOR:
  2945               pgtk_draw_hollow_cursor (w, glyph_row);
  2946               break;
  2947 
  2948             case FILLED_BOX_CURSOR:
  2949               draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
  2950               break;
  2951 
  2952             case BAR_CURSOR:
  2953               pgtk_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
  2954               break;
  2955 
  2956             case HBAR_CURSOR:
  2957               pgtk_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
  2958               break;
  2959 
  2960             case NO_CURSOR:
  2961               w->phys_cursor_width = 0;
  2962               break;
  2963 
  2964             default:
  2965               emacs_abort ();
  2966             }
  2967         }
  2968 
  2969       if (w == XWINDOW (f->selected_window))
  2970         {
  2971           int frame_x = (WINDOW_TO_FRAME_PIXEL_X (w, x)
  2972                          + WINDOW_LEFT_FRINGE_WIDTH (w)
  2973                          + WINDOW_LEFT_MARGIN_WIDTH (w));
  2974           int frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, y);
  2975           pgtk_im_set_cursor_location (f, frame_x, frame_y,
  2976                                        w->phys_cursor_width,
  2977                                        w->phys_cursor_height);
  2978         }
  2979     }
  2980 
  2981 }
  2982 
  2983 static void
  2984 pgtk_copy_bits (struct frame *f, cairo_rectangle_t *src_rect,
  2985                 cairo_rectangle_t *dst_rect)
  2986 {
  2987   cairo_t *cr;
  2988   cairo_surface_t *surface;     /* temporary surface */
  2989 
  2990   surface
  2991     = cairo_surface_create_similar (FRAME_CR_SURFACE (f),
  2992                                     CAIRO_CONTENT_COLOR_ALPHA,
  2993                                     (int) src_rect->width,
  2994                                     (int) src_rect->height);
  2995 
  2996   cr = cairo_create (surface);
  2997   cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), -src_rect->x,
  2998                             -src_rect->y);
  2999   cairo_rectangle (cr, 0, 0, src_rect->width, src_rect->height);
  3000   cairo_clip (cr);
  3001   cairo_paint (cr);
  3002   cairo_destroy (cr);
  3003 
  3004   cr = pgtk_begin_cr_clip (f);
  3005   cairo_set_source_surface (cr, surface, dst_rect->x, dst_rect->y);
  3006   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
  3007   cairo_rectangle (cr, dst_rect->x, dst_rect->y, dst_rect->width,
  3008                    dst_rect->height);
  3009   cairo_clip (cr);
  3010   cairo_paint (cr);
  3011   pgtk_end_cr_clip (f);
  3012 
  3013   cairo_surface_destroy (surface);
  3014 }
  3015 
  3016 /* Scroll part of the display as described by RUN.  */
  3017 
  3018 static void
  3019 pgtk_scroll_run (struct window *w, struct run *run)
  3020 {
  3021   struct frame *f = XFRAME (w->frame);
  3022   int x, y, width, height, from_y, to_y, bottom_y;
  3023 
  3024   /* Get frame-relative bounding box of the text display area of W,
  3025      without mode lines.  Include in this box the left and right
  3026      fringe of W.  */
  3027   window_box (w, ANY_AREA, &x, &y, &width, &height);
  3028 
  3029   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
  3030   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
  3031   bottom_y = y + height;
  3032 
  3033   if (to_y < from_y)
  3034     {
  3035       /* Scrolling up.  Make sure we don't copy part of the mode
  3036          line at the bottom.  */
  3037       if (from_y + run->height > bottom_y)
  3038         height = bottom_y - from_y;
  3039       else
  3040         height = run->height;
  3041     }
  3042   else
  3043     {
  3044       /* Scrolling down.  Make sure we don't copy over the mode line.
  3045          at the bottom.  */
  3046       if (to_y + run->height > bottom_y)
  3047         height = bottom_y - to_y;
  3048       else
  3049         height = run->height;
  3050     }
  3051 
  3052   block_input ();
  3053 
  3054 #ifdef HAVE_XWIDGETS
  3055   /* "Copy" xwidget views in the area that will be scrolled.  */
  3056   GtkWidget *tem, *parent = FRAME_GTK_WIDGET (f);
  3057   GList *children = gtk_container_get_children (GTK_CONTAINER (parent));
  3058   GList *iter;
  3059   struct xwidget_view *view;
  3060 
  3061   for (iter = children; iter; iter = iter->next)
  3062     {
  3063       tem = iter->data;
  3064       view = g_object_get_data (G_OBJECT (tem), XG_XWIDGET_VIEW);
  3065 
  3066       if (view && !view->hidden)
  3067         {
  3068           int window_y = view->y + view->clip_top;
  3069           int window_height = view->clip_bottom - view->clip_top;
  3070 
  3071           Emacs_Rectangle r1, r2, result;
  3072           r1.x = w->pixel_left;
  3073           r1.y = from_y;
  3074           r1.width = w->pixel_width;
  3075           r1.height = height;
  3076           r2 = r1;
  3077           r2.y = window_y;
  3078           r2.height = window_height;
  3079 
  3080           /* The window is offscreen, just unmap it.  */
  3081           if (window_height == 0)
  3082             {
  3083               view->hidden = true;
  3084               gtk_widget_hide (tem);
  3085               continue;
  3086             }
  3087 
  3088           bool intersects_p =
  3089             gui_intersect_rectangles (&r1, &r2, &result);
  3090 
  3091           if (XWINDOW (view->w) == w && intersects_p)
  3092             {
  3093               int y = view->y + (to_y - from_y);
  3094               int text_area_x, text_area_y, text_area_width, text_area_height;
  3095               int clip_top, clip_bottom;
  3096 
  3097               window_box (w, view->area, &text_area_x, &text_area_y,
  3098                           &text_area_width, &text_area_height);
  3099 
  3100               view->y = y;
  3101 
  3102               clip_top = 0;
  3103               clip_bottom = XXWIDGET (view->model)->height;
  3104 
  3105               if (y < text_area_y)
  3106                 clip_top = text_area_y - y;
  3107 
  3108               if ((y + clip_bottom) > (text_area_y + text_area_height))
  3109                 {
  3110                   clip_bottom -= (y + clip_bottom) - (text_area_y + text_area_height);
  3111                 }
  3112 
  3113               view->clip_top = clip_top;
  3114               view->clip_bottom = clip_bottom;
  3115 
  3116               /* This means the view has moved offscreen.  Unmap
  3117                  it and hide it here.  */
  3118               if ((view->clip_bottom - view->clip_top) <= 0)
  3119                 {
  3120                   view->hidden = true;
  3121                   gtk_widget_hide (tem);
  3122                 }
  3123               else
  3124                 {
  3125                   gtk_fixed_move (GTK_FIXED (FRAME_GTK_WIDGET (f)),
  3126                                   tem, view->x + view->clip_left,
  3127                                   view->y + view->clip_top);
  3128                   gtk_widget_set_size_request (tem, view->clip_right - view->clip_left,
  3129                                                view->clip_bottom - view->clip_top);
  3130                   gtk_widget_queue_allocate (tem);
  3131                 }
  3132             }
  3133         }
  3134     }
  3135 
  3136   g_list_free (children);
  3137 #endif
  3138 
  3139   /* Cursor off.  Will be switched on again in x_update_window_end.  */
  3140   gui_clear_cursor (w);
  3141 
  3142   {
  3143     cairo_rectangle_t src_rect = { x, from_y, width, height };
  3144     cairo_rectangle_t dst_rect = { x, to_y, width, height };
  3145     pgtk_copy_bits (f, &src_rect, &dst_rect);
  3146   }
  3147 
  3148   unblock_input ();
  3149 }
  3150 
  3151 /* Icons.  */
  3152 
  3153 static bool
  3154 pgtk_bitmap_icon (struct frame *f, Lisp_Object file)
  3155 {
  3156   /* This code has never worked anyway for the reason that Wayland
  3157      uses icons set within desktop files, and has been disabled
  3158      because leaving it intact would require image.c to retain a
  3159      reference to a GdkPixbuf (which are no longer used) within new
  3160      bitmaps.  */
  3161 #if 0
  3162   ptrdiff_t bitmap_id;
  3163 
  3164   if (FRAME_GTK_WIDGET (f) == 0)
  3165     return true;
  3166 
  3167   /* Free up our existing icon bitmap and mask if any.  */
  3168   if (f->output_data.pgtk->icon_bitmap > 0)
  3169     image_destroy_bitmap (f, f->output_data.pgtk->icon_bitmap);
  3170   f->output_data.pgtk->icon_bitmap = 0;
  3171 
  3172   if (STRINGP (file))
  3173     {
  3174       /* Use gtk_window_set_icon_from_file () if available,
  3175          It's not restricted to bitmaps */
  3176       if (xg_set_icon (f, file))
  3177         return false;
  3178       bitmap_id = image_create_bitmap_from_file (f, file);
  3179     }
  3180   else
  3181     {
  3182       /* Create the GNU bitmap and mask if necessary.  */
  3183       if (FRAME_DISPLAY_INFO (f)->icon_bitmap_id < 0)
  3184         {
  3185           ptrdiff_t rc = -1;
  3186 
  3187           if (xg_set_icon (f, xg_default_icon_file)
  3188               || xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
  3189             {
  3190               FRAME_DISPLAY_INFO (f)->icon_bitmap_id = -2;
  3191               return false;
  3192             }
  3193 
  3194           /* If all else fails, use the (black and white) xbm image. */
  3195           if (rc == -1)
  3196             {
  3197               rc = image_create_bitmap_from_data (f,
  3198                                                   (char *) gnu_xbm_bits,
  3199                                                   gnu_xbm_width,
  3200                                                   gnu_xbm_height);
  3201               if (rc == -1)
  3202                 return true;
  3203 
  3204               FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
  3205             }
  3206         }
  3207 
  3208       /* The first time we create the GNU bitmap and mask,
  3209          this increments the ref-count one extra time.
  3210          As a result, the GNU bitmap and mask are never freed.
  3211          That way, we don't have to worry about allocating it again.  */
  3212       image_reference_bitmap (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
  3213 
  3214       bitmap_id = FRAME_DISPLAY_INFO (f)->icon_bitmap_id;
  3215     }
  3216 
  3217   f->output_data.pgtk->icon_bitmap = bitmap_id;
  3218 #endif /* 0 */
  3219   return false;
  3220 }
  3221 
  3222 
  3223 /* Make the x-window of frame F use a rectangle with text.
  3224    Use ICON_NAME as the text.  */
  3225 
  3226 bool
  3227 pgtk_text_icon (struct frame *f, const char *icon_name)
  3228 {
  3229   if (FRAME_GTK_OUTER_WIDGET (f))
  3230     {
  3231       gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), NULL);
  3232       gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), icon_name);
  3233     }
  3234 
  3235   return false;
  3236 }
  3237 
  3238 /***********************************************************************
  3239                     Starting and ending an update
  3240  ***********************************************************************/
  3241 
  3242 /* Start an update of frame F.  This function is installed as a hook
  3243    for update_begin, i.e. it is called when update_begin is called.
  3244    This function is called prior to calls to x_update_window_begin for
  3245    each window being updated.  Currently, there is nothing to do here
  3246    because all interesting stuff is done on a window basis.  */
  3247 
  3248 static void
  3249 pgtk_update_begin (struct frame *f)
  3250 {
  3251   pgtk_clear_under_internal_border (f);
  3252 }
  3253 
  3254 /* Draw a vertical window border from (x,y0) to (x,y1)  */
  3255 
  3256 static void
  3257 pgtk_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
  3258 {
  3259   struct frame *f = XFRAME (WINDOW_FRAME (w));
  3260   struct face *face;
  3261   cairo_t *cr;
  3262 
  3263   cr = pgtk_begin_cr_clip (f);
  3264 
  3265   face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID);
  3266   if (face)
  3267     pgtk_set_cr_source_with_color (f, face->foreground, false);
  3268 
  3269   cairo_rectangle (cr, x, y0, 1, y1 - y0);
  3270   cairo_fill (cr);
  3271 
  3272   pgtk_end_cr_clip (f);
  3273 }
  3274 
  3275 /* Draw a window divider from (x0,y0) to (x1,y1)  */
  3276 
  3277 static void
  3278 pgtk_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
  3279 {
  3280   struct frame *f = XFRAME (WINDOW_FRAME (w));
  3281   struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID);
  3282   struct face *face_first
  3283     = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
  3284   struct face *face_last
  3285     = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
  3286   unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
  3287   unsigned long color_first = (face_first
  3288                                ? face_first->foreground
  3289                                : FRAME_FOREGROUND_PIXEL (f));
  3290   unsigned long color_last = (face_last
  3291                               ? face_last->foreground
  3292                               : FRAME_FOREGROUND_PIXEL (f));
  3293   cairo_t *cr = pgtk_begin_cr_clip (f);
  3294 
  3295   if (y1 - y0 > x1 - x0 && x1 - x0 > 2)
  3296     /* Vertical.  */
  3297     {
  3298       pgtk_set_cr_source_with_color (f, color_first, false);
  3299       cairo_rectangle (cr, x0, y0, 1, y1 - y0);
  3300       cairo_fill (cr);
  3301       pgtk_set_cr_source_with_color (f, color, false);
  3302       cairo_rectangle (cr, x0 + 1, y0, x1 - x0 - 2, y1 - y0);
  3303       cairo_fill (cr);
  3304       pgtk_set_cr_source_with_color (f, color_last, false);
  3305       cairo_rectangle (cr, x1 - 1, y0, 1, y1 - y0);
  3306       cairo_fill (cr);
  3307     }
  3308   else if (x1 - x0 > y1 - y0 && y1 - y0 > 3)
  3309     /* Horizontal.  */
  3310     {
  3311       pgtk_set_cr_source_with_color (f, color_first, false);
  3312       cairo_rectangle (cr, x0, y0, x1 - x0, 1);
  3313       cairo_fill (cr);
  3314       pgtk_set_cr_source_with_color (f, color, false);
  3315       cairo_rectangle (cr, x0, y0 + 1, x1 - x0, y1 - y0 - 2);
  3316       cairo_fill (cr);
  3317       pgtk_set_cr_source_with_color (f, color_last, false);
  3318       cairo_rectangle (cr, x0, y1 - 1, x1 - x0, 1);
  3319       cairo_fill (cr);
  3320     }
  3321   else
  3322     {
  3323       pgtk_set_cr_source_with_color (f, color, false);
  3324       cairo_rectangle (cr, x0, y0, x1 - x0, y1 - y0);
  3325       cairo_fill (cr);
  3326     }
  3327 
  3328   pgtk_end_cr_clip (f);
  3329 }
  3330 
  3331 /* End update of frame F.  This function is installed as a hook in
  3332    update_end.  */
  3333 
  3334 static void
  3335 pgtk_update_end (struct frame *f)
  3336 {
  3337   /* Mouse highlight may be displayed again.  */
  3338   MOUSE_HL_INFO (f)->mouse_face_defer = false;
  3339 }
  3340 
  3341 static void
  3342 pgtk_frame_up_to_date (struct frame *f)
  3343 {
  3344   block_input ();
  3345   FRAME_MOUSE_UPDATE (f);
  3346   if (!buffer_flipping_blocked_p ())
  3347     {
  3348       flip_cr_context (f);
  3349       gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
  3350     }
  3351   unblock_input ();
  3352 }
  3353 
  3354 /* Return the current position of the mouse.
  3355    *FP should be a frame which indicates which display to ask about.
  3356 
  3357    If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
  3358    and *PART to the frame, window, and scroll bar part that the mouse
  3359    is over.  Set *X and *Y to the portion and whole of the mouse's
  3360    position on the scroll bar.
  3361 
  3362    If the mouse movement started elsewhere, set *FP to the frame the
  3363    mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
  3364    the mouse is over.
  3365 
  3366    Set *TIMESTAMP to the server time-stamp for the time at which the mouse
  3367    was at this position.
  3368 
  3369    Don't store anything if we don't have a valid set of values to report.
  3370 
  3371    This clears the mouse_moved flag, so we can wait for the next mouse
  3372    movement.  */
  3373 
  3374 static void
  3375 pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object * bar_window,
  3376                      enum scroll_bar_part *part, Lisp_Object *x,
  3377                      Lisp_Object *y, Time *timestamp)
  3378 {
  3379   struct frame *f1;
  3380   struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
  3381   int win_x, win_y;
  3382   GdkSeat *seat;
  3383   GdkDevice *device;
  3384   GdkModifierType mask;
  3385   GdkWindow *win;
  3386   bool return_frame_flag = false;
  3387 
  3388   block_input ();
  3389 
  3390   Lisp_Object frame, tail;
  3391 
  3392   /* Clear the mouse-moved flag for every frame on this display.  */
  3393   FOR_EACH_FRAME (tail, frame)
  3394     if (FRAME_PGTK_P (XFRAME (frame))
  3395         && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
  3396     XFRAME (frame)->mouse_moved = false;
  3397 
  3398   dpyinfo->last_mouse_scroll_bar = NULL;
  3399 
  3400   if (gui_mouse_grabbed (dpyinfo)
  3401       && (!EQ (track_mouse, Qdropping)
  3402           && !EQ (track_mouse, Qdrag_source)))
  3403     f1 = dpyinfo->last_mouse_frame;
  3404   else
  3405     {
  3406       f1 = *fp;
  3407       win = gtk_widget_get_window (FRAME_GTK_WIDGET (*fp));
  3408       seat = gdk_display_get_default_seat (dpyinfo->gdpy);
  3409       device = gdk_seat_get_pointer (seat);
  3410       win = gdk_window_get_device_position (win, device, &win_x,
  3411                                             &win_y, &mask);
  3412       if (win != NULL)
  3413         f1 = pgtk_any_window_to_frame (win);
  3414       else
  3415         {
  3416           f1 = SELECTED_FRAME ();
  3417 
  3418           if (!FRAME_PGTK_P (f1))
  3419             f1 = dpyinfo->last_mouse_frame;
  3420 
  3421           return_frame_flag = EQ (track_mouse, Qdrag_source);
  3422         }
  3423     }
  3424 
  3425   /* F1 can be a terminal frame.  (Bug#50322) */
  3426   if (f1 == NULL || !FRAME_PGTK_P (f1))
  3427     {
  3428       unblock_input ();
  3429       return;
  3430     }
  3431 
  3432   win = gtk_widget_get_window (FRAME_GTK_WIDGET (f1));
  3433   seat = gdk_display_get_default_seat (dpyinfo->gdpy);
  3434   device = gdk_seat_get_pointer (seat);
  3435 
  3436   win = gdk_window_get_device_position (win, device,
  3437                                         &win_x, &win_y, &mask);
  3438 
  3439   if (f1 != NULL)
  3440     {
  3441       remember_mouse_glyph (f1, win_x, win_y,
  3442                             &dpyinfo->last_mouse_glyph);
  3443       dpyinfo->last_mouse_glyph_frame = f1;
  3444 
  3445       *bar_window = Qnil;
  3446       *part = 0;
  3447       *fp = !return_frame_flag ? f1 : NULL;
  3448       XSETINT (*x, win_x);
  3449       XSETINT (*y, win_y);
  3450       *timestamp = dpyinfo->last_mouse_movement_time;
  3451     }
  3452 
  3453   unblock_input ();
  3454 }
  3455 
  3456 /* Fringe bitmaps.  */
  3457 
  3458 static int max_fringe_bmp = 0;
  3459 static cairo_pattern_t **fringe_bmp = 0;
  3460 
  3461 static void
  3462 pgtk_define_fringe_bitmap (int which, unsigned short *bits, int h, int wd)
  3463 {
  3464   int i, stride;
  3465   cairo_surface_t *surface;
  3466   unsigned char *data;
  3467   cairo_pattern_t *pattern;
  3468 
  3469   if (which >= max_fringe_bmp)
  3470     {
  3471       i = max_fringe_bmp;
  3472       max_fringe_bmp = which + 20;
  3473       fringe_bmp
  3474         = (cairo_pattern_t **) xrealloc (fringe_bmp,
  3475                                          max_fringe_bmp *
  3476                                          sizeof (cairo_pattern_t *));
  3477       while (i < max_fringe_bmp)
  3478         fringe_bmp[i++] = 0;
  3479     }
  3480 
  3481   block_input ();
  3482 
  3483   surface = cairo_image_surface_create (CAIRO_FORMAT_A1, wd, h);
  3484   stride = cairo_image_surface_get_stride (surface);
  3485   data = cairo_image_surface_get_data (surface);
  3486 
  3487   for (i = 0; i < h; i++)
  3488     {
  3489       *((unsigned short *) data) = bits[i];
  3490       data += stride;
  3491     }
  3492 
  3493   cairo_surface_mark_dirty (surface);
  3494   pattern = cairo_pattern_create_for_surface (surface);
  3495   cairo_surface_destroy (surface);
  3496 
  3497   unblock_input ();
  3498 
  3499   fringe_bmp[which] = pattern;
  3500 }
  3501 
  3502 static void
  3503 pgtk_destroy_fringe_bitmap (int which)
  3504 {
  3505   if (which >= max_fringe_bmp)
  3506     return;
  3507 
  3508   if (fringe_bmp[which])
  3509     {
  3510       block_input ();
  3511       cairo_pattern_destroy (fringe_bmp[which]);
  3512       unblock_input ();
  3513     }
  3514   fringe_bmp[which] = 0;
  3515 }
  3516 
  3517 static void
  3518 pgtk_clip_to_row (struct window *w, struct glyph_row *row,
  3519                   enum glyph_row_area area, cairo_t * cr)
  3520 {
  3521   int window_x, window_y, window_width;
  3522   cairo_rectangle_int_t rect;
  3523 
  3524   window_box (w, area, &window_x, &window_y, &window_width, 0);
  3525 
  3526   rect.x = window_x;
  3527   rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
  3528   rect.y = max (rect.y, window_y);
  3529   rect.width = window_width;
  3530   rect.height = row->visible_height;
  3531 
  3532   cairo_rectangle (cr, rect.x, rect.y, rect.width, rect.height);
  3533   cairo_clip (cr);
  3534 }
  3535 
  3536 static void
  3537 pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
  3538                          struct draw_fringe_bitmap_params *p)
  3539 {
  3540   struct frame *f = XFRAME (WINDOW_FRAME (w));
  3541   struct face *face = p->face;
  3542 
  3543   cairo_t *cr = pgtk_begin_cr_clip (f);
  3544 
  3545   /* Must clip because of partially visible lines.  */
  3546   pgtk_clip_to_row (w, row, ANY_AREA, cr);
  3547 
  3548   if (p->bx >= 0 && !p->overlay_p)
  3549     {
  3550       /* In case the same realized face is used for fringes and for
  3551          something displayed in the text (e.g. face `region' on
  3552          mono-displays, the fill style may have been changed to
  3553          FillSolid in pgtk_draw_glyph_string_background.  */
  3554       if (face->stipple)
  3555         fill_background_by_face (f, face, p->bx, p->by, p->nx, p->ny);
  3556       else
  3557         {
  3558           pgtk_set_cr_source_with_color (f, face->background, true);
  3559           cairo_rectangle (cr, p->bx, p->by, p->nx, p->ny);
  3560           cairo_fill (cr);
  3561         }
  3562     }
  3563 
  3564   if (p->which
  3565       && p->which < max_fringe_bmp
  3566       && p->which < max_used_fringe_bitmap)
  3567     {
  3568       Emacs_GC gcv;
  3569 
  3570       if (!fringe_bmp[p->which])
  3571         {
  3572           /* This fringe bitmap is known to fringe.c, but lacks the
  3573              cairo_pattern_t pattern which shadows that bitmap.  This
  3574              is typical to define-fringe-bitmap being called when the
  3575              selected frame was not a GUI frame, for example, when
  3576              packages that define fringe bitmaps are loaded by a
  3577              daemon Emacs.  Create the missing pattern now.  */
  3578           gui_define_fringe_bitmap (f, p->which);
  3579         }
  3580 
  3581       gcv.foreground = (p->cursor_p
  3582                         ? (p->overlay_p ? face->background
  3583                            : FRAME_X_OUTPUT (f)->cursor_color)
  3584                         : face->foreground);
  3585       gcv.background = face->background;
  3586       pgtk_cr_draw_image (f, &gcv, fringe_bmp[p->which], 0, p->dh,
  3587                           p->wd, p->h, p->x, p->y, p->overlay_p);
  3588     }
  3589 
  3590   pgtk_end_cr_clip (f);
  3591 }
  3592 
  3593 static struct atimer *hourglass_atimer = NULL;
  3594 static int hourglass_enter_count = 0;
  3595 
  3596 static void
  3597 hourglass_cb (struct atimer *timer)
  3598 {
  3599 
  3600 }
  3601 
  3602 static void
  3603 pgtk_show_hourglass (struct frame *f)
  3604 {
  3605   struct pgtk_output *x = FRAME_X_OUTPUT (f);
  3606   if (x->hourglass_widget != NULL)
  3607     gtk_widget_destroy (x->hourglass_widget);
  3608 
  3609   /* This creates a GDK_INPUT_ONLY window.  */
  3610   x->hourglass_widget = gtk_event_box_new ();
  3611   gtk_widget_set_has_window (x->hourglass_widget, true);
  3612   gtk_fixed_put (GTK_FIXED (FRAME_GTK_WIDGET (f)), x->hourglass_widget, 0, 0);
  3613   gtk_widget_show (x->hourglass_widget);
  3614   gtk_widget_set_size_request (x->hourglass_widget, 30000, 30000);
  3615   gdk_window_raise (gtk_widget_get_window (x->hourglass_widget));
  3616   gdk_window_set_cursor (gtk_widget_get_window (x->hourglass_widget),
  3617                          x->hourglass_cursor);
  3618 
  3619   /* For cursor animation, we receive signals, set pending_signals,
  3620      and wait for the signal handler to run.  */
  3621   if (hourglass_enter_count++ == 0)
  3622     {
  3623       struct timespec ts = make_timespec (0, 50 * 1000 * 1000);
  3624       if (hourglass_atimer != NULL)
  3625         cancel_atimer (hourglass_atimer);
  3626       hourglass_atimer
  3627         = start_atimer (ATIMER_CONTINUOUS, ts, hourglass_cb, NULL);
  3628     }
  3629 }
  3630 
  3631 static void
  3632 pgtk_hide_hourglass (struct frame *f)
  3633 {
  3634   struct pgtk_output *x = FRAME_X_OUTPUT (f);
  3635   if (--hourglass_enter_count == 0)
  3636     {
  3637       if (hourglass_atimer != NULL)
  3638         {
  3639           cancel_atimer (hourglass_atimer);
  3640           hourglass_atimer = NULL;
  3641         }
  3642     }
  3643   if (x->hourglass_widget != NULL)
  3644     {
  3645       gtk_widget_destroy (x->hourglass_widget);
  3646       x->hourglass_widget = NULL;
  3647     }
  3648 }
  3649 
  3650 /* Flushes changes to display.  */
  3651 static void
  3652 pgtk_flush_display (struct frame *f)
  3653 {
  3654 }
  3655 
  3656 extern frame_parm_handler pgtk_frame_parm_handlers[];
  3657 
  3658 static struct redisplay_interface pgtk_redisplay_interface = {
  3659   pgtk_frame_parm_handlers,
  3660   gui_produce_glyphs,
  3661   gui_write_glyphs,
  3662   gui_insert_glyphs,
  3663   gui_clear_end_of_line,
  3664   pgtk_scroll_run,
  3665   pgtk_after_update_window_line,
  3666   NULL, /* gui_update_window_begin, */
  3667   NULL, /* gui_update_window_end, */
  3668   pgtk_flush_display,
  3669   gui_clear_window_mouse_face,
  3670   gui_get_glyph_overhangs,
  3671   gui_fix_overlapping_area,
  3672   pgtk_draw_fringe_bitmap,
  3673   pgtk_define_fringe_bitmap,
  3674   pgtk_destroy_fringe_bitmap,
  3675   pgtk_compute_glyph_string_overhangs,
  3676   pgtk_draw_glyph_string,
  3677   pgtk_define_frame_cursor,
  3678   pgtk_clear_frame_area,
  3679   pgtk_clear_under_internal_border,
  3680   pgtk_draw_window_cursor,
  3681   pgtk_draw_vertical_window_border,
  3682   pgtk_draw_window_divider,
  3683   NULL,                         /* pgtk_shift_glyphs_for_insert, */
  3684   pgtk_show_hourglass,
  3685   pgtk_hide_hourglass,
  3686   pgtk_default_font_parameter,
  3687 };
  3688 
  3689 void
  3690 pgtk_clear_frame (struct frame *f)
  3691 {
  3692   if (!FRAME_DEFAULT_FACE (f))
  3693     return;
  3694 
  3695   mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
  3696 
  3697   block_input ();
  3698   pgtk_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
  3699   unblock_input ();
  3700 }
  3701 
  3702 static void
  3703 recover_from_visible_bell (struct atimer *timer)
  3704 {
  3705   struct frame *f = timer->client_data;
  3706 
  3707   if (FRAME_X_OUTPUT (f)->cr_surface_visible_bell != NULL)
  3708     {
  3709       cairo_surface_destroy (FRAME_X_OUTPUT (f)->cr_surface_visible_bell);
  3710       FRAME_X_OUTPUT (f)->cr_surface_visible_bell = NULL;
  3711     }
  3712 
  3713   if (FRAME_X_OUTPUT (f)->atimer_visible_bell != NULL)
  3714     FRAME_X_OUTPUT (f)->atimer_visible_bell = NULL;
  3715 }
  3716 
  3717 /* Invert the middle quarter of the frame for .15 sec.  */
  3718 
  3719 static void
  3720 pgtk_flash (struct frame *f)
  3721 {
  3722   cairo_surface_t *surface_orig, *surface;
  3723   cairo_t *cr;
  3724   int width, height, flash_height, flash_left, flash_right;
  3725   struct timespec delay;
  3726 
  3727   if (!FRAME_CR_CONTEXT (f))
  3728     return;
  3729 
  3730   block_input ();
  3731 
  3732   surface_orig = FRAME_CR_SURFACE (f);
  3733 
  3734   width = FRAME_CR_SURFACE_DESIRED_WIDTH (f);
  3735   height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f);
  3736   surface = cairo_surface_create_similar (surface_orig,
  3737                                           CAIRO_CONTENT_COLOR_ALPHA,
  3738                                           width, height);
  3739 
  3740   cr = cairo_create (surface);
  3741   cairo_set_source_surface (cr, surface_orig, 0, 0);
  3742   cairo_rectangle (cr, 0, 0, width, height);
  3743   cairo_clip (cr);
  3744   cairo_paint (cr);
  3745 
  3746   cairo_set_source_rgb (cr, 1, 1, 1);
  3747   cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE);
  3748 
  3749   /* Get the height not including a menu bar widget.  */
  3750   height = FRAME_PIXEL_HEIGHT (f);
  3751   /* Height of each line to flash.  */
  3752   flash_height = FRAME_LINE_HEIGHT (f);
  3753   /* These will be the left and right margins of the rectangles.  */
  3754   flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
  3755   flash_right = (FRAME_PIXEL_WIDTH (f)
  3756                  - FRAME_INTERNAL_BORDER_WIDTH (f));
  3757   width = flash_right - flash_left;
  3758 
  3759   /* If window is tall, flash top and bottom line.  */
  3760   if (height > 3 * FRAME_LINE_HEIGHT (f))
  3761     {
  3762       cairo_rectangle (cr,
  3763                        flash_left,
  3764                        (FRAME_INTERNAL_BORDER_WIDTH (f)
  3765                         + FRAME_TOP_MARGIN_HEIGHT (f)),
  3766                        width, flash_height);
  3767       cairo_fill (cr);
  3768 
  3769       cairo_rectangle (cr,
  3770                        flash_left,
  3771                        (height - flash_height
  3772                         - FRAME_INTERNAL_BORDER_WIDTH (f)
  3773                         - FRAME_BOTTOM_MARGIN_HEIGHT (f)),
  3774                        width, flash_height);
  3775       cairo_fill (cr);
  3776     }
  3777   else
  3778     {
  3779       /* If it is short, flash it all.  */
  3780       cairo_rectangle (cr,
  3781                        flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
  3782                        width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
  3783       cairo_fill (cr);
  3784     }
  3785 
  3786   FRAME_X_OUTPUT (f)->cr_surface_visible_bell = surface;
  3787 
  3788   delay = make_timespec (0, 50 * 1000 * 1000);
  3789 
  3790   if (FRAME_X_OUTPUT (f)->atimer_visible_bell != NULL)
  3791     {
  3792       cancel_atimer (FRAME_X_OUTPUT (f)->atimer_visible_bell);
  3793       FRAME_X_OUTPUT (f)->atimer_visible_bell = NULL;
  3794     }
  3795 
  3796   FRAME_X_OUTPUT (f)->atimer_visible_bell
  3797     = start_atimer (ATIMER_RELATIVE, delay, recover_from_visible_bell, f);
  3798 
  3799 
  3800   cairo_destroy (cr);
  3801   unblock_input ();
  3802 }
  3803 
  3804 /* Make audible bell.  */
  3805 
  3806 static void
  3807 pgtk_ring_bell (struct frame *f)
  3808 {
  3809   if (visible_bell)
  3810     {
  3811       pgtk_flash (f);
  3812     }
  3813   else
  3814     {
  3815       block_input ();
  3816       gtk_widget_error_bell (FRAME_GTK_WIDGET (f));
  3817       unblock_input ();
  3818     }
  3819 }
  3820 
  3821 /* Read events coming from the X server.
  3822    Return as soon as there are no more events to be read.
  3823 
  3824    Return the number of characters stored into the buffer,
  3825    thus pretending to be `read' (except the characters we store
  3826    in the keyboard buffer can be multibyte, so are not necessarily
  3827    C chars).  */
  3828 
  3829 static int
  3830 pgtk_read_socket (struct terminal *terminal, struct input_event *hold_quit)
  3831 {
  3832   GMainContext *context;
  3833   bool context_acquired = false;
  3834   int count;
  3835 
  3836   count = evq_flush (hold_quit);
  3837   if (count > 0)
  3838     {
  3839       return count;
  3840     }
  3841 
  3842   context = g_main_context_default ();
  3843   context_acquired = g_main_context_acquire (context);
  3844 
  3845   block_input ();
  3846 
  3847   if (context_acquired)
  3848     {
  3849       while (g_main_context_pending (context))
  3850         {
  3851           g_main_context_dispatch (context);
  3852         }
  3853     }
  3854 
  3855   unblock_input ();
  3856 
  3857   if (context_acquired)
  3858     g_main_context_release (context);
  3859 
  3860   count = evq_flush (hold_quit);
  3861   if (count > 0)
  3862     {
  3863       return count;
  3864     }
  3865 
  3866   return 0;
  3867 }
  3868 
  3869 /* Lisp window being scrolled.  Set when starting to interact with
  3870    a toolkit scroll bar, reset to nil when ending the interaction.  */
  3871 
  3872 static Lisp_Object window_being_scrolled;
  3873 
  3874 static void
  3875 pgtk_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
  3876                             int portion, int whole, bool horizontal)
  3877 {
  3878   union buffered_input_event inev;
  3879 
  3880   EVENT_INIT (inev.ie);
  3881 
  3882   inev.ie.kind = (horizontal
  3883                   ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
  3884                   : SCROLL_BAR_CLICK_EVENT);
  3885   inev.ie.frame_or_window = window;
  3886   inev.ie.arg = Qnil;
  3887   inev.ie.timestamp = 0;
  3888   inev.ie.code = 0;
  3889   inev.ie.part = part;
  3890   inev.ie.x = make_fixnum (portion);
  3891   inev.ie.y = make_fixnum (whole);
  3892   inev.ie.modifiers = 0;
  3893 
  3894   evq_enqueue (&inev);
  3895 }
  3896 
  3897 
  3898 /* Scroll bar callback for GTK scroll bars.  WIDGET is the scroll
  3899    bar widget.  DATA is a pointer to the scroll_bar structure. */
  3900 
  3901 static gboolean
  3902 xg_scroll_callback (GtkRange * range,
  3903                     GtkScrollType scroll, gdouble value, gpointer user_data)
  3904 {
  3905   int whole = 0, portion = 0;
  3906   struct scroll_bar *bar = user_data;
  3907   enum scroll_bar_part part = scroll_bar_nowhere;
  3908   GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range));
  3909 
  3910   if (xg_ignore_gtk_scrollbar)
  3911     return false;
  3912 
  3913   switch (scroll)
  3914     {
  3915     case GTK_SCROLL_JUMP:
  3916       if (bar->horizontal)
  3917         {
  3918           part = scroll_bar_horizontal_handle;
  3919           whole = (int) (gtk_adjustment_get_upper (adj) -
  3920                          gtk_adjustment_get_page_size (adj));
  3921           portion = min ((int) value, whole);
  3922           bar->dragging = portion;
  3923         }
  3924       else
  3925         {
  3926           part = scroll_bar_handle;
  3927           whole = gtk_adjustment_get_upper (adj) -
  3928             gtk_adjustment_get_page_size (adj);
  3929           portion = min ((int) value, whole);
  3930           bar->dragging = portion;
  3931         }
  3932       break;
  3933     case GTK_SCROLL_STEP_BACKWARD:
  3934       part = (bar->horizontal ? scroll_bar_left_arrow : scroll_bar_up_arrow);
  3935       bar->dragging = -1;
  3936       break;
  3937     case GTK_SCROLL_STEP_FORWARD:
  3938       part = (bar->horizontal
  3939               ? scroll_bar_right_arrow : scroll_bar_down_arrow);
  3940       bar->dragging = -1;
  3941       break;
  3942     case GTK_SCROLL_PAGE_BACKWARD:
  3943       part = (bar->horizontal
  3944               ? scroll_bar_before_handle : scroll_bar_above_handle);
  3945       bar->dragging = -1;
  3946       break;
  3947     case GTK_SCROLL_PAGE_FORWARD:
  3948       part = (bar->horizontal
  3949               ? scroll_bar_after_handle : scroll_bar_below_handle);
  3950       bar->dragging = -1;
  3951       break;
  3952     default:
  3953       break;
  3954     }
  3955 
  3956   if (part != scroll_bar_nowhere)
  3957     {
  3958       window_being_scrolled = bar->window;
  3959       pgtk_send_scroll_bar_event (bar->window, part, portion, whole,
  3960                                   bar->horizontal);
  3961     }
  3962 
  3963   return false;
  3964 }
  3965 
  3966 /* Callback for button release. Sets dragging to -1 when dragging is done.  */
  3967 
  3968 static gboolean
  3969 xg_end_scroll_callback (GtkWidget * widget,
  3970                         GdkEventButton * event, gpointer user_data)
  3971 {
  3972   struct scroll_bar *bar = user_data;
  3973   bar->dragging = -1;
  3974   if (WINDOWP (window_being_scrolled))
  3975     {
  3976       pgtk_send_scroll_bar_event (window_being_scrolled,
  3977                                   scroll_bar_end_scroll, 0, 0,
  3978                                   bar->horizontal);
  3979       window_being_scrolled = Qnil;
  3980     }
  3981 
  3982   return false;
  3983 }
  3984 
  3985 #define SCROLL_BAR_NAME "verticalScrollBar"
  3986 #define SCROLL_BAR_HORIZONTAL_NAME "horizontalScrollBar"
  3987 
  3988 /* Create the widget for scroll bar BAR on frame F.  Record the widget
  3989    and X window of the scroll bar in BAR.  */
  3990 
  3991 static void
  3992 pgtk_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
  3993 {
  3994   const char *scroll_bar_name = SCROLL_BAR_NAME;
  3995 
  3996   block_input ();
  3997   xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
  3998                         G_CALLBACK (xg_end_scroll_callback), scroll_bar_name);
  3999   unblock_input ();
  4000 }
  4001 
  4002 static void
  4003 pgtk_create_horizontal_toolkit_scroll_bar (struct frame *f,
  4004                                            struct scroll_bar *bar)
  4005 {
  4006   const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
  4007 
  4008   block_input ();
  4009   xg_create_horizontal_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
  4010                                    G_CALLBACK (xg_end_scroll_callback),
  4011                                    scroll_bar_name);
  4012   unblock_input ();
  4013 }
  4014 
  4015 /* Set the thumb size and position of scroll bar BAR.  We are currently
  4016    displaying PORTION out of a whole WHOLE, and our position POSITION.  */
  4017 
  4018 static void
  4019 pgtk_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion,
  4020                                    int position, int whole)
  4021 {
  4022   xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
  4023 }
  4024 
  4025 static void
  4026 pgtk_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar,
  4027                                               int portion, int position,
  4028                                               int whole)
  4029 {
  4030   xg_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
  4031 }
  4032 
  4033 /* Create a scroll bar and return the scroll bar vector for it.  W is
  4034    the Emacs window on which to create the scroll bar. TOP, LEFT,
  4035    WIDTH and HEIGHT are the pixel coordinates and dimensions of the
  4036    scroll bar. */
  4037 
  4038 static struct scroll_bar *
  4039 pgtk_scroll_bar_create (struct window *w, int top, int left,
  4040                         int width, int height, bool horizontal)
  4041 {
  4042   struct frame *f = XFRAME (w->frame);
  4043   struct scroll_bar *bar
  4044     = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev, PVEC_OTHER);
  4045   Lisp_Object barobj;
  4046 
  4047   block_input ();
  4048 
  4049   if (horizontal)
  4050     pgtk_create_horizontal_toolkit_scroll_bar (f, bar);
  4051   else
  4052     pgtk_create_toolkit_scroll_bar (f, bar);
  4053 
  4054   XSETWINDOW (bar->window, w);
  4055   bar->top = top;
  4056   bar->left = left;
  4057   bar->width = width;
  4058   bar->height = height;
  4059   bar->start = 0;
  4060   bar->end = 0;
  4061   bar->dragging = -1;
  4062   bar->horizontal = horizontal;
  4063 
  4064   /* Add bar to its frame's list of scroll bars.  */
  4065   bar->next = FRAME_SCROLL_BARS (f);
  4066   bar->prev = Qnil;
  4067   XSETVECTOR (barobj, bar);
  4068   fset_scroll_bars (f, barobj);
  4069   if (!NILP (bar->next))
  4070     XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
  4071 
  4072   /* Map the window/widget.  */
  4073   {
  4074     if (horizontal)
  4075       xg_update_horizontal_scrollbar_pos (f, bar->x_window, top,
  4076                                           left, width, max (height, 1));
  4077     else
  4078       xg_update_scrollbar_pos (f, bar->x_window, top,
  4079                                left, width, max (height, 1));
  4080   }
  4081 
  4082   unblock_input ();
  4083   return bar;
  4084 }
  4085 
  4086 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
  4087    nil.  */
  4088 
  4089 static void
  4090 pgtk_scroll_bar_remove (struct scroll_bar *bar)
  4091 {
  4092   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
  4093   block_input ();
  4094 
  4095   xg_remove_scroll_bar (f, bar->x_window);
  4096 
  4097   /* Dissociate this scroll bar from its window.  */
  4098   if (bar->horizontal)
  4099     wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
  4100   else
  4101     wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
  4102 
  4103   unblock_input ();
  4104 }
  4105 
  4106 /* Set the handle of the vertical scroll bar for WINDOW to indicate
  4107    that we are displaying PORTION characters out of a total of WHOLE
  4108    characters, starting at POSITION.  If WINDOW has no scroll bar,
  4109    create one.  */
  4110 
  4111 static void
  4112 pgtk_set_vertical_scroll_bar (struct window *w, int portion, int whole,
  4113                               int position)
  4114 {
  4115   struct frame *f = XFRAME (w->frame);
  4116   Lisp_Object barobj;
  4117   struct scroll_bar *bar;
  4118   int top, height, left, width;
  4119   int window_y, window_height;
  4120 
  4121   /* Get window dimensions.  */
  4122   window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
  4123   top = window_y;
  4124   height = window_height;
  4125   left = WINDOW_SCROLL_BAR_AREA_X (w);
  4126   width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
  4127 
  4128   /* Does the scroll bar exist yet?  */
  4129   if (NILP (w->vertical_scroll_bar))
  4130     {
  4131       if (width > 0 && height > 0)
  4132         {
  4133           block_input ();
  4134           pgtk_clear_area (f, left, top, width, height);
  4135           unblock_input ();
  4136         }
  4137 
  4138       bar = pgtk_scroll_bar_create (w, top, left, width, max (height, 1), false);
  4139     }
  4140   else
  4141     {
  4142       /* It may just need to be moved and resized.  */
  4143       unsigned int mask = 0;
  4144 
  4145       bar = XSCROLL_BAR (w->vertical_scroll_bar);
  4146 
  4147       block_input ();
  4148 
  4149       if (left != bar->left)
  4150         mask |= 1;
  4151       if (top != bar->top)
  4152         mask |= 1;
  4153       if (width != bar->width)
  4154         mask |= 1;
  4155       if (height != bar->height)
  4156         mask |= 1;
  4157 
  4158       /* Move/size the scroll bar widget.  */
  4159       if (mask)
  4160         {
  4161           /* Since toolkit scroll bars are smaller than the space reserved
  4162              for them on the frame, we have to clear "under" them.  */
  4163           if (width > 0 && height > 0)
  4164             pgtk_clear_area (f, left, top, width, height);
  4165           xg_update_scrollbar_pos (f, bar->x_window, top,
  4166                                    left, width, max (height, 1));
  4167         }
  4168 
  4169       /* Remember new settings.  */
  4170       bar->left = left;
  4171       bar->top = top;
  4172       bar->width = width;
  4173       bar->height = height;
  4174 
  4175       unblock_input ();
  4176     }
  4177 
  4178   pgtk_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
  4179 
  4180   XSETVECTOR (barobj, bar);
  4181   wset_vertical_scroll_bar (w, barobj);
  4182 }
  4183 
  4184 static void
  4185 pgtk_set_horizontal_scroll_bar (struct window *w, int portion, int whole,
  4186                                 int position)
  4187 {
  4188   struct frame *f = XFRAME (w->frame);
  4189   Lisp_Object barobj;
  4190   struct scroll_bar *bar;
  4191   int top, height, left, width;
  4192   int window_x, window_width;
  4193   int pixel_width = WINDOW_PIXEL_WIDTH (w);
  4194 
  4195   /* Get window dimensions.  */
  4196   window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
  4197   left = window_x;
  4198   width = window_width;
  4199   top = WINDOW_SCROLL_BAR_AREA_Y (w);
  4200   height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
  4201 
  4202   /* Does the scroll bar exist yet?  */
  4203   if (NILP (w->horizontal_scroll_bar))
  4204     {
  4205       if (width > 0 && height > 0)
  4206         {
  4207           block_input ();
  4208 
  4209           /* Clear also part between window_width and
  4210              WINDOW_PIXEL_WIDTH.  */
  4211           pgtk_clear_area (f, left, top, pixel_width, height);
  4212           unblock_input ();
  4213         }
  4214 
  4215       bar = pgtk_scroll_bar_create (w, top, left, width, height, true);
  4216     }
  4217   else
  4218     {
  4219       /* It may just need to be moved and resized.  */
  4220       unsigned int mask = 0;
  4221 
  4222       bar = XSCROLL_BAR (w->horizontal_scroll_bar);
  4223 
  4224       block_input ();
  4225 
  4226       if (left != bar->left)
  4227         mask |= 1;
  4228       if (top != bar->top)
  4229         mask |= 1;
  4230       if (width != bar->width)
  4231         mask |= 1;
  4232       if (height != bar->height)
  4233         mask |= 1;
  4234 
  4235       /* Move/size the scroll bar widget.  */
  4236       if (mask)
  4237         {
  4238           /* Since toolkit scroll bars are smaller than the space reserved
  4239              for them on the frame, we have to clear "under" them.  */
  4240           if (width > 0 && height > 0)
  4241             pgtk_clear_area (f,
  4242                              WINDOW_LEFT_EDGE_X (w), top,
  4243                              pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w),
  4244                              height);
  4245           xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, left,
  4246                                               width, height);
  4247         }
  4248 
  4249       /* Remember new settings.  */
  4250       bar->left = left;
  4251       bar->top = top;
  4252       bar->width = width;
  4253       bar->height = height;
  4254 
  4255       unblock_input ();
  4256     }
  4257 
  4258   pgtk_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
  4259 
  4260   XSETVECTOR (barobj, bar);
  4261   wset_horizontal_scroll_bar (w, barobj);
  4262 }
  4263 
  4264 /* The following three hooks are used when we're doing a thorough
  4265    redisplay of the frame.  We don't explicitly know which scroll bars
  4266    are going to be deleted, because keeping track of when windows go
  4267    away is a real pain - "Can you say set-window-configuration, boys
  4268    and girls?"  Instead, we just assert at the beginning of redisplay
  4269    that *all* scroll bars are to be removed, and then save a scroll bar
  4270    from the fiery pit when we actually redisplay its window.  */
  4271 
  4272 /* Arrange for all scroll bars on FRAME to be removed at the next call
  4273    to `*judge_scroll_bars_hook'.  A scroll bar may be spared if
  4274    `*redeem_scroll_bar_hook' is applied to its window before the judgment.  */
  4275 
  4276 static void
  4277 pgtk_condemn_scroll_bars (struct frame *frame)
  4278 {
  4279   if (!NILP (FRAME_SCROLL_BARS (frame)))
  4280     {
  4281       if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
  4282         {
  4283           /* Prepend scrollbars to already condemned ones.  */
  4284           Lisp_Object last = FRAME_SCROLL_BARS (frame);
  4285 
  4286           while (!NILP (XSCROLL_BAR (last)->next))
  4287             last = XSCROLL_BAR (last)->next;
  4288 
  4289           XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
  4290           XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
  4291         }
  4292 
  4293       fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
  4294       fset_scroll_bars (frame, Qnil);
  4295     }
  4296 }
  4297 
  4298 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
  4299    Note that WINDOW isn't necessarily condemned at all.  */
  4300 
  4301 static void
  4302 pgtk_redeem_scroll_bar (struct window *w)
  4303 {
  4304   struct scroll_bar *bar;
  4305   Lisp_Object barobj;
  4306   struct frame *f;
  4307 
  4308   /* We can't redeem this window's scroll bar if it doesn't have one.  */
  4309   if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar))
  4310     emacs_abort ();
  4311 
  4312   if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
  4313     {
  4314       bar = XSCROLL_BAR (w->vertical_scroll_bar);
  4315       /* Unlink it from the condemned list.  */
  4316       f = XFRAME (WINDOW_FRAME (w));
  4317       if (NILP (bar->prev))
  4318         {
  4319           /* If the prev pointer is nil, it must be the first in one of
  4320              the lists.  */
  4321           if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
  4322             /* It's not condemned.  Everything's fine.  */
  4323             goto horizontal;
  4324           else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
  4325                        w->vertical_scroll_bar))
  4326             fset_condemned_scroll_bars (f, bar->next);
  4327           else
  4328             /* If its prev pointer is nil, it must be at the front of
  4329                one or the other!  */
  4330             emacs_abort ();
  4331         }
  4332       else
  4333         XSCROLL_BAR (bar->prev)->next = bar->next;
  4334 
  4335       if (!NILP (bar->next))
  4336         XSCROLL_BAR (bar->next)->prev = bar->prev;
  4337 
  4338       bar->next = FRAME_SCROLL_BARS (f);
  4339       bar->prev = Qnil;
  4340       XSETVECTOR (barobj, bar);
  4341       fset_scroll_bars (f, barobj);
  4342       if (!NILP (bar->next))
  4343         XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
  4344     }
  4345 
  4346 horizontal:
  4347   if (!NILP (w->horizontal_scroll_bar)
  4348       && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
  4349     {
  4350       bar = XSCROLL_BAR (w->horizontal_scroll_bar);
  4351       /* Unlink it from the condemned list.  */
  4352       f = XFRAME (WINDOW_FRAME (w));
  4353       if (NILP (bar->prev))
  4354         {
  4355           /* If the prev pointer is nil, it must be the first in one of
  4356              the lists.  */
  4357           if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
  4358             /* It's not condemned.  Everything's fine.  */
  4359             return;
  4360           else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
  4361                        w->horizontal_scroll_bar))
  4362             fset_condemned_scroll_bars (f, bar->next);
  4363           else
  4364             /* If its prev pointer is nil, it must be at the front of
  4365                one or the other!  */
  4366             emacs_abort ();
  4367         }
  4368       else
  4369         XSCROLL_BAR (bar->prev)->next = bar->next;
  4370 
  4371       if (!NILP (bar->next))
  4372         XSCROLL_BAR (bar->next)->prev = bar->prev;
  4373 
  4374       bar->next = FRAME_SCROLL_BARS (f);
  4375       bar->prev = Qnil;
  4376       XSETVECTOR (barobj, bar);
  4377       fset_scroll_bars (f, barobj);
  4378       if (!NILP (bar->next))
  4379         XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
  4380     }
  4381 }
  4382 
  4383 /* Remove all scroll bars on FRAME that haven't been saved since the
  4384    last call to `*condemn_scroll_bars_hook'.  */
  4385 
  4386 static void
  4387 pgtk_judge_scroll_bars (struct frame *f)
  4388 {
  4389   Lisp_Object bar, next;
  4390 
  4391   bar = FRAME_CONDEMNED_SCROLL_BARS (f);
  4392 
  4393   /* Clear out the condemned list now so we won't try to process any
  4394      more events on the hapless scroll bars.  */
  4395   fset_condemned_scroll_bars (f, Qnil);
  4396 
  4397   for (; !NILP (bar); bar = next)
  4398     {
  4399       struct scroll_bar *b = XSCROLL_BAR (bar);
  4400 
  4401       pgtk_scroll_bar_remove (b);
  4402 
  4403       next = b->next;
  4404       b->next = b->prev = Qnil;
  4405     }
  4406 
  4407   /* Now there should be no references to the condemned scroll bars,
  4408      and they should get garbage-collected.  */
  4409 }
  4410 
  4411 static void
  4412 set_fullscreen_state (struct frame *f)
  4413 {
  4414   if (!FRAME_GTK_OUTER_WIDGET (f))
  4415     return;
  4416 
  4417   GtkWindow *widget = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
  4418   switch (f->want_fullscreen)
  4419     {
  4420     case FULLSCREEN_NONE:
  4421       gtk_window_unfullscreen (widget);
  4422       gtk_window_unmaximize (widget);
  4423       store_frame_param (f, Qfullscreen, Qnil);
  4424       break;
  4425 
  4426     case FULLSCREEN_BOTH:
  4427       gtk_window_unmaximize (widget);
  4428       gtk_window_fullscreen (widget);
  4429       store_frame_param (f, Qfullscreen, Qfullboth);
  4430       break;
  4431 
  4432     case FULLSCREEN_MAXIMIZED:
  4433       gtk_window_unfullscreen (widget);
  4434       gtk_window_maximize (widget);
  4435       store_frame_param (f, Qfullscreen, Qmaximized);
  4436       break;
  4437 
  4438     case FULLSCREEN_WIDTH:
  4439     case FULLSCREEN_HEIGHT:
  4440       /* Not supported by gtk. Ignore them. */
  4441       break;
  4442     }
  4443 
  4444   f->want_fullscreen = FULLSCREEN_NONE;
  4445 }
  4446 
  4447 static void
  4448 pgtk_fullscreen_hook (struct frame *f)
  4449 {
  4450   if (FRAME_VISIBLE_P (f))
  4451     {
  4452       block_input ();
  4453       set_fullscreen_state (f);
  4454       unblock_input ();
  4455     }
  4456 }
  4457 
  4458 /* This function is called when the last frame on a display is deleted. */
  4459 void
  4460 pgtk_delete_terminal (struct terminal *terminal)
  4461 {
  4462   struct pgtk_display_info *dpyinfo = terminal->display_info.pgtk;
  4463 
  4464   /* Protect against recursive calls.  delete_frame in
  4465      delete_terminal calls us back when it deletes our last frame.  */
  4466   if (!terminal->name)
  4467     return;
  4468 
  4469   block_input ();
  4470 
  4471   pgtk_im_finish (dpyinfo);
  4472 
  4473   /* Normally, the display is available...  */
  4474   if (dpyinfo->gdpy)
  4475     {
  4476       image_destroy_all_bitmaps (dpyinfo);
  4477 
  4478       g_clear_object (&dpyinfo->xg_cursor);
  4479       g_clear_object (&dpyinfo->vertical_scroll_bar_cursor);
  4480       g_clear_object (&dpyinfo->horizontal_scroll_bar_cursor);
  4481       g_clear_object (&dpyinfo->invisible_cursor);
  4482       if (dpyinfo->last_click_event != NULL)
  4483         {
  4484           gdk_event_free (dpyinfo->last_click_event);
  4485           dpyinfo->last_click_event = NULL;
  4486         }
  4487 
  4488       /* Disconnect these handlers before the display closes so
  4489          useless removal signals don't fire.  */
  4490       g_signal_handlers_disconnect_by_func (G_OBJECT (dpyinfo->gdpy),
  4491                                             G_CALLBACK (pgtk_seat_added_cb),
  4492                                             dpyinfo);
  4493       g_signal_handlers_disconnect_by_func (G_OBJECT (dpyinfo->gdpy),
  4494                                             G_CALLBACK (pgtk_seat_removed_cb),
  4495                                             dpyinfo);
  4496       xg_display_close (dpyinfo->gdpy);
  4497 
  4498       dpyinfo->gdpy = NULL;
  4499     }
  4500 
  4501   if (dpyinfo->connection >= 0)
  4502     emacs_close (dpyinfo->connection);
  4503 
  4504   dpyinfo->connection = -1;
  4505 
  4506   delete_keyboard_wait_descriptor (0);
  4507 
  4508   pgtk_delete_display (dpyinfo);
  4509   unblock_input ();
  4510 }
  4511 
  4512 /* Store F's background color into *BGCOLOR.  */
  4513 static void
  4514 pgtk_query_frame_background_color (struct frame *f, Emacs_Color * bgcolor)
  4515 {
  4516   bgcolor->pixel = FRAME_BACKGROUND_PIXEL (f);
  4517   pgtk_query_color (f, bgcolor);
  4518 }
  4519 
  4520 static void
  4521 pgtk_free_pixmap (struct frame *f, Emacs_Pixmap pixmap)
  4522 {
  4523   if (pixmap)
  4524     {
  4525       xfree (pixmap->data);
  4526       xfree (pixmap);
  4527     }
  4528 }
  4529 
  4530 void
  4531 pgtk_focus_frame (struct frame *f, bool noactivate)
  4532 {
  4533   struct pgtk_display_info *dpyinfo;
  4534   GtkWidget *widget;
  4535   GtkWindow *window;
  4536 
  4537   dpyinfo = FRAME_DISPLAY_INFO (f);
  4538 
  4539   if (FRAME_GTK_OUTER_WIDGET (f) && !noactivate)
  4540     {
  4541       /* The user says it is okay to activate the frame.  Call
  4542          gtk_window_present_with_time.  If the timestamp specified
  4543          (actually a display serial on Wayland) is new enough, then
  4544          any Wayland compositor supporting gtk_surface1_present will
  4545          cause the frame to be activated.  */
  4546 
  4547       window = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
  4548       gtk_window_present_with_time (window, dpyinfo->last_user_time);
  4549       return;
  4550     }
  4551 
  4552   widget = FRAME_WIDGET (f);
  4553 
  4554   if (widget)
  4555     gtk_widget_grab_focus (widget);
  4556 }
  4557 
  4558 static void
  4559 set_opacity_recursively (GtkWidget *w, gpointer data)
  4560 {
  4561   gtk_widget_set_opacity (w, *(double *) data);
  4562 
  4563   if (GTK_IS_CONTAINER (w))
  4564     gtk_container_foreach (GTK_CONTAINER (w),
  4565                            set_opacity_recursively, data);
  4566 }
  4567 
  4568 static void
  4569 pgtk_set_frame_alpha (struct frame *f)
  4570 {
  4571   struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
  4572   double alpha = 1.0;
  4573   double alpha_min = 1.0;
  4574 
  4575   if (dpyinfo->highlight_frame == f)
  4576     alpha = f->alpha[0];
  4577   else
  4578     alpha = f->alpha[1];
  4579 
  4580   if (alpha < 0.0)
  4581     return;
  4582 
  4583   if (FLOATP (Vframe_alpha_lower_limit))
  4584     alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
  4585   else if (FIXNUMP (Vframe_alpha_lower_limit))
  4586     alpha_min = (XFIXNUM (Vframe_alpha_lower_limit)) / 100.0;
  4587 
  4588   if (alpha > 1.0)
  4589     alpha = 1.0;
  4590   else if (alpha < alpha_min && alpha_min <= 1.0)
  4591     alpha = alpha_min;
  4592 
  4593   set_opacity_recursively (FRAME_WIDGET (f), &alpha);
  4594   /* without this, blending mode is strange on wayland. */
  4595   gtk_widget_queue_resize_no_redraw (FRAME_WIDGET (f));
  4596 }
  4597 
  4598 static void
  4599 frame_highlight (struct frame *f)
  4600 {
  4601   block_input ();
  4602   GtkWidget *w = FRAME_WIDGET (f);
  4603 
  4604   char *css = g_strdup_printf ("decoration { border: solid %dpx #%06x; }",
  4605                                f->border_width,
  4606                                ((unsigned int) FRAME_X_OUTPUT (f)->border_pixel
  4607                                 & 0x00ffffff));
  4608 
  4609   GtkStyleContext *ctxt = gtk_widget_get_style_context (w);
  4610   GtkCssProvider *css_provider = gtk_css_provider_new ();
  4611   gtk_css_provider_load_from_data (css_provider, css, -1, NULL);
  4612   gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (css_provider),
  4613                                   GTK_STYLE_PROVIDER_PRIORITY_USER);
  4614   g_free (css);
  4615 
  4616   GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider;
  4617   FRAME_X_OUTPUT (f)->border_color_css_provider = css_provider;
  4618   if (old != NULL)
  4619     {
  4620       gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old));
  4621       g_object_unref (old);
  4622     }
  4623 
  4624   unblock_input ();
  4625   gui_update_cursor (f, true);
  4626   pgtk_set_frame_alpha (f);
  4627 }
  4628 
  4629 static void
  4630 frame_unhighlight (struct frame *f)
  4631 {
  4632   GtkWidget *w;
  4633   char *css;
  4634   GtkStyleContext *ctxt;
  4635   GtkCssProvider *css_provider, *old;
  4636 
  4637   block_input ();
  4638 
  4639   w = FRAME_WIDGET (f);
  4640 
  4641   css = g_strdup_printf ("decoration { border: dotted %dpx #ffffff; }",
  4642                          f->border_width);
  4643 
  4644   ctxt = gtk_widget_get_style_context (w);
  4645   css_provider = gtk_css_provider_new ();
  4646   gtk_css_provider_load_from_data (css_provider, css, -1, NULL);
  4647   gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (css_provider),
  4648                                   GTK_STYLE_PROVIDER_PRIORITY_USER);
  4649   g_free (css);
  4650 
  4651   old = FRAME_X_OUTPUT (f)->border_color_css_provider;
  4652   FRAME_X_OUTPUT (f)->border_color_css_provider = css_provider;
  4653   if (old != NULL)
  4654     {
  4655       gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old));
  4656       g_object_unref (old);
  4657     }
  4658 
  4659   unblock_input ();
  4660   gui_update_cursor (f, true);
  4661   pgtk_set_frame_alpha (f);
  4662 }
  4663 
  4664 
  4665 void
  4666 pgtk_frame_rehighlight (struct pgtk_display_info *dpyinfo)
  4667 {
  4668   struct frame *old_highlight = dpyinfo->highlight_frame;
  4669 
  4670   if (dpyinfo->x_focus_frame)
  4671     {
  4672       dpyinfo->highlight_frame
  4673         = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
  4674            ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
  4675            : dpyinfo->x_focus_frame);
  4676       if (!FRAME_LIVE_P (dpyinfo->highlight_frame))
  4677         {
  4678           fset_focus_frame (dpyinfo->x_focus_frame, Qnil);
  4679           dpyinfo->highlight_frame = dpyinfo->x_focus_frame;
  4680         }
  4681     }
  4682   else
  4683     dpyinfo->highlight_frame = 0;
  4684 
  4685   if (old_highlight)
  4686     frame_unhighlight (old_highlight);
  4687   if (dpyinfo->highlight_frame)
  4688     frame_highlight (dpyinfo->highlight_frame);
  4689 }
  4690 
  4691 /* The focus has changed, or we have redirected a frame's focus to
  4692    another frame (this happens when a frame uses a surrogate
  4693    mini-buffer frame).  Shift the highlight as appropriate.
  4694 
  4695    The FRAME argument doesn't necessarily have anything to do with which
  4696    frame is being highlighted or un-highlighted; we only use it to find
  4697    the appropriate X display info.  */
  4698 
  4699 static void
  4700 pgtk_frame_rehighlight_hook (struct frame *frame)
  4701 {
  4702   pgtk_frame_rehighlight (FRAME_DISPLAY_INFO (frame));
  4703 }
  4704 
  4705 /* Set whether or not the mouse pointer should be visible on frame
  4706    F.  */
  4707 static void
  4708 pgtk_toggle_invisible_pointer (struct frame *f, bool invisible)
  4709 {
  4710   Emacs_Cursor cursor;
  4711   if (invisible)
  4712     cursor = FRAME_DISPLAY_INFO (f)->invisible_cursor;
  4713   else
  4714     cursor = f->output_data.pgtk->current_cursor;
  4715   gdk_window_set_cursor (gtk_widget_get_window (FRAME_GTK_WIDGET (f)),
  4716                          cursor);
  4717   f->pointer_invisible = invisible;
  4718 
  4719   /* This is needed to make the pointer visible upon receiving a
  4720      motion notify event.  */
  4721   gdk_display_flush (FRAME_X_DISPLAY (f));
  4722 }
  4723 
  4724 /* The focus has changed.  Update the frames as necessary to reflect
  4725    the new situation.  Note that we can't change the selected frame
  4726    here, because the Lisp code we are interrupting might become confused.
  4727    Each event gets marked with the frame in which it occurred, so the
  4728    Lisp code can tell when the switch took place by examining the events.  */
  4729 
  4730 static void
  4731 pgtk_new_focus_frame (struct pgtk_display_info *dpyinfo, struct frame *frame)
  4732 {
  4733   struct frame *old_focus = dpyinfo->x_focus_frame;
  4734   /* doesn't work on wayland */
  4735 
  4736   if (frame != dpyinfo->x_focus_frame)
  4737     {
  4738       /* Set this before calling other routines, so that they see
  4739          the correct value of x_focus_frame.  */
  4740       dpyinfo->x_focus_frame = frame;
  4741 
  4742       if (old_focus && old_focus->auto_lower)
  4743         if (FRAME_GTK_OUTER_WIDGET (old_focus))
  4744           gdk_window_lower (gtk_widget_get_window
  4745                             (FRAME_GTK_OUTER_WIDGET (old_focus)));
  4746 
  4747       if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
  4748         if (FRAME_GTK_OUTER_WIDGET (dpyinfo->x_focus_frame))
  4749           gdk_window_raise (gtk_widget_get_window
  4750                             (FRAME_GTK_OUTER_WIDGET (dpyinfo->x_focus_frame)));
  4751     }
  4752 
  4753   pgtk_frame_rehighlight (dpyinfo);
  4754 }
  4755 
  4756 static void
  4757 pgtk_buffer_flipping_unblocked_hook (struct frame *f)
  4758 {
  4759   block_input ();
  4760   flip_cr_context (f);
  4761   gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
  4762   unblock_input ();
  4763 }
  4764 
  4765 static struct terminal *
  4766 pgtk_create_terminal (struct pgtk_display_info *dpyinfo)
  4767 {
  4768   struct terminal *terminal;
  4769 
  4770   terminal = create_terminal (output_pgtk, &pgtk_redisplay_interface);
  4771 
  4772   terminal->display_info.pgtk = dpyinfo;
  4773   dpyinfo->terminal = terminal;
  4774 
  4775   terminal->clear_frame_hook = pgtk_clear_frame;
  4776   terminal->ring_bell_hook = pgtk_ring_bell;
  4777   terminal->toggle_invisible_pointer_hook = pgtk_toggle_invisible_pointer;
  4778   terminal->update_begin_hook = pgtk_update_begin;
  4779   terminal->update_end_hook = pgtk_update_end;
  4780   terminal->read_socket_hook = pgtk_read_socket;
  4781   terminal->frame_up_to_date_hook = pgtk_frame_up_to_date;
  4782   terminal->mouse_position_hook = pgtk_mouse_position;
  4783   terminal->frame_rehighlight_hook = pgtk_frame_rehighlight_hook;
  4784   terminal->buffer_flipping_unblocked_hook = pgtk_buffer_flipping_unblocked_hook;
  4785   terminal->frame_raise_lower_hook = pgtk_frame_raise_lower;
  4786   terminal->frame_visible_invisible_hook = pgtk_make_frame_visible_invisible;
  4787   terminal->fullscreen_hook = pgtk_fullscreen_hook;
  4788   terminal->menu_show_hook = pgtk_menu_show;
  4789   terminal->activate_menubar_hook = pgtk_activate_menubar;
  4790   terminal->popup_dialog_hook = pgtk_popup_dialog;
  4791   terminal->change_tab_bar_height_hook = pgtk_change_tab_bar_height;
  4792   terminal->set_vertical_scroll_bar_hook = pgtk_set_vertical_scroll_bar;
  4793   terminal->set_horizontal_scroll_bar_hook = pgtk_set_horizontal_scroll_bar;
  4794   terminal->condemn_scroll_bars_hook = pgtk_condemn_scroll_bars;
  4795   terminal->redeem_scroll_bar_hook = pgtk_redeem_scroll_bar;
  4796   terminal->judge_scroll_bars_hook = pgtk_judge_scroll_bars;
  4797   terminal->get_string_resource_hook = pgtk_get_string_resource;
  4798   terminal->delete_frame_hook = pgtk_destroy_window;
  4799   terminal->delete_terminal_hook = pgtk_delete_terminal;
  4800   terminal->query_frame_background_color = pgtk_query_frame_background_color;
  4801   terminal->defined_color_hook = pgtk_defined_color;
  4802   terminal->set_new_font_hook = pgtk_new_font;
  4803   terminal->set_bitmap_icon_hook = pgtk_bitmap_icon;
  4804   terminal->implicit_set_name_hook = pgtk_implicitly_set_name;
  4805   terminal->iconify_frame_hook = pgtk_iconify_frame;
  4806   terminal->set_scroll_bar_default_width_hook
  4807     = pgtk_set_scroll_bar_default_width;
  4808   terminal->set_scroll_bar_default_height_hook
  4809     = pgtk_set_scroll_bar_default_height;
  4810   terminal->set_window_size_hook = pgtk_set_window_size;
  4811   terminal->query_colors = pgtk_query_colors;
  4812   terminal->get_focus_frame = pgtk_get_focus_frame;
  4813   terminal->focus_frame_hook = pgtk_focus_frame;
  4814   terminal->set_frame_offset_hook = pgtk_set_offset;
  4815   terminal->free_pixmap = pgtk_free_pixmap;
  4816   terminal->toolkit_position_hook = pgtk_toolkit_position;
  4817 
  4818   /* Other hooks are NULL by default.  */
  4819 
  4820   return terminal;
  4821 }
  4822 
  4823 struct pgtk_window_is_of_frame_recursive_t
  4824 {
  4825   GdkWindow *window;
  4826   bool result;
  4827   GtkWidget *emacs_gtk_fixed;   /* stop on emacsgtkfixed other than this. */
  4828 };
  4829 
  4830 static void
  4831 pgtk_window_is_of_frame_recursive (GtkWidget *widget, gpointer data)
  4832 {
  4833   struct pgtk_window_is_of_frame_recursive_t *datap = data;
  4834 
  4835   if (datap->result)
  4836     return;
  4837 
  4838   if (EMACS_IS_FIXED (widget) && widget != datap->emacs_gtk_fixed)
  4839     return;
  4840 
  4841   if (gtk_widget_get_window (widget) == datap->window)
  4842     {
  4843       datap->result = true;
  4844       return;
  4845     }
  4846 
  4847   if (GTK_IS_CONTAINER (widget))
  4848     gtk_container_foreach (GTK_CONTAINER (widget),
  4849                            pgtk_window_is_of_frame_recursive, datap);
  4850 }
  4851 
  4852 static bool
  4853 pgtk_window_is_of_frame (struct frame *f, GdkWindow *window)
  4854 {
  4855   struct pgtk_window_is_of_frame_recursive_t data;
  4856   data.window = window;
  4857   data.result = false;
  4858   data.emacs_gtk_fixed = FRAME_GTK_WIDGET (f);
  4859   pgtk_window_is_of_frame_recursive (FRAME_WIDGET (f), &data);
  4860   return data.result;
  4861 }
  4862 
  4863 /* Like x_window_to_frame but also compares the window with the widget's
  4864    windows.  */
  4865 static struct frame *
  4866 pgtk_any_window_to_frame (GdkWindow *window)
  4867 {
  4868   Lisp_Object tail, frame;
  4869   struct frame *f, *found = NULL;
  4870 
  4871   if (window == NULL)
  4872     return NULL;
  4873 
  4874   FOR_EACH_FRAME (tail, frame)
  4875     {
  4876       if (found)
  4877         break;
  4878       f = XFRAME (frame);
  4879       if (FRAME_PGTK_P (f))
  4880         {
  4881           if (pgtk_window_is_of_frame (f, window))
  4882             found = f;
  4883         }
  4884     }
  4885 
  4886   return found;
  4887 }
  4888 
  4889 static gboolean
  4890 pgtk_handle_event (GtkWidget *widget, GdkEvent *event, gpointer *data)
  4891 {
  4892   struct frame *f;
  4893   union buffered_input_event inev;
  4894   GtkWidget *frame_widget;
  4895   gint x, y;
  4896 
  4897   if (event->type == GDK_TOUCHPAD_PINCH
  4898       && (event->touchpad_pinch.phase
  4899           != GDK_TOUCHPAD_GESTURE_PHASE_END))
  4900     {
  4901       f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  4902       frame_widget = FRAME_GTK_WIDGET (f);
  4903 
  4904       gtk_widget_translate_coordinates (widget, frame_widget,
  4905                                         lrint (event->touchpad_pinch.x),
  4906                                         lrint (event->touchpad_pinch.y),
  4907                                         &x, &y);
  4908       if (f)
  4909         {
  4910 
  4911           inev.ie.kind = PINCH_EVENT;
  4912           XSETFRAME (inev.ie.frame_or_window, f);
  4913           XSETINT (inev.ie.x, x);
  4914           XSETINT (inev.ie.y, y);
  4915           inev.ie.arg = list4 (make_float (event->touchpad_pinch.dx),
  4916                                make_float (event->touchpad_pinch.dy),
  4917                                make_float (event->touchpad_pinch.scale),
  4918                                make_float (event->touchpad_pinch.angle_delta));
  4919           inev.ie.modifiers = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f),
  4920                                                            event->touchpad_pinch.state);
  4921           inev.ie.device
  4922             = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  4923           evq_enqueue (&inev);
  4924         }
  4925 
  4926       return TRUE;
  4927     }
  4928   return FALSE;
  4929 }
  4930 
  4931 static void
  4932 pgtk_fill_rectangle (struct frame *f, unsigned long color, int x, int y,
  4933                      int width, int height, bool respect_alpha_background)
  4934 {
  4935   cairo_t *cr;
  4936   cr = pgtk_begin_cr_clip (f);
  4937   pgtk_set_cr_source_with_color (f, color, respect_alpha_background);
  4938   cairo_rectangle (cr, x, y, width, height);
  4939   cairo_fill (cr);
  4940   pgtk_end_cr_clip (f);
  4941 }
  4942 
  4943 void
  4944 pgtk_clear_under_internal_border (struct frame *f)
  4945 {
  4946   if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
  4947       && (!FRAME_GTK_OUTER_WIDGET (f)
  4948           || gtk_widget_get_realized (FRAME_GTK_OUTER_WIDGET (f))))
  4949     {
  4950       int border = FRAME_INTERNAL_BORDER_WIDTH (f);
  4951       int width = FRAME_PIXEL_WIDTH (f);
  4952       int height = FRAME_PIXEL_HEIGHT (f);
  4953       int margin = FRAME_TOP_MARGIN_HEIGHT (f);
  4954       int bottom_margin = FRAME_BOTTOM_MARGIN_HEIGHT (f);
  4955       int face_id = (FRAME_PARENT_FRAME (f)
  4956                      ? (!NILP (Vface_remapping_alist)
  4957                         ? lookup_basic_face (NULL, f,
  4958                                              CHILD_FRAME_BORDER_FACE_ID)
  4959                         : CHILD_FRAME_BORDER_FACE_ID)
  4960                      : (!NILP (Vface_remapping_alist)
  4961                         ? lookup_basic_face (NULL, f,
  4962                                              INTERNAL_BORDER_FACE_ID)
  4963                         : INTERNAL_BORDER_FACE_ID));
  4964       struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
  4965 
  4966       block_input ();
  4967 
  4968       if (face)
  4969         {
  4970           fill_background_by_face (f, face, 0, margin, width, border);
  4971           fill_background_by_face (f, face, 0, 0, border, height);
  4972           fill_background_by_face (f, face, width - border, 0, border,
  4973                                    height);
  4974           fill_background_by_face (f, face, 0, (height
  4975                                                 - bottom_margin
  4976                                                 - border),
  4977                                    width, border);
  4978         }
  4979       else
  4980         {
  4981           pgtk_clear_area (f, 0, 0, border, height);
  4982           pgtk_clear_area (f, 0, margin, width, border);
  4983           pgtk_clear_area (f, width - border, 0, border, height);
  4984           pgtk_clear_area (f, 0, height - bottom_margin - border,
  4985                            width, border);
  4986         }
  4987 
  4988       unblock_input ();
  4989     }
  4990 }
  4991 
  4992 static gboolean
  4993 pgtk_handle_draw (GtkWidget *widget, cairo_t *cr, gpointer *data)
  4994 {
  4995   struct frame *f;
  4996 
  4997   GdkWindow *win = gtk_widget_get_window (widget);
  4998 
  4999   if (win != NULL)
  5000     {
  5001       cairo_surface_t *src = NULL;
  5002       f = pgtk_any_window_to_frame (win);
  5003       if (f != NULL)
  5004         {
  5005           src = FRAME_X_OUTPUT (f)->cr_surface_visible_bell;
  5006           if (src == NULL && FRAME_CR_ACTIVE_CONTEXT (f) != NULL)
  5007             src = cairo_get_target (FRAME_CR_ACTIVE_CONTEXT (f));
  5008         }
  5009       if (src != NULL)
  5010         {
  5011           cairo_set_source_surface (cr, src, 0, 0);
  5012           cairo_paint (cr);
  5013         }
  5014     }
  5015   return FALSE;
  5016 }
  5017 
  5018 static void
  5019 size_allocate (GtkWidget *widget, GtkAllocation *alloc,
  5020                gpointer user_data)
  5021 {
  5022   struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  5023 
  5024   if (!f)
  5025     f = user_data;
  5026 
  5027   if (f)
  5028     {
  5029       xg_frame_resized (f, alloc->width, alloc->height);
  5030       pgtk_cr_update_surface_desired_size (f, alloc->width, alloc->height, false);
  5031     }
  5032 }
  5033 
  5034 static void
  5035 get_modifier_values (int *mod_ctrl, int *mod_meta, int *mod_alt,
  5036                      int *mod_hyper, int *mod_super)
  5037 {
  5038   Lisp_Object tem;
  5039 
  5040   *mod_ctrl = ctrl_modifier;
  5041   *mod_meta = meta_modifier;
  5042   *mod_alt = alt_modifier;
  5043   *mod_hyper = hyper_modifier;
  5044   *mod_super = super_modifier;
  5045 
  5046   tem = Fget (Vx_ctrl_keysym, Qmodifier_value);
  5047   if (INTEGERP (tem))
  5048     *mod_ctrl = XFIXNUM (tem) & INT_MAX;
  5049   tem = Fget (Vx_alt_keysym, Qmodifier_value);
  5050   if (INTEGERP (tem))
  5051     *mod_alt = XFIXNUM (tem) & INT_MAX;
  5052   tem = Fget (Vx_meta_keysym, Qmodifier_value);
  5053   if (INTEGERP (tem))
  5054     *mod_meta = XFIXNUM (tem) & INT_MAX;
  5055   tem = Fget (Vx_hyper_keysym, Qmodifier_value);
  5056   if (INTEGERP (tem))
  5057     *mod_hyper = XFIXNUM (tem) & INT_MAX;
  5058   tem = Fget (Vx_super_keysym, Qmodifier_value);
  5059   if (INTEGERP (tem))
  5060     *mod_super = XFIXNUM (tem) & INT_MAX;
  5061 }
  5062 
  5063 int
  5064 pgtk_gtk_to_emacs_modifiers (struct pgtk_display_info *dpyinfo, int state)
  5065 {
  5066   int mod_ctrl;
  5067   int mod_meta;
  5068   int mod_alt;
  5069   int mod_hyper;
  5070   int mod_super;
  5071   int mod;
  5072 
  5073   get_modifier_values (&mod_ctrl, &mod_meta, &mod_alt, &mod_hyper,
  5074                        &mod_super);
  5075 
  5076   mod = 0;
  5077   if (state & GDK_SHIFT_MASK)
  5078     mod |= shift_modifier;
  5079   if (state & GDK_CONTROL_MASK)
  5080     mod |= mod_ctrl;
  5081   if (state & GDK_META_MASK || state & GDK_MOD1_MASK)
  5082     mod |= mod_meta;
  5083   if (state & GDK_SUPER_MASK)
  5084     mod |= mod_super;
  5085   if (state & GDK_HYPER_MASK)
  5086     mod |= mod_hyper;
  5087 
  5088   return mod;
  5089 }
  5090 
  5091 int
  5092 pgtk_emacs_to_gtk_modifiers (struct pgtk_display_info *dpyinfo, int state)
  5093 {
  5094   int mod_ctrl;
  5095   int mod_meta;
  5096   int mod_alt;
  5097   int mod_hyper;
  5098   int mod_super;
  5099   int mask;
  5100 
  5101   get_modifier_values (&mod_ctrl, &mod_meta, &mod_alt, &mod_hyper,
  5102                        &mod_super);
  5103 
  5104   mask = 0;
  5105   if (state & mod_super)
  5106     mask |= GDK_SUPER_MASK;
  5107   if (state & mod_hyper)
  5108     mask |= GDK_HYPER_MASK;
  5109   if (state & shift_modifier)
  5110     mask |= GDK_SHIFT_MASK;
  5111   if (state & mod_ctrl)
  5112     mask |= GDK_CONTROL_MASK;
  5113   if (state & mod_meta)
  5114     mask |= GDK_MOD1_MASK;
  5115   return mask;
  5116 }
  5117 
  5118 #define IsCursorKey(keysym)       (0xff50 <= (keysym) && (keysym) < 0xff60)
  5119 #define IsMiscFunctionKey(keysym) (0xff60 <= (keysym) && (keysym) < 0xff6c)
  5120 #define IsKeypadKey(keysym)       (0xff80 <= (keysym) && (keysym) < 0xffbe)
  5121 #define IsFunctionKey(keysym)     (0xffbe <= (keysym) && (keysym) < 0xffe1)
  5122 #define IsModifierKey(keysym)                                                   \
  5123   ((((keysym) >= GDK_KEY_Shift_L) && ((keysym) <= GDK_KEY_Hyper_R))             \
  5124    || (((keysym) >= GDK_KEY_ISO_Lock) && ((keysym) <= GDK_KEY_ISO_Level5_Lock)) \
  5125    || ((keysym) == GDK_KEY_Mode_switch)                                         \
  5126    || ((keysym) == GDK_KEY_Num_Lock))
  5127 
  5128 
  5129 void
  5130 pgtk_enqueue_string (struct frame *f, gchar *str)
  5131 {
  5132   gunichar *ustr, *uptr;
  5133 
  5134   uptr = ustr = g_utf8_to_ucs4 (str, -1, NULL, NULL, NULL);
  5135   if (ustr == NULL)
  5136     return;
  5137   for (; *ustr != 0; ustr++)
  5138     {
  5139       union buffered_input_event inev;
  5140       Lisp_Object c = make_fixnum (*ustr);
  5141       EVENT_INIT (inev.ie);
  5142       inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
  5143                       ? ASCII_KEYSTROKE_EVENT
  5144                       : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
  5145       inev.ie.arg = Qnil;
  5146       inev.ie.code = XFIXNAT (c);
  5147       XSETFRAME (inev.ie.frame_or_window, f);
  5148       inev.ie.modifiers = 0;
  5149       inev.ie.timestamp = 0;
  5150       evq_enqueue (&inev);
  5151     }
  5152 
  5153   g_free (uptr);
  5154 }
  5155 
  5156 void
  5157 pgtk_enqueue_preedit (struct frame *f, Lisp_Object preedit)
  5158 {
  5159   union buffered_input_event inev;
  5160   EVENT_INIT (inev.ie);
  5161   inev.ie.kind = PREEDIT_TEXT_EVENT;
  5162   inev.ie.arg = preedit;
  5163   inev.ie.code = 0;
  5164   XSETFRAME (inev.ie.frame_or_window, f);
  5165   inev.ie.modifiers = 0;
  5166   inev.ie.timestamp = 0;
  5167   evq_enqueue (&inev);
  5168 }
  5169 
  5170 static gboolean
  5171 key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
  5172 {
  5173   union buffered_input_event inev;
  5174   ptrdiff_t nbytes;
  5175   Mouse_HLInfo *hlinfo;
  5176   struct frame *f;
  5177   struct pgtk_display_info *dpyinfo;
  5178 
  5179   f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  5180   EVENT_INIT (inev.ie);
  5181   hlinfo = MOUSE_HL_INFO (f);
  5182   nbytes = 0;
  5183 
  5184   /* If mouse-highlight is an integer, input clears out
  5185      mouse highlighting.  */
  5186   if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
  5187     {
  5188       clear_mouse_face (hlinfo);
  5189       hlinfo->mouse_face_hidden = true;
  5190     }
  5191 
  5192   if (f != 0)
  5193     {
  5194       guint keysym, orig_keysym;
  5195       /* al%imercury@uunet.uu.net says that making this 81
  5196          instead of 80 fixed a bug whereby meta chars made
  5197          his Emacs hang.
  5198 
  5199          It seems that some version of XmbLookupString has
  5200          a bug of not returning XBufferOverflow in
  5201          status_return even if the input is too long to
  5202          fit in 81 bytes.  So, we must prepare sufficient
  5203          bytes for copy_buffer.  513 bytes (256 chars for
  5204          two-byte character set) seems to be a fairly good
  5205          approximation.  -- 2000.8.10 handa@etl.go.jp  */
  5206       unsigned char copy_buffer[513];
  5207       unsigned char *copy_bufptr = copy_buffer;
  5208       int copy_bufsiz = sizeof (copy_buffer);
  5209       int modifiers;
  5210       Lisp_Object c;
  5211       guint state;
  5212 
  5213       dpyinfo = FRAME_DISPLAY_INFO (f);
  5214 
  5215       /* Set the last user time for pgtk_focus_frame to work
  5216          correctly.  */
  5217       dpyinfo->last_user_time = event->key.time;
  5218 
  5219       state = event->key.state;
  5220 
  5221       /* While super is pressed, the input method will always always
  5222          resend the key events ignoring super.  As a workaround, don't
  5223          filter key events with super or hyper pressed.  */
  5224       if (!(event->key.state & (GDK_SUPER_MASK | GDK_HYPER_MASK)))
  5225         {
  5226           if (pgtk_im_filter_keypress (f, &event->key))
  5227             return TRUE;
  5228         }
  5229 
  5230       state |= pgtk_emacs_to_gtk_modifiers (FRAME_DISPLAY_INFO (f),
  5231                                             extra_keyboard_modifiers);
  5232       modifiers = state;
  5233 
  5234       /* This will have to go some day...  */
  5235 
  5236       /* make_lispy_event turns chars into control chars.
  5237          Don't do it here because XLookupString is too eager.  */
  5238       state &= ~GDK_CONTROL_MASK;
  5239       state &= ~(GDK_META_MASK
  5240                  | GDK_SUPER_MASK | GDK_HYPER_MASK | GDK_MOD1_MASK);
  5241 
  5242       nbytes = event->key.length;
  5243       if (nbytes > copy_bufsiz)
  5244         nbytes = copy_bufsiz;
  5245       memcpy (copy_bufptr, event->key.string, nbytes);
  5246 
  5247       keysym = event->key.keyval;
  5248       orig_keysym = keysym;
  5249 
  5250       /* Common for all keysym input events.  */
  5251       XSETFRAME (inev.ie.frame_or_window, f);
  5252       inev.ie.modifiers
  5253         = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), modifiers);
  5254       inev.ie.timestamp = event->key.time;
  5255 
  5256       /* First deal with keysyms which have defined
  5257          translations to characters.  */
  5258       if (keysym >= 32 && keysym < 128)
  5259         /* Avoid explicitly decoding each ASCII character.  */
  5260         {
  5261           inev.ie.kind = ASCII_KEYSTROKE_EVENT;
  5262           inev.ie.code = keysym;
  5263 
  5264           inev.ie.device
  5265             = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  5266           goto done;
  5267         }
  5268 
  5269       /* Keysyms directly mapped to Unicode characters.  */
  5270       if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
  5271         {
  5272           if (keysym < 0x01000080)
  5273             inev.ie.kind = ASCII_KEYSTROKE_EVENT;
  5274           else
  5275             inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
  5276           inev.ie.code = keysym & 0xFFFFFF;
  5277 
  5278           inev.ie.device
  5279             = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  5280           goto done;
  5281         }
  5282 
  5283       /* Now non-ASCII.  */
  5284       if (HASH_TABLE_P (Vpgtk_keysym_table)
  5285           && (c = Fgethash (make_fixnum (keysym),
  5286                             Vpgtk_keysym_table, Qnil), FIXNATP (c)))
  5287         {
  5288           inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
  5289                           ? ASCII_KEYSTROKE_EVENT
  5290                           : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
  5291           inev.ie.code = XFIXNAT (c);
  5292 
  5293           inev.ie.device
  5294             = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  5295           goto done;
  5296         }
  5297 
  5298       /* Random non-modifier sorts of keysyms.  */
  5299       if (((keysym >= GDK_KEY_BackSpace && keysym <= GDK_KEY_Escape)
  5300            || keysym == GDK_KEY_Delete
  5301 #ifdef GDK_KEY_ISO_Left_Tab
  5302            || (keysym >= GDK_KEY_ISO_Left_Tab && keysym <= GDK_KEY_ISO_Enter)
  5303 #endif
  5304            || IsCursorKey (keysym)      /* 0xff50 <= x < 0xff60 */
  5305            || IsMiscFunctionKey (keysym)        /* 0xff60 <= x < VARIES */
  5306 #ifdef HPUX
  5307            /* This recognizes the "extended function
  5308               keys".  It seems there's no cleaner way.
  5309               Test IsModifierKey to avoid handling
  5310               mode_switch incorrectly.  */
  5311            || (GDK_KEY_Select <= keysym && keysym < GDK_KEY_KP_Space)
  5312 #endif
  5313 #ifdef GDK_KEY_dead_circumflex
  5314            || orig_keysym == GDK_KEY_dead_circumflex
  5315 #endif
  5316 #ifdef GDK_KEY_dead_grave
  5317            || orig_keysym == GDK_KEY_dead_grave
  5318 #endif
  5319 #ifdef GDK_KEY_dead_tilde
  5320            || orig_keysym == GDK_KEY_dead_tilde
  5321 #endif
  5322 #ifdef GDK_KEY_dead_diaeresis
  5323            || orig_keysym == GDK_KEY_dead_diaeresis
  5324 #endif
  5325 #ifdef GDK_KEY_dead_macron
  5326            || orig_keysym == GDK_KEY_dead_macron
  5327 #endif
  5328 #ifdef GDK_KEY_dead_degree
  5329            || orig_keysym == GDK_KEY_dead_degree
  5330 #endif
  5331 #ifdef GDK_KEY_dead_acute
  5332            || orig_keysym == GDK_KEY_dead_acute
  5333 #endif
  5334 #ifdef GDK_KEY_dead_cedilla
  5335            || orig_keysym == GDK_KEY_dead_cedilla
  5336 #endif
  5337 #ifdef GDK_KEY_dead_breve
  5338            || orig_keysym == GDK_KEY_dead_breve
  5339 #endif
  5340 #ifdef GDK_KEY_dead_ogonek
  5341            || orig_keysym == GDK_KEY_dead_ogonek
  5342 #endif
  5343 #ifdef GDK_KEY_dead_caron
  5344            || orig_keysym == GDK_KEY_dead_caron
  5345 #endif
  5346 #ifdef GDK_KEY_dead_doubleacute
  5347            || orig_keysym == GDK_KEY_dead_doubleacute
  5348 #endif
  5349 #ifdef GDK_KEY_dead_abovedot
  5350            || orig_keysym == GDK_KEY_dead_abovedot
  5351 #endif
  5352            || IsKeypadKey (keysym)      /* 0xff80 <= x < 0xffbe */
  5353            || IsFunctionKey (keysym)    /* 0xffbe <= x < 0xffe1 */
  5354            /* Any "vendor-specific" key is ok.  */
  5355            || (orig_keysym & (1 << 28))
  5356            || (keysym != GDK_KEY_VoidSymbol && nbytes == 0))
  5357           && !(event->key.is_modifier
  5358                || IsModifierKey (orig_keysym)
  5359                /* The symbols from GDK_KEY_ISO_Lock
  5360                   to GDK_KEY_ISO_Last_Group_Lock
  5361                   don't have real modifiers but
  5362                   should be treated similarly to
  5363                   Mode_switch by Emacs. */
  5364 #if defined GDK_KEY_ISO_Lock && defined GDK_KEY_ISO_Last_Group_Lock
  5365                || (GDK_KEY_ISO_Lock <= orig_keysym
  5366                    && orig_keysym <= GDK_KEY_ISO_Last_Group_Lock)
  5367 #endif
  5368           ))
  5369         {
  5370           /* make_lispy_event will convert this to a symbolic
  5371              key.  */
  5372           inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
  5373           inev.ie.code = keysym;
  5374 
  5375           inev.ie.device
  5376             = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  5377           goto done;
  5378         }
  5379 
  5380       {
  5381         inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
  5382         inev.ie.arg = make_unibyte_string ((char *) copy_bufptr, nbytes);
  5383         inev.ie.device
  5384           = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  5385 
  5386         if (keysym == GDK_KEY_VoidSymbol)
  5387           goto done;
  5388       }
  5389     }
  5390 
  5391 done:
  5392   if (inev.ie.kind != NO_EVENT)
  5393     {
  5394       XSETFRAME (inev.ie.frame_or_window, f);
  5395       evq_enqueue (&inev);
  5396     }
  5397 
  5398   return TRUE;
  5399 }
  5400 
  5401 static struct pgtk_display_info *
  5402 pgtk_display_info_for_display (GdkDisplay *dpy)
  5403 {
  5404   struct pgtk_display_info *dpyinfo;
  5405 
  5406   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
  5407     {
  5408       if (dpyinfo->display == dpy)
  5409         return dpyinfo;
  5410     }
  5411 
  5412   return NULL;
  5413 }
  5414 
  5415 static gboolean
  5416 key_release_event (GtkWidget *widget,
  5417                    GdkEvent *event,
  5418                    gpointer *user_data)
  5419 {
  5420   GdkDisplay *display;
  5421   struct pgtk_display_info *dpyinfo;
  5422 
  5423   display = gtk_widget_get_display (widget);
  5424   dpyinfo = pgtk_display_info_for_display (display);
  5425 
  5426   if (dpyinfo)
  5427     /* This is needed on Wayland because of some brain dead
  5428        compositors.  Without them, we would not have to keep track of
  5429        the serial of key release events.  */
  5430     dpyinfo->last_user_time = event->key.time;
  5431 
  5432   return TRUE;
  5433 }
  5434 
  5435 static gboolean
  5436 configure_event (GtkWidget *widget,
  5437                  GdkEvent *event,
  5438                  gpointer *user_data)
  5439 {
  5440   struct frame *f = pgtk_any_window_to_frame (event->configure.window);
  5441 
  5442   if (f && widget == FRAME_GTK_OUTER_WIDGET (f))
  5443     {
  5444       if (any_help_event_p)
  5445         {
  5446           Lisp_Object frame;
  5447           if (f)
  5448             XSETFRAME (frame, f);
  5449           else
  5450             frame = Qnil;
  5451           help_echo_string = Qnil;
  5452           gen_help_event (Qnil, frame, Qnil, Qnil, 0);
  5453         }
  5454 
  5455       if (f->win_gravity == NorthWestGravity)
  5456         gtk_window_get_position (GTK_WINDOW (widget),
  5457                                  &f->left_pos, &f->top_pos);
  5458       else
  5459         {
  5460           f->top_pos = event->configure.y;
  5461           f->left_pos = event->configure.x;
  5462         }
  5463     }
  5464   return FALSE;
  5465 }
  5466 
  5467 static gboolean
  5468 map_event (GtkWidget *widget,
  5469            GdkEvent *event,
  5470            gpointer *user_data)
  5471 {
  5472   struct frame *f = pgtk_any_window_to_frame (event->any.window);
  5473   union buffered_input_event inev;
  5474 
  5475   EVENT_INIT (inev.ie);
  5476   inev.ie.kind = NO_EVENT;
  5477   inev.ie.arg = Qnil;
  5478 
  5479   if (f)
  5480     {
  5481       bool iconified = FRAME_ICONIFIED_P (f);
  5482 
  5483       /* Check if fullscreen was specified before we where mapped the
  5484          first time, i.e. from the command line.  */
  5485       if (!FRAME_X_OUTPUT (f)->has_been_visible)
  5486         set_fullscreen_state (f);
  5487 
  5488       if (!iconified)
  5489         {
  5490           /* The `z-group' is reset every time a frame becomes
  5491              invisible.  Handle this here.  */
  5492           if (FRAME_Z_GROUP (f) == z_group_above)
  5493             pgtk_set_z_group (f, Qabove, Qnil);
  5494           else if (FRAME_Z_GROUP (f) == z_group_below)
  5495             pgtk_set_z_group (f, Qbelow, Qnil);
  5496         }
  5497 
  5498       SET_FRAME_VISIBLE (f, 1);
  5499       SET_FRAME_ICONIFIED (f, false);
  5500       FRAME_X_OUTPUT (f)->has_been_visible = true;
  5501 
  5502       if (iconified)
  5503         {
  5504           inev.ie.kind = DEICONIFY_EVENT;
  5505           XSETFRAME (inev.ie.frame_or_window, f);
  5506         }
  5507     }
  5508 
  5509   if (inev.ie.kind != NO_EVENT)
  5510     evq_enqueue (&inev);
  5511   return FALSE;
  5512 }
  5513 
  5514 static gboolean
  5515 window_state_event (GtkWidget *widget,
  5516                     GdkEvent *event,
  5517                     gpointer *user_data)
  5518 {
  5519   struct frame *f = pgtk_any_window_to_frame (event->window_state.window);
  5520   GdkWindowState new_state;
  5521   union buffered_input_event inev;
  5522 
  5523   new_state = event->window_state.new_window_state;
  5524 
  5525   EVENT_INIT (inev.ie);
  5526   inev.ie.kind = NO_EVENT;
  5527   inev.ie.arg = Qnil;
  5528 
  5529   if (new_state & GDK_WINDOW_STATE_FULLSCREEN)
  5530     store_frame_param (f, Qfullscreen, Qfullboth);
  5531   else if (new_state & GDK_WINDOW_STATE_MAXIMIZED)
  5532     store_frame_param (f, Qfullscreen, Qmaximized);
  5533   else if ((new_state & GDK_WINDOW_STATE_TOP_TILED)
  5534            && (new_state & GDK_WINDOW_STATE_BOTTOM_TILED)
  5535            && !(new_state & GDK_WINDOW_STATE_TOP_RESIZABLE)
  5536            && !(new_state & GDK_WINDOW_STATE_BOTTOM_RESIZABLE))
  5537     store_frame_param (f, Qfullscreen, Qfullheight);
  5538   else if ((new_state & GDK_WINDOW_STATE_LEFT_TILED)
  5539            && (new_state & GDK_WINDOW_STATE_RIGHT_TILED)
  5540            && !(new_state & GDK_WINDOW_STATE_LEFT_RESIZABLE)
  5541            && !(new_state & GDK_WINDOW_STATE_RIGHT_RESIZABLE))
  5542     store_frame_param (f, Qfullscreen, Qfullwidth);
  5543   else
  5544     store_frame_param (f, Qfullscreen, Qnil);
  5545 
  5546   /* The Wayland protocol provides no way for the client to know
  5547      whether or not one of its toplevels has actually been
  5548      deiconified.  It only provides a request for clients to iconify a
  5549      toplevel, without even the ability to determine whether or not
  5550      the iconification request was rejected by the display server.
  5551 
  5552      GDK computes the iconified state by sending a window state event
  5553      containing only GDK_WINDOW_STATE_ICONIFIED immediately after
  5554      gtk_window_iconify is called.  That is error-prone if the request
  5555      to iconify the frame was rejected by the display server, but is
  5556      not the main problem here, as Wayland compositors only rarely
  5557      reject such requests.  GDK also assumes that it can clear the
  5558      iconified state upon receiving the next toplevel configure event
  5559      from the display server.  Unfortunately, such events can be sent
  5560      by Wayland compositors while the frame is iconified, and may also
  5561      not be sent upon deiconification.  So, no matter what Emacs does,
  5562      the iconification state of a frame is likely to be wrong under
  5563      one situation or another.  */
  5564 
  5565   if (new_state & GDK_WINDOW_STATE_ICONIFIED)
  5566     {
  5567       SET_FRAME_ICONIFIED (f, true);
  5568       SET_FRAME_VISIBLE (f, false);
  5569     }
  5570   else
  5571     {
  5572       FRAME_X_OUTPUT (f)->has_been_visible = true;
  5573       inev.ie.kind = DEICONIFY_EVENT;
  5574       XSETFRAME (inev.ie.frame_or_window, f);
  5575       SET_FRAME_ICONIFIED (f, false);
  5576       SET_FRAME_VISIBLE (f, true);
  5577     }
  5578 
  5579   if (new_state & GDK_WINDOW_STATE_STICKY)
  5580     store_frame_param (f, Qsticky, Qt);
  5581   else
  5582     store_frame_param (f, Qsticky, Qnil);
  5583 
  5584   if (inev.ie.kind != NO_EVENT)
  5585     evq_enqueue (&inev);
  5586   return FALSE;
  5587 }
  5588 
  5589 static gboolean
  5590 delete_event (GtkWidget *widget,
  5591               GdkEvent *event, gpointer *user_data)
  5592 {
  5593   struct frame *f = pgtk_any_window_to_frame (event->any.window);
  5594   union buffered_input_event inev;
  5595 
  5596   EVENT_INIT (inev.ie);
  5597   inev.ie.kind = NO_EVENT;
  5598   inev.ie.arg = Qnil;
  5599 
  5600   if (f)
  5601     {
  5602       inev.ie.kind = DELETE_WINDOW_EVENT;
  5603       XSETFRAME (inev.ie.frame_or_window, f);
  5604     }
  5605 
  5606   if (inev.ie.kind != NO_EVENT)
  5607     evq_enqueue (&inev);
  5608   return TRUE;
  5609 }
  5610 
  5611 /* The focus may have changed.  Figure out if it is a real focus change,
  5612    by checking both FocusIn/Out and Enter/LeaveNotify events.
  5613 
  5614    Returns FOCUS_IN_EVENT event in *BUFP. */
  5615 
  5616 /* Handle FocusIn and FocusOut state changes for FRAME.
  5617    If FRAME has focus and there exists more than one frame, puts
  5618    a FOCUS_IN_EVENT into *BUFP.  */
  5619 
  5620 static void
  5621 pgtk_focus_changed (gboolean is_enter, int state,
  5622                     struct pgtk_display_info *dpyinfo, struct frame *frame,
  5623                     union buffered_input_event *bufp)
  5624 {
  5625   if (is_enter)
  5626     {
  5627       if (dpyinfo->x_focus_event_frame != frame)
  5628         {
  5629           pgtk_new_focus_frame (dpyinfo, frame);
  5630           dpyinfo->x_focus_event_frame = frame;
  5631 
  5632           /* Don't stop displaying the initial startup message
  5633              for a switch-frame event we don't need.  */
  5634           /* When run as a daemon, Vterminal_frame is always NIL.  */
  5635           bufp->ie.arg = (((NILP (Vterminal_frame)
  5636                             || !FRAME_PGTK_P (XFRAME (Vterminal_frame))
  5637                             || EQ (Fdaemonp (), Qt))
  5638                            && CONSP (Vframe_list)
  5639                            && !NILP (XCDR (Vframe_list))) ? Qt : Qnil);
  5640           bufp->ie.kind = FOCUS_IN_EVENT;
  5641           XSETFRAME (bufp->ie.frame_or_window, frame);
  5642         }
  5643 
  5644       frame->output_data.pgtk->focus_state |= state;
  5645 
  5646     }
  5647   else
  5648     {
  5649       frame->output_data.pgtk->focus_state &= ~state;
  5650 
  5651       if (dpyinfo->x_focus_event_frame == frame)
  5652         {
  5653           dpyinfo->x_focus_event_frame = 0;
  5654           pgtk_new_focus_frame (dpyinfo, NULL);
  5655 
  5656           bufp->ie.kind = FOCUS_OUT_EVENT;
  5657           XSETFRAME (bufp->ie.frame_or_window, frame);
  5658         }
  5659 
  5660       if (frame->pointer_invisible)
  5661         pgtk_toggle_invisible_pointer (frame, false);
  5662     }
  5663 }
  5664 
  5665 static gboolean
  5666 enter_notify_event (GtkWidget *widget, GdkEvent *event,
  5667                     gpointer *user_data)
  5668 {
  5669   union buffered_input_event inev;
  5670   struct frame *frame
  5671     = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  5672 
  5673   if (frame == NULL)
  5674     return FALSE;
  5675 
  5676   struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
  5677   struct frame *focus_frame = dpyinfo->x_focus_frame;
  5678   int focus_state
  5679     = focus_frame ? focus_frame->output_data.pgtk->focus_state : 0;
  5680 
  5681   EVENT_INIT (inev.ie);
  5682   inev.ie.kind = NO_EVENT;
  5683   inev.ie.arg = Qnil;
  5684 
  5685   if (event->crossing.detail != GDK_NOTIFY_INFERIOR
  5686       && event->crossing.focus && !(focus_state & FOCUS_EXPLICIT))
  5687     pgtk_focus_changed (TRUE, FOCUS_IMPLICIT, dpyinfo, frame, &inev);
  5688   if (inev.ie.kind != NO_EVENT)
  5689     evq_enqueue (&inev);
  5690   return TRUE;
  5691 }
  5692 
  5693 static gboolean
  5694 leave_notify_event (GtkWidget *widget, GdkEvent *event,
  5695                     gpointer *user_data)
  5696 {
  5697   union buffered_input_event inev;
  5698   struct frame *frame
  5699     = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  5700 
  5701   if (frame == NULL)
  5702     return FALSE;
  5703 
  5704   struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
  5705   struct frame *focus_frame = dpyinfo->x_focus_frame;
  5706   int focus_state
  5707     = focus_frame ? focus_frame->output_data.pgtk->focus_state : 0;
  5708   Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (frame);
  5709 
  5710   if (frame == hlinfo->mouse_face_mouse_frame)
  5711     {
  5712       /* If we move outside the frame, then we're
  5713          certainly no longer on any text in the frame.  */
  5714       clear_mouse_face (hlinfo);
  5715       hlinfo->mouse_face_mouse_frame = 0;
  5716     }
  5717 
  5718   EVENT_INIT (inev.ie);
  5719   inev.ie.kind = NO_EVENT;
  5720   inev.ie.arg = Qnil;
  5721 
  5722   if (event->crossing.detail != GDK_NOTIFY_INFERIOR
  5723       && event->crossing.focus && !(focus_state & FOCUS_EXPLICIT))
  5724     pgtk_focus_changed (FALSE, FOCUS_IMPLICIT, dpyinfo, frame, &inev);
  5725 
  5726   if (frame)
  5727     {
  5728       if (any_help_event_p)
  5729         {
  5730           Lisp_Object frame_obj;
  5731           XSETFRAME (frame_obj, frame);
  5732           help_echo_string = Qnil;
  5733           gen_help_event (Qnil, frame_obj, Qnil, Qnil, 0);
  5734         }
  5735     }
  5736 
  5737   if (inev.ie.kind != NO_EVENT)
  5738     evq_enqueue (&inev);
  5739   return TRUE;
  5740 }
  5741 
  5742 static gboolean
  5743 focus_in_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
  5744 {
  5745   union buffered_input_event inev;
  5746   struct frame *frame
  5747     = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  5748 
  5749   if (frame == NULL)
  5750     return TRUE;
  5751 
  5752   EVENT_INIT (inev.ie);
  5753   inev.ie.kind = NO_EVENT;
  5754   inev.ie.arg = Qnil;
  5755 
  5756   pgtk_focus_changed (TRUE, FOCUS_EXPLICIT,
  5757                       FRAME_DISPLAY_INFO (frame), frame, &inev);
  5758   if (inev.ie.kind != NO_EVENT)
  5759     evq_enqueue (&inev);
  5760 
  5761   pgtk_im_focus_in (frame);
  5762 
  5763   return TRUE;
  5764 }
  5765 
  5766 static gboolean
  5767 focus_out_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
  5768 {
  5769   union buffered_input_event inev;
  5770   struct frame *frame
  5771     = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  5772 
  5773   if (frame == NULL)
  5774     return TRUE;
  5775 
  5776   EVENT_INIT (inev.ie);
  5777   inev.ie.kind = NO_EVENT;
  5778   inev.ie.arg = Qnil;
  5779 
  5780   pgtk_focus_changed (FALSE, FOCUS_EXPLICIT,
  5781                       FRAME_DISPLAY_INFO (frame), frame, &inev);
  5782   if (inev.ie.kind != NO_EVENT)
  5783     evq_enqueue (&inev);
  5784 
  5785   pgtk_im_focus_out (frame);
  5786 
  5787   return TRUE;
  5788 }
  5789 
  5790 /* Function to report a mouse movement to the mainstream Emacs code.
  5791    The input handler calls this.
  5792 
  5793    We have received a mouse movement event, which is given in *event.
  5794    If the mouse is over a different glyph than it was last time, tell
  5795    the mainstream emacs code by setting mouse_moved.  If not, ask for
  5796    another motion event, so we can check again the next time it moves.  */
  5797 
  5798 static bool
  5799 note_mouse_movement (struct frame *frame,
  5800                      const GdkEventMotion *event)
  5801 {
  5802   XRectangle *r;
  5803   struct pgtk_display_info *dpyinfo;
  5804 
  5805   if (!FRAME_X_OUTPUT (frame))
  5806     return false;
  5807 
  5808   dpyinfo = FRAME_DISPLAY_INFO (frame);
  5809   dpyinfo->last_mouse_movement_time = event->time;
  5810   dpyinfo->last_mouse_motion_frame = frame;
  5811   dpyinfo->last_mouse_motion_x = event->x;
  5812   dpyinfo->last_mouse_motion_y = event->y;
  5813 
  5814   if (event->window != gtk_widget_get_window (FRAME_GTK_WIDGET (frame)))
  5815     {
  5816       frame->mouse_moved = true;
  5817       dpyinfo->last_mouse_scroll_bar = NULL;
  5818       note_mouse_highlight (frame, -1, -1);
  5819       dpyinfo->last_mouse_glyph_frame = NULL;
  5820       frame->last_mouse_device
  5821         = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (frame),
  5822                                      (GdkEvent *) event);
  5823       return true;
  5824     }
  5825 
  5826 
  5827   /* Has the mouse moved off the glyph it was on at the last sighting?  */
  5828   r = &dpyinfo->last_mouse_glyph;
  5829   if (frame != dpyinfo->last_mouse_glyph_frame
  5830       || event->x < r->x || event->x >= r->x + r->width
  5831       || event->y < r->y || event->y >= r->y + r->height)
  5832     {
  5833       frame->mouse_moved = true;
  5834       dpyinfo->last_mouse_scroll_bar = NULL;
  5835       note_mouse_highlight (frame, event->x, event->y);
  5836       /* Remember which glyph we're now on.  */
  5837       remember_mouse_glyph (frame, event->x, event->y, r);
  5838       dpyinfo->last_mouse_glyph_frame = frame;
  5839       frame->last_mouse_device
  5840         = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (frame),
  5841                                      (GdkEvent *) event);
  5842       return true;
  5843     }
  5844 
  5845   return false;
  5846 }
  5847 
  5848 static gboolean
  5849 motion_notify_event (GtkWidget *widget, GdkEvent *event,
  5850                      gpointer *user_data)
  5851 {
  5852   union buffered_input_event inev;
  5853   struct frame *f, *frame;
  5854   struct pgtk_display_info *dpyinfo;
  5855   Mouse_HLInfo *hlinfo;
  5856 
  5857   EVENT_INIT (inev.ie);
  5858   inev.ie.kind = NO_EVENT;
  5859   inev.ie.arg = Qnil;
  5860 
  5861   previous_help_echo_string = help_echo_string;
  5862   help_echo_string = Qnil;
  5863 
  5864   frame = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  5865   dpyinfo = FRAME_DISPLAY_INFO (frame);
  5866   f = (gui_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
  5867        : pgtk_any_window_to_frame (gtk_widget_get_window (widget)));
  5868   hlinfo = MOUSE_HL_INFO (f);
  5869 
  5870   if (hlinfo->mouse_face_hidden)
  5871     {
  5872       hlinfo->mouse_face_hidden = false;
  5873       clear_mouse_face (hlinfo);
  5874     }
  5875 
  5876   if (f && xg_event_is_for_scrollbar (f, event, false))
  5877     f = 0;
  5878 
  5879   if (f)
  5880     {
  5881       /* Maybe generate a SELECT_WINDOW_EVENT for
  5882          `mouse-autoselect-window' but don't let popup menus
  5883          interfere with this (Bug#1261).  */
  5884       if (!NILP (Vmouse_autoselect_window)
  5885           /* Don't switch if we're currently in the minibuffer.
  5886              This tries to work around problems where the
  5887              minibuffer gets unselected unexpectedly, and where
  5888              you then have to move your mouse all the way down to
  5889              the minibuffer to select it.  */
  5890           && !MINI_WINDOW_P (XWINDOW (selected_window))
  5891           /* With `focus-follows-mouse' non-nil create an event
  5892              also when the target window is on another frame.  */
  5893           && (f == XFRAME (selected_frame) || !NILP (focus_follows_mouse)))
  5894         {
  5895           static Lisp_Object last_mouse_window;
  5896           Lisp_Object window = window_from_coordinates
  5897             (f, event->motion.x, event->motion.y, 0, false, false);
  5898 
  5899           /* A window will be autoselected only when it is not
  5900              selected now and the last mouse movement event was
  5901              not in it.  The remainder of the code is a bit vague
  5902              wrt what a "window" is.  For immediate autoselection,
  5903              the window is usually the entire window but for GTK
  5904              where the scroll bars don't count.  For delayed
  5905              autoselection the window is usually the window's text
  5906              area including the margins.  */
  5907           if (WINDOWP (window)
  5908               && !EQ (window, last_mouse_window)
  5909               && !EQ (window, selected_window))
  5910             {
  5911               inev.ie.kind = SELECT_WINDOW_EVENT;
  5912               inev.ie.frame_or_window = window;
  5913             }
  5914 
  5915           /* Remember the last window where we saw the mouse.  */
  5916           last_mouse_window = window;
  5917         }
  5918 
  5919       if (!note_mouse_movement (f, &event->motion))
  5920         help_echo_string = previous_help_echo_string;
  5921     }
  5922   else
  5923     /* If we move outside the frame, then we're
  5924        certainly no longer on any text in the frame.  */
  5925     clear_mouse_face (hlinfo);
  5926 
  5927   /* If the contents of the global variable help_echo_string
  5928      has changed, generate a HELP_EVENT.  */
  5929   int do_help = 0;
  5930   if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
  5931     do_help = 1;
  5932 
  5933   if (inev.ie.kind != NO_EVENT)
  5934     evq_enqueue (&inev);
  5935 
  5936   if (do_help > 0)
  5937     {
  5938       Lisp_Object frame;
  5939 
  5940       if (f)
  5941         XSETFRAME (frame, f);
  5942       else
  5943         frame = Qnil;
  5944 
  5945       any_help_event_p = true;
  5946       gen_help_event (help_echo_string, frame, help_echo_window,
  5947                       help_echo_object, help_echo_pos);
  5948     }
  5949 
  5950   return TRUE;
  5951 }
  5952 
  5953 /* Prepare a mouse-event in *RESULT for placement in the input queue.
  5954 
  5955    If the event is a button press, then note that we have grabbed
  5956    the mouse.  */
  5957 
  5958 static Lisp_Object
  5959 construct_mouse_click (struct input_event *result,
  5960                        const GdkEventButton *event,
  5961                        struct frame *f)
  5962 {
  5963   /* Make the event type NO_EVENT; we'll change that when we decide
  5964      otherwise.  */
  5965   result->kind = MOUSE_CLICK_EVENT;
  5966   result->code = event->button - 1;
  5967   result->timestamp = event->time;
  5968   result->modifiers = (pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f),
  5969                                                     event->state)
  5970                        | (event->type == GDK_BUTTON_RELEASE
  5971                           ? up_modifier : down_modifier));
  5972 
  5973   XSETINT (result->x, event->x);
  5974   XSETINT (result->y, event->y);
  5975   XSETFRAME (result->frame_or_window, f);
  5976   result->arg = Qnil;
  5977   result->device = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f),
  5978                                               (GdkEvent *) event);
  5979   return Qnil;
  5980 }
  5981 
  5982 static gboolean
  5983 button_event (GtkWidget *widget, GdkEvent *event,
  5984               gpointer *user_data)
  5985 {
  5986   union buffered_input_event inev;
  5987   struct frame *f, *frame;
  5988   struct pgtk_display_info *dpyinfo;
  5989 
  5990   /* If we decide we want to generate an event to be seen
  5991      by the rest of Emacs, we put it here.  */
  5992   bool tab_bar_p = false;
  5993   bool tool_bar_p = false;
  5994   Lisp_Object tab_bar_arg = Qnil;
  5995 
  5996   EVENT_INIT (inev.ie);
  5997   inev.ie.kind = NO_EVENT;
  5998   inev.ie.arg = Qnil;
  5999 
  6000   /* ignore double click and triple click. */
  6001   if (event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE)
  6002     return TRUE;
  6003 
  6004   frame = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  6005   dpyinfo = FRAME_DISPLAY_INFO (frame);
  6006 
  6007   dpyinfo->last_mouse_glyph_frame = NULL;
  6008 
  6009   if (gui_mouse_grabbed (dpyinfo))
  6010     f = dpyinfo->last_mouse_frame;
  6011   else
  6012     {
  6013       f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  6014 
  6015       if (f && event->button.type == GDK_BUTTON_PRESS
  6016           && !FRAME_NO_ACCEPT_FOCUS (f))
  6017         {
  6018           /* When clicking into a child frame or when clicking
  6019              into a parent frame with the child frame selected and
  6020              `no-accept-focus' is not set, select the clicked
  6021              frame.  */
  6022           struct frame *hf = dpyinfo->highlight_frame;
  6023 
  6024           if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
  6025             {
  6026               block_input ();
  6027               gtk_widget_grab_focus (FRAME_GTK_WIDGET (f));
  6028 
  6029               if (FRAME_GTK_OUTER_WIDGET (f))
  6030                 gtk_window_present (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
  6031               unblock_input ();
  6032             }
  6033         }
  6034     }
  6035 
  6036   /* Set the last user time, used to activate the frame in
  6037      pgtk_focus_frame.  */
  6038   dpyinfo->last_user_time = event->button.time;
  6039 
  6040   if (f)
  6041     {
  6042       /* Is this in the tab-bar?  */
  6043       if (WINDOWP (f->tab_bar_window)
  6044           && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)))
  6045         {
  6046           Lisp_Object window;
  6047           int x = event->button.x;
  6048           int y = event->button.y;
  6049 
  6050           window = window_from_coordinates (f, x, y, 0, true, true);
  6051           tab_bar_p = EQ (window, f->tab_bar_window);
  6052 
  6053           if (tab_bar_p)
  6054             tab_bar_arg = handle_tab_bar_click
  6055               (f, x, y, event->type == GDK_BUTTON_PRESS,
  6056                pgtk_gtk_to_emacs_modifiers (dpyinfo, event->button.state));
  6057         }
  6058 
  6059       if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p)
  6060         {
  6061           if (ignore_next_mouse_click_timeout)
  6062             {
  6063               if (event->type == GDK_BUTTON_PRESS
  6064                   && event->button.time > ignore_next_mouse_click_timeout)
  6065                 {
  6066                   ignore_next_mouse_click_timeout = 0;
  6067                   construct_mouse_click (&inev.ie, &event->button, f);
  6068                 }
  6069               if (event->type == GDK_BUTTON_RELEASE)
  6070                 ignore_next_mouse_click_timeout = 0;
  6071             }
  6072           else
  6073             construct_mouse_click (&inev.ie, &event->button, f);
  6074 
  6075           if (!NILP (tab_bar_arg))
  6076             inev.ie.arg = tab_bar_arg;
  6077         }
  6078     }
  6079 
  6080   if (event->type == GDK_BUTTON_PRESS)
  6081     {
  6082       dpyinfo->grabbed |= (1 << event->button.button);
  6083       dpyinfo->last_mouse_frame = f;
  6084 
  6085       if (dpyinfo->last_click_event != NULL)
  6086         gdk_event_free (dpyinfo->last_click_event);
  6087       dpyinfo->last_click_event = gdk_event_copy (event);
  6088     }
  6089   else
  6090     dpyinfo->grabbed &= ~(1 << event->button.button);
  6091 
  6092   /* Ignore any mouse motion that happened before this event;
  6093      any subsequent mouse-movement Emacs events should reflect
  6094      only motion after the ButtonPress/Release.  */
  6095   if (f != 0)
  6096     f->mouse_moved = false;
  6097 
  6098   if (inev.ie.kind != NO_EVENT)
  6099     evq_enqueue (&inev);
  6100   return TRUE;
  6101 }
  6102 
  6103 static gboolean
  6104 scroll_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
  6105 {
  6106   union buffered_input_event inev;
  6107   struct frame *f, *frame;
  6108   struct pgtk_display_info *dpyinfo;
  6109   GdkScrollDirection dir;
  6110   double delta_x, delta_y;
  6111 
  6112   EVENT_INIT (inev.ie);
  6113   inev.ie.kind = NO_EVENT;
  6114   inev.ie.arg = Qnil;
  6115 
  6116   frame = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  6117   dpyinfo = FRAME_DISPLAY_INFO (frame);
  6118 
  6119   if (gui_mouse_grabbed (dpyinfo))
  6120     f = dpyinfo->last_mouse_frame;
  6121   else
  6122     f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  6123 
  6124   inev.ie.kind = NO_EVENT;
  6125   inev.ie.timestamp = event->scroll.time;
  6126   inev.ie.modifiers
  6127     = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), event->scroll.state);
  6128   XSETINT (inev.ie.x, event->scroll.x);
  6129   XSETINT (inev.ie.y, event->scroll.y);
  6130   XSETFRAME (inev.ie.frame_or_window, f);
  6131   inev.ie.arg = Qnil;
  6132 
  6133   if (gdk_event_is_scroll_stop_event (event))
  6134     {
  6135       inev.ie.kind = TOUCH_END_EVENT;
  6136       inev.ie.device
  6137         = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  6138       evq_enqueue (&inev);
  6139       return TRUE;
  6140     }
  6141 
  6142   if (gdk_event_get_scroll_direction (event, &dir))
  6143     {
  6144       switch (dir)
  6145         {
  6146         case GDK_SCROLL_UP:
  6147           inev.ie.kind = WHEEL_EVENT;
  6148           inev.ie.modifiers |= up_modifier;
  6149           break;
  6150         case GDK_SCROLL_DOWN:
  6151           inev.ie.kind = WHEEL_EVENT;
  6152           inev.ie.modifiers |= down_modifier;
  6153           break;
  6154         case GDK_SCROLL_LEFT:
  6155           inev.ie.kind = HORIZ_WHEEL_EVENT;
  6156           inev.ie.modifiers |= up_modifier;
  6157           break;
  6158         case GDK_SCROLL_RIGHT:
  6159           inev.ie.kind = HORIZ_WHEEL_EVENT;
  6160           inev.ie.modifiers |= down_modifier;
  6161           break;
  6162         case GDK_SCROLL_SMOOTH:         /* shut up warning */
  6163           break;
  6164         }
  6165     }
  6166   else if (gdk_event_get_scroll_deltas (event, &delta_x, &delta_y))
  6167     {
  6168       if (!mwheel_coalesce_scroll_events)
  6169         {
  6170           inev.ie.kind = ((fabs (delta_x) > fabs (delta_y))
  6171                           ? HORIZ_WHEEL_EVENT
  6172                           : WHEEL_EVENT);
  6173           inev.ie.modifiers |= (inev.ie.kind == HORIZ_WHEEL_EVENT
  6174                                 ? (delta_x >= 0 ? up_modifier : down_modifier)
  6175                                 : (delta_y >= 0 ? down_modifier : up_modifier));
  6176           inev.ie.arg = list3 (Qnil, make_float (-delta_x * 100),
  6177                                make_float (-delta_y * 100));
  6178         }
  6179       else
  6180         {
  6181           dpyinfo->scroll.acc_x += delta_x;
  6182           dpyinfo->scroll.acc_y += delta_y;
  6183           if (dpyinfo->scroll.acc_y >= dpyinfo->scroll.y_per_line)
  6184             {
  6185               int nlines = dpyinfo->scroll.acc_y / dpyinfo->scroll.y_per_line;
  6186               inev.ie.kind = WHEEL_EVENT;
  6187               inev.ie.modifiers |= down_modifier;
  6188               inev.ie.arg = list3 (make_fixnum (nlines),
  6189                                    make_float (-dpyinfo->scroll.acc_x * 100),
  6190                                    make_float (-dpyinfo->scroll.acc_y * 100));
  6191               dpyinfo->scroll.acc_y -= dpyinfo->scroll.y_per_line * nlines;
  6192             }
  6193           else if (dpyinfo->scroll.acc_y <= -dpyinfo->scroll.y_per_line)
  6194             {
  6195               int nlines = -dpyinfo->scroll.acc_y / dpyinfo->scroll.y_per_line;
  6196               inev.ie.kind = WHEEL_EVENT;
  6197               inev.ie.modifiers |= up_modifier;
  6198               inev.ie.arg = list3 (make_fixnum (nlines),
  6199                                    make_float (-dpyinfo->scroll.acc_x * 100),
  6200                                    make_float (-dpyinfo->scroll.acc_y * 100));
  6201 
  6202               dpyinfo->scroll.acc_y -= -dpyinfo->scroll.y_per_line * nlines;
  6203             }
  6204           else if (dpyinfo->scroll.acc_x >= dpyinfo->scroll.x_per_char
  6205                    || !mwheel_coalesce_scroll_events)
  6206             {
  6207               int nchars = dpyinfo->scroll.acc_x / dpyinfo->scroll.x_per_char;
  6208               inev.ie.kind = HORIZ_WHEEL_EVENT;
  6209               inev.ie.modifiers |= up_modifier;
  6210               inev.ie.arg = list3 (make_fixnum (nchars),
  6211                                    make_float (-dpyinfo->scroll.acc_x * 100),
  6212                                    make_float (-dpyinfo->scroll.acc_y * 100));
  6213 
  6214               dpyinfo->scroll.acc_x -= dpyinfo->scroll.x_per_char * nchars;
  6215             }
  6216           else if (dpyinfo->scroll.acc_x <= -dpyinfo->scroll.x_per_char)
  6217             {
  6218               int nchars = -dpyinfo->scroll.acc_x / dpyinfo->scroll.x_per_char;
  6219               inev.ie.kind = HORIZ_WHEEL_EVENT;
  6220               inev.ie.modifiers |= down_modifier;
  6221               inev.ie.arg = list3 (make_fixnum (nchars),
  6222                                    make_float (-dpyinfo->scroll.acc_x * 100),
  6223                                    make_float (-dpyinfo->scroll.acc_y * 100));
  6224 
  6225               dpyinfo->scroll.acc_x -= -dpyinfo->scroll.x_per_char * nchars;
  6226             }
  6227         }
  6228     }
  6229 
  6230   if (inev.ie.kind != NO_EVENT)
  6231     {
  6232       inev.ie.device
  6233         = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  6234       evq_enqueue (&inev);
  6235     }
  6236   return TRUE;
  6237 }
  6238 
  6239 
  6240 
  6241 /* C part of drop handling code.
  6242    The Lisp part is in pgtk-dnd.el.  */
  6243 
  6244 static GdkDragAction
  6245 symbol_to_drag_action (Lisp_Object act)
  6246 {
  6247   if (EQ (act, Qcopy))
  6248     return GDK_ACTION_COPY;
  6249 
  6250   if (EQ (act, Qmove))
  6251     return GDK_ACTION_MOVE;
  6252 
  6253   if (EQ (act, Qlink))
  6254     return GDK_ACTION_LINK;
  6255 
  6256   if (EQ (act, Qprivate))
  6257     return GDK_ACTION_PRIVATE;
  6258 
  6259   if (NILP (act))
  6260     return GDK_ACTION_DEFAULT;
  6261 
  6262   signal_error ("Invalid drag acction", act);
  6263 }
  6264 
  6265 static Lisp_Object
  6266 drag_action_to_symbol (GdkDragAction action)
  6267 {
  6268   switch (action)
  6269     {
  6270     case GDK_ACTION_COPY:
  6271       return Qcopy;
  6272 
  6273     case GDK_ACTION_MOVE:
  6274       return Qmove;
  6275 
  6276     case GDK_ACTION_LINK:
  6277       return Qlink;
  6278 
  6279     case GDK_ACTION_PRIVATE:
  6280       return Qprivate;
  6281 
  6282     case GDK_ACTION_DEFAULT:
  6283     default:
  6284       return Qnil;
  6285     }
  6286 }
  6287 
  6288 void
  6289 pgtk_update_drop_status (Lisp_Object action, Lisp_Object event_time)
  6290 {
  6291   guint32 time;
  6292 
  6293   CONS_TO_INTEGER (event_time, guint32, time);
  6294 
  6295   if (!current_drop_context || time < current_drop_time)
  6296     return;
  6297 
  6298   gdk_drag_status (current_drop_context,
  6299                    symbol_to_drag_action (action),
  6300                    time);
  6301 }
  6302 
  6303 void
  6304 pgtk_finish_drop (Lisp_Object success, Lisp_Object event_time,
  6305                   Lisp_Object del)
  6306 {
  6307   guint32 time;
  6308 
  6309   CONS_TO_INTEGER (event_time, guint32, time);
  6310 
  6311   if (!current_drop_context || time < current_drop_time)
  6312     return;
  6313 
  6314   gtk_drag_finish (current_drop_context, !NILP (success),
  6315                    !NILP (del), time);
  6316 
  6317   if (current_drop_context_drop)
  6318     g_clear_pointer (&current_drop_context,
  6319                      g_object_unref);
  6320 }
  6321 
  6322 static void
  6323 drag_leave (GtkWidget *widget, GdkDragContext *context,
  6324             guint time, gpointer user_data)
  6325 {
  6326   struct frame *f;
  6327   union buffered_input_event inev;
  6328 
  6329   f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  6330 
  6331   if (current_drop_context)
  6332     {
  6333       if (current_drop_context_drop)
  6334         gtk_drag_finish (current_drop_context,
  6335                          FALSE, FALSE, current_drop_time);
  6336 
  6337       g_clear_pointer (&current_drop_context,
  6338                        g_object_unref);
  6339     }
  6340 
  6341   EVENT_INIT (inev.ie);
  6342 
  6343   inev.ie.kind = DRAG_N_DROP_EVENT;
  6344   inev.ie.modifiers = 0;
  6345   inev.ie.arg = Qnil;
  6346   inev.ie.timestamp = time;
  6347 
  6348   XSETINT (inev.ie.x, 0);
  6349   XSETINT (inev.ie.y, 0);
  6350   XSETFRAME (inev.ie.frame_or_window, f);
  6351 
  6352   evq_enqueue (&inev);
  6353 }
  6354 
  6355 static gboolean
  6356 drag_motion (GtkWidget *widget, GdkDragContext *context,
  6357              gint x, gint y, guint time)
  6358 
  6359 {
  6360   struct frame *f;
  6361   union buffered_input_event inev;
  6362   GdkAtom name;
  6363   GdkDragAction suggestion;
  6364 
  6365   f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  6366 
  6367   if (!f)
  6368     return FALSE;
  6369 
  6370   if (current_drop_context)
  6371     {
  6372       if (current_drop_context_drop)
  6373         gtk_drag_finish (current_drop_context,
  6374                          FALSE, FALSE, current_drop_time);
  6375 
  6376       g_clear_pointer (&current_drop_context,
  6377                        g_object_unref);
  6378     }
  6379 
  6380   current_drop_context = g_object_ref (context);
  6381   current_drop_time = time;
  6382   current_drop_context_drop = false;
  6383 
  6384   name = gdk_drag_get_selection (context);
  6385   suggestion = gdk_drag_context_get_suggested_action (context);
  6386 
  6387   EVENT_INIT (inev.ie);
  6388 
  6389   inev.ie.kind = DRAG_N_DROP_EVENT;
  6390   inev.ie.modifiers = 0;
  6391   inev.ie.arg = list4 (Qlambda, intern (gdk_atom_name (name)),
  6392                        make_uint (time),
  6393                        drag_action_to_symbol (suggestion));
  6394   inev.ie.timestamp = time;
  6395 
  6396   XSETINT (inev.ie.x, x);
  6397   XSETINT (inev.ie.y, y);
  6398   XSETFRAME (inev.ie.frame_or_window, f);
  6399 
  6400   evq_enqueue (&inev);
  6401 
  6402   return TRUE;
  6403 }
  6404 
  6405 static gboolean
  6406 drag_drop (GtkWidget *widget, GdkDragContext *context,
  6407            int x, int y, guint time, gpointer user_data)
  6408 {
  6409   struct frame *f;
  6410   union buffered_input_event inev;
  6411   GdkAtom name;
  6412   GdkDragAction selected_action;
  6413 
  6414   f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  6415 
  6416   if (!f)
  6417     return FALSE;
  6418 
  6419   if (current_drop_context)
  6420     {
  6421       if (current_drop_context_drop)
  6422         gtk_drag_finish (current_drop_context,
  6423                          FALSE, FALSE, current_drop_time);
  6424 
  6425       g_clear_pointer (&current_drop_context,
  6426                        g_object_unref);
  6427     }
  6428 
  6429   current_drop_context = g_object_ref (context);
  6430   current_drop_time = time;
  6431   current_drop_context_drop = true;
  6432 
  6433   name = gdk_drag_get_selection (context);
  6434   selected_action = gdk_drag_context_get_selected_action (context);
  6435 
  6436   EVENT_INIT (inev.ie);
  6437 
  6438   inev.ie.kind = DRAG_N_DROP_EVENT;
  6439   inev.ie.modifiers = 0;
  6440   inev.ie.arg = list4 (Qquote, intern (gdk_atom_name (name)),
  6441                        make_uint (time),
  6442                        drag_action_to_symbol (selected_action));
  6443   inev.ie.timestamp = time;
  6444 
  6445   XSETINT (inev.ie.x, x);
  6446   XSETINT (inev.ie.y, y);
  6447   XSETFRAME (inev.ie.frame_or_window, f);
  6448 
  6449   evq_enqueue (&inev);
  6450 
  6451   return TRUE;
  6452 }
  6453 
  6454 static void
  6455 pgtk_monitors_changed_cb (GdkScreen *screen, gpointer user_data)
  6456 {
  6457   struct terminal *terminal;
  6458   union buffered_input_event inev;
  6459 
  6460   EVENT_INIT (inev.ie);
  6461   terminal = user_data;
  6462   inev.ie.kind = MONITORS_CHANGED_EVENT;
  6463   XSETTERMINAL (inev.ie.arg, terminal);
  6464 
  6465   evq_enqueue (&inev);
  6466 }
  6467 
  6468 static gboolean pgtk_selection_event (GtkWidget *, GdkEvent *, gpointer);
  6469 
  6470 void
  6471 pgtk_set_event_handler (struct frame *f)
  6472 {
  6473   if (f->tooltip)
  6474     {
  6475       g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "draw",
  6476                         G_CALLBACK (pgtk_handle_draw), NULL);
  6477       return;
  6478     }
  6479 
  6480   gtk_drag_dest_set (FRAME_GTK_WIDGET (f), 0, NULL, 0,
  6481                      (GDK_ACTION_MOVE | GDK_ACTION_COPY
  6482                       | GDK_ACTION_LINK | GDK_ACTION_PRIVATE));
  6483 
  6484   if (FRAME_GTK_OUTER_WIDGET (f))
  6485     {
  6486       g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)),
  6487                         "window-state-event", G_CALLBACK (window_state_event),
  6488                         NULL);
  6489       g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "delete-event",
  6490                         G_CALLBACK (delete_event), NULL);
  6491       g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "event",
  6492                         G_CALLBACK (pgtk_handle_event), NULL);
  6493       g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "configure-event",
  6494                         G_CALLBACK (configure_event), NULL);
  6495     }
  6496 
  6497   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "map-event",
  6498                     G_CALLBACK (map_event), NULL);
  6499   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "size-allocate",
  6500                     G_CALLBACK (size_allocate), f);
  6501   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "key-press-event",
  6502                     G_CALLBACK (key_press_event), NULL);
  6503   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "key-release-event",
  6504                     G_CALLBACK (key_release_event), NULL);
  6505   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "focus-in-event",
  6506                     G_CALLBACK (focus_in_event), NULL);
  6507   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "focus-out-event",
  6508                     G_CALLBACK (focus_out_event), NULL);
  6509   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "enter-notify-event",
  6510                     G_CALLBACK (enter_notify_event), NULL);
  6511   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "leave-notify-event",
  6512                     G_CALLBACK (leave_notify_event), NULL);
  6513   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "motion-notify-event",
  6514                     G_CALLBACK (motion_notify_event), NULL);
  6515   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "button-press-event",
  6516                     G_CALLBACK (button_event), NULL);
  6517   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "button-release-event",
  6518                     G_CALLBACK (button_event), NULL);
  6519   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "scroll-event",
  6520                     G_CALLBACK (scroll_event), NULL);
  6521   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "configure-event",
  6522                     G_CALLBACK (configure_event), NULL);
  6523   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-leave",
  6524                     G_CALLBACK (drag_leave), NULL);
  6525   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-motion",
  6526                     G_CALLBACK (drag_motion), NULL);
  6527   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-drop",
  6528                     G_CALLBACK (drag_drop), NULL);
  6529   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "draw",
  6530                     G_CALLBACK (pgtk_handle_draw), NULL);
  6531   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "property-notify-event",
  6532                     G_CALLBACK (pgtk_selection_event), NULL);
  6533   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-clear-event",
  6534                     G_CALLBACK (pgtk_selection_event), NULL);
  6535   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-request-event",
  6536                     G_CALLBACK (pgtk_selection_event), NULL);
  6537   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-notify-event",
  6538                     G_CALLBACK (pgtk_selection_event), NULL);
  6539   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "event",
  6540                     G_CALLBACK (pgtk_handle_event), NULL);
  6541 }
  6542 
  6543 static void
  6544 my_log_handler (const gchar * log_domain, GLogLevelFlags log_level,
  6545                 const gchar * msg, gpointer user_data)
  6546 {
  6547   if (!strstr (msg, "g_set_prgname"))
  6548     fprintf (stderr, "%s-WARNING **: %s", log_domain, msg);
  6549 }
  6550 
  6551 /* Test whether two display-name strings agree up to the dot that separates
  6552    the screen number from the server number.  */
  6553 static bool
  6554 same_x_server (const char *name1, const char *name2)
  6555 {
  6556   bool seen_colon = false;
  6557   Lisp_Object sysname = Fsystem_name ();
  6558   const char *system_name = SSDATA (sysname);
  6559   ptrdiff_t system_name_length = SBYTES (sysname);
  6560   ptrdiff_t length_until_period = 0;
  6561 
  6562   while (system_name[length_until_period] != 0
  6563          && system_name[length_until_period] != '.')
  6564     length_until_period++;
  6565 
  6566   /* Treat `unix' like an empty host name.  */
  6567   if (!strncmp (name1, "unix:", 5))
  6568     name1 += 4;
  6569   if (!strncmp (name2, "unix:", 5))
  6570     name2 += 4;
  6571   /* Treat this host's name like an empty host name.  */
  6572   if (!strncmp (name1, system_name, system_name_length)
  6573       && name1[system_name_length] == ':')
  6574     name1 += system_name_length;
  6575   if (!strncmp (name2, system_name, system_name_length)
  6576       && name2[system_name_length] == ':')
  6577     name2 += system_name_length;
  6578   /* Treat this host's domainless name like an empty host name.  */
  6579   if (!strncmp (name1, system_name, length_until_period)
  6580       && name1[length_until_period] == ':')
  6581     name1 += length_until_period;
  6582   if (!strncmp (name2, system_name, length_until_period)
  6583       && name2[length_until_period] == ':')
  6584     name2 += length_until_period;
  6585 
  6586   for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
  6587     {
  6588       if (*name1 == ':')
  6589         seen_colon = true;
  6590       if (seen_colon && *name1 == '.')
  6591         return true;
  6592     }
  6593   return (seen_colon
  6594           && (*name1 == '.' || *name1 == '\0')
  6595           && (*name2 == '.' || *name2 == '\0'));
  6596 }
  6597 
  6598 static struct frame *
  6599 pgtk_find_selection_owner (GdkWindow *window)
  6600 {
  6601   Lisp_Object tail, tem;
  6602   struct frame *f;
  6603 
  6604   FOR_EACH_FRAME (tail, tem)
  6605     {
  6606       f = XFRAME (tem);
  6607 
  6608       if (FRAME_PGTK_P (f)
  6609           && (FRAME_GDK_WINDOW (f) == window))
  6610         return f;
  6611     }
  6612 
  6613   return NULL;
  6614 }
  6615 
  6616 static gboolean
  6617 pgtk_selection_event (GtkWidget *widget, GdkEvent *event,
  6618                       gpointer user_data)
  6619 {
  6620   struct frame *f;
  6621   union buffered_input_event inev;
  6622 
  6623   if (event->type == GDK_PROPERTY_NOTIFY)
  6624     pgtk_handle_property_notify (&event->property);
  6625   else if (event->type == GDK_SELECTION_CLEAR
  6626            || event->type == GDK_SELECTION_REQUEST)
  6627     {
  6628       f = pgtk_find_selection_owner (event->selection.window);
  6629 
  6630       if (f)
  6631         {
  6632           EVENT_INIT (inev.ie);
  6633 
  6634           inev.sie.kind = (event->type == GDK_SELECTION_CLEAR
  6635                            ? SELECTION_CLEAR_EVENT
  6636                            : SELECTION_REQUEST_EVENT);
  6637 
  6638           SELECTION_EVENT_DPYINFO (&inev.sie) = FRAME_DISPLAY_INFO (f);
  6639           SELECTION_EVENT_SELECTION (&inev.sie) = event->selection.selection;
  6640           SELECTION_EVENT_TIME (&inev.sie) = event->selection.time;
  6641 
  6642           if (event->type == GDK_SELECTION_REQUEST)
  6643             {
  6644               /* FIXME: when does GDK destroy the requestor GdkWindow
  6645                  object?
  6646 
  6647                  It would make sense to wait for the transfer to
  6648                  complete.  But I don't know if GDK actually does
  6649                  that.  */
  6650               SELECTION_EVENT_REQUESTOR (&inev.sie) = event->selection.requestor;
  6651               SELECTION_EVENT_TARGET (&inev.sie) = event->selection.target;
  6652               SELECTION_EVENT_PROPERTY (&inev.sie) = event->selection.property;
  6653             }
  6654 
  6655           evq_enqueue (&inev);
  6656           return TRUE;
  6657         }
  6658     }
  6659   else if (event->type == GDK_SELECTION_NOTIFY)
  6660     pgtk_handle_selection_notify (&event->selection);
  6661 
  6662   return FALSE;
  6663 }
  6664 
  6665 /* Display a warning message if the PGTK port is being used under X;
  6666    that is not supported.  */
  6667 
  6668 static void
  6669 pgtk_display_x_warning (GdkDisplay *display)
  6670 {
  6671   GtkWidget *dialog_widget, *label, *content_area;
  6672   GtkDialog *dialog;
  6673   GtkWindow *window;
  6674   GdkScreen *screen;
  6675 
  6676   /* Do this instead of GDK_IS_X11_DISPLAY because the GDK X header
  6677      pulls in Xlib, which conflicts with definitions in pgtkgui.h.  */
  6678   if (strcmp (G_OBJECT_TYPE_NAME (display),
  6679               "GdkX11Display"))
  6680     return;
  6681 
  6682   dialog_widget = gtk_dialog_new ();
  6683   dialog = GTK_DIALOG (dialog_widget);
  6684   window = GTK_WINDOW (dialog_widget);
  6685   screen = gdk_display_get_default_screen (display);
  6686   content_area = gtk_dialog_get_content_area (dialog);
  6687 
  6688   gtk_window_set_title (window, "Warning");
  6689   gtk_window_set_screen (window, screen);
  6690 
  6691   label = gtk_label_new ("You are trying to run Emacs configured with\n"
  6692                           " the \"pure-GTK\" interface under the X Window\n"
  6693                           " System.  That configuration is unsupported and\n"
  6694                           " will lead to sporadic crashes during transfer of\n"
  6695                           " large selection data.  It will also lead to\n"
  6696                           " various problems with keyboard input.\n");
  6697   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
  6698   gtk_container_add (GTK_CONTAINER (content_area), label);
  6699   gtk_widget_show (label);
  6700   gtk_widget_show (dialog_widget);
  6701 }
  6702 
  6703 /* Open a connection to X display DISPLAY_NAME, and return
  6704    the structure that describes the open display.
  6705    If we cannot contact the display, return null.  */
  6706 
  6707 struct pgtk_display_info *
  6708 pgtk_term_init (Lisp_Object display_name, char *resource_name)
  6709 {
  6710   GdkDisplay *dpy;
  6711   struct terminal *terminal;
  6712   struct pgtk_display_info *dpyinfo;
  6713   static int x_initialized = 0;
  6714   static unsigned x_display_id = 0;
  6715   static char *initial_display = NULL;
  6716   char *dpy_name;
  6717   static void *handle = NULL;
  6718   Lisp_Object lisp_dpy_name = Qnil;
  6719   GdkScreen *gscr;
  6720   gdouble dpi;
  6721 
  6722   block_input ();
  6723 
  6724   if (!x_initialized)
  6725     {
  6726       any_help_event_p = false;
  6727 
  6728       Fset_input_interrupt_mode (Qt);
  6729       baud_rate = 19200;
  6730 
  6731 #ifdef USE_CAIRO
  6732       gui_init_fringe (&pgtk_redisplay_interface);
  6733 #endif
  6734 
  6735       ++x_initialized;
  6736     }
  6737 
  6738   dpy_name = SSDATA (display_name);
  6739   if (strlen (dpy_name) == 0 && initial_display != NULL)
  6740     dpy_name = initial_display;
  6741   lisp_dpy_name = build_string (dpy_name);
  6742 
  6743   {
  6744 #define NUM_ARGV 10
  6745     int argc;
  6746     char *argv[NUM_ARGV];
  6747     char **argv2 = argv;
  6748     guint id;
  6749 
  6750     if (x_initialized++ > 1)
  6751       {
  6752         xg_display_open (dpy_name, &dpy);
  6753       }
  6754     else
  6755       {
  6756         static char display_opt[] = "--display";
  6757         static char name_opt[] = "--name";
  6758 
  6759         for (argc = 0; argc < NUM_ARGV; ++argc)
  6760           argv[argc] = 0;
  6761 
  6762         argc = 0;
  6763         argv[argc++] = initial_argv[0];
  6764 
  6765         if (strlen (dpy_name) != 0)
  6766           {
  6767             argv[argc++] = display_opt;
  6768             argv[argc++] = dpy_name;
  6769           }
  6770 
  6771         argv[argc++] = name_opt;
  6772         argv[argc++] = resource_name;
  6773 
  6774         /* Work around GLib bug that outputs a faulty warning. See
  6775            https://bugzilla.gnome.org/show_bug.cgi?id=563627.  */
  6776         id = g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL
  6777                                 | G_LOG_FLAG_RECURSION, my_log_handler, NULL);
  6778 
  6779         /* gtk_init does set_locale.  Fix locale before and after.  */
  6780         fixup_locale ();
  6781         unrequest_sigio ();     /* See comment in x_display_ok.  */
  6782         gtk_init (&argc, &argv2);
  6783         request_sigio ();
  6784         fixup_locale ();
  6785 
  6786 
  6787         g_log_remove_handler ("GLib", id);
  6788 
  6789         xg_initialize ();
  6790 
  6791         dpy = DEFAULT_GDK_DISPLAY ();
  6792 
  6793         initial_display = g_strdup (gdk_display_get_name (dpy));
  6794         dpy_name = initial_display;
  6795         lisp_dpy_name = build_string (dpy_name);
  6796       }
  6797   }
  6798 
  6799   /* Detect failure.  */
  6800   if (dpy == 0)
  6801     {
  6802       unblock_input ();
  6803       return 0;
  6804     }
  6805 
  6806   /* If the PGTK port is being used under X, complain very loudly, as
  6807      that isn't supported.  */
  6808   pgtk_display_x_warning (dpy);
  6809 
  6810   dpyinfo = xzalloc (sizeof *dpyinfo);
  6811   pgtk_initialize_display_info (dpyinfo);
  6812   terminal = pgtk_create_terminal (dpyinfo);
  6813 
  6814   {
  6815     struct pgtk_display_info *share;
  6816 
  6817     for (share = x_display_list; share; share = share->next)
  6818       if (same_x_server (SSDATA (XCAR (share->name_list_element)), dpy_name))
  6819         break;
  6820     if (share)
  6821       terminal->kboard = share->terminal->kboard;
  6822     else
  6823       {
  6824         terminal->kboard = allocate_kboard (Qpgtk);
  6825 
  6826         /* Don't let the initial kboard remain current longer than necessary.
  6827            That would cause problems if a file loaded on startup tries to
  6828            prompt in the mini-buffer.  */
  6829         if (current_kboard == initial_kboard)
  6830           current_kboard = terminal->kboard;
  6831       }
  6832     terminal->kboard->reference_count++;
  6833   }
  6834 
  6835   /* Put this display on the chain.  */
  6836   dpyinfo->next = x_display_list;
  6837   x_display_list = dpyinfo;
  6838 
  6839   dpyinfo->name_list_element = Fcons (lisp_dpy_name, Qnil);
  6840   dpyinfo->gdpy = dpy;
  6841 
  6842   /* https://lists.gnu.org/r/emacs-devel/2015-11/msg00194.html  */
  6843   dpyinfo->smallest_font_height = 1;
  6844   dpyinfo->smallest_char_width = 1;
  6845 
  6846   /* Set the name of the terminal. */
  6847   terminal->name = xlispstrdup (lisp_dpy_name);
  6848 
  6849   Lisp_Object system_name = Fsystem_name ();
  6850   ptrdiff_t nbytes;
  6851   if (ckd_add (&nbytes, SBYTES (Vinvocation_name), SBYTES (system_name) + 2))
  6852     memory_full (SIZE_MAX);
  6853   dpyinfo->x_id = ++x_display_id;
  6854   dpyinfo->x_id_name = xmalloc (nbytes);
  6855   char *nametail = lispstpcpy (dpyinfo->x_id_name, Vinvocation_name);
  6856   *nametail++ = '@';
  6857   lispstpcpy (nametail, system_name);
  6858 
  6859   /* Get the scroll bar cursor.  */
  6860   /* We must create a GTK cursor, it is required for GTK widgets.  */
  6861   dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->gdpy);
  6862 
  6863   dpyinfo->vertical_scroll_bar_cursor
  6864     = gdk_cursor_new_for_display (dpyinfo->gdpy, GDK_SB_V_DOUBLE_ARROW);
  6865 
  6866   dpyinfo->horizontal_scroll_bar_cursor
  6867     = gdk_cursor_new_for_display (dpyinfo->gdpy, GDK_SB_H_DOUBLE_ARROW);
  6868 
  6869   dpyinfo->icon_bitmap_id = -1;
  6870 
  6871   reset_mouse_highlight (&dpyinfo->mouse_highlight);
  6872 
  6873   gscr = gdk_display_get_default_screen (dpyinfo->gdpy);
  6874   dpi = gdk_screen_get_resolution (gscr);
  6875 
  6876   if (dpi < 0)
  6877     dpi = 96.0;
  6878 
  6879   dpyinfo->resx = dpi;
  6880   dpyinfo->resy = dpi;
  6881 
  6882   g_signal_connect (G_OBJECT (gscr), "monitors-changed",
  6883                     G_CALLBACK (pgtk_monitors_changed_cb),
  6884                     terminal);
  6885 
  6886   /* Set up scrolling increments.  */
  6887   dpyinfo->scroll.x_per_char = 1;
  6888   dpyinfo->scroll.y_per_line = 1;
  6889 
  6890   dpyinfo->connection = -1;
  6891 
  6892   if (!handle)
  6893     handle = dlopen (NULL, RTLD_LAZY);
  6894 
  6895 #ifdef GDK_WINDOWING_X11
  6896   if (!strcmp (G_OBJECT_TYPE_NAME (dpy), "GdkX11Display") && handle)
  6897     {
  6898       void *(*gdk_x11_display_get_xdisplay) (GdkDisplay *)
  6899         = dlsym (handle, "gdk_x11_display_get_xdisplay");
  6900       int (*x_connection_number) (void *)
  6901         = dlsym (handle, "XConnectionNumber");
  6902 
  6903       if (x_connection_number
  6904           && gdk_x11_display_get_xdisplay)
  6905         dpyinfo->connection
  6906           = x_connection_number (gdk_x11_display_get_xdisplay (dpy));
  6907     }
  6908 #endif
  6909 
  6910 #ifdef GDK_WINDOWING_WAYLAND
  6911   if (GDK_IS_WAYLAND_DISPLAY (dpy) && handle)
  6912     {
  6913       struct wl_display *wl_dpy = gdk_wayland_display_get_wl_display (dpy);
  6914       int (*display_get_fd) (struct wl_display *)
  6915         = dlsym (handle, "wl_display_get_fd");
  6916 
  6917       if (display_get_fd)
  6918         dpyinfo->connection = display_get_fd (wl_dpy);
  6919     }
  6920 #endif
  6921 
  6922   if (dpyinfo->connection >= 0)
  6923     {
  6924       add_keyboard_wait_descriptor (dpyinfo->connection);
  6925 #ifdef F_SETOWN
  6926       fcntl (dpyinfo->connection, F_SETOWN, getpid ());
  6927 #endif /* ! defined (F_SETOWN) */
  6928 
  6929       if (interrupt_input)
  6930         init_sigio (dpyinfo->connection);
  6931     }
  6932 
  6933   dpyinfo->invisible_cursor
  6934     = gdk_cursor_new_for_display (dpyinfo->gdpy, GDK_BLANK_CURSOR);
  6935 
  6936   xsettings_initialize (dpyinfo);
  6937 
  6938   pgtk_im_init (dpyinfo);
  6939 
  6940   g_signal_connect (G_OBJECT (dpyinfo->gdpy), "seat-added",
  6941                     G_CALLBACK (pgtk_seat_added_cb), dpyinfo);
  6942   g_signal_connect (G_OBJECT (dpyinfo->gdpy), "seat-removed",
  6943                     G_CALLBACK (pgtk_seat_removed_cb), dpyinfo);
  6944   pgtk_enumerate_devices (dpyinfo, true);
  6945 
  6946   unblock_input ();
  6947 
  6948   return dpyinfo;
  6949 }
  6950 
  6951 /* Get rid of display DPYINFO, deleting all frames on it,
  6952    and without sending any more commands to the X server.  */
  6953 
  6954 static void
  6955 pgtk_delete_display (struct pgtk_display_info *dpyinfo)
  6956 {
  6957   struct terminal *t;
  6958 
  6959   /* Close all frames and delete the generic struct terminal for this
  6960      X display.  */
  6961   for (t = terminal_list; t; t = t->next_terminal)
  6962     if (t->type == output_pgtk && t->display_info.pgtk == dpyinfo)
  6963       {
  6964         delete_terminal (t);
  6965         break;
  6966       }
  6967 
  6968   if (x_display_list == dpyinfo)
  6969     x_display_list = dpyinfo->next;
  6970   else
  6971     {
  6972       struct pgtk_display_info *tail;
  6973 
  6974       for (tail = x_display_list; tail; tail = tail->next)
  6975         if (tail->next == dpyinfo)
  6976           tail->next = tail->next->next;
  6977     }
  6978 
  6979   pgtk_free_devices (dpyinfo);
  6980   xfree (dpyinfo);
  6981 }
  6982 
  6983 char *
  6984 pgtk_xlfd_to_fontname (const char *xlfd)
  6985 /* --------------------------------------------------------------------------
  6986     Convert an X font name (XLFD) to an Gtk font name.
  6987     Only family is used.
  6988     The string returned is temporarily allocated.
  6989    -------------------------------------------------------------------------- */
  6990 {
  6991   char *name = xmalloc (180);
  6992 
  6993   if (!strncmp (xlfd, "--", 2))
  6994     {
  6995       if (sscanf (xlfd, "--%179[^-]-", name) != 1)
  6996         name[0] = '\0';
  6997     }
  6998   else
  6999     {
  7000       if (sscanf (xlfd, "-%*[^-]-%179[^-]-", name) != 1)
  7001         name[0] = '\0';
  7002     }
  7003 
  7004   /* stopgap for malformed XLFD input */
  7005   if (strlen (name) == 0)
  7006     strcpy (name, "Monospace");
  7007 
  7008   return name;
  7009 }
  7010 
  7011 bool
  7012 pgtk_defined_color (struct frame *f, const char *name,
  7013                     Emacs_Color *color_def, bool alloc,
  7014                     bool makeIndex)
  7015 /* --------------------------------------------------------------------------
  7016          Return true if named color found, and set color_def rgb accordingly.
  7017          If makeIndex and alloc are nonzero put the color in the color_table,
  7018          and set color_def pixel to the resulting index.
  7019          If makeIndex is zero, set color_def pixel to ARGB.
  7020          Return false if not found
  7021    -------------------------------------------------------------------------- */
  7022 {
  7023   int r;
  7024 
  7025   block_input ();
  7026   r = xg_check_special_colors (f, name, color_def);
  7027   if (!r)
  7028     r = pgtk_parse_color (f, name, color_def);
  7029   unblock_input ();
  7030   return r;
  7031 }
  7032 
  7033 /* On frame F, translate the color name to RGB values.  Use cached
  7034    information, if possible.
  7035 
  7036    Note that there is currently no way to clean old entries out of the
  7037    cache.  However, it is limited to names in the server's database,
  7038    and names we've actually looked up; list-colors-display is probably
  7039    the most color-intensive case we're likely to hit.  */
  7040 
  7041 int
  7042 pgtk_parse_color (struct frame *f, const char *color_name,
  7043                   Emacs_Color * color)
  7044 {
  7045   GdkRGBA rgba;
  7046   if (gdk_rgba_parse (&rgba, color_name))
  7047     {
  7048       color->red = rgba.red * 65535;
  7049       color->green = rgba.green * 65535;
  7050       color->blue = rgba.blue * 65535;
  7051       color->pixel = ((color->red >> 8) << 16
  7052                       | (color->green >> 8) << 8
  7053                       | (color->blue >> 8) << 0);
  7054       return 1;
  7055     }
  7056   return 0;
  7057 }
  7058 
  7059 /* On frame F, translate pixel colors to RGB values for the NCOLORS
  7060    colors in COLORS.  On W32, we no longer try to map colors to
  7061    a palette.  */
  7062 void
  7063 pgtk_query_colors (struct frame *f, Emacs_Color * colors, int ncolors)
  7064 {
  7065   int i;
  7066 
  7067   for (i = 0; i < ncolors; i++)
  7068     {
  7069       unsigned long pixel = colors[i].pixel;
  7070       /* Convert to a 16 bit value in range 0 - 0xffff. */
  7071 #define GetRValue(p) (((p) >> 16) & 0xff)
  7072 #define GetGValue(p) (((p) >> 8) & 0xff)
  7073 #define GetBValue(p) (((p) >> 0) & 0xff)
  7074       colors[i].red = GetRValue (pixel) * 257;
  7075       colors[i].green = GetGValue (pixel) * 257;
  7076       colors[i].blue = GetBValue (pixel) * 257;
  7077     }
  7078 }
  7079 
  7080 void
  7081 pgtk_query_color (struct frame *f, Emacs_Color * color)
  7082 {
  7083   pgtk_query_colors (f, color, 1);
  7084 }
  7085 
  7086 void
  7087 pgtk_clear_area (struct frame *f, int x, int y, int width, int height)
  7088 {
  7089   cairo_t *cr;
  7090 
  7091   eassert (width > 0 && height > 0);
  7092 
  7093   cr = pgtk_begin_cr_clip (f);
  7094   pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT (f)->background_color,
  7095                                  true);
  7096   cairo_rectangle (cr, x, y, width, height);
  7097   cairo_fill (cr);
  7098   pgtk_end_cr_clip (f);
  7099 }
  7100 
  7101 
  7102 void
  7103 syms_of_pgtkterm (void)
  7104 {
  7105   DEFSYM (Qmodifier_value, "modifier-value");
  7106   DEFSYM (Qalt, "alt");
  7107   DEFSYM (Qhyper, "hyper");
  7108   DEFSYM (Qmeta, "meta");
  7109   DEFSYM (Qsuper, "super");
  7110   DEFSYM (Qcontrol, "control");
  7111   DEFSYM (QUTF8_STRING, "UTF8_STRING");
  7112 
  7113   DEFSYM (Qfile, "file");
  7114   DEFSYM (Qurl, "url");
  7115 
  7116   DEFSYM (Qlatin_1, "latin-1");
  7117 
  7118   xg_default_icon_file
  7119     = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
  7120   staticpro (&xg_default_icon_file);
  7121 
  7122   DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock");
  7123 
  7124   DEFSYM (Qcopy, "copy");
  7125   DEFSYM (Qmove, "move");
  7126   DEFSYM (Qlink, "link");
  7127   DEFSYM (Qprivate, "private");
  7128 
  7129 
  7130   Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier));
  7131   Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier));
  7132   Fput (Qmeta, Qmodifier_value, make_fixnum (meta_modifier));
  7133   Fput (Qsuper, Qmodifier_value, make_fixnum (super_modifier));
  7134   Fput (Qcontrol, Qmodifier_value, make_fixnum (ctrl_modifier));
  7135 
  7136   DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym,
  7137                doc: /* SKIP: real doc in xterm.c.  */);
  7138   Vx_ctrl_keysym = Qnil;
  7139 
  7140   DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym,
  7141                doc: /* SKIP: real doc in xterm.c.  */);
  7142   Vx_alt_keysym = Qnil;
  7143 
  7144   DEFVAR_LISP ("x-hyper-keysym", Vx_hyper_keysym,
  7145                doc: /* SKIP: real doc in xterm.c.  */);
  7146   Vx_hyper_keysym = Qnil;
  7147 
  7148   DEFVAR_LISP ("x-meta-keysym", Vx_meta_keysym,
  7149                doc: /* SKIP: real doc in xterm.c.  */);
  7150   Vx_meta_keysym = Qnil;
  7151 
  7152   DEFVAR_LISP ("x-super-keysym", Vx_super_keysym,
  7153                doc: /* SKIP: real doc in xterm.c.  */);
  7154   Vx_super_keysym = Qnil;
  7155 
  7156   DEFVAR_BOOL ("x-use-underline-position-properties",
  7157                x_use_underline_position_properties,
  7158      doc: /* SKIP: real doc in xterm.c.  */);
  7159   x_use_underline_position_properties = 1;
  7160 
  7161   DEFVAR_BOOL ("x-underline-at-descent-line",
  7162                x_underline_at_descent_line,
  7163      doc: /* SKIP: real doc in xterm.c.  */);
  7164   x_underline_at_descent_line = 0;
  7165 
  7166   DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
  7167      doc: /* SKIP: real doc in xterm.c.  */);
  7168   Vx_toolkit_scroll_bars = intern_c_string ("gtk");
  7169 
  7170   DEFVAR_LISP ("pgtk-wait-for-event-timeout", Vpgtk_wait_for_event_timeout,
  7171                doc: /* How long to wait for GTK events.
  7172 
  7173 Emacs will wait up to this many seconds to receive some GTK events
  7174 after making changes which affect the state of the graphical
  7175 interface.  Under some window managers this can take an indefinite
  7176 amount of time, so it is important to limit the wait.
  7177 
  7178 If set to a non-float value, there will be no wait at all.  */);
  7179   Vpgtk_wait_for_event_timeout = make_float (0.1);
  7180 
  7181   DEFVAR_LISP ("pgtk-keysym-table", Vpgtk_keysym_table,
  7182     doc: /* Hash table of character codes indexed by X keysym codes.  */);
  7183   Vpgtk_keysym_table = make_hash_table (hashtest_eql, 900, DEFAULT_REHASH_SIZE,
  7184                                         DEFAULT_REHASH_THRESHOLD, Qnil, false);
  7185 
  7186   window_being_scrolled = Qnil;
  7187   staticpro (&window_being_scrolled);
  7188 
  7189   /* Tell Emacs about this window system.  */
  7190   Fprovide (Qpgtk, Qnil);
  7191 }
  7192 
  7193 /* Cairo does not allow resizing a surface/context after it is
  7194    created, so we need to trash the old context, create a new context
  7195    on the next cr_clip_begin with the new dimensions and request a
  7196    re-draw.
  7197 
  7198    This will leave the active context available to present on screen
  7199    until a redrawn frame is completed.  */
  7200 void
  7201 pgtk_cr_update_surface_desired_size (struct frame *f, int width, int height, bool force)
  7202 {
  7203   if (FRAME_CR_SURFACE_DESIRED_WIDTH (f) != width
  7204       || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height
  7205       || force)
  7206     {
  7207       pgtk_cr_destroy_frame_context (f);
  7208       FRAME_CR_SURFACE_DESIRED_WIDTH (f) = width;
  7209       FRAME_CR_SURFACE_DESIRED_HEIGHT (f) = height;
  7210       SET_FRAME_GARBAGED (f);
  7211     }
  7212 }
  7213 
  7214 
  7215 cairo_t *
  7216 pgtk_begin_cr_clip (struct frame *f)
  7217 {
  7218   cairo_t *cr = FRAME_CR_CONTEXT (f);
  7219 
  7220   if (!cr)
  7221     {
  7222       cairo_surface_t *surface
  7223         = gdk_window_create_similar_surface (gtk_widget_get_window
  7224                                              (FRAME_GTK_WIDGET (f)),
  7225                                              CAIRO_CONTENT_COLOR_ALPHA,
  7226                                              FRAME_CR_SURFACE_DESIRED_WIDTH (f),
  7227                                              FRAME_CR_SURFACE_DESIRED_HEIGHT
  7228                                              (f));
  7229 
  7230       cr = FRAME_CR_CONTEXT (f) = cairo_create (surface);
  7231       cairo_surface_destroy (surface);
  7232     }
  7233 
  7234   cairo_save (cr);
  7235 
  7236   return cr;
  7237 }
  7238 
  7239 void
  7240 pgtk_end_cr_clip (struct frame *f)
  7241 {
  7242   cairo_restore (FRAME_CR_CONTEXT (f));
  7243 }
  7244 
  7245 void
  7246 pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC *gc,
  7247                                        bool respects_alpha_background)
  7248 {
  7249   pgtk_set_cr_source_with_color (f, gc->foreground,
  7250                                  respects_alpha_background);
  7251 }
  7252 
  7253 void
  7254 pgtk_set_cr_source_with_gc_background (struct frame *f, Emacs_GC *gc,
  7255                                        bool respects_alpha_background)
  7256 {
  7257   pgtk_set_cr_source_with_color (f, gc->background,
  7258                                  respects_alpha_background);
  7259 }
  7260 
  7261 void
  7262 pgtk_set_cr_source_with_color (struct frame *f, unsigned long color,
  7263                                bool respects_alpha_background)
  7264 {
  7265   Emacs_Color col;
  7266   col.pixel = color;
  7267   pgtk_query_color (f, &col);
  7268 
  7269   if (!respects_alpha_background)
  7270     {
  7271       cairo_set_source_rgb (FRAME_CR_CONTEXT (f), col.red / 65535.0,
  7272                             col.green / 65535.0, col.blue / 65535.0);
  7273       cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_OVER);
  7274     }
  7275   else
  7276     {
  7277       cairo_set_source_rgba (FRAME_CR_CONTEXT (f), col.red / 65535.0,
  7278                              col.green / 65535.0, col.blue / 65535.0,
  7279                              f->alpha_background);
  7280       cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE);
  7281     }
  7282 }
  7283 
  7284 void
  7285 pgtk_cr_draw_frame (cairo_t * cr, struct frame *f)
  7286 {
  7287   cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), 0, 0);
  7288   cairo_paint (cr);
  7289 }
  7290 
  7291 static cairo_status_t
  7292 pgtk_cr_accumulate_data (void *closure, const unsigned char *data,
  7293                          unsigned int length)
  7294 {
  7295   Lisp_Object *acc = (Lisp_Object *) closure;
  7296 
  7297   *acc = Fcons (make_unibyte_string ((char const *) data, length), *acc);
  7298 
  7299   return CAIRO_STATUS_SUCCESS;
  7300 }
  7301 
  7302 void
  7303 pgtk_cr_destroy_frame_context (struct frame *f)
  7304 {
  7305   if (FRAME_CR_CONTEXT (f) != NULL)
  7306     {
  7307       cairo_destroy (FRAME_CR_CONTEXT (f));
  7308       FRAME_CR_CONTEXT (f) = NULL;
  7309     }
  7310 }
  7311 
  7312 static void
  7313 pgtk_cr_destroy (void *cr)
  7314 {
  7315   block_input ();
  7316   cairo_destroy (cr);
  7317   unblock_input ();
  7318 }
  7319 
  7320 Lisp_Object
  7321 pgtk_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
  7322 {
  7323   struct frame *f;
  7324   cairo_surface_t *surface;
  7325   cairo_t *cr;
  7326   int width, height;
  7327   void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL;
  7328   Lisp_Object acc = Qnil;
  7329   specpdl_ref count = SPECPDL_INDEX ();
  7330 
  7331   specbind (Qredisplay_dont_pause, Qt);
  7332   redisplay_preserve_echo_area (31);
  7333 
  7334   f = XFRAME (XCAR (frames));
  7335   frames = XCDR (frames);
  7336   width = FRAME_PIXEL_WIDTH (f);
  7337   height = FRAME_PIXEL_HEIGHT (f);
  7338 
  7339   block_input ();
  7340 #ifdef CAIRO_HAS_PDF_SURFACE
  7341   if (surface_type == CAIRO_SURFACE_TYPE_PDF)
  7342     {
  7343       surface = cairo_pdf_surface_create_for_stream (pgtk_cr_accumulate_data, &acc,
  7344                                                      width, height);
  7345       surface_set_size_func = cairo_pdf_surface_set_size;
  7346     }
  7347   else
  7348 #endif
  7349 #ifdef CAIRO_HAS_PNG_FUNCTIONS
  7350   if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
  7351     surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
  7352   else
  7353 #endif
  7354 #ifdef CAIRO_HAS_PS_SURFACE
  7355   if (surface_type == CAIRO_SURFACE_TYPE_PS)
  7356     {
  7357       surface = cairo_ps_surface_create_for_stream (pgtk_cr_accumulate_data, &acc,
  7358                                                     width, height);
  7359       surface_set_size_func = cairo_ps_surface_set_size;
  7360     }
  7361   else
  7362 #endif
  7363 #ifdef CAIRO_HAS_SVG_SURFACE
  7364   if (surface_type == CAIRO_SURFACE_TYPE_SVG)
  7365     surface = cairo_svg_surface_create_for_stream (pgtk_cr_accumulate_data, &acc,
  7366                                                    width, height);
  7367   else
  7368 #endif
  7369     abort ();
  7370 
  7371   cr = cairo_create (surface);
  7372   cairo_surface_destroy (surface);
  7373   record_unwind_protect_ptr (pgtk_cr_destroy, cr);
  7374 
  7375   while (1)
  7376     {
  7377       cairo_t *saved_cr = FRAME_CR_CONTEXT (f);
  7378       FRAME_CR_CONTEXT (f) = cr;
  7379       pgtk_clear_area (f, 0, 0, width, height);
  7380       expose_frame (f, 0, 0, width, height);
  7381       FRAME_CR_CONTEXT (f) = saved_cr;
  7382 
  7383       if (NILP (frames))
  7384         break;
  7385 
  7386       cairo_surface_show_page (surface);
  7387       f = XFRAME (XCAR (frames));
  7388       frames = XCDR (frames);
  7389       width = FRAME_PIXEL_WIDTH (f);
  7390       height = FRAME_PIXEL_HEIGHT (f);
  7391       if (surface_set_size_func)
  7392         (*surface_set_size_func) (surface, width, height);
  7393 
  7394       unblock_input ();
  7395       maybe_quit ();
  7396       block_input ();
  7397     }
  7398 
  7399 #ifdef CAIRO_HAS_PNG_FUNCTIONS
  7400   if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
  7401     {
  7402       cairo_surface_flush (surface);
  7403       cairo_surface_write_to_png_stream (surface, pgtk_cr_accumulate_data, &acc);
  7404     }
  7405 #endif
  7406   unblock_input ();
  7407 
  7408   unbind_to (count, Qnil);
  7409 
  7410   return CALLN (Fapply, intern ("concat"), Fnreverse (acc));
  7411 }

/* [<][>][^][v][top][bottom][index][help] */