|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* Copyright (C) 2002-2006 Sergey V. Udaltsov <svu@gnome.org>
|
|
Packit Service |
93d855 |
*
|
|
Packit Service |
93d855 |
* This library is free software; you can redistribute it and/or
|
|
Packit Service |
93d855 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit Service |
93d855 |
* License as published by the Free Software Foundation; either
|
|
Packit Service |
93d855 |
* version 2 of the License, or (at your option) any later version.
|
|
Packit Service |
93d855 |
*
|
|
Packit Service |
93d855 |
* This library is distributed in the hope that it will be useful,
|
|
Packit Service |
93d855 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
93d855 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
93d855 |
* Lesser General Public License for more details.
|
|
Packit Service |
93d855 |
*
|
|
Packit Service |
93d855 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit Service |
93d855 |
* License along with this library; if not, write to the
|
|
Packit Service |
93d855 |
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
Packit Service |
93d855 |
* Boston, MA 02111-1307, USA.
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
#include <string.h>
|
|
Packit Service |
93d855 |
#include <time.h>
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
#include <X11/Xatom.h>
|
|
Packit Service |
93d855 |
#include <X11/Xlib.h>
|
|
Packit Service |
93d855 |
#include <X11/Xutil.h>
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
#include "xklavier_private.h"
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
gint
|
|
Packit Service |
93d855 |
xkl_engine_filter_events(XklEngine * engine, XEvent * xev)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
XAnyEvent *pe = (XAnyEvent *) xev;
|
|
Packit Service |
93d855 |
xkl_debug(400,
|
|
Packit Service |
93d855 |
"**> Filtering event %d of type %d from window %d\n",
|
|
Packit Service |
93d855 |
pe->serial, pe->type, pe->window);
|
|
Packit Service |
93d855 |
xkl_engine_ensure_vtable_inited(engine);
|
|
Packit Service |
93d855 |
if (!xkl_engine_vcall(engine, process_x_event) (engine, xev))
|
|
Packit Service |
93d855 |
switch (xev->type) { /* core events */
|
|
Packit Service |
93d855 |
case FocusIn:
|
|
Packit Service |
93d855 |
xkl_engine_process_focus_in_evt(engine,
|
|
Packit Service |
93d855 |
&xev->xfocus);
|
|
Packit Service |
93d855 |
break;
|
|
Packit Service |
93d855 |
case FocusOut:
|
|
Packit Service |
93d855 |
xkl_engine_process_focus_out_evt(engine,
|
|
Packit Service |
93d855 |
&xev->xfocus);
|
|
Packit Service |
93d855 |
break;
|
|
Packit Service |
93d855 |
case PropertyNotify:
|
|
Packit Service |
93d855 |
xkl_engine_process_property_evt(engine,
|
|
Packit Service |
93d855 |
&xev->xproperty);
|
|
Packit Service |
93d855 |
break;
|
|
Packit Service |
93d855 |
case CreateNotify:
|
|
Packit Service |
93d855 |
xkl_engine_process_create_window_evt(engine,
|
|
Packit Service |
93d855 |
&xev->xcreatewindow);
|
|
Packit Service |
93d855 |
break;
|
|
Packit Service |
93d855 |
case DestroyNotify:
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"Window " WINID_FORMAT " destroyed\n",
|
|
Packit Service |
93d855 |
xev->xdestroywindow.window);
|
|
Packit Service |
93d855 |
break;
|
|
Packit Service |
93d855 |
case UnmapNotify:
|
|
Packit Service |
93d855 |
xkl_debug(200,
|
|
Packit Service |
93d855 |
"Window " WINID_FORMAT " unmapped\n",
|
|
Packit Service |
93d855 |
xev->xunmap.window);
|
|
Packit Service |
93d855 |
break;
|
|
Packit Service |
93d855 |
case MapNotify:
|
|
Packit Service |
93d855 |
case GravityNotify:
|
|
Packit Service |
93d855 |
xkl_debug(200, "%s\n",
|
|
Packit Service |
93d855 |
xkl_event_get_name(xev->type));
|
|
Packit Service |
93d855 |
break; /* Ignore these events */
|
|
Packit Service |
93d855 |
case ReparentNotify:
|
|
Packit Service |
93d855 |
xkl_debug(200,
|
|
Packit Service |
93d855 |
"Window " WINID_FORMAT " reparented to "
|
|
Packit Service |
93d855 |
WINID_FORMAT "\n", xev->xreparent.window,
|
|
Packit Service |
93d855 |
xev->xreparent.parent);
|
|
Packit Service |
93d855 |
break; /* Ignore these events */
|
|
Packit Service |
93d855 |
case MappingNotify:
|
|
Packit Service |
93d855 |
xkl_debug(200, "%s\n",
|
|
Packit Service |
93d855 |
xkl_event_get_name(xev->type));
|
|
Packit Service |
93d855 |
xkl_engine_reset_all_info(engine, FALSE,
|
|
Packit Service |
93d855 |
"X event: MappingNotify");
|
|
Packit Service |
93d855 |
break;
|
|
Packit Service |
93d855 |
default:
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
xkl_debug(200, "Unknown event %d [%s]\n",
|
|
Packit Service |
93d855 |
xev->type,
|
|
Packit Service |
93d855 |
xkl_event_get_name(xev->type));
|
|
Packit Service |
93d855 |
return 1;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
xkl_debug(400, "Filtered event %d of type %d from window %d **>\n",
|
|
Packit Service |
93d855 |
pe->serial, pe->type, pe->window);
|
|
Packit Service |
93d855 |
return 1;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* FocusIn handler
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
void
|
|
Packit Service |
93d855 |
xkl_engine_process_focus_in_evt(XklEngine * engine,
|
|
Packit Service |
93d855 |
XFocusChangeEvent * fev)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
Window win;
|
|
Packit Service |
93d855 |
Window prev_toplevel_win =
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, curr_toplvl_win);
|
|
Packit Service |
93d855 |
Window toplevel_win;
|
|
Packit Service |
93d855 |
XklState selected_window_state;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (!
|
|
Packit Service |
93d855 |
(xkl_engine_is_listening_for
|
|
Packit Service |
93d855 |
(engine, XKLL_MANAGE_WINDOW_STATES)))
|
|
Packit Service |
93d855 |
return;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
win = fev->window;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
switch (fev->mode) {
|
|
Packit Service |
93d855 |
case NotifyNormal:
|
|
Packit Service |
93d855 |
case NotifyWhileGrabbed:
|
|
Packit Service |
93d855 |
break;
|
|
Packit Service |
93d855 |
default:
|
|
Packit Service |
93d855 |
xkl_debug(160,
|
|
Packit Service |
93d855 |
"Window " WINID_FORMAT
|
|
Packit Service |
93d855 |
" has got focus during special action %d\n", win,
|
|
Packit Service |
93d855 |
fev->mode);
|
|
Packit Service |
93d855 |
return;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
xkl_debug(150, "Window " WINID_FORMAT ", '%s' has got focus\n",
|
|
Packit Service |
93d855 |
win, xkl_get_debug_window_title(engine, win));
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (!xkl_engine_find_toplevel_window(engine, win, &toplevel_win)) {
|
|
Packit Service |
93d855 |
return;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
xkl_debug(150, "Appwin " WINID_FORMAT ", '%s' has got focus\n",
|
|
Packit Service |
93d855 |
toplevel_win, xkl_get_debug_window_title(engine,
|
|
Packit Service |
93d855 |
toplevel_win));
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (xkl_engine_get_toplevel_window_state
|
|
Packit Service |
93d855 |
(engine, toplevel_win, &selected_window_state)) {
|
|
Packit Service |
93d855 |
if (prev_toplevel_win != toplevel_win) {
|
|
Packit Service |
93d855 |
gboolean new_win_transparent;
|
|
Packit Service |
93d855 |
Window parent = (Window) NULL, root =
|
|
Packit Service |
93d855 |
(Window) NULL, *children = NULL;
|
|
Packit Service |
93d855 |
guint nchildren = 0;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* If previous focused window exists - handle transparency and state
|
|
Packit Service |
93d855 |
* (optional)
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
if (xkl_engine_query_tree
|
|
Packit Service |
93d855 |
(engine, prev_toplevel_win, &root, &parent,
|
|
Packit Service |
93d855 |
&children, &nchildren) == Success) {
|
|
Packit Service |
93d855 |
XklState tmp_state;
|
|
Packit Service |
93d855 |
gboolean old_win_transparent =
|
|
Packit Service |
93d855 |
xkl_engine_is_toplevel_window_transparent
|
|
Packit Service |
93d855 |
(engine, prev_toplevel_win);
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (children != NULL)
|
|
Packit Service |
93d855 |
XFree(children);
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (old_win_transparent)
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"Leaving transparent window\n");
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* Reload the current state from the current window.
|
|
Packit Service |
93d855 |
* Do not do it for transparent window - we keep the state from
|
|
Packit Service |
93d855 |
* the _previous_ window.
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
if (!old_win_transparent
|
|
Packit Service |
93d855 |
&&
|
|
Packit Service |
93d855 |
xkl_engine_get_toplevel_window_state
|
|
Packit Service |
93d855 |
(engine, prev_toplevel_win,
|
|
Packit Service |
93d855 |
&tmp_state)) {
|
|
Packit Service |
93d855 |
xkl_engine_update_current_state
|
|
Packit Service |
93d855 |
(engine, tmp_state.group,
|
|
Packit Service |
93d855 |
tmp_state.indicators,
|
|
Packit Service |
93d855 |
"Loading current (previous) state from the current (previous) window");
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
} else
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"Current (previous) window "
|
|
Packit Service |
93d855 |
WINID_FORMAT
|
|
Packit Service |
93d855 |
" does not exist any more, so transparency/state are not analyzed\n",
|
|
Packit Service |
93d855 |
prev_toplevel_win);
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, curr_toplvl_win) =
|
|
Packit Service |
93d855 |
toplevel_win;
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"CurClient:changed to " WINID_FORMAT
|
|
Packit Service |
93d855 |
", '%s'\n", xkl_engine_priv(engine,
|
|
Packit Service |
93d855 |
curr_toplvl_win),
|
|
Packit Service |
93d855 |
xkl_get_debug_window_title(engine,
|
|
Packit Service |
93d855 |
xkl_engine_priv
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
curr_toplvl_win)));
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
new_win_transparent =
|
|
Packit Service |
93d855 |
xkl_engine_is_toplevel_window_transparent
|
|
Packit Service |
93d855 |
(engine, toplevel_win);
|
|
Packit Service |
93d855 |
if (new_win_transparent)
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"Entering transparent window\n");
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (xkl_engine_is_group_per_toplevel_window(engine)
|
|
Packit Service |
93d855 |
== !new_win_transparent) {
|
|
Packit Service |
93d855 |
/* We skip restoration only if we return to the same app window */
|
|
Packit Service |
93d855 |
gboolean do_skip = FALSE;
|
|
Packit Service |
93d855 |
if (xkl_engine_priv
|
|
Packit Service |
93d855 |
(engine, skip_one_restore)) {
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine,
|
|
Packit Service |
93d855 |
skip_one_restore) =
|
|
Packit Service |
93d855 |
FALSE;
|
|
Packit Service |
93d855 |
if (toplevel_win ==
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine,
|
|
Packit Service |
93d855 |
prev_toplvl_win))
|
|
Packit Service |
93d855 |
do_skip = TRUE;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (do_skip) {
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"Skipping one restore as requested - instead, "
|
|
Packit Service |
93d855 |
"saving the current group into the window state\n");
|
|
Packit Service |
93d855 |
xkl_engine_save_toplevel_window_state
|
|
Packit Service |
93d855 |
(engine, toplevel_win,
|
|
Packit Service |
93d855 |
&xkl_engine_priv(engine,
|
|
Packit Service |
93d855 |
curr_state));
|
|
Packit Service |
93d855 |
} else {
|
|
Packit Service |
93d855 |
if (xkl_engine_priv
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
curr_state).group !=
|
|
Packit Service |
93d855 |
selected_window_state.group) {
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"Restoring the group from %d to %d after gaining focus\n",
|
|
Packit Service |
93d855 |
xkl_engine_priv
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
curr_state).group,
|
|
Packit Service |
93d855 |
selected_window_state.group);
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* For fast mouse movements - the state is probably not updated yet
|
|
Packit Service |
93d855 |
* (because of the group change notification being late).
|
|
Packit Service |
93d855 |
* so we'll enforce the update. But this should only happen in GPA mode
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
xkl_engine_update_current_state
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
selected_window_state.group,
|
|
Packit Service |
93d855 |
selected_window_state.indicators,
|
|
Packit Service |
93d855 |
"Enforcing fast update of the current state");
|
|
Packit Service |
93d855 |
xkl_engine_lock_group
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
selected_window_state.group);
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, skip_one_save) = TRUE;
|
|
Packit Service |
93d855 |
} else {
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"Both old and new focused window "
|
|
Packit Service |
93d855 |
"have group %d so no point restoring it\n",
|
|
Packit Service |
93d855 |
selected_window_state.group);
|
|
Packit Service |
93d855 |
xkl_engine_one_switch_to_secondary_group_performed
|
|
Packit Service |
93d855 |
(engine);
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if ((xkl_engine_priv(engine, features) &
|
|
Packit Service |
93d855 |
XKLF_CAN_TOGGLE_INDICATORS)
|
|
Packit Service |
93d855 |
&&
|
|
Packit Service |
93d855 |
xkl_engine_get_indicators_handling
|
|
Packit Service |
93d855 |
(engine)) {
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"Restoring the indicators from %X to %X after gaining focus\n",
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine,
|
|
Packit Service |
93d855 |
curr_state).indicators,
|
|
Packit Service |
93d855 |
selected_window_state.indicators);
|
|
Packit Service |
93d855 |
xkl_engine_ensure_vtable_inited
|
|
Packit Service |
93d855 |
(engine);
|
|
Packit Service |
93d855 |
xkl_engine_vcall(engine,
|
|
Packit Service |
93d855 |
set_indicators)
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
&selected_window_state);
|
|
Packit Service |
93d855 |
} else
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"Not restoring the indicators %X after gaining focus: indicator handling is not enabled\n",
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine,
|
|
Packit Service |
93d855 |
curr_state).indicators);
|
|
Packit Service |
93d855 |
} else
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"Not restoring the group %d after gaining focus: global layout (xor transparent window)\n",
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine,
|
|
Packit Service |
93d855 |
curr_state).group);
|
|
Packit Service |
93d855 |
} else
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"Same app window - just do nothing\n");
|
|
Packit Service |
93d855 |
} else {
|
|
Packit Service |
93d855 |
xkl_debug(150, "But it does not have xklavier_state\n");
|
|
Packit Service |
93d855 |
if (xkl_engine_if_window_has_wm_state(engine, win)) {
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"But it does have wm_state so we'll add it\n");
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, curr_toplvl_win) =
|
|
Packit Service |
93d855 |
toplevel_win;
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"CurClient:changed to " WINID_FORMAT
|
|
Packit Service |
93d855 |
", '%s'\n", xkl_engine_priv(engine,
|
|
Packit Service |
93d855 |
curr_toplvl_win),
|
|
Packit Service |
93d855 |
xkl_get_debug_window_title(engine,
|
|
Packit Service |
93d855 |
xkl_engine_priv
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
curr_toplvl_win)));
|
|
Packit Service |
93d855 |
xkl_engine_add_toplevel_window(engine,
|
|
Packit Service |
93d855 |
xkl_engine_priv
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
curr_toplvl_win),
|
|
Packit Service |
93d855 |
(Window) NULL,
|
|
Packit Service |
93d855 |
FALSE,
|
|
Packit Service |
93d855 |
&xkl_engine_priv
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
curr_state));
|
|
Packit Service |
93d855 |
} else
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"And it does have wm_state either\n");
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* FocusOut handler
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
void
|
|
Packit Service |
93d855 |
xkl_engine_process_focus_out_evt(XklEngine * engine,
|
|
Packit Service |
93d855 |
XFocusChangeEvent * fev)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
if (!
|
|
Packit Service |
93d855 |
(xkl_engine_is_listening_for
|
|
Packit Service |
93d855 |
(engine, XKLL_MANAGE_WINDOW_STATES)))
|
|
Packit Service |
93d855 |
return;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (fev->mode != NotifyNormal) {
|
|
Packit Service |
93d855 |
xkl_debug(200,
|
|
Packit Service |
93d855 |
"Window " WINID_FORMAT
|
|
Packit Service |
93d855 |
" has lost focus during special action %d\n",
|
|
Packit Service |
93d855 |
fev->window, fev->mode);
|
|
Packit Service |
93d855 |
return;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
xkl_debug(160, "Window " WINID_FORMAT ", '%s' has lost focus\n",
|
|
Packit Service |
93d855 |
fev->window, xkl_get_debug_window_title(engine,
|
|
Packit Service |
93d855 |
fev->window));
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (xkl_engine_is_toplevel_window_transparent(engine, fev->window)) {
|
|
Packit Service |
93d855 |
xkl_debug(150, "Leaving transparent window!\n");
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* If we are leaving the transparent window - we skip the restore operation.
|
|
Packit Service |
93d855 |
* This is useful for secondary groups switching from the transparent control
|
|
Packit Service |
93d855 |
* window.
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, skip_one_restore) = TRUE;
|
|
Packit Service |
93d855 |
} else {
|
|
Packit Service |
93d855 |
Window p;
|
|
Packit Service |
93d855 |
if (xkl_engine_find_toplevel_window
|
|
Packit Service |
93d855 |
(engine, fev->window, &p))
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, prev_toplvl_win) = p;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* PropertyChange handler
|
|
Packit Service |
93d855 |
* Interested in :
|
|
Packit Service |
93d855 |
* + for XKLL_MANAGE_WINDOW_STATES
|
|
Packit Service |
93d855 |
* - WM_STATE property for all windows
|
|
Packit Service |
93d855 |
* - Configuration property of the root window
|
|
Packit Service |
93d855 |
* + for XKLL_TRACK_KEYBOARD_STATE
|
|
Packit Service |
93d855 |
* - Configuration property of the root window
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
void
|
|
Packit Service |
93d855 |
xkl_engine_process_property_evt(XklEngine * engine, XPropertyEvent * pev)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
if (400 <= xkl_debug_level) {
|
|
Packit Service |
93d855 |
char *atom_name =
|
|
Packit Service |
93d855 |
XGetAtomName(xkl_engine_get_display(engine),
|
|
Packit Service |
93d855 |
pev->atom);
|
|
Packit Service |
93d855 |
if (atom_name != NULL) {
|
|
Packit Service |
93d855 |
xkl_debug(400,
|
|
Packit Service |
93d855 |
"The property '%s' changed for "
|
|
Packit Service |
93d855 |
WINID_FORMAT "\n", atom_name,
|
|
Packit Service |
93d855 |
pev->window);
|
|
Packit Service |
93d855 |
XFree(atom_name);
|
|
Packit Service |
93d855 |
} else {
|
|
Packit Service |
93d855 |
xkl_debug(200,
|
|
Packit Service |
93d855 |
"Some magic property changed for "
|
|
Packit Service |
93d855 |
WINID_FORMAT "\n", pev->window);
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (pev->atom == xkl_engine_priv(engine, atoms)[WM_STATE]) {
|
|
Packit Service |
93d855 |
if (xkl_engine_is_listening_for
|
|
Packit Service |
93d855 |
(engine, XKLL_MANAGE_WINDOW_STATES)) {
|
|
Packit Service |
93d855 |
gboolean has_xkl_state =
|
|
Packit Service |
93d855 |
xkl_engine_get_state(engine, pev->window,
|
|
Packit Service |
93d855 |
NULL);
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (pev->state == PropertyNewValue) {
|
|
Packit Service |
93d855 |
xkl_debug(160,
|
|
Packit Service |
93d855 |
"New value of WM_STATE on window "
|
|
Packit Service |
93d855 |
WINID_FORMAT "\n", pev->window);
|
|
Packit Service |
93d855 |
if (!has_xkl_state) { /* Is this event the first or not? */
|
|
Packit Service |
93d855 |
xkl_engine_add_toplevel_window
|
|
Packit Service |
93d855 |
(engine, pev->window, (Window)
|
|
Packit Service |
93d855 |
NULL, FALSE,
|
|
Packit Service |
93d855 |
&xkl_engine_priv(engine,
|
|
Packit Service |
93d855 |
curr_state));
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
} else { /* ev->xproperty.state == PropertyDelete, either client or WM can remove it, ICCCM 4.1.3.1 */
|
|
Packit Service |
93d855 |
xkl_debug(160,
|
|
Packit Service |
93d855 |
"Something (%d) happened to WM_STATE of window 0x%x\n",
|
|
Packit Service |
93d855 |
pev->state, pev->window);
|
|
Packit Service |
93d855 |
xkl_engine_select_input_merging(engine,
|
|
Packit Service |
93d855 |
pev->window,
|
|
Packit Service |
93d855 |
PropertyChangeMask);
|
|
Packit Service |
93d855 |
if (has_xkl_state) {
|
|
Packit Service |
93d855 |
xkl_engine_delete_state(engine,
|
|
Packit Service |
93d855 |
pev->window);
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
} /* XKLL_MANAGE_WINDOW_STATES */
|
|
Packit Service |
93d855 |
} else if (pev->atom == xkl_engine_priv(engine, base_config_atom)
|
|
Packit Service |
93d855 |
&& pev->window == xkl_engine_priv(engine, root_window)) {
|
|
Packit Service |
93d855 |
if (xkl_engine_is_listening_for
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
XKLL_MANAGE_WINDOW_STATES) |
|
|
Packit Service |
93d855 |
xkl_engine_is_listening_for(engine,
|
|
Packit Service |
93d855 |
XKLL_TRACK_KEYBOARD_STATE))
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
if (pev->state == PropertyNewValue) {
|
|
Packit Service |
93d855 |
/* If root window got new *_NAMES_PROP_ATOM -
|
|
Packit Service |
93d855 |
it most probably means new keyboard config is loaded by somebody */
|
|
Packit Service |
93d855 |
xkl_engine_reset_all_info
|
|
Packit Service |
93d855 |
(engine, TRUE,
|
|
Packit Service |
93d855 |
"New value of *_NAMES_PROP_ATOM on root window");
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
} /* XKLL_MANAGE_WINDOW_STATES | XKLL_TRACK_KEYBOARD_STATE */
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* CreateNotify handler. Just interested in properties and focus events...
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
void
|
|
Packit Service |
93d855 |
xkl_engine_process_create_window_evt(XklEngine * engine,
|
|
Packit Service |
93d855 |
XCreateWindowEvent * cev)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
if (!xkl_engine_is_listening_for
|
|
Packit Service |
93d855 |
(engine, XKLL_MANAGE_WINDOW_STATES))
|
|
Packit Service |
93d855 |
return;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
xkl_debug(200,
|
|
Packit Service |
93d855 |
"Under-root window " WINID_FORMAT
|
|
Packit Service |
93d855 |
"/%s (%d,%d,%d x %d) is created\n", cev->window,
|
|
Packit Service |
93d855 |
xkl_get_debug_window_title(engine, cev->window), cev->x,
|
|
Packit Service |
93d855 |
cev->y, cev->width, cev->height);
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (!cev->override_redirect) {
|
|
Packit Service |
93d855 |
/* ICCCM 4.1.6: override-redirect is NOT private to
|
|
Packit Service |
93d855 |
* client (and must not be changed - am I right?)
|
|
Packit Service |
93d855 |
* We really need only PropertyChangeMask on this window but even in the case of
|
|
Packit Service |
93d855 |
* local server we can lose PropertyNotify events (the trip time for this CreateNotify
|
|
Packit Service |
93d855 |
* event + SelectInput request is not zero) and we definitely will (my system DO)
|
|
Packit Service |
93d855 |
* lose FocusIn/Out events after the following call of PropertyNotifyHandler.
|
|
Packit Service |
93d855 |
* So I just decided to purify this extra FocusChangeMask in the FocusIn/OutHandler. */
|
|
Packit Service |
93d855 |
xkl_engine_select_input_merging(engine, cev->window,
|
|
Packit Service |
93d855 |
PropertyChangeMask |
|
|
Packit Service |
93d855 |
FocusChangeMask);
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (xkl_engine_if_window_has_wm_state(engine, cev->window)) {
|
|
Packit Service |
93d855 |
xkl_debug(200,
|
|
Packit Service |
93d855 |
"Just created window already has WM_STATE - so I'll add it");
|
|
Packit Service |
93d855 |
xkl_engine_add_toplevel_window(engine, cev->window,
|
|
Packit Service |
93d855 |
(Window) NULL,
|
|
Packit Service |
93d855 |
FALSE,
|
|
Packit Service |
93d855 |
&xkl_engine_priv
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
curr_state));
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* Just error handler - sometimes we get BadWindow error for already gone
|
|
Packit Service |
93d855 |
* windows, so we'll just ignore
|
|
Packit Service |
93d855 |
* This handler can be called in the middle of the engine initialization -
|
|
Packit Service |
93d855 |
* so it is not fair to assume that the engine is available
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
int
|
|
Packit Service |
93d855 |
xkl_process_error(Display * dpy, XErrorEvent * evt)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
char buf[128] = "";
|
|
Packit Service |
93d855 |
XklEngine *engine = xkl_get_the_engine();
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (engine != NULL)
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, last_error_code) = evt->error_code;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
switch (evt->error_code) {
|
|
Packit Service |
93d855 |
case BadAccess:
|
|
Packit Service |
93d855 |
case BadDrawable:
|
|
Packit Service |
93d855 |
case BadWindow:
|
|
Packit Service |
93d855 |
case BadMatch:
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
XGetErrorText(evt->display, evt->error_code, buf,
|
|
Packit Service |
93d855 |
sizeof(buf));
|
|
Packit Service |
93d855 |
/* in most cases this means we are late:) */
|
|
Packit Service |
93d855 |
xkl_debug(200,
|
|
Packit Service |
93d855 |
"ERROR: %p, " WINID_FORMAT ", %d [%s], "
|
|
Packit Service |
93d855 |
"X11 request: %d, minor code: %d\n", dpy,
|
|
Packit Service |
93d855 |
(unsigned long) evt->resourceid,
|
|
Packit Service |
93d855 |
(int) evt->error_code, buf,
|
|
Packit Service |
93d855 |
(int) evt->request_code,
|
|
Packit Service |
93d855 |
(int) evt->minor_code);
|
|
Packit Service |
93d855 |
break;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
default:
|
|
Packit Service |
93d855 |
if (engine != NULL
|
|
Packit Service |
93d855 |
&& xkl_engine_priv(engine, process_x_error)) {
|
|
Packit Service |
93d855 |
if (xkl_engine_priv(engine, process_x_error)
|
|
Packit Service |
93d855 |
(engine, evt)) {
|
|
Packit Service |
93d855 |
xkl_debug(200,
|
|
Packit Service |
93d855 |
"X ERROR processed by the engine: %p, "
|
|
Packit Service |
93d855 |
WINID_FORMAT ", %d [%s], "
|
|
Packit Service |
93d855 |
"X11 request: %d, minor code: %d\n",
|
|
Packit Service |
93d855 |
dpy,
|
|
Packit Service |
93d855 |
(unsigned long) evt->resourceid,
|
|
Packit Service |
93d855 |
(int) evt->error_code, buf,
|
|
Packit Service |
93d855 |
(int) evt->request_code,
|
|
Packit Service |
93d855 |
(int) evt->minor_code);
|
|
Packit Service |
93d855 |
break;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
xkl_debug(200,
|
|
Packit Service |
93d855 |
"Unexpected by libxklavier X ERROR: %p, "
|
|
Packit Service |
93d855 |
WINID_FORMAT ", %d [%s], "
|
|
Packit Service |
93d855 |
"X11 request: %d, minor code: %d\n", dpy,
|
|
Packit Service |
93d855 |
(unsigned long) evt->resourceid,
|
|
Packit Service |
93d855 |
(int) evt->error_code, buf,
|
|
Packit Service |
93d855 |
(int) evt->request_code, (int) evt->minor_code);
|
|
Packit Service |
93d855 |
if (engine != NULL)
|
|
Packit Service |
93d855 |
if (!xkl_engine_priv(engine, critical_section))
|
|
Packit Service |
93d855 |
(*xkl_engine_priv
|
|
Packit Service |
93d855 |
(engine, default_error_handler))
|
|
Packit Service |
93d855 |
(dpy, evt);
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
/* X ignores this return value anyway */
|
|
Packit Service |
93d855 |
return 0;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* Some common functionality for Xkb handler
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
void
|
|
Packit Service |
93d855 |
xkl_engine_process_state_modification(XklEngine * engine,
|
|
Packit Service |
93d855 |
XklEngineStateChange change_type,
|
|
Packit Service |
93d855 |
gint grp, guint inds,
|
|
Packit Service |
93d855 |
gboolean set_inds)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
Window focused, focused_toplevel;
|
|
Packit Service |
93d855 |
XklState old_state;
|
|
Packit Service |
93d855 |
gint revert;
|
|
Packit Service |
93d855 |
gboolean have_old_state = TRUE;
|
|
Packit Service |
93d855 |
gboolean set_group = change_type == GROUP_CHANGED;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (xkl_engine_priv(engine, skip_one_save)) {
|
|
Packit Service |
93d855 |
xkl_debug(160, "Skipping one callback");
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, skip_one_save) = FALSE;
|
|
Packit Service |
93d855 |
return;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
XGetInputFocus(xkl_engine_get_display(engine), &focused, &revert);
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if ((focused == None) || (focused == PointerRoot)) {
|
|
Packit Service |
93d855 |
xkl_debug(160, "Something with focus: " WINID_FORMAT "\n",
|
|
Packit Service |
93d855 |
focused);
|
|
Packit Service |
93d855 |
return;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* Only if we manage states - otherwise xkl_engine_priv(engine,curr_toplvl_win) does not make sense
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
if (!xkl_engine_find_toplevel_window
|
|
Packit Service |
93d855 |
(engine, focused, &focused_toplevel)
|
|
Packit Service |
93d855 |
&& xkl_engine_is_listening_for(engine,
|
|
Packit Service |
93d855 |
XKLL_MANAGE_WINDOW_STATES))
|
|
Packit Service |
93d855 |
focused_toplevel = xkl_engine_priv(engine, curr_toplvl_win); /* what else can I do */
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
xkl_debug(150, "Focused window: " WINID_FORMAT ", '%s'\n",
|
|
Packit Service |
93d855 |
focused_toplevel,
|
|
Packit Service |
93d855 |
xkl_get_debug_window_title(engine, focused_toplevel));
|
|
Packit Service |
93d855 |
if (xkl_engine_is_listening_for(engine, XKLL_MANAGE_WINDOW_STATES)) {
|
|
Packit Service |
93d855 |
xkl_debug(150, "CurClient: " WINID_FORMAT ", '%s'\n",
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, curr_toplvl_win),
|
|
Packit Service |
93d855 |
xkl_get_debug_window_title(engine,
|
|
Packit Service |
93d855 |
xkl_engine_priv
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
curr_toplvl_win)));
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (focused_toplevel !=
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, curr_toplvl_win)) {
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* If not state - we got the new window
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
if (!xkl_engine_get_toplevel_window_state
|
|
Packit Service |
93d855 |
(engine, focused_toplevel, &old_state)) {
|
|
Packit Service |
93d855 |
xkl_engine_update_current_state(engine,
|
|
Packit Service |
93d855 |
grp, inds,
|
|
Packit Service |
93d855 |
"Updating the state from new focused window");
|
|
Packit Service |
93d855 |
if (xkl_engine_is_listening_for
|
|
Packit Service |
93d855 |
(engine, XKLL_MANAGE_WINDOW_STATES))
|
|
Packit Service |
93d855 |
xkl_engine_add_toplevel_window
|
|
Packit Service |
93d855 |
(engine, focused_toplevel,
|
|
Packit Service |
93d855 |
(Window) NULL, FALSE,
|
|
Packit Service |
93d855 |
&xkl_engine_priv(engine,
|
|
Packit Service |
93d855 |
curr_state));
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* There is state - just get the state from the window
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
else {
|
|
Packit Service |
93d855 |
grp = old_state.group;
|
|
Packit Service |
93d855 |
inds = old_state.indicators;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, curr_toplvl_win) =
|
|
Packit Service |
93d855 |
focused_toplevel;
|
|
Packit Service |
93d855 |
xkl_debug(160,
|
|
Packit Service |
93d855 |
"CurClient:changed to " WINID_FORMAT
|
|
Packit Service |
93d855 |
", '%s'\n", xkl_engine_priv(engine,
|
|
Packit Service |
93d855 |
curr_toplvl_win),
|
|
Packit Service |
93d855 |
xkl_get_debug_window_title(engine,
|
|
Packit Service |
93d855 |
xkl_engine_priv
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
curr_toplvl_win)));
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
/* If the window already has this this state - we are just restoring it!
|
|
Packit Service |
93d855 |
(see the second parameter of stateCallback */
|
|
Packit Service |
93d855 |
have_old_state =
|
|
Packit Service |
93d855 |
xkl_engine_get_toplevel_window_state(engine,
|
|
Packit Service |
93d855 |
xkl_engine_priv
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
curr_toplvl_win),
|
|
Packit Service |
93d855 |
&old_state);
|
|
Packit Service |
93d855 |
} else { /* just tracking the stuff, no smart things */
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
xkl_debug(160,
|
|
Packit Service |
93d855 |
"Just updating the current state in the tracking mode\n");
|
|
Packit Service |
93d855 |
memcpy(&old_state, &xkl_engine_priv(engine, curr_state),
|
|
Packit Service |
93d855 |
sizeof(XklState));
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (set_group || have_old_state) {
|
|
Packit Service |
93d855 |
xkl_engine_update_current_state(engine,
|
|
Packit Service |
93d855 |
set_group ? grp :
|
|
Packit Service |
93d855 |
old_state.group,
|
|
Packit Service |
93d855 |
set_inds ? inds :
|
|
Packit Service |
93d855 |
old_state.indicators,
|
|
Packit Service |
93d855 |
"Restoring the state from the window");
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (have_old_state)
|
|
Packit Service |
93d855 |
xkl_engine_try_call_state_func(engine, change_type,
|
|
Packit Service |
93d855 |
&old_state);
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (xkl_engine_is_listening_for(engine, XKLL_MANAGE_WINDOW_STATES))
|
|
Packit Service |
93d855 |
xkl_engine_save_toplevel_window_state(engine,
|
|
Packit Service |
93d855 |
xkl_engine_priv
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
curr_toplvl_win),
|
|
Packit Service |
93d855 |
&xkl_engine_priv
|
|
Packit Service |
93d855 |
(engine,
|
|
Packit Service |
93d855 |
curr_state));
|
|
Packit Service |
93d855 |
}
|