The uploaded text is syntax highlighted. Share places a link to the site that holds your content in your clipboard in return. SVN revision: 83496master
commit
ff8fbe6e4a
22 changed files with 885 additions and 0 deletions
@ -0,0 +1,32 @@ |
||||
|
||||
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 shall be included in |
||||
all copies of the Software and its Copyright notices. In addition publicly |
||||
documented acknowledgment must be given that this software has been used if no |
||||
source code of this software is made available publicly. Making the source |
||||
available publicly means including the source for this software with the |
||||
distribution, or a method to get this software via some reasonable mechanism |
||||
(electronic transfer via a network or media) as well as making an offer to |
||||
supply the source on request. This Copyright notice serves as an offer to |
||||
supply the source on on request as well. Instead of this, supplying |
||||
acknowledgments of use of this software in either Copyright notices, Manuals, |
||||
Publicity and Marketing documents or any documentation provided with any |
||||
product containing this software. This License does not apply to any software |
||||
that links to the libraries provided by this software (statically or |
||||
dynamically), but only to the software provided. |
||||
|
||||
Please see the COPYING-PLAIN for a plain-english explanation of this notice |
||||
and its intent. |
||||
|
||||
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 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. |
@ -0,0 +1,33 @@ |
||||
Plain English Copyright Notice |
||||
|
||||
This file is not intended to be the actual License. The reason this file |
||||
exists is that we here are programmers and engineers. We aren't lawyers. We |
||||
provide licenses that we THINK say the right things, but we have our own |
||||
intentions at heart. This is a plain-english explanation of what those |
||||
intentions are, and if you follow them you will be within the "spirit" of |
||||
the license. |
||||
|
||||
The intent is for us to enjoy writing software that is useful to us (the |
||||
AUTHORS) and allow others to use it freely and also benefit from the work we |
||||
put into making it. We don't want to restrict others using it. They should |
||||
not *HAVE* to make the source code of the applications they write that |
||||
simply link to these libraries (be that statically or dynamically), or for |
||||
them to be limited as to what license they choose to use (be it open, closed |
||||
or anything else). But we would like to know you are using these libraries. |
||||
We simply would like to know that it has been useful to someone. This is why |
||||
we ask for acknowledgement of some sort. |
||||
|
||||
You can do what you want with the source of this software - it doesn't |
||||
matter. We still have it here for ourselves and it is open and free to use |
||||
and download and play with. It can't be taken away. We don't really mind what |
||||
you do with the source to your software. We would simply like to know that |
||||
you are using it - especially if it makes it to a commerical product. If you |
||||
simply e-mail all the AUTHORS (see COPYING and AUTHORS files) telling us, and |
||||
then make sure you include a paragraph or page in the manual for the product |
||||
with the copyright notice and state that you used this software, we will be |
||||
very happy. If you want to contribute back modifications and fixes you may have |
||||
made we will welcome those too with open arms (generally). If you want help |
||||
with changes needed, ports needed or features to be added, arrangements can |
||||
be easily made with some dialogue. |
||||
|
||||
Leif Middelschulte <leif.middelschulte@gmail.com> |
@ -0,0 +1,11 @@ |
||||
COMPILING and INSTALLING: |
||||
|
||||
If you got a official release tar archive do: |
||||
./autogen.sh |
||||
|
||||
Then to compile: |
||||
make |
||||
|
||||
To install: |
||||
make install |
||||
|
@ -0,0 +1,25 @@ |
||||
MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.h.in \
|
||||
config.sub configure depcomp install-sh ltmain.sh \
|
||||
missing module.desktop config.rpath mkinstalldirs
|
||||
|
||||
SUBDIRS = src
|
||||
|
||||
EDJE_FLAGS = -v \
|
||||
-id $(top_srcdir)/images
|
||||
|
||||
filesdir = $(datadir)
|
||||
files_DATA = module.desktop e-module-share.edj
|
||||
|
||||
EXTRA_DIST = module.desktop.in \
|
||||
e_modules-share.spec.in \
|
||||
e-module-share.edc \
|
||||
images/module_icon.png
|
||||
|
||||
%.edj: %.edc |
||||
$(EDJE_CC) $(EDJE_FLAGS) $< $@
|
||||
|
||||
clean-local: |
||||
rm -rf e-module-share.edj module.desktop e_modules-share.spec *~
|
||||
|
||||
uninstall: |
||||
rm -rf $(DESTDIR)$(datadir)
|
@ -0,0 +1,2 @@ |
||||
This module shall share data from the clipboard online. |
||||
The user shall be given a link to the share. |
@ -0,0 +1,6 @@ |
||||
- Store and restore old links for every instance |
||||
- Enable HTTPS |
||||
|
||||
Future: |
||||
- Share files |
||||
- Extend to more services (1Click hosters and local p2p) |
@ -0,0 +1,16 @@ |
||||
#!/bin/sh |
||||
|
||||
rm -rf autom4te.cache |
||||
rm -f aclocal.m4 ltmain.sh |
||||
|
||||
touch README |
||||
|
||||
echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS || exit 1 |
||||
echo "Running autoheader..." ; autoheader || exit 1 |
||||
echo "Running autoconf..." ; autoconf || exit 1 |
||||
echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1 |
||||
echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1 |
||||
|
||||
if [ -z "$NOCONFIGURE" ]; then |
||||
./configure "$@" |
||||
fi |
@ -0,0 +1,59 @@ |
||||
dnl Process this file with autoconf to produce a configure script. |
||||
|
||||
# get rid of that stupid cache mechanism |
||||
rm -f config.cache |
||||
|
||||
AC_INIT(share, 0.0.1, enlightenment-devel@lists.sourceforge.net) |
||||
AC_PREREQ(2.52) |
||||
AC_CONFIG_SRCDIR(configure.ac) |
||||
AC_CANONICAL_BUILD |
||||
AC_CANONICAL_HOST |
||||
AC_ISC_POSIX |
||||
|
||||
AM_INIT_AUTOMAKE(1.6) |
||||
AC_CONFIG_HEADERS(config.h) |
||||
|
||||
AC_PROG_CC |
||||
AC_HEADER_STDC |
||||
AC_C_CONST |
||||
|
||||
define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl |
||||
define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl |
||||
AC_PROG_LIBTOOL |
||||
|
||||
PKG_CHECK_MODULES(E, [enlightenment]) |
||||
release=$(pkg-config --variable=release enlightenment) |
||||
MODULE_ARCH="$host_os-$host_cpu-$release" |
||||
AC_SUBST(MODULE_ARCH) |
||||
AC_DEFINE_UNQUOTED(MODULE_ARCH, "$MODULE_ARCH", "Module architecture") |
||||
|
||||
PKG_CHECK_MODULES(JSON, [json]) |
||||
|
||||
# Find edje_cc |
||||
PKG_CHECK_MODULES(EDJE, [edje >= 0.5.0]) |
||||
AC_ARG_WITH(edje-cc, |
||||
AC_HELP_STRING([--with-edje-cc=PATH], [specify a specific path to edje_cc]), |
||||
[ |
||||
v=$withval; |
||||
EDJE_CC=$v |
||||
],[ |
||||
EDJE_CC=$(pkg-config --variable=prefix edje)/bin/edje_cc |
||||
] |
||||
) |
||||
AC_SUBST(EDJE_CC) |
||||
AC_MSG_CHECKING([Which edje_cc to use]) |
||||
AC_MSG_RESULT(${EDJE_CC}) |
||||
|
||||
datadir=$(pkg-config --variable=modules enlightenment)/${PACKAGE} |
||||
AC_ARG_ENABLE(homedir-install, |
||||
AS_HELP_STRING([--enable-homedir-install], [Install module in homedir]), |
||||
[ datadir="${HOME}/.e/e/modules/${PACKAGE}" ] |
||||
) |
||||
|
||||
AC_OUTPUT([ |
||||
Makefile |
||||
src/Makefile |
||||
e_modules-share.spec |
||||
module.desktop |
||||
], [ |
||||
]) |
@ -0,0 +1,74 @@ |
||||
collections { |
||||
|
||||
images.image: "module_icon.png" COMP; |
||||
|
||||
group { |
||||
name: "icon"; |
||||
max: 48 48; |
||||
parts { |
||||
part { |
||||
name: "image"; |
||||
type: IMAGE; |
||||
mouse_events: 0; |
||||
description { |
||||
state: "default" 0.00; |
||||
visible: 1; |
||||
aspect: 1.00 1.00; |
||||
aspect_preference: BOTH; |
||||
rel1 { |
||||
relative: 0.00 0.00; |
||||
offset: 0 0; |
||||
} |
||||
rel2 { |
||||
relative: 1.00 1.00; |
||||
offset: -1 -1; |
||||
} |
||||
image.normal: "module_icon.png"; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
group { |
||||
name: "modules/share/main"; |
||||
max: 128 128; |
||||
parts { |
||||
part { name: "logo"; |
||||
type: IMAGE; |
||||
description { state: "default" 0.0; |
||||
aspect: 1.0 1.0; |
||||
aspect_preference: BOTH; |
||||
rel1.offset: 0 0; |
||||
rel2.offset: -1 -1; |
||||
image.normal: "module_icon.png"; |
||||
} |
||||
description { state: "active" 0.0; |
||||
inherit: "default" 0.0; |
||||
color: 255 255 255 128; |
||||
} |
||||
} |
||||
part { name: "inout"; |
||||
type: RECT; |
||||
mouse_events: 1; |
||||
description { state: "default" 0.0; |
||||
color: 255 255 255 0; |
||||
} |
||||
} |
||||
} |
||||
programs { |
||||
program { name: "go_active"; |
||||
signal: "active"; |
||||
source: ""; |
||||
action: STATE_SET "active" 0.0; |
||||
target: "logo"; |
||||
transition: LINEAR 0.5; |
||||
} |
||||
program { name: "go_passive"; |
||||
signal: "passive"; |
||||
source: ""; |
||||
action: STATE_SET "default" 0.0; |
||||
target: "logo"; |
||||
transition: LINEAR 0.5; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,48 @@ |
||||
%define module_name share |
||||
%{!?_rel:%{expand:%%global _rel 0.enl%{?dist}}} |
||||
|
||||
Summary: %{module_name} module for the Enlightenment window manager |
||||
Name: e_modules-%{module_name} |
||||
Version: @VERSION@ |
||||
Release: %{_rel} |
||||
License: BSD |
||||
Group: User Interface/Desktops |
||||
URL: http://www.enlightenment.org/ |
||||
Source: ftp://ftp.enlightenment.org/pub/enlightenment/%{module_name}-%{version}.tar.gz |
||||
Packager: %{?_packager:%{_packager}}%{!?_packager:Michael Jennings <mej@eterm.org>} |
||||
Vendor: %{?_vendorinfo:%{_vendorinfo}}%{!?_vendorinfo:The Enlightenment Project (http://www.enlightenment.org/)} |
||||
Distribution: %{?_distribution:%{_distribution}}%{!?_distribution:%{_vendor}} |
||||
BuildRequires: ecore-devel, evas-devel, edje-bin |
||||
BuildRequires: edje-devel, eet-devel, enlightenment-devel >= 0.16.999 |
||||
Requires: enlightenment >= 0.16.999 |
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-root |
||||
|
||||
%description |
||||
%{module_name} module for the Enlightenment window manager. |
||||
|
||||
%prep |
||||
%setup -q -n %{module_name}-%{version} |
||||
|
||||
%build |
||||
%{configure} |
||||
%{__make} %{?_smp_mflags} %{?mflags} |
||||
|
||||
%install |
||||
%{__make} %{?mflags_install} DESTDIR=$RPM_BUILD_ROOT install |
||||
%{find_lang} %{module_name} || true > %{module_name}.lang |
||||
|
||||
%clean |
||||
test "x$RPM_BUILD_ROOT" != "x/" && rm -rf $RPM_BUILD_ROOT |
||||
|
||||
%post |
||||
/sbin/ldconfig |
||||
|
||||
%postun |
||||
/sbin/ldconfig |
||||
|
||||
%files -f %{module_name}.lang |
||||
%defattr(-, root, root) |
||||
%doc AUTHORS ChangeLog COPYING* INSTALL NEWS README |
||||
%{_libdir}/enlightenment/modules/%{module_name}* |
||||
|
||||
%changelog |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
@ -0,0 +1,6 @@ |
||||
[Desktop Entry] |
||||
Type=Link |
||||
Name=Share |
||||
Icon=e-module-share |
||||
X-Enlightenment-ModuleType=utils |
||||
Comment=Gadget that shares your clipboard content online and puts a link to it into your clipboard |
@ -0,0 +1,21 @@ |
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = -I. \
|
||||
-I$(top_srcdir) \
|
||||
-I$(includedir) \
|
||||
@E_CFLAGS@ \
|
||||
@JSON_CFLAGS@
|
||||
|
||||
pkgdir = $(datadir)/$(MODULE_ARCH)
|
||||
pkg_LTLIBRARIES = module.la
|
||||
module_la_SOURCES = e_mod_main.c \
|
||||
e_mod_main.h \
|
||||
e_share.h \
|
||||
sourcedrop.c
|
||||
|
||||
module_la_LIBADD = @E_LIBS@ @JSON_LIBS@ -lm -lbsd
|
||||
module_la_LDFLAGS = -module -avoid-version
|
||||
module_la_DEPENDENCIES = $(top_builddir)/config.h
|
||||
|
||||
clean-local: |
||||
rm -rf *~
|
@ -0,0 +1,387 @@ |
||||
#include "e_mod_main.h" |
||||
#include "e_share.h" |
||||
#include <string.h> |
||||
|
||||
#define __UNUSED__ |
||||
#define _(S) S |
||||
|
||||
/* actual module specifics */ |
||||
typedef struct _Instance Instance; |
||||
struct _Instance |
||||
{ |
||||
E_Gadcon_Client *gcc; |
||||
E_Menu *menu; |
||||
Ecore_X_Window win; |
||||
Evas_Object *o_button; |
||||
Eina_List *handlers; |
||||
Eina_List *shares; |
||||
}; |
||||
|
||||
/* gadcon requirements */ |
||||
static E_Gadcon_Client *_gc_init(E_Gadcon * gc, const char *name, const char *id, const char *style); |
||||
static void _gc_shutdown(E_Gadcon_Client * gcc); |
||||
static void _gc_orient(E_Gadcon_Client * gcc, E_Gadcon_Orient orient); |
||||
static const char *_gc_label(const E_Gadcon_Client_Class *client_class); |
||||
static Evas_Object *_gc_icon(const E_Gadcon_Client_Class *client_class, Evas * evas); |
||||
static const char *_gc_id_new(const E_Gadcon_Client_Class *client_class); |
||||
|
||||
static void _share_button_cb_mouse_down(void *data, Evas *evas, Evas_Object *obj, Evas_Event_Mouse_Down *ev); |
||||
static Eina_Bool _share_x_selection_notify_handler(Instance *instance, int type, void *event); |
||||
static void _share_menu_post_cb(void *data, E_Menu *menu __UNUSED__); |
||||
static void _share_menu_share_request_click_cb(Instance *inst, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__); |
||||
static void _share_menu_share_item_click_cb(Share_Data *selected_share, E_Menu *m, E_Menu_Item *mi); |
||||
static void _share_open_link_in_browser(const Share_Data *sd); |
||||
static void _share_notify(const Share_Data *sd); |
||||
static void _share_notification_clicked_cb(void *data, unsigned int id); |
||||
static void _free_share_data(Share_Data *sd); |
||||
|
||||
static E_Module *share_module = NULL; |
||||
|
||||
/* and actually define the gadcon class that this module provides (just 1) */ |
||||
static const E_Gadcon_Client_Class _gadcon_class = { |
||||
GADCON_CLIENT_CLASS_VERSION, |
||||
"share", |
||||
{ |
||||
_gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL, |
||||
e_gadcon_site_is_not_toolbar |
||||
}, |
||||
E_GADCON_CLIENT_STYLE_PLAIN |
||||
}; |
||||
|
||||
static E_Gadcon_Client * |
||||
_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style) |
||||
{ |
||||
Evas_Object *o; |
||||
E_Gadcon_Client *gcc; |
||||
Instance *inst; |
||||
|
||||
inst = E_NEW(Instance, 1); |
||||
|
||||
/*
|
||||
char buf[PATH_MAX]; |
||||
snprintf(buf, sizeof(buf), "%s/e-module-share.edj", e_module_dir_get(share_module)); |
||||
|
||||
o = edje_object_add(gc->evas); |
||||
if (!e_theme_edje_object_set(o, "base/theme/modules/share", "modules/share/main")) |
||||
edje_object_file_set(o, buf, "modules/share/main"); |
||||
edje_object_signal_emit(o, "passive", ""); |
||||
*/ |
||||
|
||||
o = e_icon_add(gc->evas); |
||||
e_icon_fdo_icon_set(o, "emblem-shared"); |
||||
evas_object_show(o); |
||||
|
||||
gcc = e_gadcon_client_new(gc, name, id, style, o); |
||||
gcc->data = inst; |
||||
|
||||
inst->gcc = gcc; |
||||
inst->win = ecore_evas_window_get(gc->ecore_evas); |
||||
inst->o_button = o; |
||||
|
||||
e_gadcon_client_util_menu_attach(gcc); |
||||
|
||||
evas_object_event_callback_add(inst->o_button, EVAS_CALLBACK_MOUSE_DOWN, (Evas_Object_Event_Cb)_share_button_cb_mouse_down, inst); |
||||
E_LIST_HANDLER_APPEND(inst->handlers, ECORE_X_EVENT_SELECTION_NOTIFY, _share_x_selection_notify_handler, inst); |
||||
|
||||
return gcc; |
||||
} |
||||
|
||||
static void |
||||
_gc_shutdown(E_Gadcon_Client *gcc) |
||||
{ |
||||
Instance *inst; |
||||
|
||||
inst = gcc->data; |
||||
E_FREE_LIST(inst->handlers, ecore_event_handler_del); |
||||
inst->handlers = NULL; |
||||
|
||||
if (inst->menu) |
||||
{ |
||||
e_menu_post_deactivate_callback_set(inst->menu, NULL, NULL); |
||||
e_object_del(E_OBJECT(inst->menu)); |
||||
inst->menu = NULL; |
||||
} |
||||
|
||||
E_FREE_LIST(inst->shares, _free_share_data); |
||||
inst->shares = NULL; |
||||
|
||||
evas_object_del(inst->o_button); |
||||
E_FREE(inst); |
||||
} |
||||
|
||||
static void |
||||
_gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient) |
||||
{ |
||||
e_gadcon_client_aspect_set (gcc, 16, 16); |
||||
e_gadcon_client_min_size_set (gcc, 16, 16); |
||||
} |
||||
|
||||
static const char * |
||||
_gc_label (const E_Gadcon_Client_Class *client_class) |
||||
{ |
||||
return "Share"; |
||||
} |
||||
|
||||
static Evas_Object * |
||||
_gc_icon(const E_Gadcon_Client_Class *client_class, Evas * evas) |
||||
{ |
||||
Evas_Object *o; |
||||
/*
|
||||
char buf[PATH_MAX]; |
||||
|
||||
o = edje_object_add(evas); |
||||
snprintf (buf, sizeof(buf), "%s/e-module-share.edj", e_module_dir_get(share_module)); |
||||
edje_object_file_set(o, buf, "icon"); |
||||
*/ |
||||
|
||||
o = e_icon_add(evas); |
||||
e_icon_fdo_icon_set(o, "emblem-shared"); |
||||
|
||||
return o; |
||||
} |
||||
|
||||
static const char * |
||||
_gc_id_new (const E_Gadcon_Client_Class *client_class) |
||||
{ |
||||
return _gadcon_class.name; |
||||
} |
||||
|
||||
static void |
||||
_share_button_cb_mouse_down(void *data, Evas *evas, Evas_Object *obj, Evas_Event_Mouse_Down *ev) |
||||
{ |
||||
Instance *inst = (Instance*)data; |
||||
Evas_Coord x, y, w, h; |
||||
int cx, cy; |
||||
int dir; |
||||
E_Menu_Item *mi; |
||||
Eina_List *it; |
||||
Share_Data *share; |
||||
|
||||
if (!inst) return; |
||||
|
||||
if ((ev->button == 1) && (!inst->menu)) |
||||
{ |
||||
/* Coordinates and sizing */ |
||||
evas_object_geometry_get(inst->o_button, &x, &y, &w, &h); |
||||
e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &cx, &cy, |
||||
NULL, NULL); |
||||
x += cx; |
||||
y += cy; |
||||
|
||||
inst->menu = e_menu_new(); |
||||
|
||||
mi = e_menu_item_new(inst->menu); |
||||
e_menu_item_label_set(mi, _("Share Clipboard Content")); |
||||
e_menu_item_callback_set(mi, (E_Menu_Cb)_share_menu_share_request_click_cb, inst); |
||||
|
||||
mi = e_menu_item_new(inst->menu); |
||||
e_menu_item_separator_set(mi, EINA_TRUE); |
||||
|
||||
EINA_LIST_FOREACH(inst->shares, it, share) |
||||
{ |
||||
mi = e_menu_item_new(inst->menu); |
||||
e_menu_item_label_set(mi, share->name); |
||||
e_menu_item_callback_set(mi, (E_Menu_Cb)_share_menu_share_item_click_cb, share); |
||||
} |
||||
|
||||
e_menu_post_deactivate_callback_set(inst->menu, |
||||
_share_menu_post_cb, inst); |
||||
|
||||
/* Proper menu orientation */ |
||||
switch (inst->gcc->gadcon->orient) |
||||
{ |
||||
case E_GADCON_ORIENT_TOP: |
||||
case E_GADCON_ORIENT_CORNER_TL: |
||||
case E_GADCON_ORIENT_CORNER_TR: |
||||
dir = E_MENU_POP_DIRECTION_DOWN; |
||||
break; |
||||
|
||||
case E_GADCON_ORIENT_BOTTOM: |
||||
case E_GADCON_ORIENT_CORNER_BL: |
||||
case E_GADCON_ORIENT_CORNER_BR: |
||||
dir = E_MENU_POP_DIRECTION_UP; |
||||
break; |
||||
|
||||
case E_GADCON_ORIENT_LEFT: |
||||
case E_GADCON_ORIENT_CORNER_LT: |
||||
case E_GADCON_ORIENT_CORNER_LB: |
||||
dir = E_MENU_POP_DIRECTION_RIGHT; |
||||
break; |
||||
|
||||
case E_GADCON_ORIENT_RIGHT: |
||||
case E_GADCON_ORIENT_CORNER_RT: |
||||
case E_GADCON_ORIENT_CORNER_RB: |
||||
dir = E_MENU_POP_DIRECTION_LEFT; |
||||
break; |
||||
|
||||
case E_GADCON_ORIENT_FLOAT: |
||||
case E_GADCON_ORIENT_HORIZ: |
||||
case E_GADCON_ORIENT_VERT: |
||||
default: |
||||
dir = E_MENU_POP_DIRECTION_AUTO; |
||||
break; |
||||
} |
||||
|
||||
e_gadcon_locked_set(inst->gcc->gadcon, EINA_TRUE); |
||||
|
||||
/* We display not relatively to the gadget, but similarly to
|
||||
* the start menu - thus the need for direction etc. |
||||
*/ |
||||
e_menu_activate_mouse(inst->menu, |
||||
e_util_zone_current_get |
||||
(e_manager_current_get()), |
||||
x, y, w, h, dir, ev->timestamp); |
||||
} |
||||
} |
||||
|
||||
static Eina_Bool |
||||
_share_x_selection_notify_handler(Instance *instance, int type, void *event) |
||||
{ |
||||
Ecore_X_Event_Selection_Notify *ev; |
||||
Share_Data *sd = NULL; |
||||
|
||||
if (!instance) |
||||
return EINA_TRUE; |
||||
|
||||
ev = event; |
||||
if ((ev->selection == ECORE_X_SELECTION_CLIPBOARD) && |
||||
(strcmp(ev->target, ECORE_X_SELECTION_TARGET_UTF8_STRING) == 0)) |
||||
{ |
||||
Ecore_X_Selection_Data_Text *text_data; |
||||
|
||||
text_data = ev->data; |
||||
if ((text_data->data.content == ECORE_X_SELECTION_CONTENT_TEXT) && |
||||
(text_data->text)) |
||||
{ |
||||
char buf[20]; |
||||
if (text_data->data.length == 0) return EINA_TRUE; |
||||
|
||||
sd = E_NEW(Share_Data, 1); |
||||
sd->inst = instance; |
||||
snprintf(buf, ((text_data->data.length >= sizeof(buf)) ? (sizeof(buf) - 1) : text_data->data.length), text_data->text); |
||||
asprintf(&sd->name, "%s", buf); |
||||
asprintf(&sd->content, "%s", text_data->text); |
||||
|
||||
sourcedrop_share(sd); |
||||
} |
||||
} |
||||
|
||||
return ECORE_CALLBACK_PASS_ON; |
||||
} |
||||
|
||||
/* Updates the X selection with the selected text of the entry */ |
||||
void |
||||
_clipboard_update(const char *text, const Instance *inst) |
||||
{ |
||||
EINA_SAFETY_ON_NULL_RETURN(inst); |
||||
EINA_SAFETY_ON_NULL_RETURN(text); |
||||
|
||||
ecore_x_selection_clipboard_set(inst->win, text, strlen(text) + 1); |
||||
} |
||||
|
||||
void e_share_upload_completed(Share_Data *sd) |
||||
{ |
||||
if (!sd) return; |
||||
((Instance*)sd->inst)->shares = eina_list_append(((Instance*)sd->inst)->shares, sd); |
||||
_share_notify(sd); |
||||
_clipboard_update(sd->url, sd->inst); |
||||
} |
||||
|
||||
static void |
||||
_share_menu_share_request_click_cb(Instance *inst, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__) |
||||
{ |
||||
if (!inst) return; |
||||
ecore_x_selection_clipboard_request(inst->win, |
||||
ECORE_X_SELECTION_TARGET_UTF8_STRING); |
||||
} |
||||
|
||||
static void |
||||
_share_menu_share_item_click_cb(Share_Data *selected_share, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__) |
||||
{ |
||||
_share_open_link_in_browser(selected_share); |
||||
} |
||||
|
||||
static void |
||||
_share_notify(const Share_Data *sd) |
||||
{ |
||||
char buf[256]; |
||||
E_Notification_Notify *n = E_NEW(E_Notification_Notify, 1); |
||||
|
||||
if (!sd || !n) |
||||
return; |
||||
n->id = 0; |
||||
n->app_name = _("E Share"); |
||||
n->sumary = _("Your content has been shared."); |
||||
snprintf(buf, (sizeof(buf) - 1), _("Your clipboard's content is now available at <highlight>%s</highlight>."), sd->url); |
||||
n->body = buf; |
||||
n->icon.icon = "e"; |
||||
n->timeout = 2; |
||||
e_notification_client_send(n, NULL /*_share_notification_clicked_cb*/, sd); |
||||
} |
||||
|
||||
static void |
||||
_share_open_link_in_browser(const Share_Data *sd) |
||||
{ |
||||
char buf[256]; |
||||
|
||||
if (!sd) |
||||
return; |
||||
snprintf(buf, (sizeof(buf) - 1), "xdg-open %s", sd->url); |
||||
e_exec(e_gadcon_client_zone_get(((Instance*)sd->inst)->gcc), NULL, buf, NULL, NULL); |
||||
} |
||||
|
||||
static void |
||||
_share_notification_clicked_cb(void *data, unsigned int id) |
||||
{ |
||||
if (!data) |
||||
return; |
||||
_share_open_link_in_browser((Share_Data*)data); |
||||
} |
||||
|
||||
static void |
||||
_share_menu_post_cb(void *data, E_Menu *menu __UNUSED__) |
||||
{ |
||||
Instance *inst = data; |
||||
|
||||
if (!inst) return; |
||||
e_gadcon_locked_set(inst->gcc->gadcon, EINA_FALSE); |
||||
inst->menu = NULL; |
||||
} |
||||
|
||||
static void _free_share_data(Share_Data *sd) |
||||
{ |
||||
free(sd->name); |
||||
free(sd->content); |
||||
free(sd->url); |
||||
free(sd); |
||||
} |
||||
|
||||
/* module setup */ |
||||
EAPI E_Module_Api e_modapi = { |
||||
E_MODULE_API_VERSION, |
||||
"Share" |
||||
}; |
||||
|
||||
EAPI void * |
||||
e_modapi_init (E_Module * m) |
||||
{ |
||||
share_module = m; |
||||
sourcedrop_init(); |
||||
e_gadcon_provider_register(&_gadcon_class); |
||||
return share_module; |
||||
} |
||||
|
||||
EAPI int |
||||
e_modapi_shutdown (E_Module * m) |
||||
{ |
||||
sourcedrop_shutdown(); |
||||
share_module = NULL; |
||||
e_gadcon_provider_unregister(&_gadcon_class); |
||||
return 1; |
||||
} |
||||
|
||||
EAPI int |
||||
e_modapi_save(E_Module * m) |
||||
{ |
||||
return 1; |
||||
} |
@ -0,0 +1,12 @@ |
||||
#ifndef E_MOD_MAIN_H |
||||
#define E_MOD_MAIN_H |
||||
|
||||
#include <e.h> |
||||
|
||||
EAPI extern E_Module_Api e_modapi; |
||||
|
||||
EAPI void *e_modapi_init (E_Module *m); |
||||
EAPI int e_modapi_shutdown (E_Module *m); |
||||
EAPI int e_modapi_save (E_Module *m); |
||||
|
||||
#endif |
@ -0,0 +1,22 @@ |
||||
#ifndef __E_SHARE_H__ |
||||
#define __E_SHARE_H__ |
||||
|
||||
#undef LOG |
||||
#define LOG(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__) |
||||
|
||||
typedef struct _Share_Data { |
||||
void *inst; |
||||
char *name; |
||||
char *content; |
||||
char *url; |
||||
} Share_Data; |
||||
|
||||
/* API used by submodules */ |
||||
void e_share_upload_completed(Share_Data *share_data); |
||||
|
||||
/* Submodules' functions */ |
||||
void sourcedrop_init(void); |
||||
void sourcedrop_share(Share_Data *share_data); |
||||
void sourcedrop_shutdown(void); |
||||
|
||||
#endif |
@ -0,0 +1,124 @@ |
||||
#include <ctype.h> |
||||
#include <json/json.h> |
||||
#include <bsd/string.h> |
||||
|
||||
#include "e_mod_main.h" |
||||
#include "e_share.h" |
||||
|
||||
#define BUFFER_SIZE_MAX 4096 |
||||
#define DROPNAME "Sourcedrop" |
||||
#define SOURCEDROP_URL "http://www.sourcedrop.net/paste"
|
||||
#define RECOGNITION_STRING "Location: " |
||||
|
||||
static Ecore_Event_Handler *handler = NULL; |
||||
|
||||
static Eina_Bool __upload_completed_cb(void *data, int type, Ecore_Con_Event_Url_Complete *ev); |
||||
static json_object *jarray, *jparent; |
||||
|
||||
/* Converts an integer value to its hex character*/ |
||||
char to_hex(const char code) { |
||||
static char hex[] = "0123456789abcdef"; |
||||
return hex[code & 15]; |
||||
} |
||||
|
||||
/* Returns a url-encoded version of str */ |
||||
/* IMPORTANT: be sure to free() the returned string after use */ |
||||
char *url_encode(const char *str) { |
||||
const char *pstr = str; |
||||
char *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf; |
||||
while (*pstr) { |
||||
if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~')
|
||||
*pbuf++ = *pstr; |
||||
else if (*pstr == ' ')
|
||||
*pbuf++ = '+'; |
||||
else
|
||||
*pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15); |
||||
pstr++; |
||||
} |
||||
*pbuf = '\0'; |
||||
return buf; |
||||
} |
||||
|
||||
const char *json_encode(const char *title, const char *content) |
||||
{ |
||||
const char *encoded_string = NULL; |
||||
|
||||
jarray = json_object_new_array(); |
||||
jparent = json_object_new_object(); |
||||
json_object_object_add(jparent, "title", json_object_new_string(title)); |
||||
json_object_object_add(jparent, "content", json_object_new_string(content)); |
||||
json_object_array_add(jarray, jparent); |
||||
|
||||
encoded_string = json_object_to_json_string(jarray); |
||||
|
||||
return encoded_string; |
||||
} |
||||
|
||||
static Eina_Bool |
||||
__upload_completed_cb(void *data, int type, Ecore_Con_Event_Url_Complete *ev) |
||||
{ |
||||
char buf[BUFFER_SIZE_MAX]; |
||||
const Eina_List *headers = NULL, *it; |
||||
const char *header = NULL; |
||||
Share_Data *sd = NULL; |
||||
|
||||
json_object_put(jarray); |
||||
jarray = NULL; |
||||
json_object_put(jparent); |
||||
jparent = NULL; |
||||
|
||||
if (ev->status != 200) |
||||
{ |
||||
LOG("E_SHARE/" DROPNAME ": This is not supposed to happen. The server returned status code: %d\n", ev->status); |
||||
return ECORE_CALLBACK_RENEW; |
||||
} |
||||
|
||||
headers = ecore_con_url_response_headers_get(ev->url_con); |
||||
EINA_LIST_FOREACH(headers, it, header) |
||||
{ |
||||
if (strncmp(header, RECOGNITION_STRING, (sizeof(RECOGNITION_STRING) - 1)) == 0) |
||||
{ |
||||
sd = ecore_con_url_data_get(ev->url_con); |
||||
strlcpy(buf, (char*)(header + sizeof(RECOGNITION_STRING) - 1), sizeof(buf)); |
||||
asprintf(&sd->url, "%s", buf); |
||||
e_share_upload_completed(sd); |
||||
ecore_con_url_free(ev->url_con); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return ECORE_CALLBACK_CANCEL; |
||||
} |
||||
|
||||
void sourcedrop_share(Share_Data *sd) |
||||
{ |
||||
Ecore_Con_Url *request_url = NULL; |
||||
char post_data[BUFFER_SIZE_MAX]; |
||||
const char *json_encoded = NULL; |
||||
char *url_encoded = NULL; |
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(sd); |
||||
|
||||
json_encoded = json_encode(sd->name, sd->content); |
||||
request_url = ecore_con_url_new(SOURCEDROP_URL); |
||||
url_encoded = url_encode(json_encoded); |
||||
snprintf(post_data, (sizeof(post_data) - 1), "data=%s", url_encoded); |
||||
free(url_encoded); |
||||
ecore_con_url_data_set(request_url, (void*)sd); |
||||
ecore_con_url_post(request_url, (void*)post_data, sizeof(post_data), "application/x-www-form-urlencoded");
|
||||
} |
||||
|
||||
void sourcedrop_init(void) |
||||
{ |
||||
ecore_init(); |
||||
ecore_con_init(); |
||||
handler = ecore_event_handler_add(ECORE_CON_EVENT_URL_COMPLETE, (Ecore_Event_Handler_Cb)__upload_completed_cb, NULL); |
||||
} |
||||
|
||||
void sourcedrop_shutdown(void) |
||||
{ |
||||
ecore_event_handler_del(handler); |
||||
handler = NULL; |
||||
ecore_con_shutdown(); |
||||
ecore_shutdown(); |
||||
} |
Loading…
Reference in new issue