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 /* Make the x-window of frame F use the gnu icon bitmap.  */
  3154 
  3155 static bool
  3156 pgtk_bitmap_icon (struct frame *f, Lisp_Object file)
  3157 {
  3158   ptrdiff_t bitmap_id;
  3159 
  3160   if (FRAME_GTK_WIDGET (f) == 0)
  3161     return true;
  3162 
  3163   /* Free up our existing icon bitmap and mask if any.  */
  3164   if (f->output_data.pgtk->icon_bitmap > 0)
  3165     image_destroy_bitmap (f, f->output_data.pgtk->icon_bitmap);
  3166   f->output_data.pgtk->icon_bitmap = 0;
  3167 
  3168   if (STRINGP (file))
  3169     {
  3170       /* Use gtk_window_set_icon_from_file () if available,
  3171          It's not restricted to bitmaps */
  3172       if (xg_set_icon (f, file))
  3173         return false;
  3174       bitmap_id = image_create_bitmap_from_file (f, file);
  3175     }
  3176   else
  3177     {
  3178       /* Create the GNU bitmap and mask if necessary.  */
  3179       if (FRAME_DISPLAY_INFO (f)->icon_bitmap_id < 0)
  3180         {
  3181           ptrdiff_t rc = -1;
  3182 
  3183           if (xg_set_icon (f, xg_default_icon_file)
  3184               || xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
  3185             {
  3186               FRAME_DISPLAY_INFO (f)->icon_bitmap_id = -2;
  3187               return false;
  3188             }
  3189 
  3190           /* If all else fails, use the (black and white) xbm image. */
  3191           if (rc == -1)
  3192             {
  3193               rc = image_create_bitmap_from_data (f,
  3194                                                   (char *) gnu_xbm_bits,
  3195                                                   gnu_xbm_width,
  3196                                                   gnu_xbm_height);
  3197               if (rc == -1)
  3198                 return true;
  3199 
  3200               FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc;
  3201             }
  3202         }
  3203 
  3204       /* The first time we create the GNU bitmap and mask,
  3205          this increments the ref-count one extra time.
  3206          As a result, the GNU bitmap and mask are never freed.
  3207          That way, we don't have to worry about allocating it again.  */
  3208       image_reference_bitmap (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id);
  3209 
  3210       bitmap_id = FRAME_DISPLAY_INFO (f)->icon_bitmap_id;
  3211     }
  3212 
  3213   if (FRAME_DISPLAY_INFO (f)->bitmaps[bitmap_id - 1].img != NULL)
  3214     gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
  3215                          FRAME_DISPLAY_INFO (f)->bitmaps[bitmap_id - 1].img);
  3216 
  3217   f->output_data.pgtk->icon_bitmap = bitmap_id;
  3218 
  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                        width, flash_height);
  3774       cairo_fill (cr);
  3775     }
  3776   else
  3777     {
  3778       /* If it is short, flash it all.  */
  3779       cairo_rectangle (cr,
  3780                        flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
  3781                        width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
  3782       cairo_fill (cr);
  3783     }
  3784 
  3785   FRAME_X_OUTPUT (f)->cr_surface_visible_bell = surface;
  3786 
  3787   delay = make_timespec (0, 50 * 1000 * 1000);
  3788 
  3789   if (FRAME_X_OUTPUT (f)->atimer_visible_bell != NULL)
  3790     {
  3791       cancel_atimer (FRAME_X_OUTPUT (f)->atimer_visible_bell);
  3792       FRAME_X_OUTPUT (f)->atimer_visible_bell = NULL;
  3793     }
  3794 
  3795   FRAME_X_OUTPUT (f)->atimer_visible_bell
  3796     = start_atimer (ATIMER_RELATIVE, delay, recover_from_visible_bell, f);
  3797 
  3798 
  3799   cairo_destroy (cr);
  3800   unblock_input ();
  3801 }
  3802 
  3803 /* Make audible bell.  */
  3804 
  3805 static void
  3806 pgtk_ring_bell (struct frame *f)
  3807 {
  3808   if (visible_bell)
  3809     {
  3810       pgtk_flash (f);
  3811     }
  3812   else
  3813     {
  3814       block_input ();
  3815       gtk_widget_error_bell (FRAME_GTK_WIDGET (f));
  3816       unblock_input ();
  3817     }
  3818 }
  3819 
  3820 /* Read events coming from the X server.
  3821    Return as soon as there are no more events to be read.
  3822 
  3823    Return the number of characters stored into the buffer,
  3824    thus pretending to be `read' (except the characters we store
  3825    in the keyboard buffer can be multibyte, so are not necessarily
  3826    C chars).  */
  3827 
  3828 static int
  3829 pgtk_read_socket (struct terminal *terminal, struct input_event *hold_quit)
  3830 {
  3831   GMainContext *context;
  3832   bool context_acquired = false;
  3833   int count;
  3834 
  3835   count = evq_flush (hold_quit);
  3836   if (count > 0)
  3837     {
  3838       return count;
  3839     }
  3840 
  3841   context = g_main_context_default ();
  3842   context_acquired = g_main_context_acquire (context);
  3843 
  3844   block_input ();
  3845 
  3846   if (context_acquired)
  3847     {
  3848       while (g_main_context_pending (context))
  3849         {
  3850           g_main_context_dispatch (context);
  3851         }
  3852     }
  3853 
  3854   unblock_input ();
  3855 
  3856   if (context_acquired)
  3857     g_main_context_release (context);
  3858 
  3859   count = evq_flush (hold_quit);
  3860   if (count > 0)
  3861     {
  3862       return count;
  3863     }
  3864 
  3865   return 0;
  3866 }
  3867 
  3868 /* Lisp window being scrolled.  Set when starting to interact with
  3869    a toolkit scroll bar, reset to nil when ending the interaction.  */
  3870 
  3871 static Lisp_Object window_being_scrolled;
  3872 
  3873 static void
  3874 pgtk_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
  3875                             int portion, int whole, bool horizontal)
  3876 {
  3877   union buffered_input_event inev;
  3878 
  3879   EVENT_INIT (inev.ie);
  3880 
  3881   inev.ie.kind = (horizontal
  3882                   ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
  3883                   : SCROLL_BAR_CLICK_EVENT);
  3884   inev.ie.frame_or_window = window;
  3885   inev.ie.arg = Qnil;
  3886   inev.ie.timestamp = 0;
  3887   inev.ie.code = 0;
  3888   inev.ie.part = part;
  3889   inev.ie.x = make_fixnum (portion);
  3890   inev.ie.y = make_fixnum (whole);
  3891   inev.ie.modifiers = 0;
  3892 
  3893   evq_enqueue (&inev);
  3894 }
  3895 
  3896 
  3897 /* Scroll bar callback for GTK scroll bars.  WIDGET is the scroll
  3898    bar widget.  DATA is a pointer to the scroll_bar structure. */
  3899 
  3900 static gboolean
  3901 xg_scroll_callback (GtkRange * range,
  3902                     GtkScrollType scroll, gdouble value, gpointer user_data)
  3903 {
  3904   int whole = 0, portion = 0;
  3905   struct scroll_bar *bar = user_data;
  3906   enum scroll_bar_part part = scroll_bar_nowhere;
  3907   GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range));
  3908 
  3909   if (xg_ignore_gtk_scrollbar)
  3910     return false;
  3911 
  3912   switch (scroll)
  3913     {
  3914     case GTK_SCROLL_JUMP:
  3915       if (bar->horizontal)
  3916         {
  3917           part = scroll_bar_horizontal_handle;
  3918           whole = (int) (gtk_adjustment_get_upper (adj) -
  3919                          gtk_adjustment_get_page_size (adj));
  3920           portion = min ((int) value, whole);
  3921           bar->dragging = portion;
  3922         }
  3923       else
  3924         {
  3925           part = scroll_bar_handle;
  3926           whole = gtk_adjustment_get_upper (adj) -
  3927             gtk_adjustment_get_page_size (adj);
  3928           portion = min ((int) value, whole);
  3929           bar->dragging = portion;
  3930         }
  3931       break;
  3932     case GTK_SCROLL_STEP_BACKWARD:
  3933       part = (bar->horizontal ? scroll_bar_left_arrow : scroll_bar_up_arrow);
  3934       bar->dragging = -1;
  3935       break;
  3936     case GTK_SCROLL_STEP_FORWARD:
  3937       part = (bar->horizontal
  3938               ? scroll_bar_right_arrow : scroll_bar_down_arrow);
  3939       bar->dragging = -1;
  3940       break;
  3941     case GTK_SCROLL_PAGE_BACKWARD:
  3942       part = (bar->horizontal
  3943               ? scroll_bar_before_handle : scroll_bar_above_handle);
  3944       bar->dragging = -1;
  3945       break;
  3946     case GTK_SCROLL_PAGE_FORWARD:
  3947       part = (bar->horizontal
  3948               ? scroll_bar_after_handle : scroll_bar_below_handle);
  3949       bar->dragging = -1;
  3950       break;
  3951     default:
  3952       break;
  3953     }
  3954 
  3955   if (part != scroll_bar_nowhere)
  3956     {
  3957       window_being_scrolled = bar->window;
  3958       pgtk_send_scroll_bar_event (bar->window, part, portion, whole,
  3959                                   bar->horizontal);
  3960     }
  3961 
  3962   return false;
  3963 }
  3964 
  3965 /* Callback for button release. Sets dragging to -1 when dragging is done.  */
  3966 
  3967 static gboolean
  3968 xg_end_scroll_callback (GtkWidget * widget,
  3969                         GdkEventButton * event, gpointer user_data)
  3970 {
  3971   struct scroll_bar *bar = user_data;
  3972   bar->dragging = -1;
  3973   if (WINDOWP (window_being_scrolled))
  3974     {
  3975       pgtk_send_scroll_bar_event (window_being_scrolled,
  3976                                   scroll_bar_end_scroll, 0, 0,
  3977                                   bar->horizontal);
  3978       window_being_scrolled = Qnil;
  3979     }
  3980 
  3981   return false;
  3982 }
  3983 
  3984 #define SCROLL_BAR_NAME "verticalScrollBar"
  3985 #define SCROLL_BAR_HORIZONTAL_NAME "horizontalScrollBar"
  3986 
  3987 /* Create the widget for scroll bar BAR on frame F.  Record the widget
  3988    and X window of the scroll bar in BAR.  */
  3989 
  3990 static void
  3991 pgtk_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar)
  3992 {
  3993   const char *scroll_bar_name = SCROLL_BAR_NAME;
  3994 
  3995   block_input ();
  3996   xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
  3997                         G_CALLBACK (xg_end_scroll_callback), scroll_bar_name);
  3998   unblock_input ();
  3999 }
  4000 
  4001 static void
  4002 pgtk_create_horizontal_toolkit_scroll_bar (struct frame *f,
  4003                                            struct scroll_bar *bar)
  4004 {
  4005   const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME;
  4006 
  4007   block_input ();
  4008   xg_create_horizontal_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
  4009                                    G_CALLBACK (xg_end_scroll_callback),
  4010                                    scroll_bar_name);
  4011   unblock_input ();
  4012 }
  4013 
  4014 /* Set the thumb size and position of scroll bar BAR.  We are currently
  4015    displaying PORTION out of a whole WHOLE, and our position POSITION.  */
  4016 
  4017 static void
  4018 pgtk_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion,
  4019                                    int position, int whole)
  4020 {
  4021   xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
  4022 }
  4023 
  4024 static void
  4025 pgtk_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar,
  4026                                               int portion, int position,
  4027                                               int whole)
  4028 {
  4029   xg_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
  4030 }
  4031 
  4032 /* Create a scroll bar and return the scroll bar vector for it.  W is
  4033    the Emacs window on which to create the scroll bar. TOP, LEFT,
  4034    WIDTH and HEIGHT are the pixel coordinates and dimensions of the
  4035    scroll bar. */
  4036 
  4037 static struct scroll_bar *
  4038 pgtk_scroll_bar_create (struct window *w, int top, int left,
  4039                         int width, int height, bool horizontal)
  4040 {
  4041   struct frame *f = XFRAME (w->frame);
  4042   struct scroll_bar *bar
  4043     = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev, PVEC_OTHER);
  4044   Lisp_Object barobj;
  4045 
  4046   block_input ();
  4047 
  4048   if (horizontal)
  4049     pgtk_create_horizontal_toolkit_scroll_bar (f, bar);
  4050   else
  4051     pgtk_create_toolkit_scroll_bar (f, bar);
  4052 
  4053   XSETWINDOW (bar->window, w);
  4054   bar->top = top;
  4055   bar->left = left;
  4056   bar->width = width;
  4057   bar->height = height;
  4058   bar->start = 0;
  4059   bar->end = 0;
  4060   bar->dragging = -1;
  4061   bar->horizontal = horizontal;
  4062 
  4063   /* Add bar to its frame's list of scroll bars.  */
  4064   bar->next = FRAME_SCROLL_BARS (f);
  4065   bar->prev = Qnil;
  4066   XSETVECTOR (barobj, bar);
  4067   fset_scroll_bars (f, barobj);
  4068   if (!NILP (bar->next))
  4069     XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
  4070 
  4071   /* Map the window/widget.  */
  4072   {
  4073     if (horizontal)
  4074       xg_update_horizontal_scrollbar_pos (f, bar->x_window, top,
  4075                                           left, width, max (height, 1));
  4076     else
  4077       xg_update_scrollbar_pos (f, bar->x_window, top,
  4078                                left, width, max (height, 1));
  4079   }
  4080 
  4081   unblock_input ();
  4082   return bar;
  4083 }
  4084 
  4085 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
  4086    nil.  */
  4087 
  4088 static void
  4089 pgtk_scroll_bar_remove (struct scroll_bar *bar)
  4090 {
  4091   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
  4092   block_input ();
  4093 
  4094   xg_remove_scroll_bar (f, bar->x_window);
  4095 
  4096   /* Dissociate this scroll bar from its window.  */
  4097   if (bar->horizontal)
  4098     wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil);
  4099   else
  4100     wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil);
  4101 
  4102   unblock_input ();
  4103 }
  4104 
  4105 /* Set the handle of the vertical scroll bar for WINDOW to indicate
  4106    that we are displaying PORTION characters out of a total of WHOLE
  4107    characters, starting at POSITION.  If WINDOW has no scroll bar,
  4108    create one.  */
  4109 
  4110 static void
  4111 pgtk_set_vertical_scroll_bar (struct window *w, int portion, int whole,
  4112                               int position)
  4113 {
  4114   struct frame *f = XFRAME (w->frame);
  4115   Lisp_Object barobj;
  4116   struct scroll_bar *bar;
  4117   int top, height, left, width;
  4118   int window_y, window_height;
  4119 
  4120   /* Get window dimensions.  */
  4121   window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
  4122   top = window_y;
  4123   height = window_height;
  4124   left = WINDOW_SCROLL_BAR_AREA_X (w);
  4125   width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
  4126 
  4127   /* Does the scroll bar exist yet?  */
  4128   if (NILP (w->vertical_scroll_bar))
  4129     {
  4130       if (width > 0 && height > 0)
  4131         {
  4132           block_input ();
  4133           pgtk_clear_area (f, left, top, width, height);
  4134           unblock_input ();
  4135         }
  4136 
  4137       bar = pgtk_scroll_bar_create (w, top, left, width, max (height, 1), false);
  4138     }
  4139   else
  4140     {
  4141       /* It may just need to be moved and resized.  */
  4142       unsigned int mask = 0;
  4143 
  4144       bar = XSCROLL_BAR (w->vertical_scroll_bar);
  4145 
  4146       block_input ();
  4147 
  4148       if (left != bar->left)
  4149         mask |= 1;
  4150       if (top != bar->top)
  4151         mask |= 1;
  4152       if (width != bar->width)
  4153         mask |= 1;
  4154       if (height != bar->height)
  4155         mask |= 1;
  4156 
  4157       /* Move/size the scroll bar widget.  */
  4158       if (mask)
  4159         {
  4160           /* Since toolkit scroll bars are smaller than the space reserved
  4161              for them on the frame, we have to clear "under" them.  */
  4162           if (width > 0 && height > 0)
  4163             pgtk_clear_area (f, left, top, width, height);
  4164           xg_update_scrollbar_pos (f, bar->x_window, top,
  4165                                    left, width, max (height, 1));
  4166         }
  4167 
  4168       /* Remember new settings.  */
  4169       bar->left = left;
  4170       bar->top = top;
  4171       bar->width = width;
  4172       bar->height = height;
  4173 
  4174       unblock_input ();
  4175     }
  4176 
  4177   pgtk_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
  4178 
  4179   XSETVECTOR (barobj, bar);
  4180   wset_vertical_scroll_bar (w, barobj);
  4181 }
  4182 
  4183 static void
  4184 pgtk_set_horizontal_scroll_bar (struct window *w, int portion, int whole,
  4185                                 int position)
  4186 {
  4187   struct frame *f = XFRAME (w->frame);
  4188   Lisp_Object barobj;
  4189   struct scroll_bar *bar;
  4190   int top, height, left, width;
  4191   int window_x, window_width;
  4192   int pixel_width = WINDOW_PIXEL_WIDTH (w);
  4193 
  4194   /* Get window dimensions.  */
  4195   window_box (w, ANY_AREA, &window_x, 0, &window_width, 0);
  4196   left = window_x;
  4197   width = window_width;
  4198   top = WINDOW_SCROLL_BAR_AREA_Y (w);
  4199   height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
  4200 
  4201   /* Does the scroll bar exist yet?  */
  4202   if (NILP (w->horizontal_scroll_bar))
  4203     {
  4204       if (width > 0 && height > 0)
  4205         {
  4206           block_input ();
  4207 
  4208           /* Clear also part between window_width and
  4209              WINDOW_PIXEL_WIDTH.  */
  4210           pgtk_clear_area (f, left, top, pixel_width, height);
  4211           unblock_input ();
  4212         }
  4213 
  4214       bar = pgtk_scroll_bar_create (w, top, left, width, height, true);
  4215     }
  4216   else
  4217     {
  4218       /* It may just need to be moved and resized.  */
  4219       unsigned int mask = 0;
  4220 
  4221       bar = XSCROLL_BAR (w->horizontal_scroll_bar);
  4222 
  4223       block_input ();
  4224 
  4225       if (left != bar->left)
  4226         mask |= 1;
  4227       if (top != bar->top)
  4228         mask |= 1;
  4229       if (width != bar->width)
  4230         mask |= 1;
  4231       if (height != bar->height)
  4232         mask |= 1;
  4233 
  4234       /* Move/size the scroll bar widget.  */
  4235       if (mask)
  4236         {
  4237           /* Since toolkit scroll bars are smaller than the space reserved
  4238              for them on the frame, we have to clear "under" them.  */
  4239           if (width > 0 && height > 0)
  4240             pgtk_clear_area (f,
  4241                              WINDOW_LEFT_EDGE_X (w), top,
  4242                              pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w),
  4243                              height);
  4244           xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, left,
  4245                                               width, height);
  4246         }
  4247 
  4248       /* Remember new settings.  */
  4249       bar->left = left;
  4250       bar->top = top;
  4251       bar->width = width;
  4252       bar->height = height;
  4253 
  4254       unblock_input ();
  4255     }
  4256 
  4257   pgtk_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole);
  4258 
  4259   XSETVECTOR (barobj, bar);
  4260   wset_horizontal_scroll_bar (w, barobj);
  4261 }
  4262 
  4263 /* The following three hooks are used when we're doing a thorough
  4264    redisplay of the frame.  We don't explicitly know which scroll bars
  4265    are going to be deleted, because keeping track of when windows go
  4266    away is a real pain - "Can you say set-window-configuration, boys
  4267    and girls?"  Instead, we just assert at the beginning of redisplay
  4268    that *all* scroll bars are to be removed, and then save a scroll bar
  4269    from the fiery pit when we actually redisplay its window.  */
  4270 
  4271 /* Arrange for all scroll bars on FRAME to be removed at the next call
  4272    to `*judge_scroll_bars_hook'.  A scroll bar may be spared if
  4273    `*redeem_scroll_bar_hook' is applied to its window before the judgment.  */
  4274 
  4275 static void
  4276 pgtk_condemn_scroll_bars (struct frame *frame)
  4277 {
  4278   if (!NILP (FRAME_SCROLL_BARS (frame)))
  4279     {
  4280       if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
  4281         {
  4282           /* Prepend scrollbars to already condemned ones.  */
  4283           Lisp_Object last = FRAME_SCROLL_BARS (frame);
  4284 
  4285           while (!NILP (XSCROLL_BAR (last)->next))
  4286             last = XSCROLL_BAR (last)->next;
  4287 
  4288           XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
  4289           XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last;
  4290         }
  4291 
  4292       fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame));
  4293       fset_scroll_bars (frame, Qnil);
  4294     }
  4295 }
  4296 
  4297 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
  4298    Note that WINDOW isn't necessarily condemned at all.  */
  4299 
  4300 static void
  4301 pgtk_redeem_scroll_bar (struct window *w)
  4302 {
  4303   struct scroll_bar *bar;
  4304   Lisp_Object barobj;
  4305   struct frame *f;
  4306 
  4307   /* We can't redeem this window's scroll bar if it doesn't have one.  */
  4308   if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar))
  4309     emacs_abort ();
  4310 
  4311   if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
  4312     {
  4313       bar = XSCROLL_BAR (w->vertical_scroll_bar);
  4314       /* Unlink it from the condemned list.  */
  4315       f = XFRAME (WINDOW_FRAME (w));
  4316       if (NILP (bar->prev))
  4317         {
  4318           /* If the prev pointer is nil, it must be the first in one of
  4319              the lists.  */
  4320           if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar))
  4321             /* It's not condemned.  Everything's fine.  */
  4322             goto horizontal;
  4323           else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
  4324                        w->vertical_scroll_bar))
  4325             fset_condemned_scroll_bars (f, bar->next);
  4326           else
  4327             /* If its prev pointer is nil, it must be at the front of
  4328                one or the other!  */
  4329             emacs_abort ();
  4330         }
  4331       else
  4332         XSCROLL_BAR (bar->prev)->next = bar->next;
  4333 
  4334       if (!NILP (bar->next))
  4335         XSCROLL_BAR (bar->next)->prev = bar->prev;
  4336 
  4337       bar->next = FRAME_SCROLL_BARS (f);
  4338       bar->prev = Qnil;
  4339       XSETVECTOR (barobj, bar);
  4340       fset_scroll_bars (f, barobj);
  4341       if (!NILP (bar->next))
  4342         XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
  4343     }
  4344 
  4345 horizontal:
  4346   if (!NILP (w->horizontal_scroll_bar)
  4347       && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
  4348     {
  4349       bar = XSCROLL_BAR (w->horizontal_scroll_bar);
  4350       /* Unlink it from the condemned list.  */
  4351       f = XFRAME (WINDOW_FRAME (w));
  4352       if (NILP (bar->prev))
  4353         {
  4354           /* If the prev pointer is nil, it must be the first in one of
  4355              the lists.  */
  4356           if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar))
  4357             /* It's not condemned.  Everything's fine.  */
  4358             return;
  4359           else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
  4360                        w->horizontal_scroll_bar))
  4361             fset_condemned_scroll_bars (f, bar->next);
  4362           else
  4363             /* If its prev pointer is nil, it must be at the front of
  4364                one or the other!  */
  4365             emacs_abort ();
  4366         }
  4367       else
  4368         XSCROLL_BAR (bar->prev)->next = bar->next;
  4369 
  4370       if (!NILP (bar->next))
  4371         XSCROLL_BAR (bar->next)->prev = bar->prev;
  4372 
  4373       bar->next = FRAME_SCROLL_BARS (f);
  4374       bar->prev = Qnil;
  4375       XSETVECTOR (barobj, bar);
  4376       fset_scroll_bars (f, barobj);
  4377       if (!NILP (bar->next))
  4378         XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
  4379     }
  4380 }
  4381 
  4382 /* Remove all scroll bars on FRAME that haven't been saved since the
  4383    last call to `*condemn_scroll_bars_hook'.  */
  4384 
  4385 static void
  4386 pgtk_judge_scroll_bars (struct frame *f)
  4387 {
  4388   Lisp_Object bar, next;
  4389 
  4390   bar = FRAME_CONDEMNED_SCROLL_BARS (f);
  4391 
  4392   /* Clear out the condemned list now so we won't try to process any
  4393      more events on the hapless scroll bars.  */
  4394   fset_condemned_scroll_bars (f, Qnil);
  4395 
  4396   for (; !NILP (bar); bar = next)
  4397     {
  4398       struct scroll_bar *b = XSCROLL_BAR (bar);
  4399 
  4400       pgtk_scroll_bar_remove (b);
  4401 
  4402       next = b->next;
  4403       b->next = b->prev = Qnil;
  4404     }
  4405 
  4406   /* Now there should be no references to the condemned scroll bars,
  4407      and they should get garbage-collected.  */
  4408 }
  4409 
  4410 static void
  4411 set_fullscreen_state (struct frame *f)
  4412 {
  4413   if (!FRAME_GTK_OUTER_WIDGET (f))
  4414     return;
  4415 
  4416   GtkWindow *widget = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
  4417   switch (f->want_fullscreen)
  4418     {
  4419     case FULLSCREEN_NONE:
  4420       gtk_window_unfullscreen (widget);
  4421       gtk_window_unmaximize (widget);
  4422       store_frame_param (f, Qfullscreen, Qnil);
  4423       break;
  4424 
  4425     case FULLSCREEN_BOTH:
  4426       gtk_window_unmaximize (widget);
  4427       gtk_window_fullscreen (widget);
  4428       store_frame_param (f, Qfullscreen, Qfullboth);
  4429       break;
  4430 
  4431     case FULLSCREEN_MAXIMIZED:
  4432       gtk_window_unfullscreen (widget);
  4433       gtk_window_maximize (widget);
  4434       store_frame_param (f, Qfullscreen, Qmaximized);
  4435       break;
  4436 
  4437     case FULLSCREEN_WIDTH:
  4438     case FULLSCREEN_HEIGHT:
  4439       /* Not supported by gtk. Ignore them. */
  4440       break;
  4441     }
  4442 
  4443   f->want_fullscreen = FULLSCREEN_NONE;
  4444 }
  4445 
  4446 static void
  4447 pgtk_fullscreen_hook (struct frame *f)
  4448 {
  4449   if (FRAME_VISIBLE_P (f))
  4450     {
  4451       block_input ();
  4452       set_fullscreen_state (f);
  4453       unblock_input ();
  4454     }
  4455 }
  4456 
  4457 /* This function is called when the last frame on a display is deleted. */
  4458 void
  4459 pgtk_delete_terminal (struct terminal *terminal)
  4460 {
  4461   struct pgtk_display_info *dpyinfo = terminal->display_info.pgtk;
  4462 
  4463   /* Protect against recursive calls.  delete_frame in
  4464      delete_terminal calls us back when it deletes our last frame.  */
  4465   if (!terminal->name)
  4466     return;
  4467 
  4468   block_input ();
  4469 
  4470   pgtk_im_finish (dpyinfo);
  4471 
  4472   /* Normally, the display is available...  */
  4473   if (dpyinfo->gdpy)
  4474     {
  4475       image_destroy_all_bitmaps (dpyinfo);
  4476 
  4477       g_clear_object (&dpyinfo->xg_cursor);
  4478       g_clear_object (&dpyinfo->vertical_scroll_bar_cursor);
  4479       g_clear_object (&dpyinfo->horizontal_scroll_bar_cursor);
  4480       g_clear_object (&dpyinfo->invisible_cursor);
  4481       if (dpyinfo->last_click_event != NULL)
  4482         {
  4483           gdk_event_free (dpyinfo->last_click_event);
  4484           dpyinfo->last_click_event = NULL;
  4485         }
  4486 
  4487       /* Disconnect these handlers before the display closes so
  4488          useless removal signals don't fire.  */
  4489       g_signal_handlers_disconnect_by_func (G_OBJECT (dpyinfo->gdpy),
  4490                                             G_CALLBACK (pgtk_seat_added_cb),
  4491                                             dpyinfo);
  4492       g_signal_handlers_disconnect_by_func (G_OBJECT (dpyinfo->gdpy),
  4493                                             G_CALLBACK (pgtk_seat_removed_cb),
  4494                                             dpyinfo);
  4495       xg_display_close (dpyinfo->gdpy);
  4496 
  4497       dpyinfo->gdpy = NULL;
  4498     }
  4499 
  4500   if (dpyinfo->connection >= 0)
  4501     emacs_close (dpyinfo->connection);
  4502 
  4503   dpyinfo->connection = -1;
  4504 
  4505   delete_keyboard_wait_descriptor (0);
  4506 
  4507   pgtk_delete_display (dpyinfo);
  4508   unblock_input ();
  4509 }
  4510 
  4511 /* Store F's background color into *BGCOLOR.  */
  4512 static void
  4513 pgtk_query_frame_background_color (struct frame *f, Emacs_Color * bgcolor)
  4514 {
  4515   bgcolor->pixel = FRAME_BACKGROUND_PIXEL (f);
  4516   pgtk_query_color (f, bgcolor);
  4517 }
  4518 
  4519 static void
  4520 pgtk_free_pixmap (struct frame *f, Emacs_Pixmap pixmap)
  4521 {
  4522   if (pixmap)
  4523     {
  4524       xfree (pixmap->data);
  4525       xfree (pixmap);
  4526     }
  4527 }
  4528 
  4529 void
  4530 pgtk_focus_frame (struct frame *f, bool noactivate)
  4531 {
  4532   struct pgtk_display_info *dpyinfo;
  4533   GtkWidget *widget;
  4534   GtkWindow *window;
  4535 
  4536   dpyinfo = FRAME_DISPLAY_INFO (f);
  4537 
  4538   if (FRAME_GTK_OUTER_WIDGET (f) && !noactivate)
  4539     {
  4540       /* The user says it is okay to activate the frame.  Call
  4541          gtk_window_present_with_time.  If the timestamp specified
  4542          (actually a display serial on Wayland) is new enough, then
  4543          any Wayland compositor supporting gtk_surface1_present will
  4544          cause the frame to be activated.  */
  4545 
  4546       window = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
  4547       gtk_window_present_with_time (window, dpyinfo->last_user_time);
  4548       return;
  4549     }
  4550 
  4551   widget = FRAME_WIDGET (f);
  4552 
  4553   if (widget)
  4554     gtk_widget_grab_focus (widget);
  4555 }
  4556 
  4557 static void
  4558 set_opacity_recursively (GtkWidget *w, gpointer data)
  4559 {
  4560   gtk_widget_set_opacity (w, *(double *) data);
  4561 
  4562   if (GTK_IS_CONTAINER (w))
  4563     gtk_container_foreach (GTK_CONTAINER (w),
  4564                            set_opacity_recursively, data);
  4565 }
  4566 
  4567 static void
  4568 pgtk_set_frame_alpha (struct frame *f)
  4569 {
  4570   struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
  4571   double alpha = 1.0;
  4572   double alpha_min = 1.0;
  4573 
  4574   if (dpyinfo->highlight_frame == f)
  4575     alpha = f->alpha[0];
  4576   else
  4577     alpha = f->alpha[1];
  4578 
  4579   if (alpha < 0.0)
  4580     return;
  4581 
  4582   if (FLOATP (Vframe_alpha_lower_limit))
  4583     alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
  4584   else if (FIXNUMP (Vframe_alpha_lower_limit))
  4585     alpha_min = (XFIXNUM (Vframe_alpha_lower_limit)) / 100.0;
  4586 
  4587   if (alpha > 1.0)
  4588     alpha = 1.0;
  4589   else if (alpha < alpha_min && alpha_min <= 1.0)
  4590     alpha = alpha_min;
  4591 
  4592   set_opacity_recursively (FRAME_WIDGET (f), &alpha);
  4593   /* without this, blending mode is strange on wayland. */
  4594   gtk_widget_queue_resize_no_redraw (FRAME_WIDGET (f));
  4595 }
  4596 
  4597 static void
  4598 frame_highlight (struct frame *f)
  4599 {
  4600   block_input ();
  4601   GtkWidget *w = FRAME_WIDGET (f);
  4602 
  4603   char *css = g_strdup_printf ("decoration { border: solid %dpx #%06x; }",
  4604                                f->border_width,
  4605                                ((unsigned int) FRAME_X_OUTPUT (f)->border_pixel
  4606                                 & 0x00ffffff));
  4607 
  4608   GtkStyleContext *ctxt = gtk_widget_get_style_context (w);
  4609   GtkCssProvider *css_provider = gtk_css_provider_new ();
  4610   gtk_css_provider_load_from_data (css_provider, css, -1, NULL);
  4611   gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (css_provider),
  4612                                   GTK_STYLE_PROVIDER_PRIORITY_USER);
  4613   g_free (css);
  4614 
  4615   GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider;
  4616   FRAME_X_OUTPUT (f)->border_color_css_provider = css_provider;
  4617   if (old != NULL)
  4618     {
  4619       gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old));
  4620       g_object_unref (old);
  4621     }
  4622 
  4623   unblock_input ();
  4624   gui_update_cursor (f, true);
  4625   pgtk_set_frame_alpha (f);
  4626 }
  4627 
  4628 static void
  4629 frame_unhighlight (struct frame *f)
  4630 {
  4631   GtkWidget *w;
  4632   char *css;
  4633   GtkStyleContext *ctxt;
  4634   GtkCssProvider *css_provider, *old;
  4635 
  4636   block_input ();
  4637 
  4638   w = FRAME_WIDGET (f);
  4639 
  4640   css = g_strdup_printf ("decoration { border: dotted %dpx #ffffff; }",
  4641                          f->border_width);
  4642 
  4643   ctxt = gtk_widget_get_style_context (w);
  4644   css_provider = gtk_css_provider_new ();
  4645   gtk_css_provider_load_from_data (css_provider, css, -1, NULL);
  4646   gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (css_provider),
  4647                                   GTK_STYLE_PROVIDER_PRIORITY_USER);
  4648   g_free (css);
  4649 
  4650   old = FRAME_X_OUTPUT (f)->border_color_css_provider;
  4651   FRAME_X_OUTPUT (f)->border_color_css_provider = css_provider;
  4652   if (old != NULL)
  4653     {
  4654       gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old));
  4655       g_object_unref (old);
  4656     }
  4657 
  4658   unblock_input ();
  4659   gui_update_cursor (f, true);
  4660   pgtk_set_frame_alpha (f);
  4661 }
  4662 
  4663 
  4664 void
  4665 pgtk_frame_rehighlight (struct pgtk_display_info *dpyinfo)
  4666 {
  4667   struct frame *old_highlight = dpyinfo->highlight_frame;
  4668 
  4669   if (dpyinfo->x_focus_frame)
  4670     {
  4671       dpyinfo->highlight_frame
  4672         = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
  4673            ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
  4674            : dpyinfo->x_focus_frame);
  4675       if (!FRAME_LIVE_P (dpyinfo->highlight_frame))
  4676         {
  4677           fset_focus_frame (dpyinfo->x_focus_frame, Qnil);
  4678           dpyinfo->highlight_frame = dpyinfo->x_focus_frame;
  4679         }
  4680     }
  4681   else
  4682     dpyinfo->highlight_frame = 0;
  4683 
  4684   if (old_highlight)
  4685     frame_unhighlight (old_highlight);
  4686   if (dpyinfo->highlight_frame)
  4687     frame_highlight (dpyinfo->highlight_frame);
  4688 }
  4689 
  4690 /* The focus has changed, or we have redirected a frame's focus to
  4691    another frame (this happens when a frame uses a surrogate
  4692    mini-buffer frame).  Shift the highlight as appropriate.
  4693 
  4694    The FRAME argument doesn't necessarily have anything to do with which
  4695    frame is being highlighted or un-highlighted; we only use it to find
  4696    the appropriate X display info.  */
  4697 
  4698 static void
  4699 pgtk_frame_rehighlight_hook (struct frame *frame)
  4700 {
  4701   pgtk_frame_rehighlight (FRAME_DISPLAY_INFO (frame));
  4702 }
  4703 
  4704 /* Set whether or not the mouse pointer should be visible on frame
  4705    F.  */
  4706 static void
  4707 pgtk_toggle_invisible_pointer (struct frame *f, bool invisible)
  4708 {
  4709   Emacs_Cursor cursor;
  4710   if (invisible)
  4711     cursor = FRAME_DISPLAY_INFO (f)->invisible_cursor;
  4712   else
  4713     cursor = f->output_data.pgtk->current_cursor;
  4714   gdk_window_set_cursor (gtk_widget_get_window (FRAME_GTK_WIDGET (f)),
  4715                          cursor);
  4716   f->pointer_invisible = invisible;
  4717 
  4718   /* This is needed to make the pointer visible upon receiving a
  4719      motion notify event.  */
  4720   gdk_display_flush (FRAME_X_DISPLAY (f));
  4721 }
  4722 
  4723 /* The focus has changed.  Update the frames as necessary to reflect
  4724    the new situation.  Note that we can't change the selected frame
  4725    here, because the Lisp code we are interrupting might become confused.
  4726    Each event gets marked with the frame in which it occurred, so the
  4727    Lisp code can tell when the switch took place by examining the events.  */
  4728 
  4729 static void
  4730 pgtk_new_focus_frame (struct pgtk_display_info *dpyinfo, struct frame *frame)
  4731 {
  4732   struct frame *old_focus = dpyinfo->x_focus_frame;
  4733   /* doesn't work on wayland */
  4734 
  4735   if (frame != dpyinfo->x_focus_frame)
  4736     {
  4737       /* Set this before calling other routines, so that they see
  4738          the correct value of x_focus_frame.  */
  4739       dpyinfo->x_focus_frame = frame;
  4740 
  4741       if (old_focus && old_focus->auto_lower)
  4742         if (FRAME_GTK_OUTER_WIDGET (old_focus))
  4743           gdk_window_lower (gtk_widget_get_window
  4744                             (FRAME_GTK_OUTER_WIDGET (old_focus)));
  4745 
  4746       if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
  4747         if (FRAME_GTK_OUTER_WIDGET (dpyinfo->x_focus_frame))
  4748           gdk_window_raise (gtk_widget_get_window
  4749                             (FRAME_GTK_OUTER_WIDGET (dpyinfo->x_focus_frame)));
  4750     }
  4751 
  4752   pgtk_frame_rehighlight (dpyinfo);
  4753 }
  4754 
  4755 static void
  4756 pgtk_buffer_flipping_unblocked_hook (struct frame *f)
  4757 {
  4758   block_input ();
  4759   flip_cr_context (f);
  4760   gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
  4761   unblock_input ();
  4762 }
  4763 
  4764 static struct terminal *
  4765 pgtk_create_terminal (struct pgtk_display_info *dpyinfo)
  4766 {
  4767   struct terminal *terminal;
  4768 
  4769   terminal = create_terminal (output_pgtk, &pgtk_redisplay_interface);
  4770 
  4771   terminal->display_info.pgtk = dpyinfo;
  4772   dpyinfo->terminal = terminal;
  4773 
  4774   terminal->clear_frame_hook = pgtk_clear_frame;
  4775   terminal->ring_bell_hook = pgtk_ring_bell;
  4776   terminal->toggle_invisible_pointer_hook = pgtk_toggle_invisible_pointer;
  4777   terminal->update_begin_hook = pgtk_update_begin;
  4778   terminal->update_end_hook = pgtk_update_end;
  4779   terminal->read_socket_hook = pgtk_read_socket;
  4780   terminal->frame_up_to_date_hook = pgtk_frame_up_to_date;
  4781   terminal->mouse_position_hook = pgtk_mouse_position;
  4782   terminal->frame_rehighlight_hook = pgtk_frame_rehighlight_hook;
  4783   terminal->buffer_flipping_unblocked_hook = pgtk_buffer_flipping_unblocked_hook;
  4784   terminal->frame_raise_lower_hook = pgtk_frame_raise_lower;
  4785   terminal->frame_visible_invisible_hook = pgtk_make_frame_visible_invisible;
  4786   terminal->fullscreen_hook = pgtk_fullscreen_hook;
  4787   terminal->menu_show_hook = pgtk_menu_show;
  4788   terminal->activate_menubar_hook = pgtk_activate_menubar;
  4789   terminal->popup_dialog_hook = pgtk_popup_dialog;
  4790   terminal->change_tab_bar_height_hook = pgtk_change_tab_bar_height;
  4791   terminal->set_vertical_scroll_bar_hook = pgtk_set_vertical_scroll_bar;
  4792   terminal->set_horizontal_scroll_bar_hook = pgtk_set_horizontal_scroll_bar;
  4793   terminal->condemn_scroll_bars_hook = pgtk_condemn_scroll_bars;
  4794   terminal->redeem_scroll_bar_hook = pgtk_redeem_scroll_bar;
  4795   terminal->judge_scroll_bars_hook = pgtk_judge_scroll_bars;
  4796   terminal->get_string_resource_hook = pgtk_get_string_resource;
  4797   terminal->delete_frame_hook = pgtk_destroy_window;
  4798   terminal->delete_terminal_hook = pgtk_delete_terminal;
  4799   terminal->query_frame_background_color = pgtk_query_frame_background_color;
  4800   terminal->defined_color_hook = pgtk_defined_color;
  4801   terminal->set_new_font_hook = pgtk_new_font;
  4802   terminal->set_bitmap_icon_hook = pgtk_bitmap_icon;
  4803   terminal->implicit_set_name_hook = pgtk_implicitly_set_name;
  4804   terminal->iconify_frame_hook = pgtk_iconify_frame;
  4805   terminal->set_scroll_bar_default_width_hook
  4806     = pgtk_set_scroll_bar_default_width;
  4807   terminal->set_scroll_bar_default_height_hook
  4808     = pgtk_set_scroll_bar_default_height;
  4809   terminal->set_window_size_hook = pgtk_set_window_size;
  4810   terminal->query_colors = pgtk_query_colors;
  4811   terminal->get_focus_frame = pgtk_get_focus_frame;
  4812   terminal->focus_frame_hook = pgtk_focus_frame;
  4813   terminal->set_frame_offset_hook = pgtk_set_offset;
  4814   terminal->free_pixmap = pgtk_free_pixmap;
  4815   terminal->toolkit_position_hook = pgtk_toolkit_position;
  4816 
  4817   /* Other hooks are NULL by default.  */
  4818 
  4819   return terminal;
  4820 }
  4821 
  4822 struct pgtk_window_is_of_frame_recursive_t
  4823 {
  4824   GdkWindow *window;
  4825   bool result;
  4826   GtkWidget *emacs_gtk_fixed;   /* stop on emacsgtkfixed other than this. */
  4827 };
  4828 
  4829 static void
  4830 pgtk_window_is_of_frame_recursive (GtkWidget *widget, gpointer data)
  4831 {
  4832   struct pgtk_window_is_of_frame_recursive_t *datap = data;
  4833 
  4834   if (datap->result)
  4835     return;
  4836 
  4837   if (EMACS_IS_FIXED (widget) && widget != datap->emacs_gtk_fixed)
  4838     return;
  4839 
  4840   if (gtk_widget_get_window (widget) == datap->window)
  4841     {
  4842       datap->result = true;
  4843       return;
  4844     }
  4845 
  4846   if (GTK_IS_CONTAINER (widget))
  4847     gtk_container_foreach (GTK_CONTAINER (widget),
  4848                            pgtk_window_is_of_frame_recursive, datap);
  4849 }
  4850 
  4851 static bool
  4852 pgtk_window_is_of_frame (struct frame *f, GdkWindow *window)
  4853 {
  4854   struct pgtk_window_is_of_frame_recursive_t data;
  4855   data.window = window;
  4856   data.result = false;
  4857   data.emacs_gtk_fixed = FRAME_GTK_WIDGET (f);
  4858   pgtk_window_is_of_frame_recursive (FRAME_WIDGET (f), &data);
  4859   return data.result;
  4860 }
  4861 
  4862 /* Like x_window_to_frame but also compares the window with the widget's
  4863    windows.  */
  4864 static struct frame *
  4865 pgtk_any_window_to_frame (GdkWindow *window)
  4866 {
  4867   Lisp_Object tail, frame;
  4868   struct frame *f, *found = NULL;
  4869 
  4870   if (window == NULL)
  4871     return NULL;
  4872 
  4873   FOR_EACH_FRAME (tail, frame)
  4874     {
  4875       if (found)
  4876         break;
  4877       f = XFRAME (frame);
  4878       if (FRAME_PGTK_P (f))
  4879         {
  4880           if (pgtk_window_is_of_frame (f, window))
  4881             found = f;
  4882         }
  4883     }
  4884 
  4885   return found;
  4886 }
  4887 
  4888 static gboolean
  4889 pgtk_handle_event (GtkWidget *widget, GdkEvent *event, gpointer *data)
  4890 {
  4891   struct frame *f;
  4892   union buffered_input_event inev;
  4893   GtkWidget *frame_widget;
  4894   gint x, y;
  4895 
  4896   if (event->type == GDK_TOUCHPAD_PINCH
  4897       && (event->touchpad_pinch.phase
  4898           != GDK_TOUCHPAD_GESTURE_PHASE_END))
  4899     {
  4900       f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  4901       frame_widget = FRAME_GTK_WIDGET (f);
  4902 
  4903       gtk_widget_translate_coordinates (widget, frame_widget,
  4904                                         lrint (event->touchpad_pinch.x),
  4905                                         lrint (event->touchpad_pinch.y),
  4906                                         &x, &y);
  4907       if (f)
  4908         {
  4909 
  4910           inev.ie.kind = PINCH_EVENT;
  4911           XSETFRAME (inev.ie.frame_or_window, f);
  4912           XSETINT (inev.ie.x, x);
  4913           XSETINT (inev.ie.y, y);
  4914           inev.ie.arg = list4 (make_float (event->touchpad_pinch.dx),
  4915                                make_float (event->touchpad_pinch.dy),
  4916                                make_float (event->touchpad_pinch.scale),
  4917                                make_float (event->touchpad_pinch.angle_delta));
  4918           inev.ie.modifiers = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f),
  4919                                                            event->touchpad_pinch.state);
  4920           inev.ie.device
  4921             = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  4922           evq_enqueue (&inev);
  4923         }
  4924 
  4925       return TRUE;
  4926     }
  4927   return FALSE;
  4928 }
  4929 
  4930 static void
  4931 pgtk_fill_rectangle (struct frame *f, unsigned long color, int x, int y,
  4932                      int width, int height, bool respect_alpha_background)
  4933 {
  4934   cairo_t *cr;
  4935   cr = pgtk_begin_cr_clip (f);
  4936   pgtk_set_cr_source_with_color (f, color, respect_alpha_background);
  4937   cairo_rectangle (cr, x, y, width, height);
  4938   cairo_fill (cr);
  4939   pgtk_end_cr_clip (f);
  4940 }
  4941 
  4942 void
  4943 pgtk_clear_under_internal_border (struct frame *f)
  4944 {
  4945   if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
  4946       && (!FRAME_GTK_OUTER_WIDGET (f)
  4947           || gtk_widget_get_realized (FRAME_GTK_OUTER_WIDGET (f))))
  4948     {
  4949       int border = FRAME_INTERNAL_BORDER_WIDTH (f);
  4950       int width = FRAME_PIXEL_WIDTH (f);
  4951       int height = FRAME_PIXEL_HEIGHT (f);
  4952       int margin = FRAME_TOP_MARGIN_HEIGHT (f);
  4953       int face_id =
  4954         (FRAME_PARENT_FRAME (f)
  4955          ? (!NILP (Vface_remapping_alist)
  4956             ? lookup_basic_face (NULL, f, CHILD_FRAME_BORDER_FACE_ID)
  4957             : CHILD_FRAME_BORDER_FACE_ID)
  4958          : (!NILP (Vface_remapping_alist)
  4959             ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID)
  4960             : INTERNAL_BORDER_FACE_ID));
  4961       struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
  4962 
  4963       block_input ();
  4964 
  4965       if (face)
  4966         {
  4967 #define x_fill_rectangle(f, gc, x, y, w, h) \
  4968             fill_background_by_face (f, face, x, y, w, h)
  4969           x_fill_rectangle (f, gc, 0, margin, width, border);
  4970           x_fill_rectangle (f, gc, 0, 0, border, height);
  4971           x_fill_rectangle (f, gc, width - border, 0, border, height);
  4972           x_fill_rectangle (f, gc, 0, height - border, width, border);
  4973 #undef x_fill_rectangle
  4974         }
  4975       else
  4976         {
  4977 #define x_clear_area(f, x, y, w, h)  pgtk_clear_area (f, x, y, w, h)
  4978           x_clear_area (f, 0, 0, border, height);
  4979           x_clear_area (f, 0, margin, width, border);
  4980           x_clear_area (f, width - border, 0, border, height);
  4981           x_clear_area (f, 0, height - border, width, border);
  4982 #undef x_clear_area
  4983         }
  4984 
  4985       unblock_input ();
  4986     }
  4987 }
  4988 
  4989 static gboolean
  4990 pgtk_handle_draw (GtkWidget *widget, cairo_t *cr, gpointer *data)
  4991 {
  4992   struct frame *f;
  4993 
  4994   GdkWindow *win = gtk_widget_get_window (widget);
  4995 
  4996   if (win != NULL)
  4997     {
  4998       cairo_surface_t *src = NULL;
  4999       f = pgtk_any_window_to_frame (win);
  5000       if (f != NULL)
  5001         {
  5002           src = FRAME_X_OUTPUT (f)->cr_surface_visible_bell;
  5003           if (src == NULL && FRAME_CR_ACTIVE_CONTEXT (f) != NULL)
  5004             src = cairo_get_target (FRAME_CR_ACTIVE_CONTEXT (f));
  5005         }
  5006       if (src != NULL)
  5007         {
  5008           cairo_set_source_surface (cr, src, 0, 0);
  5009           cairo_paint (cr);
  5010         }
  5011     }
  5012   return FALSE;
  5013 }
  5014 
  5015 static void
  5016 size_allocate (GtkWidget *widget, GtkAllocation *alloc,
  5017                gpointer user_data)
  5018 {
  5019   struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  5020 
  5021   if (!f)
  5022     f = user_data;
  5023 
  5024   if (f)
  5025     {
  5026       xg_frame_resized (f, alloc->width, alloc->height);
  5027       pgtk_cr_update_surface_desired_size (f, alloc->width, alloc->height, false);
  5028     }
  5029 }
  5030 
  5031 static void
  5032 get_modifier_values (int *mod_ctrl, int *mod_meta, int *mod_alt,
  5033                      int *mod_hyper, int *mod_super)
  5034 {
  5035   Lisp_Object tem;
  5036 
  5037   *mod_ctrl = ctrl_modifier;
  5038   *mod_meta = meta_modifier;
  5039   *mod_alt = alt_modifier;
  5040   *mod_hyper = hyper_modifier;
  5041   *mod_super = super_modifier;
  5042 
  5043   tem = Fget (Vx_ctrl_keysym, Qmodifier_value);
  5044   if (INTEGERP (tem))
  5045     *mod_ctrl = XFIXNUM (tem) & INT_MAX;
  5046   tem = Fget (Vx_alt_keysym, Qmodifier_value);
  5047   if (INTEGERP (tem))
  5048     *mod_alt = XFIXNUM (tem) & INT_MAX;
  5049   tem = Fget (Vx_meta_keysym, Qmodifier_value);
  5050   if (INTEGERP (tem))
  5051     *mod_meta = XFIXNUM (tem) & INT_MAX;
  5052   tem = Fget (Vx_hyper_keysym, Qmodifier_value);
  5053   if (INTEGERP (tem))
  5054     *mod_hyper = XFIXNUM (tem) & INT_MAX;
  5055   tem = Fget (Vx_super_keysym, Qmodifier_value);
  5056   if (INTEGERP (tem))
  5057     *mod_super = XFIXNUM (tem) & INT_MAX;
  5058 }
  5059 
  5060 int
  5061 pgtk_gtk_to_emacs_modifiers (struct pgtk_display_info *dpyinfo, int state)
  5062 {
  5063   int mod_ctrl;
  5064   int mod_meta;
  5065   int mod_alt;
  5066   int mod_hyper;
  5067   int mod_super;
  5068   int mod;
  5069 
  5070   get_modifier_values (&mod_ctrl, &mod_meta, &mod_alt, &mod_hyper,
  5071                        &mod_super);
  5072 
  5073   mod = 0;
  5074   if (state & GDK_SHIFT_MASK)
  5075     mod |= shift_modifier;
  5076   if (state & GDK_CONTROL_MASK)
  5077     mod |= mod_ctrl;
  5078   if (state & GDK_META_MASK || state & GDK_MOD1_MASK)
  5079     mod |= mod_meta;
  5080   if (state & GDK_SUPER_MASK)
  5081     mod |= mod_super;
  5082   if (state & GDK_HYPER_MASK)
  5083     mod |= mod_hyper;
  5084 
  5085   return mod;
  5086 }
  5087 
  5088 int
  5089 pgtk_emacs_to_gtk_modifiers (struct pgtk_display_info *dpyinfo, int state)
  5090 {
  5091   int mod_ctrl;
  5092   int mod_meta;
  5093   int mod_alt;
  5094   int mod_hyper;
  5095   int mod_super;
  5096   int mask;
  5097 
  5098   get_modifier_values (&mod_ctrl, &mod_meta, &mod_alt, &mod_hyper,
  5099                        &mod_super);
  5100 
  5101   mask = 0;
  5102   if (state & mod_super)
  5103     mask |= GDK_SUPER_MASK;
  5104   if (state & mod_hyper)
  5105     mask |= GDK_HYPER_MASK;
  5106   if (state & shift_modifier)
  5107     mask |= GDK_SHIFT_MASK;
  5108   if (state & mod_ctrl)
  5109     mask |= GDK_CONTROL_MASK;
  5110   if (state & mod_meta)
  5111     mask |= GDK_MOD1_MASK;
  5112   return mask;
  5113 }
  5114 
  5115 #define IsCursorKey(keysym)       (0xff50 <= (keysym) && (keysym) < 0xff60)
  5116 #define IsMiscFunctionKey(keysym) (0xff60 <= (keysym) && (keysym) < 0xff6c)
  5117 #define IsKeypadKey(keysym)       (0xff80 <= (keysym) && (keysym) < 0xffbe)
  5118 #define IsFunctionKey(keysym)     (0xffbe <= (keysym) && (keysym) < 0xffe1)
  5119 #define IsModifierKey(keysym)                                                   \
  5120   ((((keysym) >= GDK_KEY_Shift_L) && ((keysym) <= GDK_KEY_Hyper_R))             \
  5121    || (((keysym) >= GDK_KEY_ISO_Lock) && ((keysym) <= GDK_KEY_ISO_Level5_Lock)) \
  5122    || ((keysym) == GDK_KEY_Mode_switch)                                         \
  5123    || ((keysym) == GDK_KEY_Num_Lock))
  5124 
  5125 
  5126 void
  5127 pgtk_enqueue_string (struct frame *f, gchar *str)
  5128 {
  5129   gunichar *ustr, *uptr;
  5130 
  5131   uptr = ustr = g_utf8_to_ucs4 (str, -1, NULL, NULL, NULL);
  5132   if (ustr == NULL)
  5133     return;
  5134   for (; *ustr != 0; ustr++)
  5135     {
  5136       union buffered_input_event inev;
  5137       Lisp_Object c = make_fixnum (*ustr);
  5138       EVENT_INIT (inev.ie);
  5139       inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
  5140                       ? ASCII_KEYSTROKE_EVENT
  5141                       : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
  5142       inev.ie.arg = Qnil;
  5143       inev.ie.code = XFIXNAT (c);
  5144       XSETFRAME (inev.ie.frame_or_window, f);
  5145       inev.ie.modifiers = 0;
  5146       inev.ie.timestamp = 0;
  5147       evq_enqueue (&inev);
  5148     }
  5149 
  5150   g_free (uptr);
  5151 }
  5152 
  5153 void
  5154 pgtk_enqueue_preedit (struct frame *f, Lisp_Object preedit)
  5155 {
  5156   union buffered_input_event inev;
  5157   EVENT_INIT (inev.ie);
  5158   inev.ie.kind = PREEDIT_TEXT_EVENT;
  5159   inev.ie.arg = preedit;
  5160   inev.ie.code = 0;
  5161   XSETFRAME (inev.ie.frame_or_window, f);
  5162   inev.ie.modifiers = 0;
  5163   inev.ie.timestamp = 0;
  5164   evq_enqueue (&inev);
  5165 }
  5166 
  5167 static gboolean
  5168 key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
  5169 {
  5170   union buffered_input_event inev;
  5171   ptrdiff_t nbytes;
  5172   Mouse_HLInfo *hlinfo;
  5173   struct frame *f;
  5174   struct pgtk_display_info *dpyinfo;
  5175 
  5176   f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  5177   EVENT_INIT (inev.ie);
  5178   hlinfo = MOUSE_HL_INFO (f);
  5179   nbytes = 0;
  5180 
  5181   /* If mouse-highlight is an integer, input clears out
  5182      mouse highlighting.  */
  5183   if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
  5184     {
  5185       clear_mouse_face (hlinfo);
  5186       hlinfo->mouse_face_hidden = true;
  5187     }
  5188 
  5189   if (f != 0)
  5190     {
  5191       guint keysym, orig_keysym;
  5192       /* al%imercury@uunet.uu.net says that making this 81
  5193          instead of 80 fixed a bug whereby meta chars made
  5194          his Emacs hang.
  5195 
  5196          It seems that some version of XmbLookupString has
  5197          a bug of not returning XBufferOverflow in
  5198          status_return even if the input is too long to
  5199          fit in 81 bytes.  So, we must prepare sufficient
  5200          bytes for copy_buffer.  513 bytes (256 chars for
  5201          two-byte character set) seems to be a fairly good
  5202          approximation.  -- 2000.8.10 handa@etl.go.jp  */
  5203       unsigned char copy_buffer[513];
  5204       unsigned char *copy_bufptr = copy_buffer;
  5205       int copy_bufsiz = sizeof (copy_buffer);
  5206       int modifiers;
  5207       Lisp_Object c;
  5208       guint state;
  5209 
  5210       dpyinfo = FRAME_DISPLAY_INFO (f);
  5211 
  5212       /* Set the last user time for pgtk_focus_frame to work
  5213          correctly.  */
  5214       dpyinfo->last_user_time = event->key.time;
  5215 
  5216       state = event->key.state;
  5217 
  5218       /* While super is pressed, the input method will always always
  5219          resend the key events ignoring super.  As a workaround, don't
  5220          filter key events with super or hyper pressed.  */
  5221       if (!(event->key.state & (GDK_SUPER_MASK | GDK_HYPER_MASK)))
  5222         {
  5223           if (pgtk_im_filter_keypress (f, &event->key))
  5224             return TRUE;
  5225         }
  5226 
  5227       state |= pgtk_emacs_to_gtk_modifiers (FRAME_DISPLAY_INFO (f),
  5228                                             extra_keyboard_modifiers);
  5229       modifiers = state;
  5230 
  5231       /* This will have to go some day...  */
  5232 
  5233       /* make_lispy_event turns chars into control chars.
  5234          Don't do it here because XLookupString is too eager.  */
  5235       state &= ~GDK_CONTROL_MASK;
  5236       state &= ~(GDK_META_MASK
  5237                  | GDK_SUPER_MASK | GDK_HYPER_MASK | GDK_MOD1_MASK);
  5238 
  5239       nbytes = event->key.length;
  5240       if (nbytes > copy_bufsiz)
  5241         nbytes = copy_bufsiz;
  5242       memcpy (copy_bufptr, event->key.string, nbytes);
  5243 
  5244       keysym = event->key.keyval;
  5245       orig_keysym = keysym;
  5246 
  5247       /* Common for all keysym input events.  */
  5248       XSETFRAME (inev.ie.frame_or_window, f);
  5249       inev.ie.modifiers
  5250         = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), modifiers);
  5251       inev.ie.timestamp = event->key.time;
  5252 
  5253       /* First deal with keysyms which have defined
  5254          translations to characters.  */
  5255       if (keysym >= 32 && keysym < 128)
  5256         /* Avoid explicitly decoding each ASCII character.  */
  5257         {
  5258           inev.ie.kind = ASCII_KEYSTROKE_EVENT;
  5259           inev.ie.code = keysym;
  5260 
  5261           inev.ie.device
  5262             = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  5263           goto done;
  5264         }
  5265 
  5266       /* Keysyms directly mapped to Unicode characters.  */
  5267       if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
  5268         {
  5269           if (keysym < 0x01000080)
  5270             inev.ie.kind = ASCII_KEYSTROKE_EVENT;
  5271           else
  5272             inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
  5273           inev.ie.code = keysym & 0xFFFFFF;
  5274 
  5275           inev.ie.device
  5276             = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  5277           goto done;
  5278         }
  5279 
  5280       /* Now non-ASCII.  */
  5281       if (HASH_TABLE_P (Vpgtk_keysym_table)
  5282           && (c = Fgethash (make_fixnum (keysym),
  5283                             Vpgtk_keysym_table, Qnil), FIXNATP (c)))
  5284         {
  5285           inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
  5286                           ? ASCII_KEYSTROKE_EVENT
  5287                           : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
  5288           inev.ie.code = XFIXNAT (c);
  5289 
  5290           inev.ie.device
  5291             = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  5292           goto done;
  5293         }
  5294 
  5295       /* Random non-modifier sorts of keysyms.  */
  5296       if (((keysym >= GDK_KEY_BackSpace && keysym <= GDK_KEY_Escape)
  5297            || keysym == GDK_KEY_Delete
  5298 #ifdef GDK_KEY_ISO_Left_Tab
  5299            || (keysym >= GDK_KEY_ISO_Left_Tab && keysym <= GDK_KEY_ISO_Enter)
  5300 #endif
  5301            || IsCursorKey (keysym)      /* 0xff50 <= x < 0xff60 */
  5302            || IsMiscFunctionKey (keysym)        /* 0xff60 <= x < VARIES */
  5303 #ifdef HPUX
  5304            /* This recognizes the "extended function
  5305               keys".  It seems there's no cleaner way.
  5306               Test IsModifierKey to avoid handling
  5307               mode_switch incorrectly.  */
  5308            || (GDK_KEY_Select <= keysym && keysym < GDK_KEY_KP_Space)
  5309 #endif
  5310 #ifdef GDK_KEY_dead_circumflex
  5311            || orig_keysym == GDK_KEY_dead_circumflex
  5312 #endif
  5313 #ifdef GDK_KEY_dead_grave
  5314            || orig_keysym == GDK_KEY_dead_grave
  5315 #endif
  5316 #ifdef GDK_KEY_dead_tilde
  5317            || orig_keysym == GDK_KEY_dead_tilde
  5318 #endif
  5319 #ifdef GDK_KEY_dead_diaeresis
  5320            || orig_keysym == GDK_KEY_dead_diaeresis
  5321 #endif
  5322 #ifdef GDK_KEY_dead_macron
  5323            || orig_keysym == GDK_KEY_dead_macron
  5324 #endif
  5325 #ifdef GDK_KEY_dead_degree
  5326            || orig_keysym == GDK_KEY_dead_degree
  5327 #endif
  5328 #ifdef GDK_KEY_dead_acute
  5329            || orig_keysym == GDK_KEY_dead_acute
  5330 #endif
  5331 #ifdef GDK_KEY_dead_cedilla
  5332            || orig_keysym == GDK_KEY_dead_cedilla
  5333 #endif
  5334 #ifdef GDK_KEY_dead_breve
  5335            || orig_keysym == GDK_KEY_dead_breve
  5336 #endif
  5337 #ifdef GDK_KEY_dead_ogonek
  5338            || orig_keysym == GDK_KEY_dead_ogonek
  5339 #endif
  5340 #ifdef GDK_KEY_dead_caron
  5341            || orig_keysym == GDK_KEY_dead_caron
  5342 #endif
  5343 #ifdef GDK_KEY_dead_doubleacute
  5344            || orig_keysym == GDK_KEY_dead_doubleacute
  5345 #endif
  5346 #ifdef GDK_KEY_dead_abovedot
  5347            || orig_keysym == GDK_KEY_dead_abovedot
  5348 #endif
  5349            || IsKeypadKey (keysym)      /* 0xff80 <= x < 0xffbe */
  5350            || IsFunctionKey (keysym)    /* 0xffbe <= x < 0xffe1 */
  5351            /* Any "vendor-specific" key is ok.  */
  5352            || (orig_keysym & (1 << 28))
  5353            || (keysym != GDK_KEY_VoidSymbol && nbytes == 0))
  5354           && !(event->key.is_modifier
  5355                || IsModifierKey (orig_keysym)
  5356                /* The symbols from GDK_KEY_ISO_Lock
  5357                   to GDK_KEY_ISO_Last_Group_Lock
  5358                   don't have real modifiers but
  5359                   should be treated similarly to
  5360                   Mode_switch by Emacs. */
  5361 #if defined GDK_KEY_ISO_Lock && defined GDK_KEY_ISO_Last_Group_Lock
  5362                || (GDK_KEY_ISO_Lock <= orig_keysym
  5363                    && orig_keysym <= GDK_KEY_ISO_Last_Group_Lock)
  5364 #endif
  5365           ))
  5366         {
  5367           /* make_lispy_event will convert this to a symbolic
  5368              key.  */
  5369           inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
  5370           inev.ie.code = keysym;
  5371 
  5372           inev.ie.device
  5373             = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  5374           goto done;
  5375         }
  5376 
  5377       {
  5378         inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
  5379         inev.ie.arg = make_unibyte_string ((char *) copy_bufptr, nbytes);
  5380         inev.ie.device
  5381           = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  5382 
  5383         if (keysym == GDK_KEY_VoidSymbol)
  5384           goto done;
  5385       }
  5386     }
  5387 
  5388 done:
  5389   if (inev.ie.kind != NO_EVENT)
  5390     {
  5391       XSETFRAME (inev.ie.frame_or_window, f);
  5392       evq_enqueue (&inev);
  5393     }
  5394 
  5395   return TRUE;
  5396 }
  5397 
  5398 static struct pgtk_display_info *
  5399 pgtk_display_info_for_display (GdkDisplay *dpy)
  5400 {
  5401   struct pgtk_display_info *dpyinfo;
  5402 
  5403   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
  5404     {
  5405       if (dpyinfo->display == dpy)
  5406         return dpyinfo;
  5407     }
  5408 
  5409   return NULL;
  5410 }
  5411 
  5412 static gboolean
  5413 key_release_event (GtkWidget *widget,
  5414                    GdkEvent *event,
  5415                    gpointer *user_data)
  5416 {
  5417   GdkDisplay *display;
  5418   struct pgtk_display_info *dpyinfo;
  5419 
  5420   display = gtk_widget_get_display (widget);
  5421   dpyinfo = pgtk_display_info_for_display (display);
  5422 
  5423   if (dpyinfo)
  5424     /* This is needed on Wayland because of some brain dead
  5425        compositors.  Without them, we would not have to keep track of
  5426        the serial of key release events.  */
  5427     dpyinfo->last_user_time = event->key.time;
  5428 
  5429   return TRUE;
  5430 }
  5431 
  5432 static gboolean
  5433 configure_event (GtkWidget *widget,
  5434                  GdkEvent *event,
  5435                  gpointer *user_data)
  5436 {
  5437   struct frame *f = pgtk_any_window_to_frame (event->configure.window);
  5438 
  5439   if (f && widget == FRAME_GTK_OUTER_WIDGET (f))
  5440     {
  5441       if (any_help_event_p)
  5442         {
  5443           Lisp_Object frame;
  5444           if (f)
  5445             XSETFRAME (frame, f);
  5446           else
  5447             frame = Qnil;
  5448           help_echo_string = Qnil;
  5449           gen_help_event (Qnil, frame, Qnil, Qnil, 0);
  5450         }
  5451 
  5452       if (f->win_gravity == NorthWestGravity)
  5453         gtk_window_get_position (GTK_WINDOW (widget),
  5454                                  &f->left_pos, &f->top_pos);
  5455       else
  5456         {
  5457           f->top_pos = event->configure.y;
  5458           f->left_pos = event->configure.x;
  5459         }
  5460     }
  5461   return FALSE;
  5462 }
  5463 
  5464 static gboolean
  5465 map_event (GtkWidget *widget,
  5466            GdkEvent *event,
  5467            gpointer *user_data)
  5468 {
  5469   struct frame *f = pgtk_any_window_to_frame (event->any.window);
  5470   union buffered_input_event inev;
  5471 
  5472   EVENT_INIT (inev.ie);
  5473   inev.ie.kind = NO_EVENT;
  5474   inev.ie.arg = Qnil;
  5475 
  5476   if (f)
  5477     {
  5478       bool iconified = FRAME_ICONIFIED_P (f);
  5479 
  5480       /* Check if fullscreen was specified before we where mapped the
  5481          first time, i.e. from the command line.  */
  5482       if (!FRAME_X_OUTPUT (f)->has_been_visible)
  5483         set_fullscreen_state (f);
  5484 
  5485       if (!iconified)
  5486         {
  5487           /* The `z-group' is reset every time a frame becomes
  5488              invisible.  Handle this here.  */
  5489           if (FRAME_Z_GROUP (f) == z_group_above)
  5490             pgtk_set_z_group (f, Qabove, Qnil);
  5491           else if (FRAME_Z_GROUP (f) == z_group_below)
  5492             pgtk_set_z_group (f, Qbelow, Qnil);
  5493         }
  5494 
  5495       SET_FRAME_VISIBLE (f, 1);
  5496       SET_FRAME_ICONIFIED (f, false);
  5497       FRAME_X_OUTPUT (f)->has_been_visible = true;
  5498 
  5499       if (iconified)
  5500         {
  5501           inev.ie.kind = DEICONIFY_EVENT;
  5502           XSETFRAME (inev.ie.frame_or_window, f);
  5503         }
  5504     }
  5505 
  5506   if (inev.ie.kind != NO_EVENT)
  5507     evq_enqueue (&inev);
  5508   return FALSE;
  5509 }
  5510 
  5511 static gboolean
  5512 window_state_event (GtkWidget *widget,
  5513                     GdkEvent *event,
  5514                     gpointer *user_data)
  5515 {
  5516   struct frame *f = pgtk_any_window_to_frame (event->window_state.window);
  5517   GdkWindowState new_state;
  5518   union buffered_input_event inev;
  5519 
  5520   new_state = event->window_state.new_window_state;
  5521 
  5522   EVENT_INIT (inev.ie);
  5523   inev.ie.kind = NO_EVENT;
  5524   inev.ie.arg = Qnil;
  5525 
  5526   if (new_state & GDK_WINDOW_STATE_FULLSCREEN)
  5527     store_frame_param (f, Qfullscreen, Qfullboth);
  5528   else if (new_state & GDK_WINDOW_STATE_MAXIMIZED)
  5529     store_frame_param (f, Qfullscreen, Qmaximized);
  5530   else if ((new_state & GDK_WINDOW_STATE_TOP_TILED)
  5531            && (new_state & GDK_WINDOW_STATE_BOTTOM_TILED)
  5532            && !(new_state & GDK_WINDOW_STATE_TOP_RESIZABLE)
  5533            && !(new_state & GDK_WINDOW_STATE_BOTTOM_RESIZABLE))
  5534     store_frame_param (f, Qfullscreen, Qfullheight);
  5535   else if ((new_state & GDK_WINDOW_STATE_LEFT_TILED)
  5536            && (new_state & GDK_WINDOW_STATE_RIGHT_TILED)
  5537            && !(new_state & GDK_WINDOW_STATE_LEFT_RESIZABLE)
  5538            && !(new_state & GDK_WINDOW_STATE_RIGHT_RESIZABLE))
  5539     store_frame_param (f, Qfullscreen, Qfullwidth);
  5540   else
  5541     store_frame_param (f, Qfullscreen, Qnil);
  5542 
  5543   /* The Wayland protocol provides no way for the client to know
  5544      whether or not one of its toplevels has actually been
  5545      deiconified.  It only provides a request for clients to iconify a
  5546      toplevel, without even the ability to determine whether or not
  5547      the iconification request was rejected by the display server.
  5548 
  5549      GDK computes the iconified state by sending a window state event
  5550      containing only GDK_WINDOW_STATE_ICONIFIED immediately after
  5551      gtk_window_iconify is called.  That is error-prone if the request
  5552      to iconify the frame was rejected by the display server, but is
  5553      not the main problem here, as Wayland compositors only rarely
  5554      reject such requests.  GDK also assumes that it can clear the
  5555      iconified state upon receiving the next toplevel configure event
  5556      from the display server.  Unfortunately, such events can be sent
  5557      by Wayland compositors while the frame is iconified, and may also
  5558      not be sent upon deiconification.  So, no matter what Emacs does,
  5559      the iconification state of a frame is likely to be wrong under
  5560      one situation or another.  */
  5561 
  5562   if (new_state & GDK_WINDOW_STATE_ICONIFIED)
  5563     {
  5564       SET_FRAME_ICONIFIED (f, true);
  5565       SET_FRAME_VISIBLE (f, false);
  5566     }
  5567   else
  5568     {
  5569       FRAME_X_OUTPUT (f)->has_been_visible = true;
  5570       inev.ie.kind = DEICONIFY_EVENT;
  5571       XSETFRAME (inev.ie.frame_or_window, f);
  5572       SET_FRAME_ICONIFIED (f, false);
  5573       SET_FRAME_VISIBLE (f, true);
  5574     }
  5575 
  5576   if (new_state & GDK_WINDOW_STATE_STICKY)
  5577     store_frame_param (f, Qsticky, Qt);
  5578   else
  5579     store_frame_param (f, Qsticky, Qnil);
  5580 
  5581   if (inev.ie.kind != NO_EVENT)
  5582     evq_enqueue (&inev);
  5583   return FALSE;
  5584 }
  5585 
  5586 static gboolean
  5587 delete_event (GtkWidget *widget,
  5588               GdkEvent *event, gpointer *user_data)
  5589 {
  5590   struct frame *f = pgtk_any_window_to_frame (event->any.window);
  5591   union buffered_input_event inev;
  5592 
  5593   EVENT_INIT (inev.ie);
  5594   inev.ie.kind = NO_EVENT;
  5595   inev.ie.arg = Qnil;
  5596 
  5597   if (f)
  5598     {
  5599       inev.ie.kind = DELETE_WINDOW_EVENT;
  5600       XSETFRAME (inev.ie.frame_or_window, f);
  5601     }
  5602 
  5603   if (inev.ie.kind != NO_EVENT)
  5604     evq_enqueue (&inev);
  5605   return TRUE;
  5606 }
  5607 
  5608 /* The focus may have changed.  Figure out if it is a real focus change,
  5609    by checking both FocusIn/Out and Enter/LeaveNotify events.
  5610 
  5611    Returns FOCUS_IN_EVENT event in *BUFP. */
  5612 
  5613 /* Handle FocusIn and FocusOut state changes for FRAME.
  5614    If FRAME has focus and there exists more than one frame, puts
  5615    a FOCUS_IN_EVENT into *BUFP.  */
  5616 
  5617 static void
  5618 pgtk_focus_changed (gboolean is_enter, int state,
  5619                     struct pgtk_display_info *dpyinfo, struct frame *frame,
  5620                     union buffered_input_event *bufp)
  5621 {
  5622   if (is_enter)
  5623     {
  5624       if (dpyinfo->x_focus_event_frame != frame)
  5625         {
  5626           pgtk_new_focus_frame (dpyinfo, frame);
  5627           dpyinfo->x_focus_event_frame = frame;
  5628 
  5629           /* Don't stop displaying the initial startup message
  5630              for a switch-frame event we don't need.  */
  5631           /* When run as a daemon, Vterminal_frame is always NIL.  */
  5632           bufp->ie.arg = (((NILP (Vterminal_frame)
  5633                             || !FRAME_PGTK_P (XFRAME (Vterminal_frame))
  5634                             || EQ (Fdaemonp (), Qt))
  5635                            && CONSP (Vframe_list)
  5636                            && !NILP (XCDR (Vframe_list))) ? Qt : Qnil);
  5637           bufp->ie.kind = FOCUS_IN_EVENT;
  5638           XSETFRAME (bufp->ie.frame_or_window, frame);
  5639         }
  5640 
  5641       frame->output_data.pgtk->focus_state |= state;
  5642 
  5643     }
  5644   else
  5645     {
  5646       frame->output_data.pgtk->focus_state &= ~state;
  5647 
  5648       if (dpyinfo->x_focus_event_frame == frame)
  5649         {
  5650           dpyinfo->x_focus_event_frame = 0;
  5651           pgtk_new_focus_frame (dpyinfo, NULL);
  5652 
  5653           bufp->ie.kind = FOCUS_OUT_EVENT;
  5654           XSETFRAME (bufp->ie.frame_or_window, frame);
  5655         }
  5656 
  5657       if (frame->pointer_invisible)
  5658         pgtk_toggle_invisible_pointer (frame, false);
  5659     }
  5660 }
  5661 
  5662 static gboolean
  5663 enter_notify_event (GtkWidget *widget, GdkEvent *event,
  5664                     gpointer *user_data)
  5665 {
  5666   union buffered_input_event inev;
  5667   struct frame *frame
  5668     = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  5669 
  5670   if (frame == NULL)
  5671     return FALSE;
  5672 
  5673   struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
  5674   struct frame *focus_frame = dpyinfo->x_focus_frame;
  5675   int focus_state
  5676     = focus_frame ? focus_frame->output_data.pgtk->focus_state : 0;
  5677 
  5678   EVENT_INIT (inev.ie);
  5679   inev.ie.kind = NO_EVENT;
  5680   inev.ie.arg = Qnil;
  5681 
  5682   if (event->crossing.detail != GDK_NOTIFY_INFERIOR
  5683       && event->crossing.focus && !(focus_state & FOCUS_EXPLICIT))
  5684     pgtk_focus_changed (TRUE, FOCUS_IMPLICIT, dpyinfo, frame, &inev);
  5685   if (inev.ie.kind != NO_EVENT)
  5686     evq_enqueue (&inev);
  5687   return TRUE;
  5688 }
  5689 
  5690 static gboolean
  5691 leave_notify_event (GtkWidget *widget, GdkEvent *event,
  5692                     gpointer *user_data)
  5693 {
  5694   union buffered_input_event inev;
  5695   struct frame *frame
  5696     = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  5697 
  5698   if (frame == NULL)
  5699     return FALSE;
  5700 
  5701   struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
  5702   struct frame *focus_frame = dpyinfo->x_focus_frame;
  5703   int focus_state
  5704     = focus_frame ? focus_frame->output_data.pgtk->focus_state : 0;
  5705   Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (frame);
  5706 
  5707   if (frame == hlinfo->mouse_face_mouse_frame)
  5708     {
  5709       /* If we move outside the frame, then we're
  5710          certainly no longer on any text in the frame.  */
  5711       clear_mouse_face (hlinfo);
  5712       hlinfo->mouse_face_mouse_frame = 0;
  5713     }
  5714 
  5715   EVENT_INIT (inev.ie);
  5716   inev.ie.kind = NO_EVENT;
  5717   inev.ie.arg = Qnil;
  5718 
  5719   if (event->crossing.detail != GDK_NOTIFY_INFERIOR
  5720       && event->crossing.focus && !(focus_state & FOCUS_EXPLICIT))
  5721     pgtk_focus_changed (FALSE, FOCUS_IMPLICIT, dpyinfo, frame, &inev);
  5722 
  5723   if (frame)
  5724     {
  5725       if (any_help_event_p)
  5726         {
  5727           Lisp_Object frame_obj;
  5728           XSETFRAME (frame_obj, frame);
  5729           help_echo_string = Qnil;
  5730           gen_help_event (Qnil, frame_obj, Qnil, Qnil, 0);
  5731         }
  5732     }
  5733 
  5734   if (inev.ie.kind != NO_EVENT)
  5735     evq_enqueue (&inev);
  5736   return TRUE;
  5737 }
  5738 
  5739 static gboolean
  5740 focus_in_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
  5741 {
  5742   union buffered_input_event inev;
  5743   struct frame *frame
  5744     = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  5745 
  5746   if (frame == NULL)
  5747     return TRUE;
  5748 
  5749   EVENT_INIT (inev.ie);
  5750   inev.ie.kind = NO_EVENT;
  5751   inev.ie.arg = Qnil;
  5752 
  5753   pgtk_focus_changed (TRUE, FOCUS_EXPLICIT,
  5754                       FRAME_DISPLAY_INFO (frame), frame, &inev);
  5755   if (inev.ie.kind != NO_EVENT)
  5756     evq_enqueue (&inev);
  5757 
  5758   pgtk_im_focus_in (frame);
  5759 
  5760   return TRUE;
  5761 }
  5762 
  5763 static gboolean
  5764 focus_out_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
  5765 {
  5766   union buffered_input_event inev;
  5767   struct frame *frame
  5768     = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  5769 
  5770   if (frame == NULL)
  5771     return TRUE;
  5772 
  5773   EVENT_INIT (inev.ie);
  5774   inev.ie.kind = NO_EVENT;
  5775   inev.ie.arg = Qnil;
  5776 
  5777   pgtk_focus_changed (FALSE, FOCUS_EXPLICIT,
  5778                       FRAME_DISPLAY_INFO (frame), frame, &inev);
  5779   if (inev.ie.kind != NO_EVENT)
  5780     evq_enqueue (&inev);
  5781 
  5782   pgtk_im_focus_out (frame);
  5783 
  5784   return TRUE;
  5785 }
  5786 
  5787 /* Function to report a mouse movement to the mainstream Emacs code.
  5788    The input handler calls this.
  5789 
  5790    We have received a mouse movement event, which is given in *event.
  5791    If the mouse is over a different glyph than it was last time, tell
  5792    the mainstream emacs code by setting mouse_moved.  If not, ask for
  5793    another motion event, so we can check again the next time it moves.  */
  5794 
  5795 static bool
  5796 note_mouse_movement (struct frame *frame,
  5797                      const GdkEventMotion *event)
  5798 {
  5799   XRectangle *r;
  5800   struct pgtk_display_info *dpyinfo;
  5801 
  5802   if (!FRAME_X_OUTPUT (frame))
  5803     return false;
  5804 
  5805   dpyinfo = FRAME_DISPLAY_INFO (frame);
  5806   dpyinfo->last_mouse_movement_time = event->time;
  5807   dpyinfo->last_mouse_motion_frame = frame;
  5808   dpyinfo->last_mouse_motion_x = event->x;
  5809   dpyinfo->last_mouse_motion_y = event->y;
  5810 
  5811   if (event->window != gtk_widget_get_window (FRAME_GTK_WIDGET (frame)))
  5812     {
  5813       frame->mouse_moved = true;
  5814       dpyinfo->last_mouse_scroll_bar = NULL;
  5815       note_mouse_highlight (frame, -1, -1);
  5816       dpyinfo->last_mouse_glyph_frame = NULL;
  5817       frame->last_mouse_device
  5818         = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (frame),
  5819                                      (GdkEvent *) event);
  5820       return true;
  5821     }
  5822 
  5823 
  5824   /* Has the mouse moved off the glyph it was on at the last sighting?  */
  5825   r = &dpyinfo->last_mouse_glyph;
  5826   if (frame != dpyinfo->last_mouse_glyph_frame
  5827       || event->x < r->x || event->x >= r->x + r->width
  5828       || event->y < r->y || event->y >= r->y + r->height)
  5829     {
  5830       frame->mouse_moved = true;
  5831       dpyinfo->last_mouse_scroll_bar = NULL;
  5832       note_mouse_highlight (frame, event->x, event->y);
  5833       /* Remember which glyph we're now on.  */
  5834       remember_mouse_glyph (frame, event->x, event->y, r);
  5835       dpyinfo->last_mouse_glyph_frame = frame;
  5836       frame->last_mouse_device
  5837         = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (frame),
  5838                                      (GdkEvent *) event);
  5839       return true;
  5840     }
  5841 
  5842   return false;
  5843 }
  5844 
  5845 static gboolean
  5846 motion_notify_event (GtkWidget *widget, GdkEvent *event,
  5847                      gpointer *user_data)
  5848 {
  5849   union buffered_input_event inev;
  5850   struct frame *f, *frame;
  5851   struct pgtk_display_info *dpyinfo;
  5852   Mouse_HLInfo *hlinfo;
  5853 
  5854   EVENT_INIT (inev.ie);
  5855   inev.ie.kind = NO_EVENT;
  5856   inev.ie.arg = Qnil;
  5857 
  5858   previous_help_echo_string = help_echo_string;
  5859   help_echo_string = Qnil;
  5860 
  5861   frame = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  5862   dpyinfo = FRAME_DISPLAY_INFO (frame);
  5863   f = (gui_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
  5864        : pgtk_any_window_to_frame (gtk_widget_get_window (widget)));
  5865   hlinfo = MOUSE_HL_INFO (f);
  5866 
  5867   if (hlinfo->mouse_face_hidden)
  5868     {
  5869       hlinfo->mouse_face_hidden = false;
  5870       clear_mouse_face (hlinfo);
  5871     }
  5872 
  5873   if (f && xg_event_is_for_scrollbar (f, event, false))
  5874     f = 0;
  5875 
  5876   if (f)
  5877     {
  5878       /* Maybe generate a SELECT_WINDOW_EVENT for
  5879          `mouse-autoselect-window' but don't let popup menus
  5880          interfere with this (Bug#1261).  */
  5881       if (!NILP (Vmouse_autoselect_window)
  5882           /* Don't switch if we're currently in the minibuffer.
  5883              This tries to work around problems where the
  5884              minibuffer gets unselected unexpectedly, and where
  5885              you then have to move your mouse all the way down to
  5886              the minibuffer to select it.  */
  5887           && !MINI_WINDOW_P (XWINDOW (selected_window))
  5888           /* With `focus-follows-mouse' non-nil create an event
  5889              also when the target window is on another frame.  */
  5890           && (f == XFRAME (selected_frame) || !NILP (focus_follows_mouse)))
  5891         {
  5892           static Lisp_Object last_mouse_window;
  5893           Lisp_Object window = window_from_coordinates
  5894             (f, event->motion.x, event->motion.y, 0, false, false);
  5895 
  5896           /* A window will be autoselected only when it is not
  5897              selected now and the last mouse movement event was
  5898              not in it.  The remainder of the code is a bit vague
  5899              wrt what a "window" is.  For immediate autoselection,
  5900              the window is usually the entire window but for GTK
  5901              where the scroll bars don't count.  For delayed
  5902              autoselection the window is usually the window's text
  5903              area including the margins.  */
  5904           if (WINDOWP (window)
  5905               && !EQ (window, last_mouse_window)
  5906               && !EQ (window, selected_window))
  5907             {
  5908               inev.ie.kind = SELECT_WINDOW_EVENT;
  5909               inev.ie.frame_or_window = window;
  5910             }
  5911 
  5912           /* Remember the last window where we saw the mouse.  */
  5913           last_mouse_window = window;
  5914         }
  5915 
  5916       if (!note_mouse_movement (f, &event->motion))
  5917         help_echo_string = previous_help_echo_string;
  5918     }
  5919   else
  5920     /* If we move outside the frame, then we're
  5921        certainly no longer on any text in the frame.  */
  5922     clear_mouse_face (hlinfo);
  5923 
  5924   /* If the contents of the global variable help_echo_string
  5925      has changed, generate a HELP_EVENT.  */
  5926   int do_help = 0;
  5927   if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
  5928     do_help = 1;
  5929 
  5930   if (inev.ie.kind != NO_EVENT)
  5931     evq_enqueue (&inev);
  5932 
  5933   if (do_help > 0)
  5934     {
  5935       Lisp_Object frame;
  5936 
  5937       if (f)
  5938         XSETFRAME (frame, f);
  5939       else
  5940         frame = Qnil;
  5941 
  5942       any_help_event_p = true;
  5943       gen_help_event (help_echo_string, frame, help_echo_window,
  5944                       help_echo_object, help_echo_pos);
  5945     }
  5946 
  5947   return TRUE;
  5948 }
  5949 
  5950 /* Prepare a mouse-event in *RESULT for placement in the input queue.
  5951 
  5952    If the event is a button press, then note that we have grabbed
  5953    the mouse.  */
  5954 
  5955 static Lisp_Object
  5956 construct_mouse_click (struct input_event *result,
  5957                        const GdkEventButton *event,
  5958                        struct frame *f)
  5959 {
  5960   /* Make the event type NO_EVENT; we'll change that when we decide
  5961      otherwise.  */
  5962   result->kind = MOUSE_CLICK_EVENT;
  5963   result->code = event->button - 1;
  5964   result->timestamp = event->time;
  5965   result->modifiers = (pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f),
  5966                                                     event->state)
  5967                        | (event->type == GDK_BUTTON_RELEASE
  5968                           ? up_modifier : down_modifier));
  5969 
  5970   XSETINT (result->x, event->x);
  5971   XSETINT (result->y, event->y);
  5972   XSETFRAME (result->frame_or_window, f);
  5973   result->arg = Qnil;
  5974   result->device = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f),
  5975                                               (GdkEvent *) event);
  5976   return Qnil;
  5977 }
  5978 
  5979 static gboolean
  5980 button_event (GtkWidget *widget, GdkEvent *event,
  5981               gpointer *user_data)
  5982 {
  5983   union buffered_input_event inev;
  5984   struct frame *f, *frame;
  5985   struct pgtk_display_info *dpyinfo;
  5986 
  5987   /* If we decide we want to generate an event to be seen
  5988      by the rest of Emacs, we put it here.  */
  5989   bool tab_bar_p = false;
  5990   bool tool_bar_p = false;
  5991   Lisp_Object tab_bar_arg = Qnil;
  5992 
  5993   EVENT_INIT (inev.ie);
  5994   inev.ie.kind = NO_EVENT;
  5995   inev.ie.arg = Qnil;
  5996 
  5997   /* ignore double click and triple click. */
  5998   if (event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE)
  5999     return TRUE;
  6000 
  6001   frame = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  6002   dpyinfo = FRAME_DISPLAY_INFO (frame);
  6003 
  6004   dpyinfo->last_mouse_glyph_frame = NULL;
  6005 
  6006   if (gui_mouse_grabbed (dpyinfo))
  6007     f = dpyinfo->last_mouse_frame;
  6008   else
  6009     {
  6010       f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  6011 
  6012       if (f && event->button.type == GDK_BUTTON_PRESS
  6013           && !FRAME_NO_ACCEPT_FOCUS (f))
  6014         {
  6015           /* When clicking into a child frame or when clicking
  6016              into a parent frame with the child frame selected and
  6017              `no-accept-focus' is not set, select the clicked
  6018              frame.  */
  6019           struct frame *hf = dpyinfo->highlight_frame;
  6020 
  6021           if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
  6022             {
  6023               block_input ();
  6024               gtk_widget_grab_focus (FRAME_GTK_WIDGET (f));
  6025 
  6026               if (FRAME_GTK_OUTER_WIDGET (f))
  6027                 gtk_window_present (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
  6028               unblock_input ();
  6029             }
  6030         }
  6031     }
  6032 
  6033   /* Set the last user time, used to activate the frame in
  6034      pgtk_focus_frame.  */
  6035   dpyinfo->last_user_time = event->button.time;
  6036 
  6037   if (f)
  6038     {
  6039       /* Is this in the tab-bar?  */
  6040       if (WINDOWP (f->tab_bar_window)
  6041           && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)))
  6042         {
  6043           Lisp_Object window;
  6044           int x = event->button.x;
  6045           int y = event->button.y;
  6046 
  6047           window = window_from_coordinates (f, x, y, 0, true, true);
  6048           tab_bar_p = EQ (window, f->tab_bar_window);
  6049 
  6050           if (tab_bar_p)
  6051             tab_bar_arg = handle_tab_bar_click
  6052               (f, x, y, event->type == GDK_BUTTON_PRESS,
  6053                pgtk_gtk_to_emacs_modifiers (dpyinfo, event->button.state));
  6054         }
  6055 
  6056       if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p)
  6057         {
  6058           if (ignore_next_mouse_click_timeout)
  6059             {
  6060               if (event->type == GDK_BUTTON_PRESS
  6061                   && event->button.time > ignore_next_mouse_click_timeout)
  6062                 {
  6063                   ignore_next_mouse_click_timeout = 0;
  6064                   construct_mouse_click (&inev.ie, &event->button, f);
  6065                 }
  6066               if (event->type == GDK_BUTTON_RELEASE)
  6067                 ignore_next_mouse_click_timeout = 0;
  6068             }
  6069           else
  6070             construct_mouse_click (&inev.ie, &event->button, f);
  6071 
  6072           if (!NILP (tab_bar_arg))
  6073             inev.ie.arg = tab_bar_arg;
  6074         }
  6075     }
  6076 
  6077   if (event->type == GDK_BUTTON_PRESS)
  6078     {
  6079       dpyinfo->grabbed |= (1 << event->button.button);
  6080       dpyinfo->last_mouse_frame = f;
  6081 
  6082       if (dpyinfo->last_click_event != NULL)
  6083         gdk_event_free (dpyinfo->last_click_event);
  6084       dpyinfo->last_click_event = gdk_event_copy (event);
  6085     }
  6086   else
  6087     dpyinfo->grabbed &= ~(1 << event->button.button);
  6088 
  6089   /* Ignore any mouse motion that happened before this event;
  6090      any subsequent mouse-movement Emacs events should reflect
  6091      only motion after the ButtonPress/Release.  */
  6092   if (f != 0)
  6093     f->mouse_moved = false;
  6094 
  6095   if (inev.ie.kind != NO_EVENT)
  6096     evq_enqueue (&inev);
  6097   return TRUE;
  6098 }
  6099 
  6100 static gboolean
  6101 scroll_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
  6102 {
  6103   union buffered_input_event inev;
  6104   struct frame *f, *frame;
  6105   struct pgtk_display_info *dpyinfo;
  6106   GdkScrollDirection dir;
  6107   double delta_x, delta_y;
  6108 
  6109   EVENT_INIT (inev.ie);
  6110   inev.ie.kind = NO_EVENT;
  6111   inev.ie.arg = Qnil;
  6112 
  6113   frame = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  6114   dpyinfo = FRAME_DISPLAY_INFO (frame);
  6115 
  6116   if (gui_mouse_grabbed (dpyinfo))
  6117     f = dpyinfo->last_mouse_frame;
  6118   else
  6119     f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  6120 
  6121   inev.ie.kind = NO_EVENT;
  6122   inev.ie.timestamp = event->scroll.time;
  6123   inev.ie.modifiers
  6124     = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), event->scroll.state);
  6125   XSETINT (inev.ie.x, event->scroll.x);
  6126   XSETINT (inev.ie.y, event->scroll.y);
  6127   XSETFRAME (inev.ie.frame_or_window, f);
  6128   inev.ie.arg = Qnil;
  6129 
  6130   if (gdk_event_is_scroll_stop_event (event))
  6131     {
  6132       inev.ie.kind = TOUCH_END_EVENT;
  6133       inev.ie.device
  6134         = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  6135       evq_enqueue (&inev);
  6136       return TRUE;
  6137     }
  6138 
  6139   if (gdk_event_get_scroll_direction (event, &dir))
  6140     {
  6141       switch (dir)
  6142         {
  6143         case GDK_SCROLL_UP:
  6144           inev.ie.kind = WHEEL_EVENT;
  6145           inev.ie.modifiers |= up_modifier;
  6146           break;
  6147         case GDK_SCROLL_DOWN:
  6148           inev.ie.kind = WHEEL_EVENT;
  6149           inev.ie.modifiers |= down_modifier;
  6150           break;
  6151         case GDK_SCROLL_LEFT:
  6152           inev.ie.kind = HORIZ_WHEEL_EVENT;
  6153           inev.ie.modifiers |= up_modifier;
  6154           break;
  6155         case GDK_SCROLL_RIGHT:
  6156           inev.ie.kind = HORIZ_WHEEL_EVENT;
  6157           inev.ie.modifiers |= down_modifier;
  6158           break;
  6159         case GDK_SCROLL_SMOOTH:         /* shut up warning */
  6160           break;
  6161         }
  6162     }
  6163   else if (gdk_event_get_scroll_deltas (event, &delta_x, &delta_y))
  6164     {
  6165       if (!mwheel_coalesce_scroll_events)
  6166         {
  6167           inev.ie.kind = ((fabs (delta_x) > fabs (delta_y))
  6168                           ? HORIZ_WHEEL_EVENT
  6169                           : WHEEL_EVENT);
  6170           inev.ie.modifiers |= (inev.ie.kind == HORIZ_WHEEL_EVENT
  6171                                 ? (delta_x >= 0 ? up_modifier : down_modifier)
  6172                                 : (delta_y >= 0 ? down_modifier : up_modifier));
  6173           inev.ie.arg = list3 (Qnil, make_float (-delta_x * 100),
  6174                                make_float (-delta_y * 100));
  6175         }
  6176       else
  6177         {
  6178           dpyinfo->scroll.acc_x += delta_x;
  6179           dpyinfo->scroll.acc_y += delta_y;
  6180           if (dpyinfo->scroll.acc_y >= dpyinfo->scroll.y_per_line)
  6181             {
  6182               int nlines = dpyinfo->scroll.acc_y / dpyinfo->scroll.y_per_line;
  6183               inev.ie.kind = WHEEL_EVENT;
  6184               inev.ie.modifiers |= down_modifier;
  6185               inev.ie.arg = list3 (make_fixnum (nlines),
  6186                                    make_float (-dpyinfo->scroll.acc_x * 100),
  6187                                    make_float (-dpyinfo->scroll.acc_y * 100));
  6188               dpyinfo->scroll.acc_y -= dpyinfo->scroll.y_per_line * nlines;
  6189             }
  6190           else if (dpyinfo->scroll.acc_y <= -dpyinfo->scroll.y_per_line)
  6191             {
  6192               int nlines = -dpyinfo->scroll.acc_y / dpyinfo->scroll.y_per_line;
  6193               inev.ie.kind = WHEEL_EVENT;
  6194               inev.ie.modifiers |= up_modifier;
  6195               inev.ie.arg = list3 (make_fixnum (nlines),
  6196                                    make_float (-dpyinfo->scroll.acc_x * 100),
  6197                                    make_float (-dpyinfo->scroll.acc_y * 100));
  6198 
  6199               dpyinfo->scroll.acc_y -= -dpyinfo->scroll.y_per_line * nlines;
  6200             }
  6201           else if (dpyinfo->scroll.acc_x >= dpyinfo->scroll.x_per_char
  6202                    || !mwheel_coalesce_scroll_events)
  6203             {
  6204               int nchars = dpyinfo->scroll.acc_x / dpyinfo->scroll.x_per_char;
  6205               inev.ie.kind = HORIZ_WHEEL_EVENT;
  6206               inev.ie.modifiers |= up_modifier;
  6207               inev.ie.arg = list3 (make_fixnum (nchars),
  6208                                    make_float (-dpyinfo->scroll.acc_x * 100),
  6209                                    make_float (-dpyinfo->scroll.acc_y * 100));
  6210 
  6211               dpyinfo->scroll.acc_x -= dpyinfo->scroll.x_per_char * nchars;
  6212             }
  6213           else if (dpyinfo->scroll.acc_x <= -dpyinfo->scroll.x_per_char)
  6214             {
  6215               int nchars = -dpyinfo->scroll.acc_x / dpyinfo->scroll.x_per_char;
  6216               inev.ie.kind = HORIZ_WHEEL_EVENT;
  6217               inev.ie.modifiers |= down_modifier;
  6218               inev.ie.arg = list3 (make_fixnum (nchars),
  6219                                    make_float (-dpyinfo->scroll.acc_x * 100),
  6220                                    make_float (-dpyinfo->scroll.acc_y * 100));
  6221 
  6222               dpyinfo->scroll.acc_x -= -dpyinfo->scroll.x_per_char * nchars;
  6223             }
  6224         }
  6225     }
  6226 
  6227   if (inev.ie.kind != NO_EVENT)
  6228     {
  6229       inev.ie.device
  6230         = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
  6231       evq_enqueue (&inev);
  6232     }
  6233   return TRUE;
  6234 }
  6235 
  6236 
  6237 
  6238 /* C part of drop handling code.
  6239    The Lisp part is in pgtk-dnd.el.  */
  6240 
  6241 static GdkDragAction
  6242 symbol_to_drag_action (Lisp_Object act)
  6243 {
  6244   if (EQ (act, Qcopy))
  6245     return GDK_ACTION_COPY;
  6246 
  6247   if (EQ (act, Qmove))
  6248     return GDK_ACTION_MOVE;
  6249 
  6250   if (EQ (act, Qlink))
  6251     return GDK_ACTION_LINK;
  6252 
  6253   if (EQ (act, Qprivate))
  6254     return GDK_ACTION_PRIVATE;
  6255 
  6256   if (NILP (act))
  6257     return GDK_ACTION_DEFAULT;
  6258 
  6259   signal_error ("Invalid drag acction", act);
  6260 }
  6261 
  6262 static Lisp_Object
  6263 drag_action_to_symbol (GdkDragAction action)
  6264 {
  6265   switch (action)
  6266     {
  6267     case GDK_ACTION_COPY:
  6268       return Qcopy;
  6269 
  6270     case GDK_ACTION_MOVE:
  6271       return Qmove;
  6272 
  6273     case GDK_ACTION_LINK:
  6274       return Qlink;
  6275 
  6276     case GDK_ACTION_PRIVATE:
  6277       return Qprivate;
  6278 
  6279     case GDK_ACTION_DEFAULT:
  6280     default:
  6281       return Qnil;
  6282     }
  6283 }
  6284 
  6285 void
  6286 pgtk_update_drop_status (Lisp_Object action, Lisp_Object event_time)
  6287 {
  6288   guint32 time;
  6289 
  6290   CONS_TO_INTEGER (event_time, guint32, time);
  6291 
  6292   if (!current_drop_context || time < current_drop_time)
  6293     return;
  6294 
  6295   gdk_drag_status (current_drop_context,
  6296                    symbol_to_drag_action (action),
  6297                    time);
  6298 }
  6299 
  6300 void
  6301 pgtk_finish_drop (Lisp_Object success, Lisp_Object event_time,
  6302                   Lisp_Object del)
  6303 {
  6304   guint32 time;
  6305 
  6306   CONS_TO_INTEGER (event_time, guint32, time);
  6307 
  6308   if (!current_drop_context || time < current_drop_time)
  6309     return;
  6310 
  6311   gtk_drag_finish (current_drop_context, !NILP (success),
  6312                    !NILP (del), time);
  6313 
  6314   if (current_drop_context_drop)
  6315     g_clear_pointer (&current_drop_context,
  6316                      g_object_unref);
  6317 }
  6318 
  6319 static void
  6320 drag_leave (GtkWidget *widget, GdkDragContext *context,
  6321             guint time, gpointer user_data)
  6322 {
  6323   struct frame *f;
  6324   union buffered_input_event inev;
  6325 
  6326   f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  6327 
  6328   if (current_drop_context)
  6329     {
  6330       if (current_drop_context_drop)
  6331         gtk_drag_finish (current_drop_context,
  6332                          FALSE, FALSE, current_drop_time);
  6333 
  6334       g_clear_pointer (&current_drop_context,
  6335                        g_object_unref);
  6336     }
  6337 
  6338   EVENT_INIT (inev.ie);
  6339 
  6340   inev.ie.kind = DRAG_N_DROP_EVENT;
  6341   inev.ie.modifiers = 0;
  6342   inev.ie.arg = Qnil;
  6343   inev.ie.timestamp = time;
  6344 
  6345   XSETINT (inev.ie.x, 0);
  6346   XSETINT (inev.ie.y, 0);
  6347   XSETFRAME (inev.ie.frame_or_window, f);
  6348 
  6349   evq_enqueue (&inev);
  6350 }
  6351 
  6352 static gboolean
  6353 drag_motion (GtkWidget *widget, GdkDragContext *context,
  6354              gint x, gint y, guint time)
  6355 
  6356 {
  6357   struct frame *f;
  6358   union buffered_input_event inev;
  6359   GdkAtom name;
  6360   GdkDragAction suggestion;
  6361 
  6362   f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  6363 
  6364   if (!f)
  6365     return FALSE;
  6366 
  6367   if (current_drop_context)
  6368     {
  6369       if (current_drop_context_drop)
  6370         gtk_drag_finish (current_drop_context,
  6371                          FALSE, FALSE, current_drop_time);
  6372 
  6373       g_clear_pointer (&current_drop_context,
  6374                        g_object_unref);
  6375     }
  6376 
  6377   current_drop_context = g_object_ref (context);
  6378   current_drop_time = time;
  6379   current_drop_context_drop = false;
  6380 
  6381   name = gdk_drag_get_selection (context);
  6382   suggestion = gdk_drag_context_get_suggested_action (context);
  6383 
  6384   EVENT_INIT (inev.ie);
  6385 
  6386   inev.ie.kind = DRAG_N_DROP_EVENT;
  6387   inev.ie.modifiers = 0;
  6388   inev.ie.arg = list4 (Qlambda, intern (gdk_atom_name (name)),
  6389                        make_uint (time),
  6390                        drag_action_to_symbol (suggestion));
  6391   inev.ie.timestamp = time;
  6392 
  6393   XSETINT (inev.ie.x, x);
  6394   XSETINT (inev.ie.y, y);
  6395   XSETFRAME (inev.ie.frame_or_window, f);
  6396 
  6397   evq_enqueue (&inev);
  6398 
  6399   return TRUE;
  6400 }
  6401 
  6402 static gboolean
  6403 drag_drop (GtkWidget *widget, GdkDragContext *context,
  6404            int x, int y, guint time, gpointer user_data)
  6405 {
  6406   struct frame *f;
  6407   union buffered_input_event inev;
  6408   GdkAtom name;
  6409   GdkDragAction selected_action;
  6410 
  6411   f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
  6412 
  6413   if (!f)
  6414     return FALSE;
  6415 
  6416   if (current_drop_context)
  6417     {
  6418       if (current_drop_context_drop)
  6419         gtk_drag_finish (current_drop_context,
  6420                          FALSE, FALSE, current_drop_time);
  6421 
  6422       g_clear_pointer (&current_drop_context,
  6423                        g_object_unref);
  6424     }
  6425 
  6426   current_drop_context = g_object_ref (context);
  6427   current_drop_time = time;
  6428   current_drop_context_drop = true;
  6429 
  6430   name = gdk_drag_get_selection (context);
  6431   selected_action = gdk_drag_context_get_selected_action (context);
  6432 
  6433   EVENT_INIT (inev.ie);
  6434 
  6435   inev.ie.kind = DRAG_N_DROP_EVENT;
  6436   inev.ie.modifiers = 0;
  6437   inev.ie.arg = list4 (Qquote, intern (gdk_atom_name (name)),
  6438                        make_uint (time),
  6439                        drag_action_to_symbol (selected_action));
  6440   inev.ie.timestamp = time;
  6441 
  6442   XSETINT (inev.ie.x, x);
  6443   XSETINT (inev.ie.y, y);
  6444   XSETFRAME (inev.ie.frame_or_window, f);
  6445 
  6446   evq_enqueue (&inev);
  6447 
  6448   return TRUE;
  6449 }
  6450 
  6451 static void
  6452 pgtk_monitors_changed_cb (GdkScreen *screen, gpointer user_data)
  6453 {
  6454   struct terminal *terminal;
  6455   union buffered_input_event inev;
  6456 
  6457   EVENT_INIT (inev.ie);
  6458   terminal = user_data;
  6459   inev.ie.kind = MONITORS_CHANGED_EVENT;
  6460   XSETTERMINAL (inev.ie.arg, terminal);
  6461 
  6462   evq_enqueue (&inev);
  6463 }
  6464 
  6465 static gboolean pgtk_selection_event (GtkWidget *, GdkEvent *, gpointer);
  6466 
  6467 void
  6468 pgtk_set_event_handler (struct frame *f)
  6469 {
  6470   if (f->tooltip)
  6471     {
  6472       g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "draw",
  6473                         G_CALLBACK (pgtk_handle_draw), NULL);
  6474       return;
  6475     }
  6476 
  6477   gtk_drag_dest_set (FRAME_GTK_WIDGET (f), 0, NULL, 0,
  6478                      (GDK_ACTION_MOVE | GDK_ACTION_COPY
  6479                       | GDK_ACTION_LINK | GDK_ACTION_PRIVATE));
  6480 
  6481   if (FRAME_GTK_OUTER_WIDGET (f))
  6482     {
  6483       g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)),
  6484                         "window-state-event", G_CALLBACK (window_state_event),
  6485                         NULL);
  6486       g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "delete-event",
  6487                         G_CALLBACK (delete_event), NULL);
  6488       g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "event",
  6489                         G_CALLBACK (pgtk_handle_event), NULL);
  6490       g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "configure-event",
  6491                         G_CALLBACK (configure_event), NULL);
  6492     }
  6493 
  6494   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "map-event",
  6495                     G_CALLBACK (map_event), NULL);
  6496   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "size-allocate",
  6497                     G_CALLBACK (size_allocate), f);
  6498   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "key-press-event",
  6499                     G_CALLBACK (key_press_event), NULL);
  6500   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "key-release-event",
  6501                     G_CALLBACK (key_release_event), NULL);
  6502   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "focus-in-event",
  6503                     G_CALLBACK (focus_in_event), NULL);
  6504   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "focus-out-event",
  6505                     G_CALLBACK (focus_out_event), NULL);
  6506   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "enter-notify-event",
  6507                     G_CALLBACK (enter_notify_event), NULL);
  6508   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "leave-notify-event",
  6509                     G_CALLBACK (leave_notify_event), NULL);
  6510   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "motion-notify-event",
  6511                     G_CALLBACK (motion_notify_event), NULL);
  6512   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "button-press-event",
  6513                     G_CALLBACK (button_event), NULL);
  6514   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "button-release-event",
  6515                     G_CALLBACK (button_event), NULL);
  6516   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "scroll-event",
  6517                     G_CALLBACK (scroll_event), NULL);
  6518   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "configure-event",
  6519                     G_CALLBACK (configure_event), NULL);
  6520   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-leave",
  6521                     G_CALLBACK (drag_leave), NULL);
  6522   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-motion",
  6523                     G_CALLBACK (drag_motion), NULL);
  6524   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-drop",
  6525                     G_CALLBACK (drag_drop), NULL);
  6526   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "draw",
  6527                     G_CALLBACK (pgtk_handle_draw), NULL);
  6528   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "property-notify-event",
  6529                     G_CALLBACK (pgtk_selection_event), NULL);
  6530   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-clear-event",
  6531                     G_CALLBACK (pgtk_selection_event), NULL);
  6532   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-request-event",
  6533                     G_CALLBACK (pgtk_selection_event), NULL);
  6534   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-notify-event",
  6535                     G_CALLBACK (pgtk_selection_event), NULL);
  6536   g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "event",
  6537                     G_CALLBACK (pgtk_handle_event), NULL);
  6538 }
  6539 
  6540 static void
  6541 my_log_handler (const gchar * log_domain, GLogLevelFlags log_level,
  6542                 const gchar * msg, gpointer user_data)
  6543 {
  6544   if (!strstr (msg, "g_set_prgname"))
  6545     fprintf (stderr, "%s-WARNING **: %s", log_domain, msg);
  6546 }
  6547 
  6548 /* Test whether two display-name strings agree up to the dot that separates
  6549    the screen number from the server number.  */
  6550 static bool
  6551 same_x_server (const char *name1, const char *name2)
  6552 {
  6553   bool seen_colon = false;
  6554   Lisp_Object sysname = Fsystem_name ();
  6555   const char *system_name = SSDATA (sysname);
  6556   ptrdiff_t system_name_length = SBYTES (sysname);
  6557   ptrdiff_t length_until_period = 0;
  6558 
  6559   while (system_name[length_until_period] != 0
  6560          && system_name[length_until_period] != '.')
  6561     length_until_period++;
  6562 
  6563   /* Treat `unix' like an empty host name.  */
  6564   if (!strncmp (name1, "unix:", 5))
  6565     name1 += 4;
  6566   if (!strncmp (name2, "unix:", 5))
  6567     name2 += 4;
  6568   /* Treat this host's name like an empty host name.  */
  6569   if (!strncmp (name1, system_name, system_name_length)
  6570       && name1[system_name_length] == ':')
  6571     name1 += system_name_length;
  6572   if (!strncmp (name2, system_name, system_name_length)
  6573       && name2[system_name_length] == ':')
  6574     name2 += system_name_length;
  6575   /* Treat this host's domainless name like an empty host name.  */
  6576   if (!strncmp (name1, system_name, length_until_period)
  6577       && name1[length_until_period] == ':')
  6578     name1 += length_until_period;
  6579   if (!strncmp (name2, system_name, length_until_period)
  6580       && name2[length_until_period] == ':')
  6581     name2 += length_until_period;
  6582 
  6583   for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
  6584     {
  6585       if (*name1 == ':')
  6586         seen_colon = true;
  6587       if (seen_colon && *name1 == '.')
  6588         return true;
  6589     }
  6590   return (seen_colon
  6591           && (*name1 == '.' || *name1 == '\0')
  6592           && (*name2 == '.' || *name2 == '\0'));
  6593 }
  6594 
  6595 static struct frame *
  6596 pgtk_find_selection_owner (GdkWindow *window)
  6597 {
  6598   Lisp_Object tail, tem;
  6599   struct frame *f;
  6600 
  6601   FOR_EACH_FRAME (tail, tem)
  6602     {
  6603       f = XFRAME (tem);
  6604 
  6605       if (FRAME_PGTK_P (f)
  6606           && (FRAME_GDK_WINDOW (f) == window))
  6607         return f;
  6608     }
  6609 
  6610   return NULL;
  6611 }
  6612 
  6613 static gboolean
  6614 pgtk_selection_event (GtkWidget *widget, GdkEvent *event,
  6615                       gpointer user_data)
  6616 {
  6617   struct frame *f;
  6618   union buffered_input_event inev;
  6619 
  6620   if (event->type == GDK_PROPERTY_NOTIFY)
  6621     pgtk_handle_property_notify (&event->property);
  6622   else if (event->type == GDK_SELECTION_CLEAR
  6623            || event->type == GDK_SELECTION_REQUEST)
  6624     {
  6625       f = pgtk_find_selection_owner (event->selection.window);
  6626 
  6627       if (f)
  6628         {
  6629           EVENT_INIT (inev.ie);
  6630 
  6631           inev.sie.kind = (event->type == GDK_SELECTION_CLEAR
  6632                            ? SELECTION_CLEAR_EVENT
  6633                            : SELECTION_REQUEST_EVENT);
  6634 
  6635           SELECTION_EVENT_DPYINFO (&inev.sie) = FRAME_DISPLAY_INFO (f);
  6636           SELECTION_EVENT_SELECTION (&inev.sie) = event->selection.selection;
  6637           SELECTION_EVENT_TIME (&inev.sie) = event->selection.time;
  6638 
  6639           if (event->type == GDK_SELECTION_REQUEST)
  6640             {
  6641               /* FIXME: when does GDK destroy the requestor GdkWindow
  6642                  object?
  6643 
  6644                  It would make sense to wait for the transfer to
  6645                  complete.  But I don't know if GDK actually does
  6646                  that.  */
  6647               SELECTION_EVENT_REQUESTOR (&inev.sie) = event->selection.requestor;
  6648               SELECTION_EVENT_TARGET (&inev.sie) = event->selection.target;
  6649               SELECTION_EVENT_PROPERTY (&inev.sie) = event->selection.property;
  6650             }
  6651 
  6652           evq_enqueue (&inev);
  6653           return TRUE;
  6654         }
  6655     }
  6656   else if (event->type == GDK_SELECTION_NOTIFY)
  6657     pgtk_handle_selection_notify (&event->selection);
  6658 
  6659   return FALSE;
  6660 }
  6661 
  6662 /* Display a warning message if the PGTK port is being used under X;
  6663    that is not supported.  */
  6664 
  6665 static void
  6666 pgtk_display_x_warning (GdkDisplay *display)
  6667 {
  6668   GtkWidget *dialog_widget, *label, *content_area;
  6669   GtkDialog *dialog;
  6670   GtkWindow *window;
  6671   GdkScreen *screen;
  6672 
  6673   /* Do this instead of GDK_IS_X11_DISPLAY because the GDK X header
  6674      pulls in Xlib, which conflicts with definitions in pgtkgui.h.  */
  6675   if (strcmp (G_OBJECT_TYPE_NAME (display),
  6676               "GdkX11Display"))
  6677     return;
  6678 
  6679   dialog_widget = gtk_dialog_new ();
  6680   dialog = GTK_DIALOG (dialog_widget);
  6681   window = GTK_WINDOW (dialog_widget);
  6682   screen = gdk_display_get_default_screen (display);
  6683   content_area = gtk_dialog_get_content_area (dialog);
  6684 
  6685   gtk_window_set_title (window, "Warning");
  6686   gtk_window_set_screen (window, screen);
  6687 
  6688   label = gtk_label_new ("You are trying to run Emacs configured with"
  6689                           " the \"pure-GTK\" interface under the X Window"
  6690                           " System.  That configuration is unsupported and"
  6691                           " will lead to sporadic crashes during transfer of"
  6692                           " large selection data.  It will also lead to"
  6693                           " various problems with keyboard input.");
  6694   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
  6695   gtk_container_add (GTK_CONTAINER (content_area), label);
  6696   gtk_widget_show (label);
  6697   gtk_widget_show (dialog_widget);
  6698 }
  6699 
  6700 /* Open a connection to X display DISPLAY_NAME, and return
  6701    the structure that describes the open display.
  6702    If we cannot contact the display, return null.  */
  6703 
  6704 struct pgtk_display_info *
  6705 pgtk_term_init (Lisp_Object display_name, char *resource_name)
  6706 {
  6707   GdkDisplay *dpy;
  6708   struct terminal *terminal;
  6709   struct pgtk_display_info *dpyinfo;
  6710   static int x_initialized = 0;
  6711   static unsigned x_display_id = 0;
  6712   static char *initial_display = NULL;
  6713   char *dpy_name;
  6714   static void *handle = NULL;
  6715   Lisp_Object lisp_dpy_name = Qnil;
  6716   GdkScreen *gscr;
  6717   gdouble dpi;
  6718 
  6719   block_input ();
  6720 
  6721   if (!x_initialized)
  6722     {
  6723       any_help_event_p = false;
  6724 
  6725       Fset_input_interrupt_mode (Qt);
  6726       baud_rate = 19200;
  6727 
  6728 #ifdef USE_CAIRO
  6729       gui_init_fringe (&pgtk_redisplay_interface);
  6730 #endif
  6731 
  6732       ++x_initialized;
  6733     }
  6734 
  6735   dpy_name = SSDATA (display_name);
  6736   if (strlen (dpy_name) == 0 && initial_display != NULL)
  6737     dpy_name = initial_display;
  6738   lisp_dpy_name = build_string (dpy_name);
  6739 
  6740   {
  6741 #define NUM_ARGV 10
  6742     int argc;
  6743     char *argv[NUM_ARGV];
  6744     char **argv2 = argv;
  6745     guint id;
  6746 
  6747     if (x_initialized++ > 1)
  6748       {
  6749         xg_display_open (dpy_name, &dpy);
  6750       }
  6751     else
  6752       {
  6753         static char display_opt[] = "--display";
  6754         static char name_opt[] = "--name";
  6755 
  6756         for (argc = 0; argc < NUM_ARGV; ++argc)
  6757           argv[argc] = 0;
  6758 
  6759         argc = 0;
  6760         argv[argc++] = initial_argv[0];
  6761 
  6762         if (strlen (dpy_name) != 0)
  6763           {
  6764             argv[argc++] = display_opt;
  6765             argv[argc++] = dpy_name;
  6766           }
  6767 
  6768         argv[argc++] = name_opt;
  6769         argv[argc++] = resource_name;
  6770 
  6771         /* Work around GLib bug that outputs a faulty warning. See
  6772            https://bugzilla.gnome.org/show_bug.cgi?id=563627.  */
  6773         id = g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL
  6774                                 | G_LOG_FLAG_RECURSION, my_log_handler, NULL);
  6775 
  6776         /* gtk_init does set_locale.  Fix locale before and after.  */
  6777         fixup_locale ();
  6778         unrequest_sigio ();     /* See comment in x_display_ok.  */
  6779         gtk_init (&argc, &argv2);
  6780         request_sigio ();
  6781         fixup_locale ();
  6782 
  6783 
  6784         g_log_remove_handler ("GLib", id);
  6785 
  6786         xg_initialize ();
  6787 
  6788         dpy = DEFAULT_GDK_DISPLAY ();
  6789 
  6790         initial_display = g_strdup (gdk_display_get_name (dpy));
  6791         dpy_name = initial_display;
  6792         lisp_dpy_name = build_string (dpy_name);
  6793       }
  6794   }
  6795 
  6796   /* Detect failure.  */
  6797   if (dpy == 0)
  6798     {
  6799       unblock_input ();
  6800       return 0;
  6801     }
  6802 
  6803   /* If the PGTK port is being used under X, complain very loudly, as
  6804      that isn't supported.  */
  6805   pgtk_display_x_warning (dpy);
  6806 
  6807   dpyinfo = xzalloc (sizeof *dpyinfo);
  6808   pgtk_initialize_display_info (dpyinfo);
  6809   terminal = pgtk_create_terminal (dpyinfo);
  6810 
  6811   {
  6812     struct pgtk_display_info *share;
  6813 
  6814     for (share = x_display_list; share; share = share->next)
  6815       if (same_x_server (SSDATA (XCAR (share->name_list_element)), dpy_name))
  6816         break;
  6817     if (share)
  6818       terminal->kboard = share->terminal->kboard;
  6819     else
  6820       {
  6821         terminal->kboard = allocate_kboard (Qpgtk);
  6822 
  6823         /* Don't let the initial kboard remain current longer than necessary.
  6824            That would cause problems if a file loaded on startup tries to
  6825            prompt in the mini-buffer.  */
  6826         if (current_kboard == initial_kboard)
  6827           current_kboard = terminal->kboard;
  6828       }
  6829     terminal->kboard->reference_count++;
  6830   }
  6831 
  6832   /* Put this display on the chain.  */
  6833   dpyinfo->next = x_display_list;
  6834   x_display_list = dpyinfo;
  6835 
  6836   dpyinfo->name_list_element = Fcons (lisp_dpy_name, Qnil);
  6837   dpyinfo->gdpy = dpy;
  6838 
  6839   /* https://lists.gnu.org/r/emacs-devel/2015-11/msg00194.html  */
  6840   dpyinfo->smallest_font_height = 1;
  6841   dpyinfo->smallest_char_width = 1;
  6842 
  6843   /* Set the name of the terminal. */
  6844   terminal->name = xlispstrdup (lisp_dpy_name);
  6845 
  6846   Lisp_Object system_name = Fsystem_name ();
  6847   ptrdiff_t nbytes;
  6848   if (INT_ADD_WRAPV (SBYTES (Vinvocation_name), SBYTES (system_name) + 2,
  6849                      &nbytes))
  6850     memory_full (SIZE_MAX);
  6851   dpyinfo->x_id = ++x_display_id;
  6852   dpyinfo->x_id_name = xmalloc (nbytes);
  6853   char *nametail = lispstpcpy (dpyinfo->x_id_name, Vinvocation_name);
  6854   *nametail++ = '@';
  6855   lispstpcpy (nametail, system_name);
  6856 
  6857   /* Get the scroll bar cursor.  */
  6858   /* We must create a GTK cursor, it is required for GTK widgets.  */
  6859   dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->gdpy);
  6860 
  6861   dpyinfo->vertical_scroll_bar_cursor
  6862     = gdk_cursor_new_for_display (dpyinfo->gdpy, GDK_SB_V_DOUBLE_ARROW);
  6863 
  6864   dpyinfo->horizontal_scroll_bar_cursor
  6865     = gdk_cursor_new_for_display (dpyinfo->gdpy, GDK_SB_H_DOUBLE_ARROW);
  6866 
  6867   dpyinfo->icon_bitmap_id = -1;
  6868 
  6869   reset_mouse_highlight (&dpyinfo->mouse_highlight);
  6870 
  6871   gscr = gdk_display_get_default_screen (dpyinfo->gdpy);
  6872   dpi = gdk_screen_get_resolution (gscr);
  6873 
  6874   if (dpi < 0)
  6875     dpi = 96.0;
  6876 
  6877   dpyinfo->resx = dpi;
  6878   dpyinfo->resy = dpi;
  6879 
  6880   g_signal_connect (G_OBJECT (gscr), "monitors-changed",
  6881                     G_CALLBACK (pgtk_monitors_changed_cb),
  6882                     terminal);
  6883 
  6884   /* Set up scrolling increments.  */
  6885   dpyinfo->scroll.x_per_char = 1;
  6886   dpyinfo->scroll.y_per_line = 1;
  6887 
  6888   dpyinfo->connection = -1;
  6889 
  6890   if (!handle)
  6891     handle = dlopen (NULL, RTLD_LAZY);
  6892 
  6893 #ifdef GDK_WINDOWING_X11
  6894   if (!strcmp (G_OBJECT_TYPE_NAME (dpy), "GdkX11Display") && handle)
  6895     {
  6896       void *(*gdk_x11_display_get_xdisplay) (GdkDisplay *)
  6897         = dlsym (handle, "gdk_x11_display_get_xdisplay");
  6898       int (*x_connection_number) (void *)
  6899         = dlsym (handle, "XConnectionNumber");
  6900 
  6901       if (x_connection_number
  6902           && gdk_x11_display_get_xdisplay)
  6903         dpyinfo->connection
  6904           = x_connection_number (gdk_x11_display_get_xdisplay (dpy));
  6905     }
  6906 #endif
  6907 
  6908 #ifdef GDK_WINDOWING_WAYLAND
  6909   if (GDK_IS_WAYLAND_DISPLAY (dpy) && handle)
  6910     {
  6911       struct wl_display *wl_dpy = gdk_wayland_display_get_wl_display (dpy);
  6912       int (*display_get_fd) (struct wl_display *)
  6913         = dlsym (handle, "wl_display_get_fd");
  6914 
  6915       if (display_get_fd)
  6916         dpyinfo->connection = display_get_fd (wl_dpy);
  6917     }
  6918 #endif
  6919 
  6920   if (dpyinfo->connection >= 0)
  6921     {
  6922       add_keyboard_wait_descriptor (dpyinfo->connection);
  6923 #ifdef F_SETOWN
  6924       fcntl (dpyinfo->connection, F_SETOWN, getpid ());
  6925 #endif /* ! defined (F_SETOWN) */
  6926 
  6927       if (interrupt_input)
  6928         init_sigio (dpyinfo->connection);
  6929     }
  6930 
  6931   dpyinfo->invisible_cursor
  6932     = gdk_cursor_new_for_display (dpyinfo->gdpy, GDK_BLANK_CURSOR);
  6933 
  6934   xsettings_initialize (dpyinfo);
  6935 
  6936   pgtk_im_init (dpyinfo);
  6937 
  6938   g_signal_connect (G_OBJECT (dpyinfo->gdpy), "seat-added",
  6939                     G_CALLBACK (pgtk_seat_added_cb), dpyinfo);
  6940   g_signal_connect (G_OBJECT (dpyinfo->gdpy), "seat-removed",
  6941                     G_CALLBACK (pgtk_seat_removed_cb), dpyinfo);
  6942   pgtk_enumerate_devices (dpyinfo, true);
  6943 
  6944   unblock_input ();
  6945 
  6946   return dpyinfo;
  6947 }
  6948 
  6949 /* Get rid of display DPYINFO, deleting all frames on it,
  6950    and without sending any more commands to the X server.  */
  6951 
  6952 static void
  6953 pgtk_delete_display (struct pgtk_display_info *dpyinfo)
  6954 {
  6955   struct terminal *t;
  6956 
  6957   /* Close all frames and delete the generic struct terminal for this
  6958      X display.  */
  6959   for (t = terminal_list; t; t = t->next_terminal)
  6960     if (t->type == output_pgtk && t->display_info.pgtk == dpyinfo)
  6961       {
  6962         delete_terminal (t);
  6963         break;
  6964       }
  6965 
  6966   if (x_display_list == dpyinfo)
  6967     x_display_list = dpyinfo->next;
  6968   else
  6969     {
  6970       struct pgtk_display_info *tail;
  6971 
  6972       for (tail = x_display_list; tail; tail = tail->next)
  6973         if (tail->next == dpyinfo)
  6974           tail->next = tail->next->next;
  6975     }
  6976 
  6977   pgtk_free_devices (dpyinfo);
  6978   xfree (dpyinfo);
  6979 }
  6980 
  6981 char *
  6982 pgtk_xlfd_to_fontname (const char *xlfd)
  6983 /* --------------------------------------------------------------------------
  6984     Convert an X font name (XLFD) to an Gtk font name.
  6985     Only family is used.
  6986     The string returned is temporarily allocated.
  6987    -------------------------------------------------------------------------- */
  6988 {
  6989   char *name = xmalloc (180);
  6990 
  6991   if (!strncmp (xlfd, "--", 2))
  6992     {
  6993       if (sscanf (xlfd, "--%179[^-]-", name) != 1)
  6994         name[0] = '\0';
  6995     }
  6996   else
  6997     {
  6998       if (sscanf (xlfd, "-%*[^-]-%179[^-]-", name) != 1)
  6999         name[0] = '\0';
  7000     }
  7001 
  7002   /* stopgap for malformed XLFD input */
  7003   if (strlen (name) == 0)
  7004     strcpy (name, "Monospace");
  7005 
  7006   return name;
  7007 }
  7008 
  7009 bool
  7010 pgtk_defined_color (struct frame *f, const char *name,
  7011                     Emacs_Color *color_def, bool alloc,
  7012                     bool makeIndex)
  7013 /* --------------------------------------------------------------------------
  7014          Return true if named color found, and set color_def rgb accordingly.
  7015          If makeIndex and alloc are nonzero put the color in the color_table,
  7016          and set color_def pixel to the resulting index.
  7017          If makeIndex is zero, set color_def pixel to ARGB.
  7018          Return false if not found
  7019    -------------------------------------------------------------------------- */
  7020 {
  7021   int r;
  7022 
  7023   block_input ();
  7024   r = xg_check_special_colors (f, name, color_def);
  7025   if (!r)
  7026     r = pgtk_parse_color (f, name, color_def);
  7027   unblock_input ();
  7028   return r;
  7029 }
  7030 
  7031 /* On frame F, translate the color name to RGB values.  Use cached
  7032    information, if possible.
  7033 
  7034    Note that there is currently no way to clean old entries out of the
  7035    cache.  However, it is limited to names in the server's database,
  7036    and names we've actually looked up; list-colors-display is probably
  7037    the most color-intensive case we're likely to hit.  */
  7038 
  7039 int
  7040 pgtk_parse_color (struct frame *f, const char *color_name,
  7041                   Emacs_Color * color)
  7042 {
  7043   GdkRGBA rgba;
  7044   if (gdk_rgba_parse (&rgba, color_name))
  7045     {
  7046       color->red = rgba.red * 65535;
  7047       color->green = rgba.green * 65535;
  7048       color->blue = rgba.blue * 65535;
  7049       color->pixel = ((color->red >> 8) << 16
  7050                       | (color->green >> 8) << 8
  7051                       | (color->blue >> 8) << 0);
  7052       return 1;
  7053     }
  7054   return 0;
  7055 }
  7056 
  7057 /* On frame F, translate pixel colors to RGB values for the NCOLORS
  7058    colors in COLORS.  On W32, we no longer try to map colors to
  7059    a palette.  */
  7060 void
  7061 pgtk_query_colors (struct frame *f, Emacs_Color * colors, int ncolors)
  7062 {
  7063   int i;
  7064 
  7065   for (i = 0; i < ncolors; i++)
  7066     {
  7067       unsigned long pixel = colors[i].pixel;
  7068       /* Convert to a 16 bit value in range 0 - 0xffff. */
  7069 #define GetRValue(p) (((p) >> 16) & 0xff)
  7070 #define GetGValue(p) (((p) >> 8) & 0xff)
  7071 #define GetBValue(p) (((p) >> 0) & 0xff)
  7072       colors[i].red = GetRValue (pixel) * 257;
  7073       colors[i].green = GetGValue (pixel) * 257;
  7074       colors[i].blue = GetBValue (pixel) * 257;
  7075     }
  7076 }
  7077 
  7078 void
  7079 pgtk_query_color (struct frame *f, Emacs_Color * color)
  7080 {
  7081   pgtk_query_colors (f, color, 1);
  7082 }
  7083 
  7084 void
  7085 pgtk_clear_area (struct frame *f, int x, int y, int width, int height)
  7086 {
  7087   cairo_t *cr;
  7088 
  7089   eassert (width > 0 && height > 0);
  7090 
  7091   cr = pgtk_begin_cr_clip (f);
  7092   pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT (f)->background_color,
  7093                                  true);
  7094   cairo_rectangle (cr, x, y, width, height);
  7095   cairo_fill (cr);
  7096   pgtk_end_cr_clip (f);
  7097 }
  7098 
  7099 
  7100 void
  7101 syms_of_pgtkterm (void)
  7102 {
  7103   DEFSYM (Qmodifier_value, "modifier-value");
  7104   DEFSYM (Qalt, "alt");
  7105   DEFSYM (Qhyper, "hyper");
  7106   DEFSYM (Qmeta, "meta");
  7107   DEFSYM (Qsuper, "super");
  7108   DEFSYM (Qcontrol, "control");
  7109   DEFSYM (QUTF8_STRING, "UTF8_STRING");
  7110 
  7111   DEFSYM (Qfile, "file");
  7112   DEFSYM (Qurl, "url");
  7113 
  7114   DEFSYM (Qlatin_1, "latin-1");
  7115 
  7116   xg_default_icon_file
  7117     = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
  7118   staticpro (&xg_default_icon_file);
  7119 
  7120   DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock");
  7121 
  7122   DEFSYM (Qcopy, "copy");
  7123   DEFSYM (Qmove, "move");
  7124   DEFSYM (Qlink, "link");
  7125   DEFSYM (Qprivate, "private");
  7126 
  7127 
  7128   Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier));
  7129   Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier));
  7130   Fput (Qmeta, Qmodifier_value, make_fixnum (meta_modifier));
  7131   Fput (Qsuper, Qmodifier_value, make_fixnum (super_modifier));
  7132   Fput (Qcontrol, Qmodifier_value, make_fixnum (ctrl_modifier));
  7133 
  7134   DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym,
  7135                doc: /* SKIP: real doc in xterm.c.  */);
  7136   Vx_ctrl_keysym = Qnil;
  7137 
  7138   DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym,
  7139                doc: /* SKIP: real doc in xterm.c.  */);
  7140   Vx_alt_keysym = Qnil;
  7141 
  7142   DEFVAR_LISP ("x-hyper-keysym", Vx_hyper_keysym,
  7143                doc: /* SKIP: real doc in xterm.c.  */);
  7144   Vx_hyper_keysym = Qnil;
  7145 
  7146   DEFVAR_LISP ("x-meta-keysym", Vx_meta_keysym,
  7147                doc: /* SKIP: real doc in xterm.c.  */);
  7148   Vx_meta_keysym = Qnil;
  7149 
  7150   DEFVAR_LISP ("x-super-keysym", Vx_super_keysym,
  7151                doc: /* SKIP: real doc in xterm.c.  */);
  7152   Vx_super_keysym = Qnil;
  7153 
  7154   DEFVAR_BOOL ("x-use-underline-position-properties",
  7155                x_use_underline_position_properties,
  7156      doc: /* SKIP: real doc in xterm.c.  */);
  7157   x_use_underline_position_properties = 1;
  7158 
  7159   DEFVAR_BOOL ("x-underline-at-descent-line",
  7160                x_underline_at_descent_line,
  7161      doc: /* SKIP: real doc in xterm.c.  */);
  7162   x_underline_at_descent_line = 0;
  7163 
  7164   DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
  7165      doc: /* SKIP: real doc in xterm.c.  */);
  7166   Vx_toolkit_scroll_bars = intern_c_string ("gtk");
  7167 
  7168   DEFVAR_LISP ("pgtk-wait-for-event-timeout", Vpgtk_wait_for_event_timeout,
  7169                doc: /* How long to wait for GTK events.
  7170 
  7171 Emacs will wait up to this many seconds to receive some GTK events
  7172 after making changes which affect the state of the graphical
  7173 interface.  Under some window managers this can take an indefinite
  7174 amount of time, so it is important to limit the wait.
  7175 
  7176 If set to a non-float value, there will be no wait at all.  */);
  7177   Vpgtk_wait_for_event_timeout = make_float (0.1);
  7178 
  7179   DEFVAR_LISP ("pgtk-keysym-table", Vpgtk_keysym_table,
  7180     doc: /* Hash table of character codes indexed by X keysym codes.  */);
  7181   Vpgtk_keysym_table = make_hash_table (hashtest_eql, 900, DEFAULT_REHASH_SIZE,
  7182                                         DEFAULT_REHASH_THRESHOLD, Qnil, false);
  7183 
  7184   window_being_scrolled = Qnil;
  7185   staticpro (&window_being_scrolled);
  7186 
  7187   /* Tell Emacs about this window system.  */
  7188   Fprovide (Qpgtk, Qnil);
  7189 }
  7190 
  7191 /* Cairo does not allow resizing a surface/context after it is
  7192    created, so we need to trash the old context, create a new context
  7193    on the next cr_clip_begin with the new dimensions and request a
  7194    re-draw.
  7195 
  7196    This will leave the active context available to present on screen
  7197    until a redrawn frame is completed.  */
  7198 void
  7199 pgtk_cr_update_surface_desired_size (struct frame *f, int width, int height, bool force)
  7200 {
  7201   if (FRAME_CR_SURFACE_DESIRED_WIDTH (f) != width
  7202       || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height
  7203       || force)
  7204     {
  7205       pgtk_cr_destroy_frame_context (f);
  7206       FRAME_CR_SURFACE_DESIRED_WIDTH (f) = width;
  7207       FRAME_CR_SURFACE_DESIRED_HEIGHT (f) = height;
  7208       SET_FRAME_GARBAGED (f);
  7209     }
  7210 }
  7211 
  7212 
  7213 cairo_t *
  7214 pgtk_begin_cr_clip (struct frame *f)
  7215 {
  7216   cairo_t *cr = FRAME_CR_CONTEXT (f);
  7217 
  7218   if (!cr)
  7219     {
  7220       cairo_surface_t *surface
  7221         = gdk_window_create_similar_surface (gtk_widget_get_window
  7222                                              (FRAME_GTK_WIDGET (f)),
  7223                                              CAIRO_CONTENT_COLOR_ALPHA,
  7224                                              FRAME_CR_SURFACE_DESIRED_WIDTH (f),
  7225                                              FRAME_CR_SURFACE_DESIRED_HEIGHT
  7226                                              (f));
  7227 
  7228       cr = FRAME_CR_CONTEXT (f) = cairo_create (surface);
  7229       cairo_surface_destroy (surface);
  7230     }
  7231 
  7232   cairo_save (cr);
  7233 
  7234   return cr;
  7235 }
  7236 
  7237 void
  7238 pgtk_end_cr_clip (struct frame *f)
  7239 {
  7240   cairo_restore (FRAME_CR_CONTEXT (f));
  7241 }
  7242 
  7243 void
  7244 pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC *gc,
  7245                                        bool respects_alpha_background)
  7246 {
  7247   pgtk_set_cr_source_with_color (f, gc->foreground,
  7248                                  respects_alpha_background);
  7249 }
  7250 
  7251 void
  7252 pgtk_set_cr_source_with_gc_background (struct frame *f, Emacs_GC *gc,
  7253                                        bool respects_alpha_background)
  7254 {
  7255   pgtk_set_cr_source_with_color (f, gc->background,
  7256                                  respects_alpha_background);
  7257 }
  7258 
  7259 void
  7260 pgtk_set_cr_source_with_color (struct frame *f, unsigned long color,
  7261                                bool respects_alpha_background)
  7262 {
  7263   Emacs_Color col;
  7264   col.pixel = color;
  7265   pgtk_query_color (f, &col);
  7266 
  7267   if (!respects_alpha_background)
  7268     {
  7269       cairo_set_source_rgb (FRAME_CR_CONTEXT (f), col.red / 65535.0,
  7270                             col.green / 65535.0, col.blue / 65535.0);
  7271       cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_OVER);
  7272     }
  7273   else
  7274     {
  7275       cairo_set_source_rgba (FRAME_CR_CONTEXT (f), col.red / 65535.0,
  7276                              col.green / 65535.0, col.blue / 65535.0,
  7277                              f->alpha_background);
  7278       cairo_set_operator (FRAME_CR_CONTEXT (f), CAIRO_OPERATOR_SOURCE);
  7279     }
  7280 }
  7281 
  7282 void
  7283 pgtk_cr_draw_frame (cairo_t * cr, struct frame *f)
  7284 {
  7285   cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), 0, 0);
  7286   cairo_paint (cr);
  7287 }
  7288 
  7289 static cairo_status_t
  7290 pgtk_cr_accumulate_data (void *closure, const unsigned char *data,
  7291                          unsigned int length)
  7292 {
  7293   Lisp_Object *acc = (Lisp_Object *) closure;
  7294 
  7295   *acc = Fcons (make_unibyte_string ((char const *) data, length), *acc);
  7296 
  7297   return CAIRO_STATUS_SUCCESS;
  7298 }
  7299 
  7300 void
  7301 pgtk_cr_destroy_frame_context (struct frame *f)
  7302 {
  7303   if (FRAME_CR_CONTEXT (f) != NULL)
  7304     {
  7305       cairo_destroy (FRAME_CR_CONTEXT (f));
  7306       FRAME_CR_CONTEXT (f) = NULL;
  7307     }
  7308 }
  7309 
  7310 static void
  7311 pgtk_cr_destroy (void *cr)
  7312 {
  7313   block_input ();
  7314   cairo_destroy (cr);
  7315   unblock_input ();
  7316 }
  7317 
  7318 Lisp_Object
  7319 pgtk_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
  7320 {
  7321   struct frame *f;
  7322   cairo_surface_t *surface;
  7323   cairo_t *cr;
  7324   int width, height;
  7325   void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL;
  7326   Lisp_Object acc = Qnil;
  7327   specpdl_ref count = SPECPDL_INDEX ();
  7328 
  7329   specbind (Qredisplay_dont_pause, Qt);
  7330   redisplay_preserve_echo_area (31);
  7331 
  7332   f = XFRAME (XCAR (frames));
  7333   frames = XCDR (frames);
  7334   width = FRAME_PIXEL_WIDTH (f);
  7335   height = FRAME_PIXEL_HEIGHT (f);
  7336 
  7337   block_input ();
  7338 #ifdef CAIRO_HAS_PDF_SURFACE
  7339   if (surface_type == CAIRO_SURFACE_TYPE_PDF)
  7340     {
  7341       surface = cairo_pdf_surface_create_for_stream (pgtk_cr_accumulate_data, &acc,
  7342                                                      width, height);
  7343       surface_set_size_func = cairo_pdf_surface_set_size;
  7344     }
  7345   else
  7346 #endif
  7347 #ifdef CAIRO_HAS_PNG_FUNCTIONS
  7348   if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
  7349     surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
  7350   else
  7351 #endif
  7352 #ifdef CAIRO_HAS_PS_SURFACE
  7353   if (surface_type == CAIRO_SURFACE_TYPE_PS)
  7354     {
  7355       surface = cairo_ps_surface_create_for_stream (pgtk_cr_accumulate_data, &acc,
  7356                                                     width, height);
  7357       surface_set_size_func = cairo_ps_surface_set_size;
  7358     }
  7359   else
  7360 #endif
  7361 #ifdef CAIRO_HAS_SVG_SURFACE
  7362   if (surface_type == CAIRO_SURFACE_TYPE_SVG)
  7363     surface = cairo_svg_surface_create_for_stream (pgtk_cr_accumulate_data, &acc,
  7364                                                    width, height);
  7365   else
  7366 #endif
  7367     abort ();
  7368 
  7369   cr = cairo_create (surface);
  7370   cairo_surface_destroy (surface);
  7371   record_unwind_protect_ptr (pgtk_cr_destroy, cr);
  7372 
  7373   while (1)
  7374     {
  7375       cairo_t *saved_cr = FRAME_CR_CONTEXT (f);
  7376       FRAME_CR_CONTEXT (f) = cr;
  7377       pgtk_clear_area (f, 0, 0, width, height);
  7378       expose_frame (f, 0, 0, width, height);
  7379       FRAME_CR_CONTEXT (f) = saved_cr;
  7380 
  7381       if (NILP (frames))
  7382         break;
  7383 
  7384       cairo_surface_show_page (surface);
  7385       f = XFRAME (XCAR (frames));
  7386       frames = XCDR (frames);
  7387       width = FRAME_PIXEL_WIDTH (f);
  7388       height = FRAME_PIXEL_HEIGHT (f);
  7389       if (surface_set_size_func)
  7390         (*surface_set_size_func) (surface, width, height);
  7391 
  7392       unblock_input ();
  7393       maybe_quit ();
  7394       block_input ();
  7395     }
  7396 
  7397 #ifdef CAIRO_HAS_PNG_FUNCTIONS
  7398   if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
  7399     {
  7400       cairo_surface_flush (surface);
  7401       cairo_surface_write_to_png_stream (surface, pgtk_cr_accumulate_data, &acc);
  7402     }
  7403 #endif
  7404   unblock_input ();
  7405 
  7406   unbind_to (count, Qnil);
  7407 
  7408   return CALLN (Fapply, intern ("concat"), Fnreverse (acc));
  7409 }

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