summaryrefslogtreecommitdiff
path: root/src/lib/efl_canvas_wl/copiedfromweston.x
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/efl_canvas_wl/copiedfromweston.x')
-rw-r--r--src/lib/efl_canvas_wl/copiedfromweston.x413
1 files changed, 413 insertions, 0 deletions
diff --git a/src/lib/efl_canvas_wl/copiedfromweston.x b/src/lib/efl_canvas_wl/copiedfromweston.x
new file mode 100644
index 0000000000..d5c35eee75
--- /dev/null
+++ b/src/lib/efl_canvas_wl/copiedfromweston.x
@@ -0,0 +1,413 @@
+/*
+ * Copyright © 2011 Kristian Høgsberg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \
+ WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \
+ WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
+
+static uint32_t
+data_offer_choose_action(Comp_Data_Device_Offer *offer)
+{
+ uint32_t available_actions, preferred_action = 0;
+ uint32_t source_actions, offer_actions;
+
+ if (wl_resource_get_version(offer->res) >=
+ WL_DATA_OFFER_ACTION_SINCE_VERSION)
+ {
+ offer_actions = offer->dnd_actions;
+ preferred_action = offer->preferred_dnd_action;
+ }
+ else
+ {
+ offer_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
+ }
+
+ if (wl_resource_get_version(offer->source->res) >=
+ WL_DATA_SOURCE_ACTION_SINCE_VERSION)
+ source_actions = offer->source->dnd_actions;
+ else
+ source_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
+
+ available_actions = offer_actions & source_actions;
+
+ if (!available_actions)
+ return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
+
+ if (offer->source->seat &&
+ offer->source->compositor_action & available_actions)
+ return offer->source->compositor_action;
+
+ /* If the dest side has a preferred DnD action, use it */
+ if ((preferred_action & available_actions) != 0)
+ return preferred_action;
+
+ /* Use the first found action, in bit order */
+ return 1 << (ffs(available_actions) - 1);
+}
+
+static void
+data_offer_update_action(Comp_Data_Device_Offer *offer)
+{
+ uint32_t action;
+
+ if (!offer->source)
+ return;
+
+ action = data_offer_choose_action(offer);
+
+ if (offer->source->current_dnd_action == action)
+ return;
+
+ offer->source->current_dnd_action = action;
+
+ if (offer->in_ask)
+ return;
+
+ if (wl_resource_get_version(offer->source->res) >=
+ WL_DATA_SOURCE_ACTION_SINCE_VERSION)
+ wl_data_source_send_action(offer->source->res, action);
+
+ if (wl_resource_get_version(offer->res) >=
+ WL_DATA_OFFER_ACTION_SINCE_VERSION)
+ wl_data_offer_send_action(offer->res, action);
+}
+
+static void
+data_device_offer_set_actions(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t dnd_actions, uint32_t preferred_action)
+{
+ Comp_Data_Device_Offer *offer = wl_resource_get_user_data(resource);
+
+ if (dnd_actions & ~ALL_ACTIONS)
+ {
+ wl_resource_post_error(offer->res,
+ WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK,
+ "invalid action mask %x", dnd_actions);
+ return;
+ }
+
+ if (preferred_action &&
+ (!(preferred_action & dnd_actions) ||
+ __builtin_popcount(preferred_action) > 1))
+ {
+ wl_resource_post_error(offer->res,
+ WL_DATA_OFFER_ERROR_INVALID_ACTION,
+ "invalid action %x", preferred_action);
+ return;
+ }
+
+ offer->dnd_actions = dnd_actions;
+ offer->preferred_dnd_action = preferred_action;
+ data_offer_update_action(offer);
+}
+
+#ifdef HAVE_ECORE_X
+static Ecore_X_Atom
+action_convert(uint32_t action)
+{
+ if (action == WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
+ return ECORE_X_ATOM_XDND_ACTION_MOVE;
+ if (action == WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
+ return ECORE_X_ATOM_XDND_ACTION_ASK;
+ return ECORE_X_ATOM_XDND_ACTION_COPY;
+}
+#endif
+static void
+data_device_offer_accept(struct wl_client *client, struct wl_resource *resource,
+ uint32_t serial, const char *mime_type)
+{
+ Comp_Data_Device_Offer *offer = wl_resource_get_user_data(resource);
+ Comp_Surface *cs;
+
+ /* Protect against untimely calls from older data offers */
+ if (!offer->source || offer != offer->source->offer)
+ return;
+
+ switch (offer->type)
+ {
+ case COMP_DATA_DEVICE_OFFER_TYPE_DND:
+ cs = offer->source->seat->drag.enter;
+ if (!offer->source->seat->drag.res) return;
+ if ((!offer->source->seat->drag.source) &&
+ (wl_resource_get_client(cs->res) != wl_resource_get_client(offer->source->seat->drag.res)))
+ return;
+#ifdef HAVE_ECORE_X
+ if (offer->source->x11_owner)
+ {
+ Ecore_Window win = ecore_evas_window_get(ecore_evas_ecore_evas_get(offer->source->seat->c->evas));
+ offer->source->accepted = mime_type != NULL;
+ ecore_x_client_message32_send(offer->source->x11_owner,
+ ECORE_X_ATOM_XDND_STATUS, ECORE_X_EVENT_MASK_NONE,
+ win, 2 | !!mime_type, 0, 0,
+ (!!mime_type) * action_convert(offer->source->current_dnd_action));
+ return;
+ }
+#endif
+ break;
+
+ case COMP_DATA_DEVICE_OFFER_TYPE_CLIPBOARD:
+ break;
+ default: return;
+ }
+ if (offer->source->seat->client_offer)
+ ecore_wl2_offer_accept(offer->source->seat->client_offer, mime_type);
+ else
+ wl_data_source_send_target(offer->source->res, mime_type);
+ offer->source->accepted = mime_type != NULL;
+}
+
+static void
+data_device_offer_receive(struct wl_client *client, struct wl_resource *resource,
+ const char *mime_type, int32_t fd)
+{
+ Comp_Data_Device_Offer *offer = wl_resource_get_user_data(resource);
+
+ if (offer->source && offer == offer->source->offer)
+ {
+ if (offer->proxy)
+ {
+ Ecore_Wl2_Offer *off;
+#ifdef HAVE_ECORE_X
+ if (offer->source->x11_owner)
+ {
+ x11_send_send(offer->source, mime_type, fd, offer->type);
+ return;
+ }
+#endif
+ if (offer->type == COMP_DATA_DEVICE_OFFER_TYPE_CLIPBOARD)
+ off = ecore_wl2_dnd_selection_get(offer->source->seat->seat);
+ else
+ {
+ off = offer->source->seat->client_offer;
+ offer->source->seat->client_offer = NULL;
+ }
+ ecore_wl2_offer_proxy_receive(off, mime_type, fd);
+ offer->proxy_offer = off;
+ }
+ else
+ wl_data_source_send_send(offer->source->res, mime_type, fd);
+ }
+ close(fd);
+}
+
+static void
+data_source_notify_finish(Comp_Data_Device_Source *source)
+{
+ if (!source->actions_set)
+ return;
+
+ if (source->proxy && (!source->x11_owner))
+ ecore_wl2_offer_finish(source->offer->proxy_offer);
+
+ if (source->offer && source->offer->in_ask &&
+ wl_resource_get_version(source->res) >=
+ WL_DATA_SOURCE_ACTION_SINCE_VERSION)
+ {
+ wl_data_source_send_action(source->res,
+ source->current_dnd_action);
+ }
+
+ if (wl_resource_get_version(source->res) >=
+ WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION)
+ {
+ wl_data_source_send_dnd_finished(source->res);
+ }
+
+ source->offer = NULL;
+}
+
+static void
+data_device_offer_finish(struct wl_client *client, struct wl_resource *resource)
+{
+ Comp_Data_Device_Offer *offer = wl_resource_get_user_data(resource);
+
+ if (!offer->source || offer->source->offer != offer)
+ return;
+
+ /* Disallow finish while we have a grab driving drag-and-drop, or
+ * if the negotiation is not at the right stage
+ */
+ if (((!offer->proxy) && offer->source->seat) ||
+ !offer->source->accepted)
+ {
+ wl_resource_post_error(offer->res,
+ WL_DATA_OFFER_ERROR_INVALID_FINISH,
+ "premature finish request");
+ return;
+ }
+
+ switch (offer->source->current_dnd_action)
+ {
+ case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE:
+ case WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK:
+ wl_resource_post_error(offer->res,
+ WL_DATA_OFFER_ERROR_INVALID_OFFER,
+ "offer finished with an invalid action");
+ return;
+
+ default:
+ break;
+ }
+
+ data_source_notify_finish(offer->source);
+}
+
+static void
+data_device_offer_impl_destroy(struct wl_resource *resource)
+{
+ Comp_Data_Device_Offer *offer = wl_resource_get_user_data(resource);
+
+ if (!offer->source)
+ goto out;
+
+ if (offer->source->offer != offer)
+ goto out;
+
+ if (offer->type == COMP_DATA_DEVICE_OFFER_TYPE_DND)
+ {
+ /* If the drag destination has version < 3, wl_data_offer.finish
+ * won't be called, so do this here as a safety net, because
+ * we still want the version >=3 drag source to be happy.
+ */
+ if (wl_resource_get_version(offer->res) <
+ WL_DATA_OFFER_ACTION_SINCE_VERSION)
+ {
+ data_source_notify_finish(offer->source);
+ }
+ else if (offer->source->res &&
+ wl_resource_get_version(offer->source->res) >=
+ WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION)
+ {
+ wl_data_source_send_cancelled(offer->source->res);
+ }
+ }
+
+ offer->source->offer = NULL;
+ if (offer->proxy_offer && offer->proxy)
+ ecore_wl2_offer_proxy_receive_end(offer->proxy_offer);
+out:
+ free(offer);
+}
+
+static void
+drag_grab_button(Comp_Seat *s,
+ uint32_t time, uint32_t button, uint32_t state_w)
+{
+ Comp_Data_Device_Source *data_source = s->drag.source;
+ enum wl_pointer_button_state state = state_w;
+ struct wl_resource *res;
+
+ if (data_source &&
+ s->drag.id == button &&
+ state == WL_POINTER_BUTTON_STATE_RELEASED)
+ {
+ if ((s->drag.enter || (s->drag.x11_owner == ecore_evas_window_get(ecore_evas_ecore_evas_get(s->c->evas)))) &&
+ data_source->accepted &&
+ data_source->current_dnd_action)
+ {
+ if (s->drag.enter)
+ {
+ res = data_device_find(s, s->drag.enter->res);
+ if (!res) return;
+
+ wl_data_device_send_drop(res);
+ }
+ if (wl_resource_get_version(data_source->res) >=
+ WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION)
+ wl_data_source_send_dnd_drop_performed(data_source->res);
+
+ if (data_source->offer)
+ data_source->offer->in_ask =
+ data_source->current_dnd_action ==
+ WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
+
+ if (!data_source->proxy)
+ data_source->seat = NULL;
+ }
+ else if (wl_resource_get_version(data_source->res) >=
+ WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION)
+ {
+ wl_data_source_send_cancelled(data_source->res);
+ }
+ seat_drag_end(s);
+ if (!data_source->x11_owner)
+ s->drag.source = NULL;
+#ifdef HAVE_ECORE_X
+ if (ecore_x_display_get())
+ ecore_x_pointer_ungrab();
+#endif
+ }
+}
+
+#ifdef HAVE_ECORE_X
+static xkb_mod_index_t x11_kbd_shift_mod;
+static xkb_mod_index_t x11_kbd_caps_mod;
+static xkb_mod_index_t x11_kbd_ctrl_mod;
+static xkb_mod_index_t x11_kbd_alt_mod;
+static xkb_mod_index_t x11_kbd_mod2_mod;
+static xkb_mod_index_t x11_kbd_mod3_mod;
+static xkb_mod_index_t x11_kbd_super_mod;
+static xkb_mod_index_t x11_kbd_mod5_mod;
+
+static void
+keymap_mods_init(struct xkb_keymap *keymap)
+{
+ x11_kbd_shift_mod = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT);
+ x11_kbd_caps_mod = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS);
+ x11_kbd_ctrl_mod = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL);
+ x11_kbd_alt_mod = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_ALT);
+ x11_kbd_mod2_mod = xkb_keymap_mod_get_index(keymap, "Mod2");
+ x11_kbd_mod3_mod = xkb_keymap_mod_get_index(keymap, "Mod3");
+ x11_kbd_super_mod = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_LOGO);
+ x11_kbd_mod5_mod = xkb_keymap_mod_get_index(keymap, "Mod5");
+}
+
+static uint32_t
+get_xkb_mod_mask(uint32_t in)
+{
+ uint32_t ret = 0;
+
+ if ((in & ECORE_X_MODIFIER_SHIFT) && x11_kbd_shift_mod != XKB_MOD_INVALID)
+ ret |= (1 << x11_kbd_shift_mod);
+ if ((in & ECORE_X_LOCK_CAPS) && x11_kbd_caps_mod != XKB_MOD_INVALID)
+ ret |= (1 << x11_kbd_caps_mod);
+ if ((in & ECORE_X_MODIFIER_CTRL) && x11_kbd_ctrl_mod != XKB_MOD_INVALID)
+ ret |= (1 << x11_kbd_ctrl_mod);
+ if ((in & ECORE_X_MODIFIER_ALT) && x11_kbd_alt_mod != XKB_MOD_INVALID)
+ ret |= (1 << x11_kbd_alt_mod);
+ if ((in & ECORE_X_LOCK_NUM) && x11_kbd_mod2_mod != XKB_MOD_INVALID)
+ ret |= (1 << x11_kbd_mod2_mod);
+ if ((in & ECORE_X_LOCK_SCROLL) && x11_kbd_mod3_mod != XKB_MOD_INVALID)
+ ret |= (1 << x11_kbd_mod3_mod);
+ if ((in & ECORE_X_MODIFIER_WIN) && x11_kbd_super_mod != XKB_MOD_INVALID)
+ ret |= (1 << x11_kbd_super_mod);
+ if ((in & ECORE_X_MODIFIER_ALTGR) && x11_kbd_mod5_mod != XKB_MOD_INVALID)
+ ret |= (1 << x11_kbd_mod5_mod);
+
+ return ret;
+}
+
+#endif