|
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 <time.h>
|
|
Packit Service |
93d855 |
#include <string.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 |
XklState *
|
|
Packit Service |
93d855 |
_xkl_state_copy(XklState * state)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
XklState * copy;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
copy = g_new(XklState, 1);
|
|
Packit Service |
93d855 |
copy->group = state->group;
|
|
Packit Service |
93d855 |
copy->indicators = state->indicators;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
return copy;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
G_DEFINE_BOXED_TYPE (XklState, xkl_state, _xkl_state_copy, g_free);
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
XklState *
|
|
Packit Service |
93d855 |
xkl_engine_get_current_state(XklEngine * engine)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
return &xkl_engine_priv(engine, curr_state);
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
const gchar *
|
|
Packit Service |
93d855 |
xkl_get_last_error()
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
return xkl_last_error_message;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
gchar *
|
|
Packit Service |
93d855 |
xkl_engine_get_window_title(XklEngine * engine, Window w)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
Atom type_ret;
|
|
Packit Service |
93d855 |
int format_ret;
|
|
Packit Service |
93d855 |
unsigned long nitems, rest;
|
|
Packit Service |
93d855 |
unsigned char *prop;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if ((w == xkl_engine_priv(engine, root_window))
|
|
Packit Service |
93d855 |
|| (w == PointerRoot))
|
|
Packit Service |
93d855 |
return g_strdup("ROOT");
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (Success ==
|
|
Packit Service |
93d855 |
XGetWindowProperty(xkl_engine_get_display(engine), w,
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, atoms)[WM_NAME], 0L,
|
|
Packit Service |
93d855 |
-1L, False, XA_STRING, &type_ret,
|
|
Packit Service |
93d855 |
&format_ret, &nitems, &rest, &prop))
|
|
Packit Service |
93d855 |
return (gchar *) prop;
|
|
Packit Service |
93d855 |
else
|
|
Packit Service |
93d855 |
return NULL;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
gboolean
|
|
Packit Service |
93d855 |
xkl_engine_is_window_from_same_toplevel_window(XklEngine * engine,
|
|
Packit Service |
93d855 |
Window win1, Window win2)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
Window app1, app2;
|
|
Packit Service |
93d855 |
return xkl_engine_find_toplevel_window(engine, win1, &app1) &&
|
|
Packit Service |
93d855 |
xkl_engine_find_toplevel_window(engine, win2, &app2)
|
|
Packit Service |
93d855 |
&& app1 == app2;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
gboolean
|
|
Packit Service |
93d855 |
xkl_engine_get_state(XklEngine * engine, Window win, XklState * state_out)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
Window app_win;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (!xkl_engine_find_toplevel_window(engine, win, &app_win)) {
|
|
Packit Service |
93d855 |
if (state_out != NULL)
|
|
Packit Service |
93d855 |
state_out->group = -1;
|
|
Packit Service |
93d855 |
return FALSE;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
return xkl_engine_get_toplevel_window_state(engine, app_win,
|
|
Packit Service |
93d855 |
state_out);
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
void
|
|
Packit Service |
93d855 |
xkl_engine_delete_state(XklEngine * engine, Window win)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
Window app_win;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (xkl_engine_find_toplevel_window(engine, win, &app_win))
|
|
Packit Service |
93d855 |
xkl_engine_remove_toplevel_window_state(engine, app_win);
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
void
|
|
Packit Service |
93d855 |
xkl_engine_save_state(XklEngine * engine, Window win, XklState * state)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
Window app_win;
|
|
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 (xkl_engine_find_toplevel_window(engine, win, &app_win))
|
|
Packit Service |
93d855 |
xkl_engine_save_toplevel_window_state(engine, app_win,
|
|
Packit Service |
93d855 |
state);
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* Prepares the name of window suitable for debugging (32characters long).
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
gchar *
|
|
Packit Service |
93d855 |
xkl_get_debug_window_title(XklEngine * engine, Window win)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
static gchar sname[33];
|
|
Packit Service |
93d855 |
gchar *name;
|
|
Packit Service |
93d855 |
strcpy(sname, "NULL");
|
|
Packit Service |
93d855 |
if (win != (Window) NULL) {
|
|
Packit Service |
93d855 |
name = xkl_engine_get_window_title(engine, win);
|
|
Packit Service |
93d855 |
if (name != NULL) {
|
|
Packit Service |
93d855 |
g_snprintf(sname, sizeof(sname), "%.32s", name);
|
|
Packit Service |
93d855 |
g_free(name);
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
return sname;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
Window
|
|
Packit Service |
93d855 |
xkl_engine_get_current_window(XklEngine * engine)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
return xkl_engine_priv(engine, curr_toplvl_win);
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* Loads subtree.
|
|
Packit Service |
93d855 |
* All the windows with WM_STATE are added.
|
|
Packit Service |
93d855 |
* All the windows within level 0 are listened for focus and property
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
gboolean
|
|
Packit Service |
93d855 |
xkl_engine_load_subtree(XklEngine * engine, Window window, gint level,
|
|
Packit Service |
93d855 |
XklState * init_state)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
Window rwin = (Window) NULL,
|
|
Packit Service |
93d855 |
parent = (Window) NULL, *children = NULL, *child;
|
|
Packit Service |
93d855 |
guint num = 0;
|
|
Packit Service |
93d855 |
gboolean retval = True;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, last_error_code) =
|
|
Packit Service |
93d855 |
xkl_engine_query_tree(engine, window, &rwin, &parent,
|
|
Packit Service |
93d855 |
&children, &num);
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (xkl_engine_priv(engine, last_error_code) != Success) {
|
|
Packit Service |
93d855 |
return FALSE;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
child = children;
|
|
Packit Service |
93d855 |
while (num) {
|
|
Packit Service |
93d855 |
if (xkl_engine_if_window_has_wm_state(engine, *child)) {
|
|
Packit Service |
93d855 |
xkl_debug(160,
|
|
Packit Service |
93d855 |
"Window " WINID_FORMAT
|
|
Packit Service |
93d855 |
" '%s' has WM_STATE so we'll add it\n",
|
|
Packit Service |
93d855 |
*child,
|
|
Packit Service |
93d855 |
xkl_get_debug_window_title(engine,
|
|
Packit Service |
93d855 |
*child));
|
|
Packit Service |
93d855 |
xkl_engine_add_toplevel_window(engine, *child,
|
|
Packit Service |
93d855 |
window, TRUE,
|
|
Packit Service |
93d855 |
init_state);
|
|
Packit Service |
93d855 |
} else {
|
|
Packit Service |
93d855 |
xkl_debug(200,
|
|
Packit Service |
93d855 |
"Window " WINID_FORMAT
|
|
Packit Service |
93d855 |
" '%s' does not have have WM_STATE so we'll not add it\n",
|
|
Packit Service |
93d855 |
*child,
|
|
Packit Service |
93d855 |
xkl_get_debug_window_title(engine,
|
|
Packit Service |
93d855 |
*child));
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (level == 0) {
|
|
Packit Service |
93d855 |
xkl_debug(200,
|
|
Packit Service |
93d855 |
"But we are at level 0 so we'll spy on it\n");
|
|
Packit Service |
93d855 |
xkl_engine_select_input_merging(engine,
|
|
Packit Service |
93d855 |
*child,
|
|
Packit Service |
93d855 |
FocusChangeMask
|
|
Packit Service |
93d855 |
|
|
|
Packit Service |
93d855 |
PropertyChangeMask);
|
|
Packit Service |
93d855 |
} else
|
|
Packit Service |
93d855 |
xkl_debug(200,
|
|
Packit Service |
93d855 |
"And we are at level %d so we'll not spy on it\n",
|
|
Packit Service |
93d855 |
level);
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
retval =
|
|
Packit Service |
93d855 |
xkl_engine_load_subtree(engine, *child,
|
|
Packit Service |
93d855 |
level + 1, init_state);
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
child++;
|
|
Packit Service |
93d855 |
num--;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (children != NULL)
|
|
Packit Service |
93d855 |
XFree(children);
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
return retval;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* Checks whether given window has WM_STATE property (i.e. "App window").
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
gboolean
|
|
Packit Service |
93d855 |
xkl_engine_if_window_has_wm_state(XklEngine * engine, Window win)
|
|
Packit Service |
93d855 |
{ /* ICCCM 4.1.3.1 */
|
|
Packit Service |
93d855 |
Atom type = None;
|
|
Packit Service |
93d855 |
int format;
|
|
Packit Service |
93d855 |
unsigned long nitems;
|
|
Packit Service |
93d855 |
unsigned long after;
|
|
Packit Service |
93d855 |
unsigned char *data = NULL; /* Helps in the case of BadWindow error */
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
XGetWindowProperty(xkl_engine_get_display(engine), win,
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, atoms)[WM_STATE], 0, 0,
|
|
Packit Service |
93d855 |
False, xkl_engine_priv(engine, atoms)[WM_STATE],
|
|
Packit Service |
93d855 |
&type, &format, &nitems, &after, &data);
|
|
Packit Service |
93d855 |
if (data != NULL)
|
|
Packit Service |
93d855 |
XFree(data); /* To avoid an one-byte memory leak because after successfull return
|
|
Packit Service |
93d855 |
* data array always contains at least one nul byte (NULL-equivalent) */
|
|
Packit Service |
93d855 |
return type != None;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* Finds out the official parent window (accortind to XQueryTree)
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
Window
|
|
Packit Service |
93d855 |
xkl_engine_get_registered_parent(XklEngine * engine, Window win)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
Window parent = (Window) NULL, rw = (Window) NULL, *children =
|
|
Packit Service |
93d855 |
NULL;
|
|
Packit Service |
93d855 |
guint nchildren = 0;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, last_error_code) =
|
|
Packit Service |
93d855 |
xkl_engine_query_tree(engine, win, &rw, &parent, &children,
|
|
Packit Service |
93d855 |
&nchildren);
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (children != NULL)
|
|
Packit Service |
93d855 |
XFree(children);
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
return xkl_engine_priv(engine, last_error_code) ==
|
|
Packit Service |
93d855 |
Success ? parent : (Window) NULL;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
/*
|
|
Packit Service |
93d855 |
* Make sure about the result. Origial XQueryTree is pretty stupid beast:)
|
|
Packit Service |
93d855 |
*/
|
|
Packit Service |
93d855 |
Status
|
|
Packit Service |
93d855 |
xkl_engine_query_tree(XklEngine * engine, Window w,
|
|
Packit Service |
93d855 |
Window * root_out,
|
|
Packit Service |
93d855 |
Window * parent_out,
|
|
Packit Service |
93d855 |
Window ** children_out, guint * nchildren_out)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
gboolean result;
|
|
Packit Service |
93d855 |
unsigned int nc;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
result = (gboolean) XQueryTree(xkl_engine_get_display(engine),
|
|
Packit Service |
93d855 |
w,
|
|
Packit Service |
93d855 |
root_out,
|
|
Packit Service |
93d855 |
parent_out, children_out, &nc);
|
|
Packit Service |
93d855 |
*nchildren_out = nc;
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
if (!result) {
|
|
Packit Service |
93d855 |
xkl_debug(160,
|
|
Packit Service |
93d855 |
"Could not get tree info for window "
|
|
Packit Service |
93d855 |
WINID_FORMAT ": %d\n", w, result);
|
|
Packit Service |
93d855 |
xkl_last_error_message = "Could not get the tree info";
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
return result ? Success : FirstExtensionError;
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
const gchar *
|
|
Packit Service |
93d855 |
xkl_event_get_name(gint type)
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
/* Not really good to use the fact of consecutivity
|
|
Packit Service |
93d855 |
but X protocol is already standartized so... */
|
|
Packit Service |
93d855 |
static const gchar *evt_names[] = {
|
|
Packit Service |
93d855 |
"KeyPress",
|
|
Packit Service |
93d855 |
"KeyRelease",
|
|
Packit Service |
93d855 |
"ButtonPress",
|
|
Packit Service |
93d855 |
"ButtonRelease",
|
|
Packit Service |
93d855 |
"MotionNotify",
|
|
Packit Service |
93d855 |
"EnterNotify",
|
|
Packit Service |
93d855 |
"LeaveNotify",
|
|
Packit Service |
93d855 |
"FocusIn",
|
|
Packit Service |
93d855 |
"FocusOut",
|
|
Packit Service |
93d855 |
"KeymapNotify",
|
|
Packit Service |
93d855 |
"Expose",
|
|
Packit Service |
93d855 |
"GraphicsExpose",
|
|
Packit Service |
93d855 |
"NoExpose",
|
|
Packit Service |
93d855 |
"VisibilityNotify",
|
|
Packit Service |
93d855 |
"CreateNotify",
|
|
Packit Service |
93d855 |
"DestroyNotify",
|
|
Packit Service |
93d855 |
"UnmapNotify",
|
|
Packit Service |
93d855 |
"MapNotify",
|
|
Packit Service |
93d855 |
"MapRequest",
|
|
Packit Service |
93d855 |
"ReparentNotify",
|
|
Packit Service |
93d855 |
"ConfigureNotify",
|
|
Packit Service |
93d855 |
"ConfigureRequest",
|
|
Packit Service |
93d855 |
"GravityNotify",
|
|
Packit Service |
93d855 |
"ResizeRequest",
|
|
Packit Service |
93d855 |
"CirculateNotify",
|
|
Packit Service |
93d855 |
"CirculateRequest",
|
|
Packit Service |
93d855 |
"PropertyNotify",
|
|
Packit Service |
93d855 |
"SelectionClear",
|
|
Packit Service |
93d855 |
"SelectionRequest",
|
|
Packit Service |
93d855 |
"SelectionNotify",
|
|
Packit Service |
93d855 |
"ColormapNotify", "ClientMessage", "MappingNotify",
|
|
Packit Service |
93d855 |
"LASTEvent"
|
|
Packit Service |
93d855 |
};
|
|
Packit Service |
93d855 |
type -= KeyPress;
|
|
Packit Service |
93d855 |
if (type < 0 || type >= (sizeof(evt_names) / sizeof(evt_names[0])))
|
|
Packit Service |
93d855 |
return "UNKNOWN";
|
|
Packit Service |
93d855 |
return evt_names[type];
|
|
Packit Service |
93d855 |
}
|
|
Packit Service |
93d855 |
|
|
Packit Service |
93d855 |
void
|
|
Packit Service |
93d855 |
xkl_engine_update_current_state(XklEngine * engine, int group,
|
|
Packit Service |
93d855 |
unsigned indicators, const char reason[])
|
|
Packit Service |
93d855 |
{
|
|
Packit Service |
93d855 |
xkl_debug(150,
|
|
Packit Service |
93d855 |
"Updating the current state with [g:%d/i:%u], reason: %s\n",
|
|
Packit Service |
93d855 |
group, indicators, reason);
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, curr_state).group = group;
|
|
Packit Service |
93d855 |
xkl_engine_priv(engine, curr_state).indicators = indicators;
|
|
Packit Service |
93d855 |
}
|