summaryrefslogtreecommitdiff
path: root/src/xterm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xterm.c')
-rw-r--r--src/xterm.c175
1 files changed, 136 insertions, 39 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 977325f0b75..efbc3c7b7ea 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1,6 +1,6 @@
/* X Communication module for terminals which understand the X protocol.
Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -282,6 +282,10 @@ static Lisp_Object last_mouse_scroll_bar;
static Time last_mouse_movement_time;
+/* Time for last user interaction as returned in X events. */
+
+static Time last_user_time;
+
/* Incremented by XTread_socket whenever it really tries to read
events. */
@@ -6115,6 +6119,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
break;
case SelectionNotify:
+ last_user_time = event.xselection.time;
#ifdef USE_X_TOOLKIT
if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
goto OTHER;
@@ -6123,6 +6128,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
break;
case SelectionClear: /* Someone has grabbed ownership. */
+ last_user_time = event.xselectionclear.time;
#ifdef USE_X_TOOLKIT
if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
goto OTHER;
@@ -6139,6 +6145,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
break;
case SelectionRequest: /* Someone wants our selection. */
+ last_user_time = event.xselectionrequest.time;
#ifdef USE_X_TOOLKIT
if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
goto OTHER;
@@ -6159,6 +6166,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
break;
case PropertyNotify:
+ last_user_time = event.xproperty.time;
#if 0 /* This is plain wrong. In the case that we are waiting for a
PropertyNotify used as an ACK in incremental selection
transfer, the property will be on the receiver's window. */
@@ -6182,6 +6190,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
/* Perhaps reparented due to a WM restart. Reset this. */
FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
+ FRAME_X_DISPLAY_INFO (f)->net_supported_window = 0;
}
goto OTHER;
@@ -6340,6 +6349,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
case KeyPress:
+ last_user_time = event.xkey.time;
ignore_next_mouse_click_timeout = 0;
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
@@ -6704,6 +6714,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
#endif
case KeyRelease:
+ last_user_time = event.xkey.time;
#ifdef HAVE_X_I18N
/* Don't dispatch this event since XtDispatchEvent calls
XFilterEvent, and two calls in a row may freeze the
@@ -6714,6 +6725,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
#endif
case EnterNotify:
+ last_user_time = event.xcrossing.time;
x_detect_focus_change (dpyinfo, &event, &inev.ie);
f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
@@ -6754,6 +6766,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
goto OTHER;
case LeaveNotify:
+ last_user_time = event.xcrossing.time;
x_detect_focus_change (dpyinfo, &event, &inev.ie);
f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
@@ -6787,6 +6800,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
case MotionNotify:
{
+ last_user_time = event.xmotion.time;
previous_help_echo_string = help_echo_string;
help_echo_string = Qnil;
@@ -6935,6 +6949,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
bzero (&compose_status, sizeof (compose_status));
last_mouse_glyph_frame = 0;
+ last_user_time = event.xbutton.time;
if (dpyinfo->grabbed
&& last_mouse_frame
@@ -8595,40 +8610,111 @@ x_set_offset (f, xoff, yoff, change_gravity)
UNBLOCK_INPUT;
}
-/* Do fullscreen as specified in extended window manager hints */
+/* Return non-zero if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED
+ on the root window for frame F contains ATOMNAME.
+ This is how a WM check shall be done according to the Window Manager
+ Specification/Extended Window Manager Hints at
+ http://freedesktop.org/wiki/Standards_2fwm_2dspec. */
+
static int
-do_ewmh_fullscreen (f)
+wm_supports (f, atomname)
struct frame *f;
+ const char *atomname;
{
- int have_net_atom = FRAME_X_DISPLAY_INFO (f)->have_net_atoms;
+ Atom actual_type;
+ unsigned long actual_size, bytes_remaining;
+ int i, rc, actual_format;
+ Atom prop_atom;
+ Window wmcheck_window;
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ Window target_window = dpyinfo->root_window;
+ long max_len = 65536;
+ Display *dpy = FRAME_X_DISPLAY (f);
+ unsigned char *tmp_data = NULL;
+ Atom target_type = XA_WINDOW;
+ Atom want_atom;
- if (!have_net_atom)
+ BLOCK_INPUT;
+
+ prop_atom = XInternAtom (dpy, "_NET_SUPPORTING_WM_CHECK", False);
+
+ x_catch_errors (dpy);
+ rc = XGetWindowProperty (dpy, target_window,
+ prop_atom, 0, max_len, False, target_type,
+ &actual_type, &actual_format, &actual_size,
+ &bytes_remaining, &tmp_data);
+
+ if (rc != Success || actual_type != XA_WINDOW || x_had_errors_p (dpy))
+ {
+ if (tmp_data) XFree (tmp_data);
+ x_uncatch_errors ();
+ UNBLOCK_INPUT;
+ return 0;
+ }
+
+ wmcheck_window = *(Window *) tmp_data;
+ XFree (tmp_data);
+
+ /* Check if window exists. */
+ XSelectInput (dpy, wmcheck_window, StructureNotifyMask);
+ x_sync (f);
+ if (x_had_errors_p (dpy))
+ {
+ x_uncatch_errors ();
+ UNBLOCK_INPUT;
+ return 0;
+ }
+
+ if (dpyinfo->net_supported_window != wmcheck_window)
{
- int num;
- Atom *atoms = XListProperties (FRAME_X_DISPLAY (f),
- FRAME_X_DISPLAY_INFO (f)->root_window,
- &num);
- if (atoms && num > 0)
+ /* Window changed, reload atoms */
+ if (dpyinfo->net_supported_atoms != NULL)
+ XFree (dpyinfo->net_supported_atoms);
+ dpyinfo->net_supported_atoms = NULL;
+ dpyinfo->nr_net_supported_atoms = 0;
+ dpyinfo->net_supported_window = 0;
+
+ target_type = XA_ATOM;
+ prop_atom = XInternAtom (dpy, "_NET_SUPPORTED", False);
+ tmp_data = NULL;
+ rc = XGetWindowProperty (dpy, target_window,
+ prop_atom, 0, max_len, False, target_type,
+ &actual_type, &actual_format, &actual_size,
+ &bytes_remaining, &tmp_data);
+
+ if (rc != Success || actual_type != XA_ATOM || x_had_errors_p (dpy))
{
- char **names = (char **) xmalloc (num * sizeof(*names));
- if (XGetAtomNames (FRAME_X_DISPLAY (f), atoms, num, names))
- {
- int i;
- for (i = 0; i < num; ++i)
- {
- if (!have_net_atom)
- have_net_atom = strncmp (names[i], "_NET_", 5) == 0;
- XFree (names[i]);
- }
- }
- xfree (names);
+ if (tmp_data) XFree (tmp_data);
+ x_uncatch_errors ();
+ UNBLOCK_INPUT;
+ return 0;
}
- if (atoms)
- XFree (atoms);
- FRAME_X_DISPLAY_INFO (f)->have_net_atoms = have_net_atom;
+ dpyinfo->net_supported_atoms = (Atom *)tmp_data;
+ dpyinfo->nr_net_supported_atoms = actual_size;
+ dpyinfo->net_supported_window = wmcheck_window;
}
+ rc = 0;
+ want_atom = XInternAtom (dpy, atomname, False);
+
+ for (i = 0; rc == 0 && i < dpyinfo->nr_net_supported_atoms; ++i)
+ rc = dpyinfo->net_supported_atoms[i] == want_atom;
+
+ x_uncatch_errors ();
+ UNBLOCK_INPUT;
+
+ return rc;
+}
+
+/* Do fullscreen as specified in extended window manager hints */
+
+static int
+do_ewmh_fullscreen (f)
+ struct frame *f;
+{
+ int have_net_atom = wm_supports (f, "_NET_WM_STATE");
+
if (have_net_atom)
{
Lisp_Object frame;
@@ -8655,6 +8741,9 @@ do_ewmh_fullscreen (f)
break;
}
+ if (!wm_supports (f, what)) return 0;
+
+
Fx_send_client_event (frame, make_number (0), frame,
make_unibyte_string (atom, strlen (atom)),
make_number (32),
@@ -9055,23 +9144,27 @@ XTframe_raise_lower (f, raise_flag)
/* The following code is needed for `raise-frame' to work on
some versions of metacity; see Window Manager
Specification/Extended Window Manager Hints at
- http://freedesktop.org/wiki/Standards_2fwm_2dspec
+ http://freedesktop.org/wiki/Standards_2fwm_2dspec */
- However, on other versions (metacity 2.17.2-1.fc7), it
+#if 0
+ /* However, on other versions (metacity 2.17.2-1.fc7), it
reportedly causes hangs when resizing frames. */
- /* Lisp_Object frame;
- const char *atom = "_NET_ACTIVE_WINDOW"; */
-
- x_raise_frame (f);
-
- /* XSETFRAME (frame, f);
- Fx_send_client_event (frame, make_number (0), frame,
- make_unibyte_string (atom, strlen (atom)),
- make_number (32),
- Fcons (make_number (1),
- Fcons (make_number (time (NULL) * 1000),
- Qnil))); */
+ const char *atom = "_NET_ACTIVE_WINDOW";
+ if (f->async_visible && wm_supports (f, atom))
+ {
+ Lisp_Object frame;
+ XSETFRAME (frame, f);
+ Fx_send_client_event (frame, make_number (0), frame,
+ make_unibyte_string (atom, strlen (atom)),
+ make_number (32),
+ Fcons (make_number (1),
+ Fcons (make_number (last_user_time),
+ Qnil)));
+ }
+ else
+#endif
+ x_raise_frame (f);
}
else
x_lower_frame (f);
@@ -11210,6 +11303,10 @@ x_term_init (display_name, xrm_option, resource_name)
dpyinfo->x_dnd_atoms = xmalloc (sizeof (*dpyinfo->x_dnd_atoms)
* dpyinfo->x_dnd_atoms_size);
+ dpyinfo->net_supported_atoms = NULL;
+ dpyinfo->nr_net_supported_atoms = 0;
+ dpyinfo->net_supported_window = 0;
+
connection = ConnectionNumber (dpyinfo->display);
dpyinfo->connection = connection;