diff options
Diffstat (limited to 'src/xterm.c')
-rw-r--r-- | src/xterm.c | 226 |
1 files changed, 146 insertions, 80 deletions
diff --git a/src/xterm.c b/src/xterm.c index aaf2e7988be..d35af7a8de2 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1425,9 +1425,6 @@ struct x_client_list_window /* The width and height of the window. */ int width, height; - /* Whether or not the window is mapped. */ - bool mapped_p; - /* A bitmask describing events Emacs was listening for from the window before some extra events were added in `x_dnd_compute_toplevels'. */ @@ -1439,9 +1436,6 @@ struct x_client_list_window /* The next window in this list. */ struct x_client_list_window *next; - /* The Motif protocol style of this window, if any. */ - uint8_t xm_protocol_style; - /* The extents of the frame window in each direction. */ int frame_extents_left; int frame_extents_right; @@ -1452,18 +1446,24 @@ struct x_client_list_window /* The border width of this window. */ int border_width; - /* The rectangles making up the input shape. */ - XRectangle *input_rects; - /* The number of rectangles composing the input shape. */ int n_input_rects; + /* The rectangles making up the input shape. */ + XRectangle *input_rects; + /* The rectangles making up the bounding shape. */ XRectangle *bounding_rects; /* The number of rectangles composing the bounding shape. */ int n_bounding_rects; #endif + + /* The Motif protocol style of this window, if any. */ + uint8_t xm_protocol_style; + + /* Whether or not the window is mapped. */ + bool mapped_p; }; /* List of all toplevels in stacking order, from top to bottom. */ @@ -5139,24 +5139,20 @@ x_update_opaque_region (struct frame *f, XEvent *configure) if (!FRAME_DISPLAY_INFO (f)->alpha_bits) return; - block_input (); if (f->alpha_background < 1.0) - XChangeProperty (FRAME_X_DISPLAY (f), - FRAME_X_WINDOW (f), + XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region, XA_CARDINAL, 32, PropModeReplace, NULL, 0); #ifndef HAVE_GTK3 else - XChangeProperty (FRAME_X_DISPLAY (f), - FRAME_X_WINDOW (f), + XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opaque_region, 4); #else else if (FRAME_TOOLTIP_P (f)) - XChangeProperty (FRAME_X_DISPLAY (f), - FRAME_X_WINDOW (f), + XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_net_wm_opaque_region, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opaque_region, 4); @@ -5174,7 +5170,6 @@ x_update_opaque_region (struct frame *f, XEvent *configure) } } #endif - unblock_input (); } @@ -7144,8 +7139,6 @@ show_back_buffer (struct frame *f) cairo_t *cr; #endif - block_input (); - if (FRAME_X_DOUBLE_BUFFERED_P (f)) { #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME @@ -7174,8 +7167,6 @@ show_back_buffer (struct frame *f) } FRAME_X_NEED_BUFFER_FLIP (f) = false; - - unblock_input (); } #endif @@ -7283,8 +7274,12 @@ XTframe_up_to_date (struct frame *f) static void XTbuffer_flipping_unblocked_hook (struct frame *f) { + block_input (); + if (FRAME_X_NEED_BUFFER_FLIP (f)) show_back_buffer (f); + + unblock_input (); } #endif @@ -7313,8 +7308,6 @@ x_clear_under_internal_border (struct frame *f) : INTERNAL_BORDER_FACE_ID)); struct face *face = FACE_FROM_ID_OR_NULL (f, face_id); - block_input (); - if (face) { unsigned long color = face->background; @@ -7335,8 +7328,6 @@ x_clear_under_internal_border (struct frame *f) x_clear_area (f, width - border, 0, border, height); x_clear_area (f, 0, height - border, width, border); } - - unblock_input (); } } @@ -7384,7 +7375,6 @@ x_after_update_window_line (struct window *w, struct glyph_row *desired_row) : INTERNAL_BORDER_FACE_ID)); struct face *face = FACE_FROM_ID_OR_NULL (f, face_id); - block_input (); if (face) { unsigned long color = face->background; @@ -7402,7 +7392,6 @@ x_after_update_window_line (struct window *w, struct glyph_row *desired_row) x_clear_area (f, 0, y, width, height); x_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height); } - unblock_input (); } } #endif @@ -7601,11 +7590,27 @@ static void x_check_font (struct frame *, struct font *); user time. We don't sanitize timestamps from events sent by the X server itself because some Lisp might have set the user time to a ridiculously large value, and this way a more reasonable timestamp - can be obtained upon the next event. */ + can be obtained upon the next event. + + Alternatively, the server time could've overflowed. + + SET_PROPERTY specifies whether or not to change the user time + property for the active frame. The important thing is to not set + the last user time upon leave events; on Metacity and GNOME Shell, + mapping a new frame on top of the old frame potentially causes + crossing events to be sent to the old frame if it contains the + pointer, as the new frame will initially stack above the old frame. + If _NET_WM_USER_TIME is changed at that point, then GNOME may get + notified about the user time change on the old frame before it + tries to focus the new frame, which will make it consider the new + frame (whose user time property will not have been updated at that + point, due to not being focused) as having been mapped + out-of-order, and lower the new frame, which is typically not what + users want. */ static void x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time, - bool send_event) + bool send_event, bool set_property) { #if defined HAVE_XSYNC && !defined USE_GTK && defined HAVE_CLOCK_GETTIME uint_fast64_t monotonic_time; @@ -7678,7 +7683,8 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time, #ifndef USE_GTK /* Don't waste bandwidth if the time hasn't actually changed. */ - if (focus_frame && old_time != dpyinfo->last_user_time) + if (focus_frame && old_time != dpyinfo->last_user_time + && set_property) { time = dpyinfo->last_user_time; @@ -7719,6 +7725,7 @@ x_set_gtk_user_time (struct frame *f, Time time) itself. */ #ifndef USE_GTK + static void x_update_frame_user_time_window (struct frame *f) { @@ -7782,13 +7789,14 @@ x_update_frame_user_time_window (struct frame *f) } } } + #endif void x_set_last_user_time_from_lisp (struct x_display_info *dpyinfo, Time time) { - x_display_set_last_user_time (dpyinfo, time, true); + x_display_set_last_user_time (dpyinfo, time, true, true); } @@ -9595,31 +9603,49 @@ x_draw_glyph_string_box (struct glyph_string *s) #ifndef USE_CAIRO + static void x_composite_image (struct glyph_string *s, Pixmap dest, +#ifdef HAVE_XRENDER + Picture destination, +#endif int srcX, int srcY, int dstX, int dstY, int width, int height) { - Display *display = FRAME_X_DISPLAY (s->f); + Display *display; #ifdef HAVE_XRENDER - if (s->img->picture && FRAME_X_PICTURE_FORMAT (s->f)) - { - Picture destination; - XRenderPictFormat *default_format; - XRenderPictureAttributes attr UNINIT; + XRenderPictFormat *default_format; + XRenderPictureAttributes attr UNINIT; +#endif - default_format = FRAME_X_PICTURE_FORMAT (s->f); - destination = XRenderCreatePicture (display, dest, - default_format, 0, &attr); + display = FRAME_X_DISPLAY (s->f); - XRenderComposite (display, s->img->mask_picture ? PictOpOver : PictOpSrc, - s->img->picture, s->img->mask_picture, destination, - srcX, srcY, - srcX, srcY, - dstX, dstY, - width, height); +#ifdef HAVE_XRENDER + if (s->img->picture && FRAME_X_PICTURE_FORMAT (s->f)) + { + if (destination == None) + { + /* The destination picture was not specified. This means we + have to create a picture representing the */ + default_format = FRAME_X_PICTURE_FORMAT (s->f); + destination = XRenderCreatePicture (display, dest, + default_format, 0, &attr); + + XRenderComposite (display, (s->img->mask_picture + ? PictOpOver : PictOpSrc), + s->img->picture, s->img->mask_picture, + destination, srcX, srcY, srcX, srcY, + dstX, dstY, width, height); + + XRenderFreePicture (display, destination); + } + else + XRenderComposite (display, (s->img->mask_picture + ? PictOpOver : PictOpSrc), + s->img->picture, s->img->mask_picture, + destination, srcX, srcY, srcX, srcY, + dstX, dstY, width, height); - XRenderFreePicture (display, destination); return; } #endif @@ -9629,6 +9655,7 @@ x_composite_image (struct glyph_string *s, Pixmap dest, srcX, srcY, width, height, dstX, dstY); } + #endif /* !USE_CAIRO */ @@ -9707,6 +9734,9 @@ x_draw_image_foreground (struct glyph_string *s) image_rect.height = s->slice.height; if (gui_intersect_rectangles (&clip_rect, &image_rect, &r)) x_composite_image (s, FRAME_X_DRAWABLE (s->f), +#ifdef HAVE_XRENDER + FRAME_X_PICTURE (s->f), +#endif s->slice.x + r.x - x, s->slice.y + r.y - y, r.x, r.y, r.width, r.height); } @@ -9720,7 +9750,12 @@ x_draw_image_foreground (struct glyph_string *s) image_rect.width = s->slice.width; image_rect.height = s->slice.height; if (gui_intersect_rectangles (&clip_rect, &image_rect, &r)) - x_composite_image (s, FRAME_X_DRAWABLE (s->f), s->slice.x + r.x - x, s->slice.y + r.y - y, + x_composite_image (s, FRAME_X_DRAWABLE (s->f), +#ifdef HAVE_XRENDER + FRAME_X_PICTURE (s->f), +#endif + s->slice.x + r.x - x, + s->slice.y + r.y - y, r.x, r.y, r.width, r.height); /* When the image has a mask, we can expect that at @@ -9886,8 +9921,11 @@ x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap) XChangeGC (display, s->gc, mask, &xgcv); x_composite_image (s, pixmap, - s->slice.x, s->slice.y, - x, y, s->slice.width, s->slice.height); +#ifdef HAVE_XRENDER + None, +#endif + s->slice.x, s->slice.y, x, y, + s->slice.width, s->slice.height); XSetClipMask (display, s->gc, None); } else @@ -12761,7 +12799,7 @@ xi_focus_handle_for_device (struct x_display_info *dpyinfo, /* The last-focus-change time of the device changed, so update the frame's user time. */ x_display_set_last_user_time (dpyinfo, event->time, - event->send_event); + event->send_event, true); device->focus_frame = mentioned_frame; device->focus_frame_time = event->time; @@ -12771,7 +12809,7 @@ xi_focus_handle_for_device (struct x_display_info *dpyinfo, /* The last-focus-change time of the device changed, so update the frame's user time. */ x_display_set_last_user_time (dpyinfo, event->time, - event->send_event); + event->send_event, false); device->focus_frame = NULL; @@ -14153,7 +14191,8 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, < dpyinfo->last_mouse_movement_time)) x_display_set_last_user_time (dpyinfo, dpyinfo->last_mouse_movement_time, - dpyinfo->last_mouse_movement_time_send_event); + dpyinfo->last_mouse_movement_time_send_event, + true); if ((!f1 || FRAME_TOOLTIP_P (f1)) && (EQ (track_mouse, Qdropping) @@ -14769,7 +14808,8 @@ xg_scroll_callback (GtkRange *range, GtkScrollType scroll, dpyinfo = FRAME_DISPLAY_INFO (f); if (time != GDK_CURRENT_TIME) - x_display_set_last_user_time (dpyinfo, time, true); + x_display_set_last_user_time (dpyinfo, time, true, + true); switch (scroll) { @@ -18091,7 +18131,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, required for SetInputFocus to work correctly after taking the input focus. */ x_display_set_last_user_time (dpyinfo, event->xclient.data.l[1], - true); + true, true); goto done; } @@ -19079,7 +19119,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, case KeyPress: x_display_set_last_user_time (dpyinfo, event->xkey.time, - event->xkey.send_event); + event->xkey.send_event, + true); ignore_next_mouse_click_timeout = 0; coding = Qlatin_1; @@ -19558,7 +19599,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, case EnterNotify: x_display_set_last_user_time (dpyinfo, event->xcrossing.time, - event->xcrossing.send_event); + event->xcrossing.send_event, false); #ifdef HAVE_XINPUT2 /* For whatever reason, the X server continues to deliver @@ -19681,7 +19722,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, case LeaveNotify: x_display_set_last_user_time (dpyinfo, event->xcrossing.time, - event->xcrossing.send_event); + event->xcrossing.send_event, false); #ifdef HAVE_XINPUT2 /* For whatever reason, the X server continues to deliver @@ -20496,7 +20537,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, { if (event->xbutton.type == ButtonPress) x_display_set_last_user_time (dpyinfo, event->xbutton.time, - event->xbutton.send_event); + event->xbutton.send_event, true); #ifdef HAVE_XWIDGETS struct xwidget_view *xvw = xwidget_view_from_window (event->xbutton.window); @@ -20548,7 +20589,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (event->type == ButtonPress) { x_display_set_last_user_time (dpyinfo, event->xbutton.time, - event->xbutton.send_event); + event->xbutton.send_event, true); dpyinfo->grabbed |= (1 << event->xbutton.button); dpyinfo->last_mouse_frame = f; @@ -21105,7 +21146,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, ev.send_event = enter->send_event; x_display_set_last_user_time (dpyinfo, enter->time, - enter->send_event); + enter->send_event, false); #ifdef USE_MOTIF use_copy = true; @@ -21291,7 +21332,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif x_display_set_last_user_time (dpyinfo, leave->time, - leave->send_event); + leave->send_event, false); #ifdef HAVE_XWIDGETS { @@ -21566,7 +21607,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, state = xi_convert_event_state (xev); x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); if (found_valuator) xwidget_scroll (xv, xev->event_x, xev->event_y, @@ -21586,7 +21627,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (found_valuator) { x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); #if defined USE_GTK && !defined HAVE_GTK3 @@ -22077,7 +22118,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (xev->evtype == XI_ButtonPress) { x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); dpyinfo->grabbed |= (1 << xev->detail); dpyinfo->last_mouse_frame = f; @@ -22120,7 +22161,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (xev->flags & XIPointerEmulated) x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); #endif x_dnd_note_self_wheel (dpyinfo, x_dnd_last_seen_window, @@ -22356,7 +22397,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (xev->evtype == XI_ButtonPress) x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); source = xi_device_from_id (dpyinfo, xev->sourceid); device = xi_device_from_id (dpyinfo, xev->deviceid); @@ -22735,7 +22776,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); ignore_next_mouse_click_timeout = 0; f = x_any_window_to_frame (dpyinfo, xev->event); @@ -23374,7 +23415,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, device = xi_device_from_id (dpyinfo, xev->deviceid); source = xi_device_from_id (dpyinfo, xev->sourceid); x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); if (!device) goto XI_OTHER; @@ -23472,7 +23513,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, device = xi_device_from_id (dpyinfo, xev->deviceid); source = xi_device_from_id (dpyinfo, xev->sourceid); x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); if (!device) goto XI_OTHER; @@ -23519,7 +23560,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, device = xi_device_from_id (dpyinfo, xev->deviceid); source = xi_device_from_id (dpyinfo, xev->sourceid); x_display_set_last_user_time (dpyinfo, xev->time, - xev->send_event); + xev->send_event, true); if (!device) goto XI_OTHER; @@ -23560,7 +23601,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, device = xi_device_from_id (dpyinfo, pev->deviceid); source = xi_device_from_id (dpyinfo, pev->sourceid); x_display_set_last_user_time (dpyinfo, pev->time, - pev->send_event); + pev->send_event, true); if (!device) goto XI_OTHER; @@ -27995,6 +28036,7 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) Window window = FRAME_OUTER_WINDOW (f); #ifdef USE_X_TOOLKIT WMShellWidget shell; + bool hints_changed; #endif if (!window) @@ -28021,8 +28063,9 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) shell->wm.size_hints.flags |= USPosition; } - widget_update_wm_size_hints (f->output_data.x->widget, - f->output_data.x->edit_widget); + hints_changed + = widget_update_wm_size_hints (f->output_data.x->widget, + f->output_data.x->edit_widget); #ifdef USE_MOTIF /* Do this all over again for the benefit of Motif, which always @@ -28035,6 +28078,7 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) shell->wm.size_hints.flags &= ~PPosition; shell->wm.size_hints.flags |= USPosition; } +#endif /* Drill hints into Motif, since it keeps setting its own. */ size_hints.flags = shell->wm.size_hints.flags; @@ -28052,15 +28096,23 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position) size_hints.min_aspect.y = shell->wm.size_hints.min_aspect.y; size_hints.max_aspect.x = shell->wm.size_hints.max_aspect.x; size_hints.max_aspect.y = shell->wm.size_hints.max_aspect.y; -#ifdef HAVE_X11XTR6 size_hints.base_width = shell->wm.base_width; size_hints.base_height = shell->wm.base_height; size_hints.win_gravity = shell->wm.win_gravity; -#endif +#ifdef USE_MOTIF XSetWMNormalHints (XtDisplay (f->output_data.x->widget), XtWindow (f->output_data.x->widget), &size_hints); +#else + /* In many cases, widget_update_wm_size_hints will not have + updated the size hints if only flags changed. When that + happens, set the WM hints manually. */ + + if (!hints_changed) + XSetWMNormalHints (XtDisplay (f->output_data.x->widget), + XtWindow (f->output_data.x->widget), + &size_hints); #endif return; @@ -28475,9 +28527,10 @@ xi_check_toolkit (Display *display) #endif -/* Open a connection to X display DISPLAY_NAME, and return - the structure that describes the open display. - If we cannot contact the display, return null. */ +/* Open a connection to X display DISPLAY_NAME, and return the + structure that describes the open display. If obtaining the XCB + connection or toolkit-specific display fails, return NULL. Signal + an error if opening the display itself failed. */ struct x_display_info * x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) @@ -28504,9 +28557,13 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) ++x_initialized; } - if (! x_display_ok (SSDATA (display_name))) +#if defined USE_X_TOOLKIT || defined USE_GTK + + if (!x_display_ok (SSDATA (display_name))) error ("Display %s can't be opened", SSDATA (display_name)); +#endif + #ifdef USE_GTK { #define NUM_ARGV 10 @@ -28633,6 +28690,15 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) /* Detect failure. */ if (dpy == 0) { +#if !defined USE_X_TOOLKIT && !defined USE_GTK + /* Avoid opening a display three times (once in dispextern.c + upon startup, once in x_display_ok, and once above) to + determine whether or not the display is alive on no toolkit + builds, where no toolkit initialization happens at all. */ + + error ("Display %s can't be opened", SSDATA (display_name)); +#endif + unblock_input (); return 0; } |