EAPI void ecore_x_dnd_type_set(Ecore_X_Window win, const char *type, int on);
EAPI void ecore_x_dnd_types_set(Ecore_X_Window win, char **types, unsigned int num_types);
EAPI int ecore_x_dnd_begin(Ecore_X_Window source, unsigned char *data, int size);
-EAPI void ecore_x_dnd_drop(void);
+EAPI int ecore_x_dnd_drop(void);
EAPI void ecore_x_dnd_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectangle, Ecore_X_Atom action);
EAPI void ecore_x_dnd_send_finished(void);
EAPI void ecore_x_window_cursor_set(Ecore_X_Window win,
Ecore_X_Cursor c);
EAPI void ecore_x_window_del(Ecore_X_Window win);
+EAPI void ecore_x_window_ignore_set(Ecore_X_Window win, int ignore);
+EAPI Ecore_X_Window *ecore_x_window_ignore_list(int *num);
+
EAPI void ecore_x_window_delete_request_send(Ecore_X_Window win);
EAPI void ecore_x_window_show(Ecore_X_Window win);
EAPI void ecore_x_window_hide(Ecore_X_Window win);
EAPI void ecore_x_window_defaults_set(Ecore_X_Window win);
EAPI int ecore_x_window_visible_get(Ecore_X_Window win);
EAPI Ecore_X_Window ecore_x_window_at_xy_get(int x, int y);
+EAPI Ecore_X_Window ecore_x_window_at_xy_with_skip_get(int x, int y, Ecore_X_Window *skip, int skip_num);
EAPI Ecore_X_Window ecore_x_window_parent_get(Ecore_X_Window win);
EAPI void ecore_x_window_background_color_set(Ecore_X_Window win,
return 0;
_source->win = source;
+ ecore_x_window_ignore_set(_source->win, 1);
printf("source: 0x%x\n", source);
_source->state = ECORE_X_DND_SOURCE_DRAGGING;
_source->time = _ecore_x_event_last_time;
return 1;
}
-void
+int
ecore_x_dnd_drop(void)
{
XEvent xev;
+ int status = 0;
if (_source->dest)
{
xev.xclient.data.l[2] = _source->time;
XSendEvent(_ecore_x_disp, _source->dest, False, 0, &xev);
_source->state = ECORE_X_DND_SOURCE_DROPPED;
+ status = 1;
}
else
{
ecore_x_selection_xdnd_clear();
_source->state = ECORE_X_DND_SOURCE_IDLE;
}
+ ecore_x_window_ignore_set(_source->win, 0);
+ return status;
}
void
void
_ecore_x_dnd_drag(int x, int y)
{
- XEvent xev;
- Ecore_X_Window win;
+ XEvent xev;
+ Ecore_X_Window win;
+ Ecore_X_Window *skip;
+ int num;
if (_source->state != ECORE_X_DND_SOURCE_DRAGGING)
return;
xev.xclient.format = 32;
/* Attempt to find a DND-capable window under the cursor */
- win = ecore_x_window_at_xy_get(x, y);
+ skip = ecore_x_window_ignore_list(&num);
+ win = ecore_x_window_at_xy_with_skip_get(x, y, skip, num);
while ((win) && !(ecore_x_dnd_version_get(win)))
win = ecore_x_window_parent_get(win);
#include "Ecore_X.h"
#include "Ecore_X_Atoms.h"
+static int ignore_num = 0;
+static Ecore_X_Window *ignore_list = NULL;
+
/**
* @defgroup Ecore_X_Window_Create_Group X Window Creation Functions
*
}
/**
+ * Set if a window should be ignored.
+ * @param win The given window.
+ * @param ignore if to ignore
+ */
+void
+ecore_x_window_ignore_set(Ecore_X_Window win, int ignore)
+{
+ int i, j;
+
+ if (ignore)
+ {
+ if (ignore_list)
+ {
+ for (i = 0; i < ignore_num; i++)
+ {
+ if (win == ignore_list[i])
+ return;
+ }
+ ignore_list = realloc(ignore_list, (ignore_num + 1) * sizeof(Ecore_X_Window));
+ if (!ignore_list) return;
+ ignore_list[ignore_num++] = win;
+ }
+ else
+ {
+ ignore_num = 0;
+ ignore_list = malloc(sizeof(Ecore_X_Window));
+ ignore_list[ignore_num++] = win;
+ }
+ }
+ else
+ {
+ if (!ignore_list) return;
+ for (i = 0, j = 0; i < ignore_num; i++)
+ {
+ if (win != ignore_list[i])
+ ignore_list[i] = ignore_list[j++];
+ else
+ ignore_num--;
+ }
+ ignore_list = realloc(ignore_list, ignore_num * sizeof(Ecore_X_Window));
+ }
+}
+
+/**
+ * Get the ignore list
+ * @param num number of windows in the list
+ * @return list of windows to ignore
+ */
+Ecore_X_Window *
+ecore_x_window_ignore_list(int *num)
+{
+ if (num) *num = ignore_num;
+ return ignore_list;
+}
+
+/**
* Sends a delete request to the given window.
* @param win The given window.
* @ingroup Evas_X_Window_Destroy_Group
}
static Window
-_ecore_x_window_at_xy_get(Window base, int bx, int by, int x, int y)
+_ecore_x_window_at_xy_get(Window base, int bx, int by, int x, int y,
+ Ecore_X_Window *skip, int skip_num)
{
Window *list = NULL;
Window parent_win = 0, child = 0, root_win = 0;
- int i, wx, wy, ww, wh;
+ int i, j, wx, wy, ww, wh;
unsigned int num;
if (!ecore_x_window_visible_get(base))
- return 0;
+ return 0;
ecore_x_window_geometry_get(base, &wx, &wy, &ww, &wh);
wx += bx;
wy += by;
if (!((x >= wx) && (y >= wy) && (x < (wx + ww)) && (y < (wy + wh))))
- return 0;
-
+ return 0;
+
if (!XQueryTree(_ecore_x_disp, base, &root_win, &parent_win, &list, &num))
- return base;
+ {
+ if (skip)
+ {
+ for (i = 0; i < skip_num; i++)
+ if (base == skip[i])
+ return 0;
+ }
+ return base;
+ }
if (list)
- {
- for (i = num - 1;; --i)
- {
- if ((child = _ecore_x_window_at_xy_get(list[i], wx, wy, x, y)))
- {
- XFree(list);
- return child;
- }
- if (!i)
- break;
- }
- XFree(list);
- }
+ {
+ for (i = num - 1; i >= 0; --i)
+ {
+ if (skip)
+ {
+ for (j = 0; j < skip_num; j++)
+ if (list[i] == skip[j])
+ continue;
+ }
+ if ((child = _ecore_x_window_at_xy_get(list[i], wx, wy, x, y, skip, skip_num)))
+ {
+ XFree(list);
+ return child;
+ }
+ }
+ XFree(list);
+ }
+
+ if (skip)
+ {
+ for (i = 0; i < skip_num; i++)
+ if (base == skip[i])
+ return 0;
+ }
return base;
}
root = DefaultRootWindow(_ecore_x_disp);
ecore_x_grab();
- win = _ecore_x_window_at_xy_get(root, 0, 0, x, y);
+ win = _ecore_x_window_at_xy_get(root, 0, 0, x, y, NULL, 0);
+ ecore_x_ungrab();
+
+ return win ? win : root;
+}
+
+/**
+ * Retrieves the top, visible window at the given location,
+ * but skips the windows in the list.
+ * @param x The given X position.
+ * @param y The given Y position.
+ * @return The window at that position.
+ * @ingroup Ecore_X_Window_Geometry_Group
+ */
+Ecore_X_Window
+ecore_x_window_at_xy_with_skip_get(int x, int y, Ecore_X_Window *skip, int skip_num)
+{
+ Ecore_X_Window win, root;
+
+ /* FIXME: Proper function to determine current root/virtual root
+ * window missing here */
+ root = DefaultRootWindow(_ecore_x_disp);
+
+ ecore_x_grab();
+ win = _ecore_x_window_at_xy_get(root, 0, 0, x, y, skip, skip_num);
ecore_x_ungrab();
return win ? win : root;