#include "bitmaps/gray.xbm"
+#ifdef HAVE_XKB
+#include <X11/XKBlib.h>
+#endif
+
/* Default to using XIM if available. */
#ifdef USE_XIM
int use_xim = 1;
XTframe_up_to_date (struct frame *f)
{
if (FRAME_X_P (f))
- {
- Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
-
- if (hlinfo->mouse_face_deferred_gc
- || f == hlinfo->mouse_face_mouse_frame)
- {
- block_input ();
- if (hlinfo->mouse_face_mouse_frame)
- note_mouse_highlight (hlinfo->mouse_face_mouse_frame,
- hlinfo->mouse_face_mouse_x,
- hlinfo->mouse_face_mouse_y);
- hlinfo->mouse_face_deferred_gc = 0;
- unblock_input ();
- }
- }
+ FRAME_MOUSE_UPDATE (f);
}
x_frame_of_widget (Widget widget)
{
struct x_display_info *dpyinfo;
- Lisp_Object tail;
+ Lisp_Object tail, frame;
struct frame *f;
dpyinfo = x_display_info_for_display (XtDisplay (widget));
/* Look for a frame with that top-level widget. Allocate the color
on that frame to get the right gamma correction value. */
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
- if (FRAMEP (XCAR (tail))
- && (f = XFRAME (XCAR (tail)),
- (FRAME_X_P (f)
- && f->output_data.nothing != 1
- && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
- && f->output_data.x->widget == widget)
- return f;
-
+ FOR_EACH_FRAME (tail, frame)
+ {
+ f = XFRAME (frame);
+ if (FRAME_X_P (f)
+ && f->output_data.nothing != 1
+ && FRAME_X_DISPLAY_INFO (f) == dpyinfo
+ && f->output_data.x->widget == widget)
+ return f;
+ }
emacs_abort ();
}
for (i = (width > 1 ? 1 : 0); i < width; ++i)
XDrawLine (dpy, window, gc,
- left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
+ left_x + i, top_y + (i + 1) * top_p,
+ left_x + i, bottom_y + 1 - (i + 1) * bot_p);
}
XSetClipMask (dpy, gc, None);
XClearArea (dpy, window, right_x, bottom_y, 1, 1, False);
for (i = 0; i < width; ++i)
XDrawLine (dpy, window, gc,
- right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
+ right_x - i, top_y + (i + 1) * top_p,
+ right_x - i, bottom_y + 1 - (i + 1) * bot_p);
}
XSetClipMask (dpy, gc, None);
nothing here for mouse-face. */
if (s->hl == DRAW_CURSOR)
{
- int relief = s->img->relief;
- if (relief < 0) relief = -relief;
+ int relief = eabs (s->img->relief);
XDrawRectangle (s->display, s->window, s->gc,
x - relief, y - relief,
s->slice.width + relief*2 - 1,
static void
x_draw_image_relief (struct glyph_string *s)
{
- int x0, y0, x1, y1, thick, raised_p;
- int extra_x, extra_y;
+ int x1, y1, thick, raised_p, top_p, bot_p, left_p, right_p;
XRectangle r;
int x = s->x;
int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
raised_p = s->img->relief > 0;
}
- extra_x = extra_y = 0;
- if (s->face->id == TOOL_BAR_FACE_ID)
- {
- if (CONSP (Vtool_bar_button_margin)
- && INTEGERP (XCAR (Vtool_bar_button_margin))
- && INTEGERP (XCDR (Vtool_bar_button_margin)))
- {
- extra_x = XINT (XCAR (Vtool_bar_button_margin));
- extra_y = XINT (XCDR (Vtool_bar_button_margin));
- }
- else if (INTEGERP (Vtool_bar_button_margin))
- extra_x = extra_y = XINT (Vtool_bar_button_margin);
- }
+ x1 = x + s->slice.width - 1;
+ y1 = y + s->slice.height - 1;
+ top_p = bot_p = left_p = right_p = 0;
- x0 = x - thick - extra_x;
- y0 = y - thick - extra_y;
- x1 = x + s->slice.width + thick - 1 + extra_x;
- y1 = y + s->slice.height + thick - 1 + extra_y;
+ if (s->slice.x == 0)
+ x -= thick, left_p = 1;
+ if (s->slice.y == 0)
+ y -= thick, top_p = 1;
+ if (s->slice.x + s->slice.width == s->img->width)
+ x1 += thick, right_p = 1;
+ if (s->slice.y + s->slice.height == s->img->height)
+ y1 += thick, bot_p = 1;
x_setup_relief_colors (s);
get_glyph_string_clip_rect (s, &r);
- x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
- s->slice.y == 0,
- s->slice.y + s->slice.height == s->img->height,
- s->slice.x == 0,
- s->slice.x + s->slice.width == s->img->width,
- &r);
+ x_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p,
+ top_p, bot_p, left_p, right_p, &r);
}
nothing here for mouse-face. */
if (s->hl == DRAW_CURSOR)
{
- int r = s->img->relief;
- if (r < 0) r = -r;
+ int r = eabs (s->img->relief);
XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
s->slice.width + r*2 - 1,
s->slice.height + r*2 - 1);
else
{
block_input ();
+#ifdef HAVE_XKB
+ XkbBell (FRAME_X_DISPLAY (f), None, 0, None);
+#else
XBell (FRAME_X_DISPLAY (f), 0);
+#endif
XFlush (FRAME_X_DISPLAY (f));
unblock_input ();
}
static struct scroll_bar *
x_window_to_scroll_bar (Display *display, Window window_id)
{
- Lisp_Object tail;
+ Lisp_Object tail, frame;
#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
#endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+ FOR_EACH_FRAME (tail, frame)
{
- Lisp_Object frame, bar, condemned;
-
- frame = XCAR (tail);
- /* All elements of Vframe_list should be frames. */
- if (! FRAMEP (frame))
- emacs_abort ();
+ Lisp_Object bar, condemned;
if (! FRAME_X_P (XFRAME (frame)))
continue;
static Widget
x_window_to_menu_bar (Window window)
{
- Lisp_Object tail;
-
- for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
- {
- if (FRAME_X_P (XFRAME (XCAR (tail))))
- {
- Lisp_Object frame = XCAR (tail);
- Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
+ Lisp_Object tail, frame;
- if (menu_bar && xlwmenu_window_p (menu_bar, window))
- return menu_bar;
- }
- }
+ FOR_EACH_FRAME (tail, frame)
+ if (FRAME_X_P (XFRAME (frame)))
+ {
+ Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
+ if (menu_bar && xlwmenu_window_p (menu_bar, window))
+ return menu_bar;
+ }
return NULL;
}
#ifdef USE_MOTIF
- /* We use an estimate of 30 chars per line rather than the real
- `portion' value. This has the disadvantage that the thumb size
- is not very representative, but it makes our life a lot easier.
- Otherwise, we have to constantly adjust the thumb size, which
- we can't always do quickly enough: while dragging, the size of
- the thumb might prevent the user from dragging the thumb all the
- way to the end. but Motif and some versions of Xaw3d don't allow
- updating the thumb size while dragging. Also, even if we can update
- its size, the update will often happen too late.
- If you don't believe it, check out revision 1.650 of xterm.c to see
- what hoops we were going through and the still poor behavior we got. */
- portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
- /* When the thumb is at the bottom, position == whole.
- So we need to increase `whole' to make space for the thumb. */
- whole += portion;
+ if (scroll_bar_adjust_thumb_portion_p)
+ {
+ /* We use an estimate of 30 chars per line rather than the real
+ `portion' value. This has the disadvantage that the thumb size
+ is not very representative, but it makes our life a lot easier.
+ Otherwise, we have to constantly adjust the thumb size, which
+ we can't always do quickly enough: while dragging, the size of
+ the thumb might prevent the user from dragging the thumb all the
+ way to the end. but Motif and some versions of Xaw3d don't allow
+ updating the thumb size while dragging. Also, even if we can update
+ its size, the update will often happen too late.
+ If you don't believe it, check out revision 1.650 of xterm.c to see
+ what hoops we were going through and the still poor behavior we got. */
+ portion = WINDOW_TOTAL_LINES (XWINDOW (bar->window)) * 30;
+ /* When the thumb is at the bottom, position == whole.
+ So we need to increase `whole' to make space for the thumb. */
+ whole += portion;
+ }
if (whole <= 0)
top = 0, shown = 1;
/* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
is the scroll bar's maximum and MIN is the scroll bar's minimum
value. */
- size = shown * XM_SB_MAX;
- size = min (size, XM_SB_MAX);
- size = max (size, 1);
+ size = clip_to_bounds (1, shown * XM_SB_MAX, XM_SB_MAX);
/* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
value = top * XM_SB_MAX;
/* Draw the empty space above the handle. Note that we can't clear
zero-height areas; that means "clear to end of window." */
- if (0 < start)
+ if (start > 0)
x_clear_area (FRAME_X_DISPLAY (f), w,
/* x, y, width, height, and exposures. */
VERTICAL_SCROLL_BAR_LEFT_BORDER,
SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
- inev.ie.frame_or_window = Qnil;
}
break;
SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
- inev.ie.frame_or_window = Qnil;
}
break;
last_user_time = event.xproperty.time;
f = x_top_window_to_frame (dpyinfo, event.xproperty.window);
if (f && event.xproperty.atom == dpyinfo->Xatom_net_wm_state)
- if (x_handle_net_wm_state (f, &event.xproperty) && f->iconified
- && f->output_data.x->net_wm_state_hidden_seen)
+ if (x_handle_net_wm_state (f, &event.xproperty)
+ && FRAME_ICONIFIED_P (f)
+ && f->output_data.x->net_wm_state_hidden_seen)
{
- /* Gnome shell does not iconify us when C-z is pressed. It hides
- the frame. So if our state says we aren't hidden anymore,
- treat it as deiconified. */
- if (! f->async_iconified)
- SET_FRAME_GARBAGED (f);
- f->async_visible = 1;
- f->async_iconified = 0;
+ /* Gnome shell does not iconify us when C-z is pressed.
+ It hides the frame. So if our state says we aren't
+ hidden anymore, treat it as deiconified. */
+ SET_FRAME_VISIBLE (f, 1);
+ SET_FRAME_ICONIFIED (f, 0);
f->output_data.x->has_been_visible = 1;
f->output_data.x->net_wm_state_hidden_seen = 0;
inev.ie.kind = DEICONIFY_EVENT;
event.xexpose.width, event.xexpose.height,
FALSE);
#endif
- if (f->async_visible == 0)
+ if (!FRAME_VISIBLE_P (f))
{
- f->async_visible = 1;
- f->async_iconified = 0;
+ SET_FRAME_VISIBLE (f, 1);
+ SET_FRAME_ICONIFIED (f, 0);
f->output_data.x->has_been_visible = 1;
SET_FRAME_GARBAGED (f);
}
if (f) /* F may no longer exist if
the frame was deleted. */
{
+ bool visible = FRAME_VISIBLE_P (f);
/* While a frame is unmapped, display generation is
disabled; you don't want to spend time updating a
display that won't ever be seen. */
- f->async_visible = 0;
+ SET_FRAME_VISIBLE (f, 0);
/* We can't distinguish, from the event, whether the window
has become iconified or invisible. So assume, if it
was previously visible, than now it is iconified.
But x_make_frame_invisible clears both
the visible flag and the iconified flag;
and that way, we know the window is not iconified now. */
- if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
+ if (visible || FRAME_ICONIFIED_P (f))
{
- f->async_iconified = 1;
-
+ SET_FRAME_ICONIFIED (f, 1);
inev.ie.kind = ICONIFY_EVENT;
XSETFRAME (inev.ie.frame_or_window, f);
}
f = x_top_window_to_frame (dpyinfo, event.xmap.window);
if (f)
{
+ bool iconified = FRAME_ICONIFIED_P (f);
/* wait_reading_process_output will notice this and update
the frame's display structures.
If we where iconified, we should not set garbaged,
because that stops redrawing on Expose events. This looks
bad if we are called from a recursive event loop
(x_dispatch_event), for example when a dialog is up. */
- if (! f->async_iconified)
+ if (!iconified)
SET_FRAME_GARBAGED (f);
/* Check if fullscreen was specified before we where mapped the
if (!f->output_data.x->has_been_visible)
x_check_fullscreen (f);
- f->async_visible = 1;
- f->async_iconified = 0;
+ SET_FRAME_VISIBLE (f, 1);
+ SET_FRAME_ICONIFIED (f, 0);
f->output_data.x->has_been_visible = 1;
- if (f->iconified)
+ if (iconified)
{
inev.ie.kind = DEICONIFY_EVENT;
XSETFRAME (inev.ie.frame_or_window, f);
}
- else if (! NILP (Vframe_list)
- && ! NILP (XCDR (Vframe_list)))
- /* Force a redisplay sooner or later
- to update the frame titles
- in case this is the second frame. */
+ else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
+ /* Force a redisplay sooner or later to update the
+ frame titles in case this is the second frame. */
record_asynch_buffer_change ();
#ifdef USE_GTK
static int
x_error_handler (Display *display, XErrorEvent *event)
{
-#ifdef HAVE_GTK3
+#if defined USE_GTK && defined HAVE_GTK3
if (event->error_code == BadMatch
&& event->request_code == X_SetInputFocus
&& event->minor_code == 0)
FRAME_FONT (f) = font;
FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
FRAME_COLUMN_WIDTH (f) = font->average_width;
- FRAME_SPACE_WIDTH (f) = font->space_width;
FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font);
compute_fringe_widths (f, 1);
if (tmp_data) XFree (tmp_data);
x_uncatch_errors ();
unblock_input ();
- return ! f->iconified;
+ return !FRAME_ICONIFIED_P (f);
}
x_uncatch_errors ();
static void
XTfullscreen_hook (FRAME_PTR f)
{
- if (f->async_visible)
+ if (FRAME_VISIBLE_P (f))
{
block_input ();
x_check_fullscreen (f);
/* But the ConfigureNotify may in fact never arrive, and then this is
not right if the frame is visible. Instead wait (with timeout)
for the ConfigureNotify. */
- if (f->async_visible)
+ if (FRAME_VISIBLE_P (f))
x_wait_for_event (f, ConfigureNotify);
else
{
x_raise_frame (struct frame *f)
{
block_input ();
- if (f->async_visible)
+ if (FRAME_VISIBLE_P (f))
XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
-
XFlush (FRAME_X_DISPLAY (f));
unblock_input ();
}
static void
x_lower_frame (struct frame *f)
{
- if (f->async_visible)
+ if (FRAME_VISIBLE_P (f))
{
block_input ();
XLowerWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
{
/* See XEmbed Protocol Specification at
http://freedesktop.org/wiki/Specifications/xembed-spec */
- if (f->async_visible)
+ if (FRAME_VISIBLE_P (f))
xembed_send_message (f, CurrentTime,
XEMBED_REQUEST_FOCUS, 0, 0, 0);
}
http://freedesktop.org/wiki/Specifications/wm-spec */
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
- if (f->async_visible && wm_supports (f, dpyinfo->Xatom_net_active_window))
+
+ if (FRAME_VISIBLE_P (f) && wm_supports (f, dpyinfo->Xatom_net_active_window))
{
Lisp_Object frame;
XSETFRAME (frame, f);
x_send_client_event (frame, make_number (0), frame,
dpyinfo->Xatom_net_active_window,
- make_number (32),
- Fcons (make_number (1),
- Fcons (make_number (last_user_time),
- Qnil)));
+ make_number (32), list2i (1, last_user_time));
}
}
poll_for_input_1 ();
poll_suppress_count = old_poll_suppress_count;
}
-
- /* See if a MapNotify event has been processed. */
- FRAME_SAMPLE_VISIBILITY (f);
}
/* 2000-09-28: In
So we can't win using the usual strategy of letting
FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
and synchronize with the server to make sure we agree. */
- f->visible = 0;
- FRAME_ICONIFIED_P (f) = 0;
- f->async_visible = 0;
- f->async_iconified = 0;
+ SET_FRAME_VISIBLE (f, 0);
+ SET_FRAME_ICONIFIED (f, 0);
x_sync (f);
if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
- if (f->async_iconified)
+ if (FRAME_ICONIFIED_P (f))
return;
block_input ();
- FRAME_SAMPLE_VISIBILITY (f);
-
type = x_icon_type (f);
if (!NILP (type))
x_bitmap_icon (f, type);
gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
- f->iconified = 1;
- f->visible = 1;
- f->async_iconified = 1;
- f->async_visible = 0;
+ SET_FRAME_VISIBLE (f, 0);
+ SET_FRAME_ICONIFIED (f, 1);
unblock_input ();
return;
}
/* The server won't give us any event to indicate
that an invisible frame was changed to an icon,
so we have to record it here. */
- f->iconified = 1;
- f->visible = 1;
- f->async_iconified = 1;
- f->async_visible = 0;
+ SET_FRAME_VISIBLE (f, 0);
+ SET_FRAME_ICONIFIED (f, 1);
unblock_input ();
return;
}
if (!result)
error ("Can't notify window manager of iconification");
- f->async_iconified = 1;
- f->async_visible = 0;
-
+ SET_FRAME_ICONIFIED (f, 1);
+ SET_FRAME_VISIBLE (f, 0);
block_input ();
XFlush (FRAME_X_DISPLAY (f));
XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
}
- f->async_iconified = 1;
- f->async_visible = 0;
+ SET_FRAME_ICONIFIED (f, 1);
+ SET_FRAME_VISIBLE (f, 0);
XFlush (FRAME_X_DISPLAY (f));
unblock_input ();
hlinfo->mouse_face_end_row
= hlinfo->mouse_face_end_col = -1;
hlinfo->mouse_face_window = Qnil;
- hlinfo->mouse_face_deferred_gc = 0;
hlinfo->mouse_face_mouse_frame = 0;
}
/* Emacs can only handle core input events, so make sure
Gtk doesn't use Xinput or Xinput2 extensions. */
- {
- static char fix_events[] = "GDK_CORE_DEVICE_EVENTS=1";
- putenv (fix_events);
- }
+ xputenv ("GDK_CORE_DEVICE_EVENTS=1");
/* Work around GLib bug that outputs a faulty warning. See
https://bugzilla.gnome.org/show_bug.cgi?id=563627. */
dpy = DEFAULT_GDK_DISPLAY ();
-#if GTK_MAJOR_VERSION <= 2 && GTK_MINOR_VERSION <= 90
+#if ! GTK_CHECK_VERSION (2, 90, 0)
/* Load our own gtkrc if it exists. */
{
const char *file = "~/.emacs.d/gtkrc";
dpyinfo->bitmaps_last = 0;
dpyinfo->scratch_cursor_gc = 0;
hlinfo->mouse_face_mouse_frame = 0;
- hlinfo->mouse_face_deferred_gc = 0;
hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
hlinfo->mouse_face_face_id = DEFAULT_FACE_ID;
{ "_NET_WM_WINDOW_OPACITY", &dpyinfo->Xatom_net_wm_window_opacity },
{ "_NET_ACTIVE_WINDOW", &dpyinfo->Xatom_net_active_window },
{ "_NET_FRAME_EXTENTS", &dpyinfo->Xatom_net_frame_extents },
+ { "_NET_CURRENT_DESKTOP", &dpyinfo->Xatom_net_current_desktop },
+ { "_NET_WORKAREA", &dpyinfo->Xatom_net_workarea },
/* Session management */
{ "SM_CLIENT_ID", &dpyinfo->Xatom_SM_CLIENT_ID },
{ "_XSETTINGS_SETTINGS", &dpyinfo->Xatom_xsettings_prop },
DEFVAR_LISP ("x-keysym-table", Vx_keysym_table,
doc: /* Hash table of character codes indexed by X keysym codes. */);
- Vx_keysym_table = make_hash_table (Qeql, make_number (900),
+ Vx_keysym_table = make_hash_table (hashtest_eql, make_number (900),
make_float (DEFAULT_REHASH_SIZE),
make_float (DEFAULT_REHASH_THRESHOLD),
- Qnil, Qnil, Qnil);
+ Qnil);
}
#endif /* HAVE_X_WINDOWS */