static gboolean utf8_string_from_results (GetPropertyResults *results, char **str_p) { *str_p = NULL; if (!validate_or_free_results (results, 8, results->display->atom_UTF8_STRING, FALSE)) return FALSE; if (results->n_items > 0 && !g_utf8_validate ((gchar *)results->prop, results->n_items, NULL)) { char *name; name = XGetAtomName (results->display->xdisplay, results->xatom); meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8\n"), name, results->xwindow); meta_XFree (name); XFree (results->prop); results->prop = NULL; return FALSE; } *str_p = (char*) results->prop; results->prop = NULL; return TRUE; }
static void change_property (ClutterInputDevice *device, const gchar *property, Atom type, int format, void *data, gulong nitems) { MetaBackend *backend = meta_get_backend (); Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); int device_id; Atom property_atom; guchar *data_ret; property_atom = XInternAtom (xdisplay, property, False); device_id = clutter_input_device_get_device_id (device); data_ret = get_property (device, property, type, format, nitems); if (!data_ret) return; XIChangeProperty (xdisplay, device_id, property_atom, type, format, XIPropModeReplace, data, nitems); meta_XFree (data_ret); }
static void * get_property (ClutterInputDevice *device, const gchar *property, Atom type, int format, gulong nitems) { MetaBackend *backend = meta_get_backend (); Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); gulong nitems_ret, bytes_after_ret; int rc, device_id, format_ret; Atom property_atom, type_ret; guchar *data_ret = NULL; property_atom = XInternAtom (xdisplay, property, False); device_id = clutter_input_device_get_device_id (device); rc = XIGetProperty (xdisplay, device_id, property_atom, 0, 10, False, type, &type_ret, &format_ret, &nitems_ret, &bytes_after_ret, &data_ret); if (rc == Success && type_ret == type && format_ret == format && nitems_ret >= nitems) { if (nitems_ret > nitems) g_warning ("Property '%s' for device '%s' returned %lu items, expected %lu", property, clutter_input_device_get_device_name (device), nitems_ret, nitems); return data_ret; } meta_XFree (data_ret); return NULL; }
static void meta_input_settings_x11_set_click_method (MetaInputSettings *settings, ClutterInputDevice *device, GDesktopTouchpadClickMethod mode) { guchar values[2] = { 0 }; /* buttonareas, clickfinger */ guchar *defaults; switch (mode) { case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT: defaults = get_property (device, "libinput Click Method Enabled Default", XA_INTEGER, 8, 2); if (!defaults) break; memcpy (values, defaults, 2); meta_XFree (defaults); break; case G_DESKTOP_TOUCHPAD_CLICK_METHOD_NONE: break; case G_DESKTOP_TOUCHPAD_CLICK_METHOD_AREAS: values[0] = 1; break; case G_DESKTOP_TOUCHPAD_CLICK_METHOD_FINGERS: values[1] = 1; break; default: g_assert_not_reached (); return; } change_property (device, "libinput Click Method Enabled", XA_INTEGER, 8, &values, 2); }
static void free_value (MetaPropValue *value) { switch (value->type) { case META_PROP_VALUE_INVALID: break; case META_PROP_VALUE_UTF8: case META_PROP_VALUE_STRING: case META_PROP_VALUE_STRING_AS_UTF8: meta_XFree (value->v.str); break; case META_PROP_VALUE_MOTIF_HINTS: meta_XFree (value->v.motif_hints); break; case META_PROP_VALUE_CARDINAL: break; case META_PROP_VALUE_WINDOW: break; case META_PROP_VALUE_ATOM_LIST: meta_XFree (value->v.atom_list.atoms); break; case META_PROP_VALUE_TEXT_PROPERTY: meta_XFree (value->v.str); break; case META_PROP_VALUE_WM_HINTS: meta_XFree (value->v.wm_hints); break; case META_PROP_VALUE_CLASS_HINT: meta_XFree (value->v.class_hint.res_class); meta_XFree (value->v.class_hint.res_name); break; case META_PROP_VALUE_SIZE_HINTS: meta_XFree (value->v.size_hints.hints); break; case META_PROP_VALUE_UTF8_LIST: g_strfreev (value->v.string_list.strings); break; case META_PROP_VALUE_CARDINAL_LIST: meta_XFree (value->v.cardinal_list.cardinals); break; case META_PROP_VALUE_SYNC_COUNTER: break; } }
static char * text_property_to_utf8 (Display *xdisplay, const XTextProperty *prop) { char *ret = NULL; char **local_list = NULL; int count = 0; int res; res = XmbTextPropertyToTextList (xdisplay, prop, &local_list, &count); if (res == XNoMemory || res == XLocaleNotSupported || res == XConverterNotFound) goto out; if (count == 0) goto out; ret = g_strdup (local_list[0]); out: meta_XFree (local_list); return ret; }
void meta_prop_get_values (MetaDisplay *display, Window xwindow, MetaPropValue *values, int n_values) { int i; AgGetPropertyTask **tasks; meta_verbose ("Requesting %d properties of 0x%lx at once\n", n_values, xwindow); if (n_values == 0) return; tasks = g_new0 (AgGetPropertyTask*, n_values); /* Start up tasks. The "values" array can have values * with atom == None, which means to ignore that element. */ i = 0; while (i < n_values) { if (values[i].required_type == None) { switch (values[i].type) { case META_PROP_VALUE_INVALID: /* This means we don't really want a value, e.g. got * property notify on an atom we don't care about. */ if (values[i].atom != None) meta_bug ("META_PROP_VALUE_INVALID requested in %s\n", G_STRFUNC); break; case META_PROP_VALUE_UTF8_LIST: case META_PROP_VALUE_UTF8: values[i].required_type = display->atom_UTF8_STRING; break; case META_PROP_VALUE_STRING: case META_PROP_VALUE_STRING_AS_UTF8: values[i].required_type = XA_STRING; break; case META_PROP_VALUE_MOTIF_HINTS: values[i].required_type = AnyPropertyType; break; case META_PROP_VALUE_CARDINAL_LIST: case META_PROP_VALUE_CARDINAL: values[i].required_type = XA_CARDINAL; break; case META_PROP_VALUE_WINDOW: values[i].required_type = XA_WINDOW; break; case META_PROP_VALUE_ATOM_LIST: values[i].required_type = XA_ATOM; break; case META_PROP_VALUE_TEXT_PROPERTY: values[i].required_type = AnyPropertyType; break; case META_PROP_VALUE_WM_HINTS: values[i].required_type = XA_WM_HINTS; break; case META_PROP_VALUE_CLASS_HINT: values[i].required_type = XA_STRING; break; case META_PROP_VALUE_SIZE_HINTS: values[i].required_type = XA_WM_SIZE_HINTS; break; case META_PROP_VALUE_SYNC_COUNTER: values[i].required_type = XA_CARDINAL; break; } } if (values[i].atom != None) tasks[i] = get_task (display, xwindow, values[i].atom, values[i].required_type); ++i; } /* Get replies for all our tasks */ meta_topic (META_DEBUG_SYNC, "Syncing to get %d GetProperty replies in %s\n", n_values, G_STRFUNC); XSync (display->xdisplay, False); /* Collect results, should arrive in order requested */ i = 0; while (i < n_values) { AgGetPropertyTask *task; GetPropertyResults results; if (tasks[i] == NULL) { /* Probably values[i].type was None, or ag_task_create() * returned NULL. */ values[i].type = META_PROP_VALUE_INVALID; goto next; } task = ag_get_next_completed_task (display->xdisplay); g_assert (task != NULL); g_assert (ag_task_have_reply (task)); results.display = display; results.xwindow = xwindow; results.xatom = values[i].atom; results.prop = NULL; results.n_items = 0; results.type = None; results.bytes_after = 0; results.format = 0; if (ag_task_get_reply_and_free (task, &results.type, &results.format, &results.n_items, &results.bytes_after, &results.prop) != Success || results.type == None) { values[i].type = META_PROP_VALUE_INVALID; if (results.prop) { XFree (results.prop); results.prop = NULL; } goto next; } switch (values[i].type) { case META_PROP_VALUE_INVALID: g_assert_not_reached (); break; case META_PROP_VALUE_UTF8_LIST: if (!utf8_list_from_results (&results, &values[i].v.string_list.strings, &values[i].v.string_list.n_strings)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_UTF8: if (!utf8_string_from_results (&results, &values[i].v.str)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_STRING: if (!latin1_string_from_results (&results, &values[i].v.str)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_STRING_AS_UTF8: if (!latin1_string_from_results (&results, &values[i].v.str)) values[i].type = META_PROP_VALUE_INVALID; else { char *new_str; char *xmalloc_new_str; new_str = latin1_to_utf8 (values[i].v.str); xmalloc_new_str = ag_Xmalloc (strlen (new_str) + 1); if (xmalloc_new_str != NULL) { strcpy (xmalloc_new_str, new_str); meta_XFree (values[i].v.str); values[i].v.str = xmalloc_new_str; } g_free (new_str); } break; case META_PROP_VALUE_MOTIF_HINTS: if (!motif_hints_from_results (&results, &values[i].v.motif_hints)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_CARDINAL_LIST: if (!cardinal_list_from_results (&results, &values[i].v.cardinal_list.cardinals, &values[i].v.cardinal_list.n_cardinals)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_CARDINAL: if (!cardinal_with_atom_type_from_results (&results, values[i].required_type, &values[i].v.cardinal)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_WINDOW: if (!window_from_results (&results, &values[i].v.xwindow)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_ATOM_LIST: if (!atom_list_from_results (&results, &values[i].v.atom_list.atoms, &values[i].v.atom_list.n_atoms)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_TEXT_PROPERTY: if (!text_property_from_results (&results, &values[i].v.str)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_WM_HINTS: if (!wm_hints_from_results (&results, &values[i].v.wm_hints)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_CLASS_HINT: if (!class_hint_from_results (&results, &values[i].v.class_hint)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_SIZE_HINTS: if (!size_hints_from_results (&results, &values[i].v.size_hints.hints, &values[i].v.size_hints.flags)) values[i].type = META_PROP_VALUE_INVALID; break; case META_PROP_VALUE_SYNC_COUNTER: #ifdef HAVE_XSYNC if (!counter_from_results (&results, &values[i].v.xcounter)) values[i].type = META_PROP_VALUE_INVALID; #else values[i].type = META_PROP_VALUE_INVALID; if (results.prop) { XFree (results.prop); results.prop = NULL; } #endif break; } next: ++i; } g_free (tasks); }
/* this one freakishly returns g_malloc memory */ static gboolean utf8_list_from_results (GetPropertyResults *results, char ***str_p, int *n_str_p) { int i; int n_strings; char **retval; const char *p; *str_p = NULL; *n_str_p = 0; if (!validate_or_free_results (results, 8, results->display->atom_UTF8_STRING, FALSE)) return FALSE; /* I'm not sure this is right, but I'm guessing the * property is nul-separated */ i = 0; n_strings = 0; while (i < (int) results->n_items) { if (results->prop[i] == '\0') ++n_strings; ++i; } if (results->prop[results->n_items - 1] != '\0') ++n_strings; /* we're guaranteed that results->prop has a nul on the end * by XGetWindowProperty */ retval = g_new0 (char*, n_strings + 1); p = (char *)results->prop; i = 0; while (i < n_strings) { if (!g_utf8_validate (p, -1, NULL)) { char *name; meta_error_trap_push (results->display); name = XGetAtomName (results->display->xdisplay, results->xatom); meta_error_trap_pop (results->display, TRUE); meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n"), name, results->xwindow, i); meta_XFree (name); meta_XFree (results->prop); results->prop = NULL; g_strfreev (retval); return FALSE; } retval[i] = g_strdup (p); p = p + strlen (p) + 1; ++i; } *str_p = retval; *n_str_p = i; meta_XFree (results->prop); results->prop = NULL; return TRUE; }