From 50c7942cb5bbd03925922e0dd41f43c6da027f43 Mon Sep 17 00:00:00 2001 From: mannol Date: Wed, 1 Oct 2014 23:28:34 +0200 Subject: [PATCH 1/4] Started working on dnd for toxic --- src/friendlist.c | 2 +- src/notify.c | 29 ++--------- src/toxic.c | 39 ++++++++------ src/xtra.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++ src/xtra.h | 12 +++++ 5 files changed, 170 insertions(+), 44 deletions(-) create mode 100644 src/xtra.c create mode 100644 src/xtra.h diff --git a/src/friendlist.c b/src/friendlist.c index 04f422a..29b4bbb 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -115,7 +115,7 @@ void kill_friendlist(void) int i; for (i = 0; i <= Friends.max_idx; ++i) { - if (Friends.list[i].group_invite.key != NULL) + if (Friends.list[i].active && Friends.list[i].group_invite.key != NULL) free(Friends.list[i].group_invite.key); } diff --git a/src/notify.c b/src/notify.c index b0f4259..25c7639 100644 --- a/src/notify.c +++ b/src/notify.c @@ -35,6 +35,7 @@ #include "settings.h" #include "line_info.h" #include "misc_tools.h" +#include "xtra.h" #if defined(AUDIO) || defined(SOUND_NOTIFY) #ifdef __APPLE__ @@ -53,10 +54,6 @@ #endif #endif /* AUDIO */ -#ifdef X11 - #include -#endif /* X11 */ - #ifdef BOX_NOTIFY #include #endif @@ -70,11 +67,7 @@ extern struct user_settings *user_settings; struct Control { time_t cooldown; time_t notif_timeout; -#ifdef X11 - Display *display; - unsigned long this_window; -#endif /* X11 */ - + #if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY) pthread_mutex_t poll_mutex[1]; bool poll_active; @@ -122,23 +115,11 @@ static void tab_notify(ToxWindow *self, uint64_t flags) self->alert = WINDOW_ALERT_2; } -#ifdef X11 -long unsigned int get_focused_window_id() -{ - if (!Control.display) return 0; - - Window focus; - int revert; - XGetInputFocus(Control.display, &focus, &revert); - return focus; -} -#endif /* X11 */ - static bool notifications_are_disabled(uint64_t flags) { bool res = flags & NT_RESTOL && Control.cooldown > get_unix_time(); #ifdef X11 - return res || (flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()); + return res || (flags & NT_NOFOCUS && xtra_is_this_focused()); #else return res; #endif @@ -383,10 +364,6 @@ int init_notify(int login_cooldown, int notification_timeout) #endif Control.cooldown = time(NULL) + login_cooldown; -#ifdef X11 - Control.display = XOpenDisplay(NULL); - Control.this_window = get_focused_window_id(); -#endif /* X11 */ #ifdef BOX_NOTIFY diff --git a/src/toxic.c b/src/toxic.c index 0bba549..be880b5 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -58,18 +58,19 @@ #include "message_queue.h" #include "execute.h" -#ifdef AUDIO -#include "audio_call.h" -#endif /* AUDIO */ - -#ifndef PACKAGE_DATADIR -#define PACKAGE_DATADIR "." +#ifdef X11 + #include "xtra.h" #endif #ifdef AUDIO +#include "audio_call.h" ToxAv *av; #endif /* AUDIO */ +#ifndef PACKAGE_DATADIR + #define PACKAGE_DATADIR "." +#endif + /* Export for use in Callbacks */ char *DATA_FILE = NULL; char *BLOCK_FILE = NULL; @@ -1002,36 +1003,40 @@ int main(int argc, char *argv[]) const char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL; int settings_err = settings_load(user_settings, p); +#ifdef X11 + xtra_init(); +#endif + Tox *m = init_tox(); - + if (m == NULL) exit_toxic_err("failed in main", FATALERR_NETWORKINIT); - + if (!arg_opts.ignore_data_file) { if (arg_opts.encrypt_data && !datafile_exists) arg_opts.encrypt_data = 0; - + load_data(m, DATA_FILE); - + } - + init_term(); prompt = init_windows(m); prompt_init_statusbar(prompt, m); - + /* thread for ncurses stuff */ if (pthread_mutex_init(&Winthread.lock, NULL) != 0) exit_toxic_err("failed in main", FATALERR_MUTEX_INIT); - + if (pthread_create(&Winthread.tid, NULL, thread_winref, (void *) m) != 0) exit_toxic_err("failed in main", FATALERR_THREAD_CREATE); - + /* thread for message queue */ if (pthread_create(&cqueue_thread.tid, NULL, thread_cqueue, (void *) m) != 0) exit_toxic_err("failed in main", FATALERR_THREAD_CREATE); - -#ifdef AUDIO - + + #ifdef AUDIO + av = init_audio(prompt, m); set_primary_device(input, user_settings->audio_in_dev); diff --git a/src/xtra.c b/src/xtra.c new file mode 100644 index 0000000..d4edceb --- /dev/null +++ b/src/xtra.c @@ -0,0 +1,132 @@ +#include "xtra.h" + +#include +#include +// #include +// #include + +#include +#include + +static Display *the_d = NULL; +static Window self_window; /* We will assume that during initialization + * we have this window focused */ + +/* For dnd protocol NOTE: copied from utox's code */ +Atom XdndAware, + XdndEnter, + XdndLeave, + XdndPosition, + XdndStatus, + XdndDrop, + XdndSelection, + XdndDATA, + XdndActionCopy; + +void *event_loop(void* p) +{ + (void) p; + + XEvent event; + while (the_d) + { + XNextEvent(the_d, &event); + + switch (event.type) + { + case ClientMessage: + { + + assert(0); + if(event.xclient.message_type == XdndEnter) { + } else if(event.xclient.message_type == XdndPosition) { + Window src = event.xclient.data.l[0]; + XEvent event = { + .xclient = { + .type = ClientMessage, + .display = the_d, + .window = src, + .message_type = XdndStatus, + .format = 32, + .data = { + .l = {self_window, 1, 0, 0, XdndActionCopy} + } + } + }; + XSendEvent(the_d, src, 0, 0, &event); + } else if(event.xclient.message_type == XdndStatus) { + } else if(event.xclient.message_type == XdndDrop) { + XConvertSelection(the_d, XdndSelection, XA_STRING, XdndDATA, self_window, CurrentTime); + } else if(event.xclient.message_type == XdndLeave) { + } else { + } + + goto exit; + } break; + + default: + break; + } + } + +exit: + /* Actual XTRA termination + * Please call xtra_terminate() at exit + * otherwise bad stuff happens + */ + if (the_d) XCloseDisplay(the_d); + return NULL; +} + +void xtra_init() +{ + the_d = XOpenDisplay(NULL); + self_window = xtra_focused_window_id(); + + XSelectInput(the_d, self_window, ExposureMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | + PointerMotionMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask | FocusChangeMask | + PropertyChangeMask); + + XdndAware = XInternAtom(the_d, "XdndAware", False); + XdndEnter = XInternAtom(the_d, "XdndEnter", False); + XdndLeave = XInternAtom(the_d, "XdndLeave", False); + XdndPosition = XInternAtom(the_d, "XdndPosition", False); + XdndStatus = XInternAtom(the_d, "XdndStatus", False); + XdndDrop = XInternAtom(the_d, "XdndDrop", False); + XdndSelection = XInternAtom(the_d, "XdndSelection", False); + XdndDATA = XInternAtom(the_d, "XdndDATA", False); + XdndActionCopy = XInternAtom(the_d, "XdndActionCopy", False); + + Atom Xdndversion = 3; + XChangeProperty(the_d, self_window, XdndAware, XA_ATOM, 32, 0, (unsigned char*)&Xdndversion, 1); + /*XSelectInput(the_d, self_window, ExposureMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask);*/ + pthread_t id; + pthread_create(&id, NULL, event_loop, NULL); + pthread_detach(id); +} + +void xtra_terminate() +{ + XEvent terminate_event; + terminate_event.xclient.display = the_d; + terminate_event.type = ClientMessage; + + + XDeleteProperty(the_d, self_window, XdndAware); + XSendEvent(the_d, self_window, 0, NoEventMask, &terminate_event); +} + +long unsigned int xtra_focused_window_id() +{ + if (!the_d) return 0; + + Window focus; + int revert; + XGetInputFocus(the_d, &focus, &revert); + return focus; +} + +int xtra_is_this_focused() +{ + return self_window == xtra_focused_window_id(); +} diff --git a/src/xtra.h b/src/xtra.h new file mode 100644 index 0000000..1159adf --- /dev/null +++ b/src/xtra.h @@ -0,0 +1,12 @@ +#ifndef XTRA_H +#define XTRA_H + +/* NOTE: If no xlib present don't compile */ + +void xtra_init(); +void xtra_terminate(); + +long unsigned int xtra_focused_window_id(); +int xtra_is_this_focused(); /* returns bool */ + +#endif /* DND_H */ \ No newline at end of file From 70add920fe7f89753019f1bf53089b76a8c07825 Mon Sep 17 00:00:00 2001 From: mannol Date: Fri, 3 Oct 2014 16:59:32 +0200 Subject: [PATCH 2/4] Making progress with dnd --- src/xtra.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/src/xtra.c b/src/xtra.c index d4edceb..f930b7b 100644 --- a/src/xtra.c +++ b/src/xtra.c @@ -12,7 +12,6 @@ static Display *the_d = NULL; static Window self_window; /* We will assume that during initialization * we have this window focused */ -/* For dnd protocol NOTE: copied from utox's code */ Atom XdndAware, XdndEnter, XdndLeave, @@ -21,7 +20,10 @@ Atom XdndAware, XdndDrop, XdndSelection, XdndDATA, - XdndActionCopy; + XdndActionCopy, + XdndActionAsk, + XdndTypeList; + void *event_loop(void* p) { @@ -36,7 +38,6 @@ void *event_loop(void* p) { case ClientMessage: { - assert(0); if(event.xclient.message_type == XdndEnter) { } else if(event.xclient.message_type == XdndPosition) { @@ -59,12 +60,13 @@ void *event_loop(void* p) XConvertSelection(the_d, XdndSelection, XA_STRING, XdndDATA, self_window, CurrentTime); } else if(event.xclient.message_type == XdndLeave) { } else { + goto exit; } - goto exit; } break; default: +// XSendEvent(the_d, self_window, 0, 0, &event); break; } } @@ -83,10 +85,53 @@ void xtra_init() the_d = XOpenDisplay(NULL); self_window = xtra_focused_window_id(); - XSelectInput(the_d, self_window, ExposureMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | - PointerMotionMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask | FocusChangeMask | - PropertyChangeMask); - + Window m_wndProxy; + + { + /* Create an invisible window which will act as proxy for the DnD + * operation. This window will be used for both the GH and HG + * direction. + */ + XSetWindowAttributes attr = {0}; + attr.event_mask = EnterWindowMask | + LeaveWindowMask | + ButtonMotionMask | + ButtonPressMask | + ButtonReleaseMask | + ResizeRedirectMask; + + attr.do_not_propagate_mask = NoEventMask; + + Window root; + int x, y; + unsigned int wht, hht, b, d; + + /* Since we cannot capture resize events for parent window we will have to create + * this window to have maximum size as defined in root window + */ + XGetGeometry(the_d, XDefaultRootWindow(the_d), &root, &x, &y, &wht, &hht, &b, &d); + + m_wndProxy = XCreateWindow(the_d, self_window /* Parent */, + 0, 0, /* Position */ + wht, hht, /* Width + height */ + 0, /* Border width */ + CopyFromParent, /* Depth */ + InputOnly, /* Class */ + CopyFromParent, /* Visual */ + CWDontPropagate | CWEventMask | CWCursor, /* Value mask */ + &attr /* Attributes for value mask */); + if (!m_wndProxy) + { + //TODO return status + assert(0); + } + } + + XMapWindow(the_d, m_wndProxy); + XLowerWindow(the_d, m_wndProxy); /* Don't interfere with parent lmao */ + + self_window = m_wndProxy; + XdndAware = XInternAtom(the_d, "XdndAware", False); XdndEnter = XInternAtom(the_d, "XdndEnter", False); XdndLeave = XInternAtom(the_d, "XdndLeave", False); @@ -96,10 +141,12 @@ void xtra_init() XdndSelection = XInternAtom(the_d, "XdndSelection", False); XdndDATA = XInternAtom(the_d, "XdndDATA", False); XdndActionCopy = XInternAtom(the_d, "XdndActionCopy", False); + XdndActionAsk = XInternAtom(the_d, "XdndActionAsk", False); + XdndTypeList = XInternAtom(the_d, "XdndTypeList", False); Atom Xdndversion = 3; - XChangeProperty(the_d, self_window, XdndAware, XA_ATOM, 32, 0, (unsigned char*)&Xdndversion, 1); - /*XSelectInput(the_d, self_window, ExposureMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask);*/ + XChangeProperty(the_d, m_wndProxy, XdndAware, XA_ATOM, 32, PropModeReplace, (unsigned char*)&Xdndversion, 1); + pthread_t id; pthread_create(&id, NULL, event_loop, NULL); pthread_detach(id); From c825adc1e355cb133c9ce8d16a2c1878285d0484 Mon Sep 17 00:00:00 2001 From: mannol Date: Sat, 11 Oct 2014 23:53:02 +0200 Subject: [PATCH 3/4] Dnd works --- src/toxic.c | 8 +- src/xtra.c | 388 ++++++++++++++++++++++++++++++++++++++-------------- src/xtra.h | 15 +- 3 files changed, 300 insertions(+), 111 deletions(-) diff --git a/src/toxic.c b/src/toxic.c index be880b5..98cb1d8 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -967,6 +967,12 @@ static useconds_t optimal_msleepval(uint64_t *looptimer, uint64_t *loopcount, ui return new_sleep; } +void cb(const char* asdv, DropType dt) +{ + if (dt != DT_plain) + line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, asdv); +} + int main(int argc, char *argv[]) { parse_args(argc, argv); @@ -1004,7 +1010,7 @@ int main(int argc, char *argv[]) int settings_err = settings_load(user_settings, p); #ifdef X11 - xtra_init(); + xtra_init(cb); #endif Tox *m = init_tox(); diff --git a/src/xtra.c b/src/xtra.c index f930b7b..1afbf14 100644 --- a/src/xtra.c +++ b/src/xtra.c @@ -2,96 +2,255 @@ #include #include -// #include -// #include #include #include +#include +#include +#include -static Display *the_d = NULL; -static Window self_window; /* We will assume that during initialization - * we have this window focused */ -Atom XdndAware, - XdndEnter, - XdndLeave, - XdndPosition, - XdndStatus, - XdndDrop, - XdndSelection, - XdndDATA, - XdndActionCopy, - XdndActionAsk, - XdndTypeList; +const Atom XtraTerminate = 1; +const Atom XtraNil = 0; +static Atom XdndAware; +static Atom XdndEnter; +static Atom XdndLeave; +static Atom XdndPosition; +static Atom XdndStatus; +static Atom XdndDrop; +static Atom XdndSelection; +static Atom XdndDATA; +static Atom XdndTypeList; +static Atom XdndActionCopy; +static Atom XdndFinished; + +struct _Xtra { + drop_callback on_drop; + Display *display; + Window terminal_window; + Window proxy_window; + Window source_window; /* When we have a drop */ + Atom handling_version; + Atom expecting_type; +} Xtra; + +typedef struct _Property +{ + unsigned char *data; + int read_format; + unsigned long read_num; + Atom read_type; +} Property; + +Property read_property(Window s, Atom p) +{ + Atom read_type; + int read_format; + unsigned long read_num; + unsigned long left_bytes; + unsigned char *data = NULL; + + int read_bytes = 1024; + + /* Keep trying to read the property until there are no bytes unread */ + do { + if (data) XFree(data); + + XGetWindowProperty(Xtra.display, s, + p, 0, + read_bytes, + False, AnyPropertyType, + &read_type, &read_format, + &read_num, &left_bytes, + &data); + + read_bytes *= 2; + } while (left_bytes != 0); + + Property property = {data, read_format, read_num, read_type}; + return property; +} + +Atom get_dnd_type(long *a, int l) +{ + int i = 0; + for (; i < l; i ++) { + if (a[i] != XtraNil) return a[i]; /* Get first valid */ + } + return XtraNil; +} + +/* TODO maybe support only certain types in the future */ +static void handle_xdnd_enter(XClientMessageEvent* e) +{ + Xtra.handling_version = (e->data.l[1] >> 24); + + if ((e->data.l[1] & 1)) { + // Fetch the list of possible conversions + Property p = read_property(e->data.l[0], XdndTypeList); + Xtra.expecting_type = get_dnd_type((long*)p.data, p.read_num); + XFree(p.data); + } else { + // Use the available list + Xtra.expecting_type = get_dnd_type(e->data.l + 2, 3); + } +} + +static void handle_xdnd_position(XClientMessageEvent* e) +{ + XEvent ev = { + .xclient = { + .type = ClientMessage, + .display = e->display, + .window = e->data.l[0], + .message_type = XdndStatus, + .format = 32, + .data = { + .l = { + Xtra.proxy_window, + (Xtra.expecting_type != XtraNil), + 0, 0, + XdndActionCopy + } + } + } + }; + + XSendEvent(Xtra.display, e->data.l[0], False, NoEventMask, &ev); + XFlush(Xtra.display); +} + +static void handle_xdnd_drop(XClientMessageEvent* e) +{ + /* Not expecting any type */ + if (Xtra.expecting_type == XtraNil) { + XEvent ev = { + .xclient = { + .type = ClientMessage, + .display = e->display, + .window = e->data.l[0], + .message_type = XdndFinished, + .format = 32, + .data = { + .l = {Xtra.proxy_window, 0, 0} + } + } + }; + + XSendEvent(Xtra.display, e->data.l[0], False, NoEventMask, &ev); + } else { + Xtra.source_window = e->data.l[0]; + XConvertSelection(Xtra.display, + XdndSelection, + Xtra.expecting_type, + XdndSelection, + Xtra.proxy_window, + Xtra.handling_version >= 1 ? e->data.l[2] : CurrentTime); + } +} + +static void handle_xdnd_selection(XSelectionEvent* e) +{ + /* DnD succesfully finished, send finished and call callback */ + XEvent ev = { + .xclient = { + .type = ClientMessage, + .display = Xtra.display, + .window = Xtra.source_window, + .message_type = XdndFinished, + .format = 32, + .data = { + .l = {Xtra.proxy_window, 1, XdndActionCopy} + } + } + }; + XSendEvent(Xtra.display, Xtra.source_window, False, NoEventMask, &ev); + + Property p = read_property(Xtra.proxy_window, XdndSelection); + DropType dt; + + if (strcmp(XGetAtomName(Xtra.display, p.read_type), "text/uri-list") == 0) + dt = DT_file_list; + else /* text/uri-list */ + dt = DT_plain; + + + /* Call callback for every entry */ + if (Xtra.on_drop && p.read_num) + { + char *sptr; + char *str = strtok_r((char*)p.data, "\n\r", &sptr); + + if (str) Xtra.on_drop(str, dt); + while ((str = strtok_r(NULL, "\n\r", &sptr))) + Xtra.on_drop(str, dt); + } + + if (p.data) XFree(p.data); +} void *event_loop(void* p) { - (void) p; + /* Handle events like a real nigga */ + + (void) p; /* DINDUNOTHIN */ XEvent event; - while (the_d) + int pending; + + while (Xtra.display) { - XNextEvent(the_d, &event); + /* NEEDMOEVENTSFODEMPROGRAMS */ - switch (event.type) + XLockDisplay(Xtra.display); + if((pending = XPending(Xtra.display))) XNextEvent(Xtra.display, &event); + + if (!pending) { - case ClientMessage: - { - assert(0); - if(event.xclient.message_type == XdndEnter) { - } else if(event.xclient.message_type == XdndPosition) { - Window src = event.xclient.data.l[0]; - XEvent event = { - .xclient = { - .type = ClientMessage, - .display = the_d, - .window = src, - .message_type = XdndStatus, - .format = 32, - .data = { - .l = {self_window, 1, 0, 0, XdndActionCopy} - } - } - }; - XSendEvent(the_d, src, 0, 0, &event); - } else if(event.xclient.message_type == XdndStatus) { - } else if(event.xclient.message_type == XdndDrop) { - XConvertSelection(the_d, XdndSelection, XA_STRING, XdndDATA, self_window, CurrentTime); - } else if(event.xclient.message_type == XdndLeave) { - } else { - goto exit; - } - - } break; - - default: -// XSendEvent(the_d, self_window, 0, 0, &event); - break; + XUnlockDisplay(Xtra.display); + usleep(10000); + continue; } + + if (event.type == ClientMessage) + { + Atom type = event.xclient.message_type; + + if (type == XdndEnter) handle_xdnd_enter(&event.xclient); + else if (type == XdndPosition) handle_xdnd_position(&event.xclient); + else if (type == XdndDrop) handle_xdnd_drop(&event.xclient); + else if (type == XtraTerminate) break; + } + else if (event.type == SelectionNotify) handle_xdnd_selection(&event.xselection); + /* AINNOBODYCANHANDLEDEMEVENTS*/ + else XSendEvent(Xtra.display, Xtra.terminal_window, 0, 0, &event); + + XUnlockDisplay(Xtra.display); } -exit: /* Actual XTRA termination * Please call xtra_terminate() at exit * otherwise bad stuff happens */ - if (the_d) XCloseDisplay(the_d); - return NULL; + if (Xtra.display) XCloseDisplay(Xtra.display); + return (Xtra.display = NULL); } -void xtra_init() +int xtra_init(drop_callback d) { - the_d = XOpenDisplay(NULL); - self_window = xtra_focused_window_id(); + memset(&Xtra, 0, sizeof(Xtra)); - Window m_wndProxy; + if (!d) return -1; + else Xtra.on_drop = d; + + XInitThreads(); + if ( !(Xtra.display = XOpenDisplay(NULL))) return -1; + + Xtra.terminal_window = xtra_focused_window_id(); { - /* Create an invisible window which will act as proxy for the DnD - * operation. This window will be used for both the GH and HG - * direction. - */ + /* Create an invisible window which will act as proxy for the DnD operation. */ XSetWindowAttributes attr = {0}; attr.event_mask = EnterWindowMask | LeaveWindowMask | @@ -99,9 +258,9 @@ void xtra_init() ButtonPressMask | ButtonReleaseMask | ResizeRedirectMask; - + attr.do_not_propagate_mask = NoEventMask; - + Window root; int x, y; unsigned int wht, hht, b, d; @@ -109,71 +268,88 @@ void xtra_init() /* Since we cannot capture resize events for parent window we will have to create * this window to have maximum size as defined in root window */ - XGetGeometry(the_d, XDefaultRootWindow(the_d), &root, &x, &y, &wht, &hht, &b, &d); + XGetGeometry(Xtra.display, + XDefaultRootWindow(Xtra.display), + &root, &x, &y, &wht, &hht, &b, &d); - m_wndProxy = XCreateWindow(the_d, self_window /* Parent */, - 0, 0, /* Position */ - wht, hht, /* Width + height */ - 0, /* Border width */ - CopyFromParent, /* Depth */ - InputOnly, /* Class */ - CopyFromParent, /* Visual */ - CWDontPropagate | CWEventMask | CWCursor, /* Value mask */ - &attr /* Attributes for value mask */); - if (!m_wndProxy) - { - //TODO return status - assert(0); - } + if (! (Xtra.proxy_window = XCreateWindow + (Xtra.display, Xtra.terminal_window, /* Parent */ + 0, 0, /* Position */ + wht, hht, /* Width + height */ + 0, /* Border width */ + CopyFromParent, /* Depth */ + InputOnly, /* Class */ + CopyFromParent, /* Visual */ + CWEventMask | CWCursor, /* Value mask */ + &attr)) ) /* Attributes for value mask */ + return -1; } - XMapWindow(the_d, m_wndProxy); - XLowerWindow(the_d, m_wndProxy); /* Don't interfere with parent lmao */ + XMapWindow(Xtra.display, Xtra.proxy_window); /* Show window (sandwich) */ + XLowerWindow(Xtra.display, Xtra.proxy_window); /* Don't interfere with parent lmao */ + + XdndAware = XInternAtom(Xtra.display, "XdndAware", False); + XdndEnter = XInternAtom(Xtra.display, "XdndEnter", False); + XdndLeave = XInternAtom(Xtra.display, "XdndLeave", False); + XdndPosition = XInternAtom(Xtra.display, "XdndPosition", False); + XdndStatus = XInternAtom(Xtra.display, "XdndStatus", False); + XdndDrop = XInternAtom(Xtra.display, "XdndDrop", False); + XdndSelection = XInternAtom(Xtra.display, "XdndSelection", False); + XdndDATA = XInternAtom(Xtra.display, "XdndDATA", False); + XdndTypeList = XInternAtom(Xtra.display, "XdndTypeList", False); + XdndActionCopy = XInternAtom(Xtra.display, "XdndActionCopy", False); + XdndFinished = XInternAtom(Xtra.display, "XdndFinished", False); - self_window = m_wndProxy; - - XdndAware = XInternAtom(the_d, "XdndAware", False); - XdndEnter = XInternAtom(the_d, "XdndEnter", False); - XdndLeave = XInternAtom(the_d, "XdndLeave", False); - XdndPosition = XInternAtom(the_d, "XdndPosition", False); - XdndStatus = XInternAtom(the_d, "XdndStatus", False); - XdndDrop = XInternAtom(the_d, "XdndDrop", False); - XdndSelection = XInternAtom(the_d, "XdndSelection", False); - XdndDATA = XInternAtom(the_d, "XdndDATA", False); - XdndActionCopy = XInternAtom(the_d, "XdndActionCopy", False); - XdndActionAsk = XInternAtom(the_d, "XdndActionAsk", False); - XdndTypeList = XInternAtom(the_d, "XdndTypeList", False); - - Atom Xdndversion = 3; - XChangeProperty(the_d, m_wndProxy, XdndAware, XA_ATOM, 32, PropModeReplace, (unsigned char*)&Xdndversion, 1); + /* Inform my nigga windows that we are aware of dnd */ + Atom XdndVersion = 3; + XChangeProperty(Xtra.display, + Xtra.proxy_window, + XdndAware, + XA_ATOM, + 32, + PropModeReplace, + (unsigned char*)&XdndVersion, 1); pthread_t id; pthread_create(&id, NULL, event_loop, NULL); pthread_detach(id); + + return 0; } void xtra_terminate() { - XEvent terminate_event; - terminate_event.xclient.display = the_d; - terminate_event.type = ClientMessage; + if (!Xtra.display) return; + XEvent terminate = { + .xclient = { + .type = ClientMessage, + .display = Xtra.display, + .message_type = XtraTerminate, + } + }; - XDeleteProperty(the_d, self_window, XdndAware); - XSendEvent(the_d, self_window, 0, NoEventMask, &terminate_event); + XLockDisplay(Xtra.display); + XDeleteProperty(Xtra.display, Xtra.proxy_window, XdndAware); + XSendEvent(Xtra.display, Xtra.proxy_window, 0, NoEventMask, &terminate); + XUnlockDisplay(Xtra.display); + + while (Xtra.display); /* Wait for termination */ } long unsigned int xtra_focused_window_id() { - if (!the_d) return 0; + if (!Xtra.display) return 0; Window focus; int revert; - XGetInputFocus(the_d, &focus, &revert); + XLockDisplay(Xtra.display); + XGetInputFocus(Xtra.display, &focus, &revert); + XUnlockDisplay(Xtra.display); return focus; } int xtra_is_this_focused() { - return self_window == xtra_focused_window_id(); + return Xtra.proxy_window == xtra_focused_window_id(); } diff --git a/src/xtra.h b/src/xtra.h index 1159adf..89a096d 100644 --- a/src/xtra.h +++ b/src/xtra.h @@ -3,10 +3,17 @@ /* NOTE: If no xlib present don't compile */ -void xtra_init(); -void xtra_terminate(); +typedef enum { + DT_plain, + DT_file_list +} +DropType; +typedef void (*drop_callback) (const char*, DropType); + +int xtra_init(drop_callback d); +void xtra_terminate(); long unsigned int xtra_focused_window_id(); -int xtra_is_this_focused(); /* returns bool */ +int xtra_is_this_focused(); /* returns bool */ -#endif /* DND_H */ \ No newline at end of file +#endif /* XTRA_H */ \ No newline at end of file From 2cc261c619976c73dbd5f2b8ae6eb9f6d457e201 Mon Sep 17 00:00:00 2001 From: mannol Date: Sun, 12 Oct 2014 22:54:18 +0200 Subject: [PATCH 4/4] Some random fixups --- src/notify.c | 2 +- src/toxic.c | 19 ++++++++++--------- src/xtra.c | 14 +++++++------- src/xtra.h | 8 ++++---- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/notify.c b/src/notify.c index 25c7639..74d0130 100644 --- a/src/notify.c +++ b/src/notify.c @@ -119,7 +119,7 @@ static bool notifications_are_disabled(uint64_t flags) { bool res = flags & NT_RESTOL && Control.cooldown > get_unix_time(); #ifdef X11 - return res || (flags & NT_NOFOCUS && xtra_is_this_focused()); + return res || (flags & NT_NOFOCUS && is_focused()); #else return res; #endif diff --git a/src/toxic.c b/src/toxic.c index 98cb1d8..4f101aa 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -128,15 +128,20 @@ void exit_toxic_success(Tox *m) free(BLOCK_FILE); free(user_settings); -#ifdef SOUND_NOTIFY -// sound_notify(NULL, self_log_out, NT_ALWAYS, NULL); -#endif /* SOUND_NOTIFY */ terminate_notify(); #ifdef AUDIO terminate_audio(); #endif /* AUDIO */ + tox_kill(m); endwin(); + +#ifdef X11 + /* We have to terminate xtra last coz reasons + * Please don't call this anywhere else coz trust me + */ + terminate_xtra(); +#endif /* X11 */ exit(EXIT_SUCCESS); } @@ -1010,7 +1015,7 @@ int main(int argc, char *argv[]) int settings_err = settings_load(user_settings, p); #ifdef X11 - xtra_init(cb); + init_xtra(cb); #endif Tox *m = init_tox(); @@ -1041,7 +1046,7 @@ int main(int argc, char *argv[]) if (pthread_create(&cqueue_thread.tid, NULL, thread_cqueue, (void *) m) != 0) exit_toxic_err("failed in main", FATALERR_THREAD_CREATE); - #ifdef AUDIO +#ifdef AUDIO av = init_audio(prompt, m); @@ -1055,10 +1060,6 @@ int main(int argc, char *argv[]) #endif /* AUDIO */ init_notify(60, 3000); - -#ifdef SOUND_NOTIFY -// sound_notify(prompt, self_log_in, 0, NULL); -#endif /* SOUND_NOTIFY */ const char *msg; diff --git a/src/xtra.c b/src/xtra.c index 1afbf14..adaec88 100644 --- a/src/xtra.c +++ b/src/xtra.c @@ -231,13 +231,13 @@ void *event_loop(void* p) /* Actual XTRA termination * Please call xtra_terminate() at exit - * otherwise bad stuff happens + * otherwise HEWUSAGUDBOI happens */ if (Xtra.display) XCloseDisplay(Xtra.display); return (Xtra.display = NULL); } -int xtra_init(drop_callback d) +int init_xtra(drop_callback d) { memset(&Xtra, 0, sizeof(Xtra)); @@ -247,7 +247,7 @@ int xtra_init(drop_callback d) XInitThreads(); if ( !(Xtra.display = XOpenDisplay(NULL))) return -1; - Xtra.terminal_window = xtra_focused_window_id(); + Xtra.terminal_window = focused_window_id(); { /* Create an invisible window which will act as proxy for the DnD operation. */ @@ -317,7 +317,7 @@ int xtra_init(drop_callback d) return 0; } -void xtra_terminate() +void terminate_xtra() { if (!Xtra.display) return; @@ -337,7 +337,7 @@ void xtra_terminate() while (Xtra.display); /* Wait for termination */ } -long unsigned int xtra_focused_window_id() +long unsigned int focused_window_id() { if (!Xtra.display) return 0; @@ -349,7 +349,7 @@ long unsigned int xtra_focused_window_id() return focus; } -int xtra_is_this_focused() +int is_focused() { - return Xtra.proxy_window == xtra_focused_window_id(); + return Xtra.proxy_window == focused_window_id(); } diff --git a/src/xtra.h b/src/xtra.h index 89a096d..a2acee6 100644 --- a/src/xtra.h +++ b/src/xtra.h @@ -11,9 +11,9 @@ DropType; typedef void (*drop_callback) (const char*, DropType); -int xtra_init(drop_callback d); -void xtra_terminate(); -long unsigned int xtra_focused_window_id(); -int xtra_is_this_focused(); /* returns bool */ +int init_xtra(drop_callback d); +void terminate_xtra(); +long unsigned int focused_window_id(); +int is_focused(); /* returns bool */ #endif /* XTRA_H */ \ No newline at end of file