mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
Compare commits
127 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
9804f0e93a | ||
|
a04496c7f0 | ||
|
84f195c9b7 | ||
|
5489ef0b70 | ||
|
cbcb0e2ce4 | ||
|
09039b46c9 | ||
|
7cc34bd248 | ||
|
482ced1c5c | ||
|
f09dd4d3d6 | ||
|
9c6d7ebd0e | ||
|
9029fb2f45 | ||
|
6f0fa02cbe | ||
|
f799482f64 | ||
|
da0370a255 | ||
|
3042413e36 | ||
|
29475da925 | ||
|
09b1d6fe74 | ||
|
ef64e70a8b | ||
|
bd1f834431 | ||
|
8f5f3a94ca | ||
|
e154972cdd | ||
|
8f8a937e98 | ||
|
f0c50eeebf | ||
|
002bd6b2e7 | ||
|
0d0cc8d8b1 | ||
|
a2b2ae0e27 | ||
|
e529fb9794 | ||
|
cdccbe7ce6 | ||
|
a735fa7e84 | ||
|
7ebc86ca41 | ||
|
d6dd94778c | ||
|
f1a37cefd2 | ||
|
30d0261cd3 | ||
|
97886f254a | ||
|
095feb98e7 | ||
|
361d3a532a | ||
|
2c9f804aa3 | ||
|
bee5fd8fb9 | ||
|
db9e0bad61 | ||
|
fc433aa342 | ||
|
0d6f18e867 | ||
|
932e2c85fd | ||
|
2726a2af37 | ||
|
756b95587d | ||
|
6d1a140375 | ||
|
ca5911fe94 | ||
|
05f7fc15e1 | ||
|
b24b859a4f | ||
|
8a0f7135ee | ||
|
a2a6f6034d | ||
|
d30685514c | ||
|
85490945e6 | ||
|
5bfe346880 | ||
|
9d1f4699de | ||
|
70e9a9b0b6 | ||
|
a8b01d75c1 | ||
|
c8323b386d | ||
|
229914358a | ||
|
7c4628dfa1 | ||
|
7760130feb | ||
|
8237708d54 | ||
|
19da305d71 | ||
|
0b4d9a7f26 | ||
|
6495f53404 | ||
|
d0d94e21dd | ||
|
465eb7dfe3 | ||
|
e01506d58a | ||
|
e4cf7ba8cf | ||
|
24a85295fa | ||
|
b5d2e20cee | ||
|
31d35e627a | ||
|
c93bfdf7ee | ||
|
6a7296bcae | ||
|
7b1245f06a | ||
|
d09f846380 | ||
|
7431373b29 | ||
|
22f4e094cf | ||
|
1046c2d4d5 | ||
|
97da788155 | ||
|
3df8f4ed7e | ||
|
eed00b3fbc | ||
|
8bb9028df3 | ||
|
a3f2a79d5f | ||
|
fc4474f1c7 | ||
|
68959abca2 | ||
|
fb708f76ed | ||
|
9751acdd9e | ||
|
a970841a4f | ||
|
804374ebe3 | ||
|
e4d7e831c9 | ||
|
0cd54534d1 | ||
|
6f93f25468 | ||
|
c5fd4cd9ee | ||
|
b7eb2760dc | ||
|
15dd0b0a80 | ||
|
c605359ea1 | ||
|
013dfcc481 | ||
|
0301585b3c | ||
|
07e43f1c2b | ||
|
61bd398054 | ||
|
4e0bd12967 | ||
|
1cc61c1d29 | ||
|
b19a713bdf | ||
|
c39c0718f9 | ||
|
240c195d87 | ||
|
5f89e0a412 | ||
|
599356843b | ||
|
c3aa1a61e6 | ||
|
c26b526dcd | ||
|
0ad6617df4 | ||
|
9eca312821 | ||
|
2d028fe4a6 | ||
|
b4ad2fb11b | ||
|
89ec43af74 | ||
|
1dde9f92da | ||
|
a45609e945 | ||
|
705ea3ebf2 | ||
|
8eeca59484 | ||
|
3ff0844756 | ||
|
a024e66550 | ||
|
59a16eff0e | ||
|
db1ebec5d9 | ||
|
39ffa8406b | ||
|
fde927b627 | ||
|
eb175fa89f | ||
|
9a664ddb92 | ||
|
0d061c24e7 |
|
@ -129,10 +129,16 @@ X_EXTRA_LIBS ?= @X_EXTRA_LIBS@ ;
|
|||
# solo XKB extension library
|
||||
XKB_LIBS ?= @XKB_LIBS@ ;
|
||||
|
||||
# shape extension
|
||||
XSHAPE_LIBS ?= @XSHAPE_LIBS@ ;
|
||||
|
||||
# curl libraries
|
||||
CURL_CFLAGS ?= @CURL_CFLAGS@ ;
|
||||
CURL_LIBS ?= @CURL_LIBS@ ;
|
||||
|
||||
# kstat
|
||||
KSTAT_LIBS ?= @KSTAT_LIBS@ ;
|
||||
|
||||
# platform specific pthread flags
|
||||
# FIXME: a quick hack to work everything on SunStudio
|
||||
if $(SUN_COMPILER) {
|
||||
|
|
3
Jamfile
3
Jamfile
|
@ -10,7 +10,7 @@
|
|||
|
||||
SubDir TOP ;
|
||||
|
||||
EdeManualWithToc README ;
|
||||
# EdeManualWithToc README ;
|
||||
|
||||
Clean distclean : $(JCACHEFILE) $(HCACHEFILE) ;
|
||||
|
||||
|
@ -31,7 +31,6 @@ SubInclude TOP ede-screen-lock ;
|
|||
SubInclude TOP ede-help ;
|
||||
SubInclude TOP ede-image-view ;
|
||||
SubInclude TOP ede-launch ;
|
||||
SubInclude TOP emountd ;
|
||||
SubInclude TOP ede-timedate ;
|
||||
SubInclude TOP ede-tip ;
|
||||
SubInclude TOP ede-preferred-applications ;
|
||||
|
|
58
README
58
README
|
@ -1,58 +0,0 @@
|
|||
Readme for EDE
|
||||
==============
|
||||
|
||||
Thank you for showing interest in EDE project. EDE is small and fast desktop environment
|
||||
that uses http://www.fltk.org[FLTK Toolkit]. For more details and philosophy behind it, check
|
||||
http://equinox-project.org/wiki/AboutEde[about EDE on our wiki].
|
||||
|
||||
As every software project, EDE is always in development so your contribution is always welcome!
|
||||
|
||||
Build requirements
|
||||
------------------
|
||||
|
||||
EDE is using FLTK toolkit from http://www.fltk.org[www.fltk.org]. At the time
|
||||
of this writing, latest stable tree is 1.3.x.
|
||||
|
||||
Since FLTK lacks many things needed for developing a full *nix desktop
|
||||
environment, we have developed a small add-on library called 'edelib'. This
|
||||
library is also required for compiling EDE and is released together with EDE.
|
||||
|
||||
We *strongly* recommend that you use matching versions of EDE and
|
||||
edelib (e.g. released at the same time) or you make repository checkout at the same time due
|
||||
their frequent changes.
|
||||
|
||||
Also you will need a 'jam' tool. Jam is a make replacement and you will find it on our repository.
|
||||
|
||||
Downloading the code
|
||||
--------------------
|
||||
|
||||
The best way to download latest code is checking it out from our repository. These modules
|
||||
you should checkout (with their paths):
|
||||
|
||||
- jam : 'svn co https://ede.svn.sourceforge.net/svnroot/ede/trunk/jam'
|
||||
- edelib : 'svn co https://ede.svn.sourceforge.net/svnroot/ede/trunk/edelib'
|
||||
- ede : 'svn co https://ede.svn.sourceforge.net/svnroot/ede/trunk/ede2'
|
||||
|
||||
If you already have Jam installed, there is no need to download it.
|
||||
|
||||
Compiling and installing
|
||||
------------------------
|
||||
|
||||
In order to build and install EDE do the following steps:
|
||||
|
||||
1. compile and install jam first; going to jam source directory and running 'make' will do
|
||||
the job; after that you should get 'bin.YOUR_PLATFORM' directory (on Linux it will be
|
||||
bin.linux) and copy 'jam' executable in your $PATH, e.g. /usr/local/bin
|
||||
|
||||
2. compile and install edelib; please read README file in edelib directory
|
||||
|
||||
3. go in ede2 directory and run './autogen.sh'
|
||||
|
||||
4. after that, goes './configure --enable-debug'
|
||||
|
||||
5. jam
|
||||
|
||||
6. jam install
|
||||
|
||||
Please note how this document is quick and short tutorial about EDE installation. For more details,
|
||||
please check http://equinox-project.org/wiki/InstallationHowTo[Installation Howto] on our wiki.
|
58
README.md
Normal file
58
README.md
Normal file
|
@ -0,0 +1,58 @@
|
|||
# EDE
|
||||
|
||||
EDE, the `Equinox Desktop Environment`, is a small and fast desktop
|
||||
environment that uses the [FLTK toolkit](http://www.fltk.org).
|
||||
For more details and the philosophy behind it, see
|
||||
[about EDE on our wiki](http://equinox-project.org/wiki/AboutEde).
|
||||
|
||||
## Build requirements
|
||||
|
||||
EDE requires FLTK; at the time of this writing, the latest stable
|
||||
branch is 1.3.x.
|
||||
|
||||
Since FLTK lacks many things needed for developing a full *nix desktop
|
||||
environment, we have developed a small add-on library called
|
||||
`edelib`. This library is needed both for building and running the
|
||||
desktop. Edelib is developed and released together with EDE.
|
||||
|
||||
It is *strongly* recommended to use matching versions of EDE and
|
||||
edelib (i.e. versions released at the same time) or to checkout
|
||||
both from the repository at the same time to make sure they work
|
||||
together well.
|
||||
|
||||
Also you will need the `jam` tool. Jam is a *make* replacement and you
|
||||
can find it on our repository.
|
||||
|
||||
## Downloading the code
|
||||
|
||||
The best way to get the latest code is checking it out from our
|
||||
repository. These are the modules you should checkout (with their paths):
|
||||
|
||||
- *jam* - `git clone https://github.com/edeproject/jam.git`
|
||||
- *edelib* - `git clone https://github.com/edeproject/edelib.git`
|
||||
- *ede* - `git clone https://github.com/edeproject/ede.git`
|
||||
|
||||
If you already have Jam installed, there is of course no need to download
|
||||
it again. Either vanilla Jam or FTJam can be used to build EDE. Boost Jam is
|
||||
known to *not* work.
|
||||
|
||||
## Compiling and installing
|
||||
|
||||
In order to build and install EDE do the following steps:
|
||||
|
||||
1. compile and install `jam` first; going to jam source directory and running `make` will do
|
||||
the job; after that you should get `bin.YOUR_PLATFORM` directory (e.g. on Linux it will be
|
||||
bin.linux) and copy `jam` executable in your $PATH, e.g. */usr/local/bin*
|
||||
|
||||
2. compile and install `edelib`; please read README file in edelib directory
|
||||
|
||||
3. change into the ede directory and run `./autogen.sh`
|
||||
|
||||
4. after that, do `./configure --enable-debug`
|
||||
|
||||
5. jam
|
||||
|
||||
6. jam install
|
||||
|
||||
Please note that this document is only a quick and short tutorial on installing EDE. For more details
|
||||
please see [Installation Howto](http://equinox-project.org/wiki/InstallationHowTo) on our wiki.
|
|
@ -109,26 +109,6 @@ rule EdeProgramAsFltkBare
|
|||
}
|
||||
}
|
||||
|
||||
# EfltkProgram [target] : [sources] : [noinstall] ;
|
||||
# Creates programs that will be linked with efltk. If [noinstall] is given,
|
||||
# [target] will not be installed wit 'jam install'.
|
||||
rule EfltkProgram
|
||||
{
|
||||
if ! $(EFLTKINCLUDE) || ! $(EFLTKLIB) {
|
||||
Echo "EFLTKINCLUDE or EFLTKLIB not defined; $(1) will not be built" ;
|
||||
return ;
|
||||
}
|
||||
|
||||
MakeProgramPrivate $(1) : $(2)
|
||||
: $(EFLTKLIB) $(STDLIB)
|
||||
: $(GLOBALFLAGS) $(EFLTKINCLUDE) ;
|
||||
|
||||
# install it where ede binaries resides
|
||||
if $(3) != "noinstall" {
|
||||
InstallEdeProgram $(1) ;
|
||||
}
|
||||
}
|
||||
|
||||
# FltkProgram [target] : [sources] : [noinstall] ;
|
||||
# Creates programs that will be linked with fltk only. It will use full fltk
|
||||
# dependencies (images).
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
# GNU General Public License version 2 or newer.
|
||||
# See COPYING for details.
|
||||
|
||||
SVG_CONVERTOR = "rsvg" ;
|
||||
SVG_CONVERTOR = "rsvg-convert" ;
|
||||
|
||||
# SvgToPng [target-png] : [source-svg] : [width] : [height] ;
|
||||
rule SvgToPng
|
||||
|
|
49
configure.in
49
configure.in
|
@ -2,14 +2,14 @@ dnl
|
|||
dnl $Id: configure.in 1719 2006-08-15 08:56:42Z karijes $
|
||||
dnl
|
||||
dnl Part of Equinox Desktop Environment (EDE).
|
||||
dnl Copyright (c) 2000-2012 EDE Authors.
|
||||
dnl Copyright (c) 2000-2014 EDE Authors.
|
||||
dnl
|
||||
dnl This program is licenced under terms of the
|
||||
dnl GNU General Public Licence version 2 or newer.
|
||||
dnl See COPYING for details.
|
||||
|
||||
m4_define([ede_major_version], [2])
|
||||
m4_define([ede_minor_version], [0])
|
||||
m4_define([ede_minor_version], [2])
|
||||
m4_define([ede_patch_version], [0])
|
||||
m4_define([ede_version], [ede_major_version.ede_minor_version.ede_patch_version])
|
||||
|
||||
|
@ -56,6 +56,17 @@ AC_PATH_XTRA
|
|||
|
||||
AC_HEADER_STDC
|
||||
|
||||
dnl for xmlrpc-c
|
||||
AC_CHECK_FUNC(pselect, AC_DEFINE(HAVE_PSELECT, 1, [Define to 1 if you have pselect()]))
|
||||
AC_CHECK_FUNC(setgroups, AC_DEFINE(HAVE_SETGROUPS, 1, [Define to 1 if you have setgroups()]))
|
||||
AC_CHECK_FUNC(asprintf, AC_DEFINE(HAVE_ASPRINTF, 1, [Define to 1 if you have asprintf()]))
|
||||
AC_CHECK_FUNC(setenv, AC_DEFINE(HAVE_SETENV, 1, [Define to 1 if you have setenv()]))
|
||||
AC_CHECK_FUNC(wcsncmp, AC_DEFINE(HAVE_WCSNCMP, 1, [Define to 1 if you have wcsncmp()]))
|
||||
AC_CHECK_FUNC(gettimeofday, AC_DEFINE(HAVE_GETTIMEOFDAY, 1, [Define to 1 if you have gettimeofday()]))
|
||||
AC_CHECK_FUNC(localtime_r, AC_DEFINE(HAVE_LOCALTIME_R, 1, [Define to 1 if you have localtime_r()]))
|
||||
AC_CHECK_FUNC(gmtime_r, AC_DEFINE(HAVE_GMTIME_R, 1, [Define to 1 if you have gmtime_r()]))
|
||||
AC_CHECK_FUNC(strcasecmp, AC_DEFINE(HAVE_STRCASECMP, 1, [Define to 1 if you have strcasecmp()]))
|
||||
|
||||
if test "$enable_profile" = "yes"; then
|
||||
enable_debug=yes
|
||||
fi
|
||||
|
@ -78,6 +89,7 @@ if test "$enable_shape" = "yes"; then
|
|||
|
||||
if test "$have_xshape" = "yes"; then
|
||||
AC_DEFINE(HAVE_SHAPE, 1, [Define to 1 if you have XShape extension])
|
||||
XSHAPE_LIBS="-lXext"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
@ -106,10 +118,7 @@ else
|
|||
fi
|
||||
|
||||
if test -n "$with_edelib_path"; then
|
||||
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$with_edelib_path"
|
||||
else
|
||||
dnl TODO: remove this in release
|
||||
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/opt/ede/lib/pkgconfig"
|
||||
export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$with_edelib_path/lib/pkgconfig"
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES(EDELIB, [edelib],, [have_edelib=no])
|
||||
|
@ -129,7 +138,7 @@ fi
|
|||
|
||||
PKG_CHECK_MODULES(EDELIB_DBUS, [edelib-dbus],, [have_edelib_dbus=no])
|
||||
if test "$have_edelib_dbus" = "no"; then
|
||||
AC_MSG_ERROR(edelib-dbus not found! You must install it first)
|
||||
AC_MSG_RESULT(edelib is compiled without DBus so EDE will be compiled without DBus support)
|
||||
fi
|
||||
|
||||
dnl find edelib documentation
|
||||
|
@ -249,6 +258,30 @@ else
|
|||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
dnl kstat/solaris
|
||||
AC_CHECK_HEADER(kstat.h, [have_kstat_h=yes],)
|
||||
if test "x$have_kstat_h" = "xyes"; then
|
||||
AC_MSG_CHECKING([for kstat presence])
|
||||
|
||||
AC_LANG_SAVE
|
||||
AC_LANG_C
|
||||
AC_TRY_COMPILE([
|
||||
#include <kstat.h>
|
||||
],[
|
||||
kstat_named_t k;
|
||||
k.value.ui32;
|
||||
],[have_kstat=yes],[])
|
||||
AC_LANG_RESTORE
|
||||
|
||||
if test "x$have_kstat" = "xyes"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_KSTAT, 1, [Define to 1 if you have kstat])
|
||||
KSTAT_LIBS=" -lkstat"
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl pekwm specific macros
|
||||
EDE_CHECK_PEKWM_DEPENDENCIES
|
||||
|
||||
|
@ -268,7 +301,9 @@ AC_SUBST(CURL_CFLAGS)
|
|||
AC_SUBST(CURL_LIBS)
|
||||
AC_SUBST(LARGEFILE)
|
||||
AC_SUBST(XKB_LIBS)
|
||||
AC_SUBST(XSHAPE_LIBS)
|
||||
AC_SUBST(my_sysconfdir)
|
||||
AC_SUBST(KSTAT_LIBS)
|
||||
AC_SUBST(PEKWM_CXXFLAGS)
|
||||
AC_SUBST(PEKWM_LIBS)
|
||||
|
||||
|
|
|
@ -20,10 +20,10 @@ Global {
|
|||
KeyPress = "Mod4 Up" { Actions = "FocusDirectional Up" }
|
||||
KeyPress = "Mod4 Down" { Actions = "FocusDirectional Down" }
|
||||
# Moving in workspaces
|
||||
KeyPress = "Ctrl Mod1 Left" { Actions = "GotoWorkspace Left" }
|
||||
KeyPress = "Ctrl Mod1 Right" { Actions = "GotoWorkspace Right" }
|
||||
KeyPress = "Ctrl Mod1 Up" { Actions = "GotoWorkspace Up" }
|
||||
KeyPress = "Ctrl Mod1 Down" { Actions = "GotoWorkspace Down" }
|
||||
KeyPress = "Ctrl Mod1 Left" { Actions = "HideAllMenus; GotoWorkspace Left" }
|
||||
KeyPress = "Ctrl Mod1 Right" { Actions = "HideAllMenus; GotoWorkspace Right" }
|
||||
KeyPress = "Ctrl Mod1 Up" { Actions = "HideAllMenus; GotoWorkspace Up" }
|
||||
KeyPress = "Ctrl Mod1 Down" { Actions = "HideAllMenus; GotoWorkspace Down" }
|
||||
KeyPress = "Mod4 1" { Actions = "GotoWorkspace 1" }
|
||||
KeyPress = "Mod4 2" { Actions = "GotoWorkspace 2" }
|
||||
KeyPress = "Mod4 3" { Actions = "GotoWorkspace 3" }
|
||||
|
|
|
@ -2,3 +2,49 @@
|
|||
|
||||
# Variables
|
||||
INCLUDE = "vars"
|
||||
|
||||
WindowMenu = "Window Menu" {
|
||||
Entry = "(Un)Stick" { Actions = "Toggle Sticky" }
|
||||
Entry = "(Un)Shade" { Actions = "Toggle Shaded" }
|
||||
Entry = "Iconify" { Actions = "Set Iconified" }
|
||||
|
||||
Submenu = "Maximize" {
|
||||
Entry = "Toggle Full" { Actions = "Toggle Maximized True True" }
|
||||
Entry = "Toggle Horizontal" { Actions = "Toggle Maximized True False" }
|
||||
Entry = "Toggle Vertical" { Actions = "Toggle Maximized False True" }
|
||||
}
|
||||
Submenu = "Fill" {
|
||||
Entry = "Full" { Actions = "MaxFill True True" }
|
||||
Entry = "Horizontal" { Actions = "MaxFill True False" }
|
||||
Entry = "Vertical" { Actions = "MaxFill False True" }
|
||||
}
|
||||
Submenu = "Stacking" {
|
||||
Entry = "Raise" { Actions = "Raise" }
|
||||
Entry = "Lower" { Actions = "Lower" }
|
||||
Entry = "Toggle Always On Top" { Actions = "Toggle AlwaysOnTop" }
|
||||
Entry = "Toggle Always Below" { Actions = "Toggle AlwaysBelow" }
|
||||
}
|
||||
Submenu = "Decorations" {
|
||||
Entry = "Toggle Decorations" { Actions = "Toggle DecorBorder; Toggle DecorTitlebar" }
|
||||
Entry = "Toggle Borders" { Actions = "Toggle DecorBorder" }
|
||||
Entry = "Toggle Titlebar" { Actions = "Toggle DecorTitlebar" }
|
||||
}
|
||||
Submenu = "Skip" {
|
||||
Entry = "Toggle showing this frame in menus" { Actions = "Toggle Skip Menus" }
|
||||
Entry = "Toggle including this frame in focus toggle" { Actions = "Toggle Skip FocusToggle" }
|
||||
Entry = "Toggle if this frame snaps to other windows" { Actions = "Toggle Skip Snap" }
|
||||
}
|
||||
SubMenu = "Send To" {
|
||||
# Create sendto menu once per pekwm config reload. The fast way that
|
||||
# will work for most if not all users.
|
||||
COMMAND = "$_PEKWM_SCRIPT_PATH/pekwm_ws_menu.sh send"
|
||||
# Create sendto menu every time the menu is opened. The slow way.
|
||||
# This is what you want if you are using external tools to make
|
||||
# the amount of workspaces something else than what you define in
|
||||
# ~/.pekwm/config. You will know if you want this.
|
||||
# Entry = "" { Actions = "Dynamic $_PEKWM_SCRIPT_PATH/pekwm_ws_menu.sh send dynamic" }
|
||||
}
|
||||
Separator {}
|
||||
Entry = "Close" { Actions = "Close" }
|
||||
Submenu = "Kill" { Entry = "Kill application" { Actions = "Kill" } }
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
FrameTitle {
|
||||
ButtonRelease = "1" { Actions = "Raise; Focus; ActivateClient" }
|
||||
ButtonRelease = "1" { Actions = "HideAllMenus; Raise; Focus; ActivateClient" }
|
||||
ButtonRelease = "Mod1 1" { Actions = "Focus; Raise" }
|
||||
ButtonRelease = "Mod4 1" { Actions = "Focus; Raise" }
|
||||
ButtonRelease = "2" { Actions = "ActivateClient" }
|
||||
ButtonRelease = "Mod4 3" { Actions = "Close" }
|
||||
ButtonRelease = "3" { Actions = "ShowMenu Window" }
|
||||
ButtonRelease = "3" { Actions = "HideAllMenus; ShowMenu Window" }
|
||||
ButtonRelease = "4" { Actions = "ActivateClientRel 1" }
|
||||
ButtonRelease = "5" { Actions = "ActivateClientRel -1" }
|
||||
ButtonRelease = "Mod1 4" { Actions = "SendToWorkspace Next; GotoWorkspace Next" }
|
||||
|
@ -16,8 +16,8 @@ FrameTitle {
|
|||
ButtonRelease = "Ctrl Mod1 1" { Actions = "Focus; Raise True" }
|
||||
DoubleClick = "2" { Actions = "Toggle Shaded" }
|
||||
DoubleClick = "Mod1 2" { Actions = "Toggle Shaded" }
|
||||
DoubleClick = "1" { Actions = "MaxFill True True" }
|
||||
DoubleClick = "Mod1 1" { Actions = "Toggle Maximized True True" }
|
||||
DoubleClick = "1" { Actions = "Toggle Maximized True True" }
|
||||
DoubleClick = "Mod1 1" { Actions = "Toggle MaxFill True True" }
|
||||
Motion = "1" { Threshold = "4"; Actions = "Raise; Move" }
|
||||
Motion = "Mod1 1" { Threshold = "4"; Actions = "Raise; Move" }
|
||||
Motion = "Mod4 1" { Threshold = "4"; Actions = "Raise; Move" }
|
||||
|
@ -135,7 +135,7 @@ Client {
|
|||
# Remove the following line and uncomment the alternative if windows should raise when clicked.
|
||||
#ButtonPress = "1" { Actions = "Focus" }
|
||||
# Uncomment the following line if windows should raise when clicked.
|
||||
ButtonPress = "1" { Actions = "Focus; Raise" }
|
||||
ButtonPress = "1" { Actions = "HideAllMenus; Focus; Raise" }
|
||||
|
||||
ButtonRelease = "Mod1 1" { Actions = "Focus; Raise" }
|
||||
ButtonRelease = "Mod4 1" { Actions = "Lower" }
|
||||
|
|
|
@ -10,4 +10,4 @@
|
|||
|
||||
SubDir TOP data pekwm scripts ;
|
||||
|
||||
InstallProgram "$(PEKWM_DATA_DIR)/scripts" : pekwm_themeset.sh pekwm_ws_menu.sh ;
|
||||
# InstallProgram "$(PEKWM_DATA_DIR)/scripts" : pekwm_themeset.sh pekwm_ws_menu.sh ;
|
||||
|
|
|
@ -154,7 +154,7 @@ PDecor {
|
|||
|
||||
Decor = "Menu" {
|
||||
Title {
|
||||
@DecorBase
|
||||
@DecorEmpty
|
||||
@DecorBorder
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# $Id$
|
||||
#
|
||||
# Part of Equinox Desktop Environment (EDE).
|
||||
# Copyright (c) 2007-2009 EDE Authors.
|
||||
# Copyright (c) 2007-2013 EDE Authors.
|
||||
#
|
||||
# This program is licensed under terms of the
|
||||
# GNU General Public License version 2 or newer.
|
||||
|
@ -41,6 +41,8 @@ if [ "x$XDG_MENU_PREFIX" = "x" ]; then
|
|||
XDG_MENU_PREFIX="ede-"
|
||||
fi
|
||||
|
||||
XDG_CURRENT_DESKTOP="EDE"
|
||||
|
||||
[ -d $XDG_DATA_HOME ] || mkdir -p $XDG_DATA_HOME
|
||||
[ -d $XDG_CONFIG_HOME ] || mkdir -p $XDG_CONFIG_HOME
|
||||
[ -d $XDG_CACHE_HOME ] || mkdir -p $XDG_CACHE_HOME
|
||||
|
@ -51,25 +53,14 @@ export XDG_CACHE_HOME
|
|||
export XDG_DATA_DIRS
|
||||
export XDG_CONFIG_DIRS
|
||||
export XDG_MENU_PREFIX
|
||||
export XDG_CURRENT_DESKTOP
|
||||
|
||||
PATH=$PATH:$PREFIX:$PREFIX/bin
|
||||
export PATH
|
||||
|
||||
userresources=$HOME/.Xdefaults
|
||||
sysresources=/usr/X11R6/lib/X11/xinit/.Xresources
|
||||
|
||||
if [ -f $sysresources ]; then
|
||||
xrdb -merge $sysresources
|
||||
fi
|
||||
|
||||
if [ -f $userresources ]; then
|
||||
xrdb -merge $userresources
|
||||
fi
|
||||
|
||||
# set background inside X
|
||||
XSETROOT=`which xsetroot 2> /dev/null`
|
||||
if [ "$XSETROOT" ]; then
|
||||
$XSETROOT -solid black
|
||||
# set the background color inside X
|
||||
if command -v xsetroot > /dev/null 2>&1; then
|
||||
xsetroot -solid black
|
||||
fi
|
||||
|
||||
# remove leftovers if evoke crashed
|
||||
|
|
|
@ -1,21 +1,6 @@
|
|||
/////////////////////////////////////////////////
|
||||
From this file is generated index.html
|
||||
and is placed in 'manual' directory.
|
||||
|
||||
Also rest of the html files are generated
|
||||
from various places in the tree and put
|
||||
in 'manual' too.
|
||||
|
||||
Knowing this, url links should point in
|
||||
local directory, not 'manual'.
|
||||
|
||||
Before doing _any_ changes, consulting asciidoc
|
||||
documentation about tags and usage will be applauded.
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
{edeversion} manual
|
||||
{edeversion} manual
|
||||
===================
|
||||
:Revision: 0.1
|
||||
:Revision: 0.2
|
||||
|
||||
*Introduction*
|
||||
|
||||
|
@ -28,7 +13,7 @@
|
|||
- link:ede-help.html[ede-help]
|
||||
- link:ede-tip.html[ede-tip]
|
||||
- link:evoke.html[evoke]
|
||||
- link:emountd.html[emountd]
|
||||
- link:ede-notify-daemon.html[ede-notify-daemon]
|
||||
|
||||
*Development*
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Eabout, display version and authors
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2008-2012 EDE Authors.
|
||||
* Copyright (c) 2008-2014 EDE Authors.
|
||||
*
|
||||
* This program is licensed under terms of the
|
||||
* GNU General Public License version 2 or newer.
|
||||
|
@ -102,11 +102,11 @@ const char* bold_keywords[] = {
|
|||
|
||||
#define BOLD_KEYWORDS_LEN 8
|
||||
|
||||
void close_cb(Fl_Widget*, void*) {
|
||||
static void close_cb(Fl_Widget*, void*) {
|
||||
win->hide();
|
||||
}
|
||||
|
||||
char* prepare_style(char* txt, int len) {
|
||||
static char* prepare_style(char* txt, int len) {
|
||||
// paint all with 'A' style at startup
|
||||
char* style = new char[len + 1];
|
||||
memset(style, 'A', len - 1);
|
||||
|
@ -114,12 +114,13 @@ char* prepare_style(char* txt, int len) {
|
|||
|
||||
// find bold keywords and paint them
|
||||
char* p = 0;
|
||||
unsigned int ln;
|
||||
for(int i = 0; i < BOLD_KEYWORDS_LEN; i++) {
|
||||
p = strstr(txt, bold_keywords[i]);
|
||||
if(!p)
|
||||
continue;
|
||||
unsigned int len = strlen(bold_keywords[i]);
|
||||
memset(&style[p - txt], 'B', len);
|
||||
if(!p) continue;
|
||||
|
||||
ln = strlen(bold_keywords[i]);
|
||||
memset(&style[p - txt], 'B', ln);
|
||||
}
|
||||
|
||||
return style;
|
||||
|
@ -141,7 +142,7 @@ int main(int argc, char **argv) {
|
|||
ede_label_box->labelfont(1);
|
||||
ede_label_box->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
|
||||
|
||||
Fl_Box* ede_copy_box = new Fl_Box(70, 35, 300, 25, "Copyright (c) by EDE Authors 2000-2012");
|
||||
Fl_Box* ede_copy_box = new Fl_Box(70, 35, 300, 25, "Copyright (c) by EDE Authors 2000-2014");
|
||||
ede_copy_box->labelsize(11);
|
||||
ede_copy_box->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_TOP);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Check_Browser.H>
|
||||
|
@ -41,7 +42,7 @@
|
|||
#include <edelib/Ede.h>
|
||||
|
||||
EDELIB_NS_USING_AS(Window, AppWindow)
|
||||
EDELIB_NS_USING_LIST(15, (String,
|
||||
EDELIB_NS_USING_LIST(17, (String,
|
||||
DesktopFile,
|
||||
IconLoader,
|
||||
list,
|
||||
|
@ -49,8 +50,10 @@ EDELIB_NS_USING_LIST(15, (String,
|
|||
system_config_dirs,
|
||||
user_config_dir,
|
||||
str_ends,
|
||||
str_tolower,
|
||||
run_async,
|
||||
ask,
|
||||
alert,
|
||||
file_test,
|
||||
window_center_on_screen,
|
||||
FILE_TEST_IS_REGULAR,
|
||||
|
@ -135,8 +138,8 @@ static void unique_by_basename(StringList& lst) {
|
|||
}
|
||||
|
||||
static void entry_list_run_clear(DialogEntryList& l, bool run) {
|
||||
DialogEntryListIter dit = l.begin(), dit_end = l.end();
|
||||
for(; dit != dit_end; ++dit) {
|
||||
DialogEntryListIter dit = l.begin(), dite = l.end();
|
||||
for(; dit != dite; ++dit) {
|
||||
if(run)
|
||||
AUTOSTART_RUN((*dit)->exec.c_str());
|
||||
delete *dit;
|
||||
|
@ -188,8 +191,8 @@ static void run_autostart_dialog(DialogEntryList& l) {
|
|||
txt->align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT | FL_ALIGN_WRAP);
|
||||
cbrowser = new Fl_Check_Browser(10, 75, 350, 185);
|
||||
|
||||
DialogEntryListIter it = l.begin(), it_end = l.end();
|
||||
for(; it != it_end; ++it) {
|
||||
DialogEntryListIter it = l.begin(), ite = l.end();
|
||||
for(; it != ite; ++it) {
|
||||
if((*it)->comment.empty())
|
||||
cbrowser->add((*it)->name.c_str());
|
||||
else {
|
||||
|
@ -222,13 +225,13 @@ static void perform_autostart(bool safe) {
|
|||
adir += AUTOSTART_DIRNAME;
|
||||
|
||||
StringList dfiles, sysdirs, tmp;
|
||||
StringListIter it, it_end, tmp_it, tmp_it_end;
|
||||
StringListIter it, ite, tmp_it, tmp_ite;
|
||||
|
||||
dir_list(adir.c_str(), dfiles, true);
|
||||
|
||||
system_config_dirs(sysdirs);
|
||||
if(!sysdirs.empty()) {
|
||||
for(it = sysdirs.begin(), it_end = sysdirs.end(); it != it_end; ++it) {
|
||||
for(it = sysdirs.begin(), ite = sysdirs.end(); it != ite; ++it) {
|
||||
*it += AUTOSTART_DIRNAME;
|
||||
|
||||
/*
|
||||
|
@ -237,22 +240,18 @@ static void perform_autostart(bool safe) {
|
|||
* probably via merge() member
|
||||
*/
|
||||
dir_list((*it).c_str(), tmp, true);
|
||||
for(tmp_it = tmp.begin(), tmp_it_end = tmp.end(); tmp_it != tmp_it_end; ++tmp_it)
|
||||
for(tmp_it = tmp.begin(), tmp_ite = tmp.end(); tmp_it != tmp_ite; ++tmp_it)
|
||||
dfiles.push_back(*tmp_it);
|
||||
}
|
||||
}
|
||||
|
||||
if(dfiles.empty())
|
||||
return;
|
||||
if(dfiles.empty()) return;
|
||||
|
||||
/*
|
||||
* Remove duplicates where first one seen have priority to be keept.
|
||||
* This way is required by spec.
|
||||
* Remove duplicates where first one seen have priority to be keept. This way is required by spec.
|
||||
*
|
||||
* Also handle this case (noted in spec):
|
||||
* if $XDG_CONFIG_HOME/autostart/foo.desktop and $XDG_CONFIG_DIRS/autostart/foo.desktop
|
||||
* exists, but $XDG_CONFIG_HOME/autostart/foo.desktop have 'Hidden = true',
|
||||
* $XDG_CONFIG_DIRS/autostart/foo.autostart is ignored too.
|
||||
* Also handle this case (noted in spec): * if $XDG_CONFIG_HOME/autostart/foo.desktop and $XDG_CONFIG_DIRS/autostart/foo.desktop
|
||||
* exists, but $XDG_CONFIG_HOME/autostart/foo.desktop have 'Hidden = true', * $XDG_CONFIG_DIRS/autostart/foo.autostart is ignored too.
|
||||
*
|
||||
* Later is implied via unique_by_basename().
|
||||
*/
|
||||
|
@ -263,7 +262,7 @@ static void perform_autostart(bool safe) {
|
|||
DesktopFile df;
|
||||
DialogEntryList entry_list;
|
||||
|
||||
for(it = dfiles.begin(), it_end = dfiles.end(); it != it_end; ++it) {
|
||||
for(it = dfiles.begin(), ite = dfiles.end(); it != ite; ++it) {
|
||||
if((*it).empty())
|
||||
continue;
|
||||
|
||||
|
@ -276,12 +275,23 @@ static void perform_autostart(bool safe) {
|
|||
E_WARNING(E_STRLOC ": Can't load '%s'. Skipping...\n", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* obey to OnlyShowIn rule */
|
||||
if(df.only_show_in(buf, sizeof(buf))) {
|
||||
str_tolower((unsigned char*)buf);
|
||||
if(strstr(buf, "ede") == NULL)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* obey to NotShowIn rule */
|
||||
if(df.not_show_in(buf, sizeof(buf))) {
|
||||
str_tolower((unsigned char*)buf);
|
||||
if(strstr(buf, "ede") != NULL)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* files marked as hidden must be skipped */
|
||||
if(df.hidden())
|
||||
continue;
|
||||
|
||||
if(!df.exec(buf, sizeof(buf)))
|
||||
if(df.hidden() || !df.exec(buf, sizeof(buf)))
|
||||
continue;
|
||||
|
||||
DialogEntry* en = new DialogEntry;
|
||||
|
@ -321,8 +331,11 @@ static void perform_autostart_scripts(const char* dir) {
|
|||
"Would you like to start them?"), dir))
|
||||
{
|
||||
/* spec said how we must chdir to the root of the medium */
|
||||
chdir(dir);
|
||||
AUTOSTART_RUN(path);
|
||||
errno = 0;
|
||||
if(chdir(dir) == 0)
|
||||
AUTOSTART_RUN(path);
|
||||
else
|
||||
alert(_("Unable to change folder: %s"), strerror(errno));
|
||||
}
|
||||
|
||||
/* we only match the one file */
|
||||
|
|
|
@ -28,14 +28,18 @@ struct BugzillaData {
|
|||
xmlrpc_env xenv;
|
||||
xmlrpc_client *xcli;
|
||||
String url;
|
||||
|
||||
BugzillaErrorCallback cb;
|
||||
void *cb_data;
|
||||
};
|
||||
|
||||
BugzillaData *bugzilla_new(const char *u) {
|
||||
BugzillaData *bugzilla_new(const char *url, BugzillaErrorCallback cb, void *cb_data) {
|
||||
BugzillaData *data = new BugzillaData;
|
||||
bugzilla_set_error_callback(data, cb, cb_data);
|
||||
|
||||
xmlrpc_env_init(&data->xenv);
|
||||
xmlrpc_client_setup_global_const(&data->xenv);
|
||||
data->url = u;
|
||||
data->url = url;
|
||||
|
||||
/*
|
||||
* to allow https connections; curl by default refuse connections without valid certificate
|
||||
|
@ -51,6 +55,7 @@ BugzillaData *bugzilla_new(const char *u) {
|
|||
xmlrpc_client_create(&data->xenv, XMLRPC_CLIENT_NO_FLAGS, "ede-bug-report", "0.1", &gparms, sizeof(gparms), &data->xcli);
|
||||
if(data->xenv.fault_occurred) {
|
||||
E_WARNING(E_STRLOC ": Unable to init xmlrpc client data (%s)\n", data->xenv.fault_string);
|
||||
if(cb) cb(data->xenv.fault_string, cb_data);
|
||||
delete data;
|
||||
data = NULL;
|
||||
}
|
||||
|
@ -68,6 +73,12 @@ void bugzilla_free(BugzillaData *data) {
|
|||
delete data;
|
||||
}
|
||||
|
||||
void bugzilla_set_error_callback(BugzillaData *data, BugzillaErrorCallback cb, void *cb_data) {
|
||||
E_ASSERT(data != NULL);
|
||||
data->cb = cb;
|
||||
data->cb_data = cb_data;
|
||||
}
|
||||
|
||||
char *bugzilla_get_version(BugzillaData *data) {
|
||||
E_ASSERT(data != NULL);
|
||||
|
||||
|
@ -76,12 +87,12 @@ char *bugzilla_get_version(BugzillaData *data) {
|
|||
|
||||
if(data->xenv.fault_occurred) {
|
||||
E_WARNING(E_STRLOC ": Unable to call xmlrpc function (%s)\n", data->xenv.fault_string);
|
||||
if(data->cb) (data->cb)(data->xenv.fault_string, data->cb_data);
|
||||
return (char*)"";
|
||||
}
|
||||
|
||||
/* this value will be malloc()-ated by xmlrpc_decompose_value() and should be freeed by user */
|
||||
char *ret;
|
||||
|
||||
xmlrpc_decompose_value(&data->xenv, result, "{s:s,*}", "version", &ret);
|
||||
xmlrpc_DECREF(result);
|
||||
|
||||
|
@ -103,6 +114,7 @@ int bugzilla_login(BugzillaData *data, const char *user, const char *passwd) {
|
|||
|
||||
if(data->xenv.fault_occurred) {
|
||||
E_WARNING(E_STRLOC ": Unable to perform login function (%s)\n", data->xenv.fault_string);
|
||||
if(data->cb) (data->cb)(data->xenv.fault_string, data->cb_data);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -120,41 +132,70 @@ void bugzilla_logout(BugzillaData *data) {
|
|||
|
||||
if(data->xenv.fault_occurred) {
|
||||
E_WARNING(E_STRLOC ": Unable to call xmlrpc function (%s)\n", data->xenv.fault_string);
|
||||
if(data->cb) (data->cb)(data->xenv.fault_string, data->cb_data);
|
||||
return;
|
||||
}
|
||||
|
||||
xmlrpc_DECREF(result);
|
||||
}
|
||||
|
||||
int bugzilla_submit_bug(BugzillaData *data, const char *product,
|
||||
const char *component,
|
||||
const char *summary,
|
||||
const char *version,
|
||||
const char *description,
|
||||
const char *op_sys,
|
||||
const char *platform,
|
||||
const char *priority,
|
||||
const char *severity)
|
||||
int bugzilla_submit_bug(BugzillaData *data,
|
||||
const char *product,
|
||||
const char *component,
|
||||
const char *summary,
|
||||
const char *version,
|
||||
const char *description,
|
||||
const char *op_sys,
|
||||
const char *platform,
|
||||
const char *priority,
|
||||
const char *severity,
|
||||
const char *cc)
|
||||
{
|
||||
E_ASSERT(data != NULL);
|
||||
|
||||
int bug_id = -1;
|
||||
xmlrpc_value *result;
|
||||
|
||||
xmlrpc_client_call2f(&data->xenv, data->xcli, data->url.c_str(), "Bug.create", &result,
|
||||
"({s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s})",
|
||||
"product", product,
|
||||
"component", component,
|
||||
"summary", summary,
|
||||
"version", version,
|
||||
"description", description,
|
||||
"op_sys", op_sys,
|
||||
"platform", platform,
|
||||
"priority", priority,
|
||||
"severity", severity);
|
||||
/* if given CC, add it so bugzilla assign that email as notification receiver */
|
||||
if(cc) {
|
||||
/* as for now we only support single email address */
|
||||
xmlrpc_value *cc_array, *cc_str;
|
||||
|
||||
cc_array = xmlrpc_array_new(&data->xenv);
|
||||
cc_str = xmlrpc_string_new(&data->xenv, (const char *const)cc);
|
||||
xmlrpc_array_append_item(&data->xenv, cc_array, cc_str);
|
||||
xmlrpc_DECREF(cc_str);
|
||||
|
||||
xmlrpc_client_call2f(&data->xenv, data->xcli, data->url.c_str(), "Bug.create", &result,
|
||||
"({s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:A})",
|
||||
"product", product,
|
||||
"component", component,
|
||||
"summary", summary,
|
||||
"version", version,
|
||||
"description", description,
|
||||
"op_sys", op_sys,
|
||||
"platform", platform,
|
||||
"priority", priority,
|
||||
"severity", severity,
|
||||
"cc", cc_array);
|
||||
xmlrpc_DECREF(cc_array);
|
||||
} else {
|
||||
xmlrpc_client_call2f(&data->xenv, data->xcli, data->url.c_str(), "Bug.create", &result,
|
||||
"({s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s})",
|
||||
"product", product,
|
||||
"component", component,
|
||||
"summary", summary,
|
||||
"version", version,
|
||||
"description", description,
|
||||
"op_sys", op_sys,
|
||||
"platform", platform,
|
||||
"priority", priority,
|
||||
"severity", severity);
|
||||
}
|
||||
|
||||
if(data->xenv.fault_occurred) {
|
||||
E_WARNING(E_STRLOC ": Unable to perform submit function (%s)\n", data->xenv.fault_string);
|
||||
if(data->cb) (data->cb)(data->xenv.fault_string, data->cb_data);
|
||||
return bug_id;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,9 +14,11 @@
|
|||
#define __BUGZILLA_H__
|
||||
|
||||
struct BugzillaData;
|
||||
typedef void (*BugzillaErrorCallback)(const char *str, void *data);
|
||||
|
||||
BugzillaData *bugzilla_new(const char *url);
|
||||
BugzillaData *bugzilla_new(const char *url, BugzillaErrorCallback cb = NULL, void *data = NULL);
|
||||
void bugzilla_free(BugzillaData *data);
|
||||
void bugzilla_set_error_callback(BugzillaData *data, BugzillaErrorCallback cb, void *cb_data = NULL);
|
||||
|
||||
/* return bugzilla version or empty string if fails; returned value must be free()-ed */
|
||||
char *bugzilla_get_version(BugzillaData *data);
|
||||
|
@ -26,13 +28,15 @@ int bugzilla_login(BugzillaData *data, const char *user, const char *
|
|||
void bugzilla_logout(BugzillaData *data);
|
||||
|
||||
/* return bug id or -1 if fails */
|
||||
int bugzilla_submit_bug(BugzillaData *data, const char *product,
|
||||
const char *component,
|
||||
const char *summary,
|
||||
const char *version,
|
||||
const char *description,
|
||||
const char *op_sys,
|
||||
const char *platform,
|
||||
const char *priority,
|
||||
const char *severity);
|
||||
int bugzilla_submit_bug(BugzillaData *data,
|
||||
const char *product,
|
||||
const char *component,
|
||||
const char *summary,
|
||||
const char *version,
|
||||
const char *description,
|
||||
const char *op_sys,
|
||||
const char *platform,
|
||||
const char *priority,
|
||||
const char *severity,
|
||||
const char *cc);
|
||||
#endif
|
||||
|
|
|
@ -27,10 +27,10 @@
|
|||
#include <edelib/String.h>
|
||||
|
||||
#include "PulseProgress.h"
|
||||
#include "BugzillaSender.h"
|
||||
#include "Bugzilla.h"
|
||||
#include "BugzillaSender.h"
|
||||
|
||||
#define EDE_BUGZILLA_XMLRPC_URL "http://bugs.equinox-project.org/xmlrpc.cgi"
|
||||
#define EDE_BUGZILLA_XMLRPC_URL "http://bugs.equinox-project.org/xmlrpc.cgi"
|
||||
|
||||
/* must match to existing user */
|
||||
#define EDE_BUGZILLA_USER "ede-bugs@lists.sourceforge.net"
|
||||
|
@ -49,6 +49,7 @@ EDELIB_NS_USING(String)
|
|||
struct BugContent {
|
||||
const char *bug_title;
|
||||
const char *bug_content;
|
||||
const char *bug_sender;
|
||||
};
|
||||
|
||||
static Fl_Double_Window *win;
|
||||
|
@ -176,13 +177,13 @@ static void* thread_worker(void *d) {
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* wait some time if user decided to press 'Cancel' */
|
||||
sleep(1);
|
||||
|
||||
pthread_mutex_lock(&runner_mutex);
|
||||
should_cancel = cancel_sending;
|
||||
pthread_mutex_unlock(&runner_mutex);
|
||||
|
||||
/* allow user to cancel it */
|
||||
sleep(1);
|
||||
|
||||
if(should_cancel) {
|
||||
write_string(report_pipe[1], "CANCELED");
|
||||
goto done;
|
||||
|
@ -190,18 +191,18 @@ static void* thread_worker(void *d) {
|
|||
|
||||
write_string(report_pipe[1], _("Submitting the report..."));
|
||||
ret = bugzilla_submit_bug(bdata,
|
||||
"ede",
|
||||
"general",
|
||||
data->bug_title,
|
||||
"unspecified",
|
||||
data->bug_content,
|
||||
"All",
|
||||
"All",
|
||||
"P5",
|
||||
"normal");
|
||||
|
||||
"ede",
|
||||
"general",
|
||||
data->bug_title,
|
||||
"unspecified",
|
||||
data->bug_content,
|
||||
"All",
|
||||
"All",
|
||||
"P5",
|
||||
"normal",
|
||||
data->bug_sender);
|
||||
if(ret == -1) {
|
||||
write_string_fail(report_pipe[1], _("Unable to properly submit the data. Please try again"));
|
||||
write_string_fail(report_pipe[1], _("Unable to send the data. Either your email address is not registered on EDE Tracker or the host is temporarily down"));
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
@ -214,11 +215,11 @@ done:
|
|||
delete data;
|
||||
pthread_exit(NULL);
|
||||
|
||||
/* shutup compiler */
|
||||
/* shutup the compiler */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void perform_send(const char *title, const char *content) {
|
||||
static void perform_send(const char *title, const char *content, const char *sender) {
|
||||
pthread_t thread;
|
||||
|
||||
/*
|
||||
|
@ -228,6 +229,7 @@ static void perform_send(const char *title, const char *content) {
|
|||
BugContent *c = new BugContent;
|
||||
c->bug_title = title;
|
||||
c->bug_content = content;
|
||||
c->bug_sender = sender;
|
||||
|
||||
/* Create joinable thread. Some implementations prefer this explicitly was set. */
|
||||
pthread_attr_t attr;
|
||||
|
@ -244,33 +246,36 @@ static void perform_send(const char *title, const char *content) {
|
|||
pthread_attr_destroy(&attr);
|
||||
}
|
||||
|
||||
bool bugzilla_send_with_progress(const char *title, const char *content) {
|
||||
bool bugzilla_send_with_progress(const char *title, const char *content, const char *cc) {
|
||||
data_submitted = false;
|
||||
cancel_sending = false;
|
||||
|
||||
bdata = bugzilla_new(EDE_BUGZILLA_XMLRPC_URL);
|
||||
if(!bdata) {
|
||||
alert(_("Unable to initialize bugzilla interface!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* setup communication as soon as possible */
|
||||
if(pipe(report_pipe) != 0) {
|
||||
alert(_("Unable to initialize communication pipe"));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* prepare mutex */
|
||||
pthread_mutex_init(&runner_mutex, NULL);
|
||||
Fl_Button *cancel;
|
||||
|
||||
/* register our callback on pipe */
|
||||
Fl::add_fd(report_pipe[0], FL_READ, report_pipe_cb);
|
||||
|
||||
bdata = bugzilla_new(EDE_BUGZILLA_XMLRPC_URL);
|
||||
if(!bdata) {
|
||||
alert(_("Unable to initialize bugzilla interface!"));
|
||||
goto send_done;
|
||||
}
|
||||
|
||||
/* prepare mutex */
|
||||
pthread_mutex_init(&runner_mutex, NULL);
|
||||
|
||||
win = new Fl_Double_Window(275, 90, _("Sending report data"));
|
||||
win->begin();
|
||||
progress = new PulseProgress(10, 20, 255, 25, _("Sending report..."));
|
||||
progress->selection_color((Fl_Color)137);
|
||||
|
||||
Fl_Button *cancel = new Fl_Button(175, 55, 90, 25, _("&Cancel"));
|
||||
cancel = new Fl_Button(175, 55, 90, 25, _("&Cancel"));
|
||||
cancel->callback(cancel_cb);
|
||||
win->end();
|
||||
|
||||
|
@ -280,17 +285,18 @@ bool bugzilla_send_with_progress(const char *title, const char *content) {
|
|||
progress->label(_("Preparing data..."));
|
||||
Fl::add_timeout(PROGRESS_STEP_REFRESH, progress_timeout);
|
||||
|
||||
perform_send(title, content);
|
||||
perform_send(title, content, cc);
|
||||
|
||||
while(win->shown())
|
||||
Fl::wait();
|
||||
|
||||
pthread_mutex_destroy(&runner_mutex);
|
||||
|
||||
send_done:
|
||||
/* clear pipe callback */
|
||||
Fl::remove_fd(report_pipe[0]);
|
||||
clear_timeouts();
|
||||
|
||||
pthread_mutex_destroy(&runner_mutex);
|
||||
|
||||
close(report_pipe[0]);
|
||||
close(report_pipe[1]);
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#ifndef __BUGZILLASENDER_H__
|
||||
#define __BUGZILLASENDER_H__
|
||||
|
||||
bool bugzilla_send_with_progress(const char *title, const char *content);
|
||||
bool bugzilla_send_with_progress(const char *title,
|
||||
const char *content,
|
||||
const char *cc);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -50,16 +50,20 @@ if $(CURL_CFLAGS) || $(CURL_LIBS) {
|
|||
$(PTHREAD_CFLAGS)
|
||||
$(PTHREAD_LIBS) ;
|
||||
|
||||
MkDir $(XMLRPC_C_LIB_DIR) ;
|
||||
|
||||
# xmlrpc-c related builds
|
||||
rule XmlrpcLibrary {
|
||||
local lib = [ FDirName $(XMLRPC_C_LIB_DIR) $(<) ] ;
|
||||
local libe = $(lib:S=$(SUFLIB)) ;
|
||||
|
||||
# compile it with OPTIMFLAGS got from top Jamconfig
|
||||
ObjectCcFlags $(>) : $(XMLRPC_C_FLAGS) $(OPTIMFLAGS) ;
|
||||
StaticLibrary $(lib) : $(>) ;
|
||||
|
||||
LocalDepends $(libe) : $(XMLRPC_C_LIB_DIR) ;
|
||||
# make sure libraries are build first
|
||||
LocalDepends $(BINARY) : $(lib:S=$(SUFLIB)) ;
|
||||
LocalDepends $(BINARY) : $(libe) ;
|
||||
}
|
||||
|
||||
SEARCH_SOURCE += [ FDirName $(XMLRPC_C_SRC_PATH) src ] ;
|
||||
|
@ -99,7 +103,7 @@ if $(CURL_CFLAGS) || $(CURL_LIBS) {
|
|||
curlmulti.c
|
||||
lock_pthread.c ;
|
||||
|
||||
ObjectCcFlags $(CURL_TRANSPORT_SRC) : $(CURL_CFLAGS) ;
|
||||
ObjectCcFlags $(CURL_TRANSPORT_SRC) : $(XMLRPC_C_FLAGS) $(CURL_CFLAGS) ;
|
||||
|
||||
UTIL_SRC =
|
||||
casprintf.c
|
||||
|
|
|
@ -43,7 +43,7 @@ void PulseProgress::draw(void) {
|
|||
|
||||
draw_box(box(), x(), y(), w(), h(), color());
|
||||
|
||||
fl_clip(xoff, yoff, woff, hoff);
|
||||
fl_push_clip(xoff, yoff, woff, hoff);
|
||||
Fl_Color c = fl_color();
|
||||
fl_color(color2());
|
||||
|
||||
|
@ -63,6 +63,7 @@ void PulseProgress::draw(void) {
|
|||
fl_color(c);
|
||||
fl_pop_clip();
|
||||
|
||||
labelcolor(fl_contrast(labelcolor(), color()));
|
||||
draw_label(x() + bx, y() + by, w() - bw, h() - bh);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,8 +23,10 @@
|
|||
#include <FL/Fl_Text_Editor.H>
|
||||
#include <FL/Fl_Text_Buffer.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Check_Button.H>
|
||||
|
||||
#include <edelib/Window.h>
|
||||
#include <edelib/WindowUtils.h>
|
||||
#include <edelib/MessageBox.h>
|
||||
#include <edelib/String.h>
|
||||
#include <edelib/Regex.h>
|
||||
|
@ -41,12 +43,14 @@ EDELIB_NS_USING(String)
|
|||
EDELIB_NS_USING(Regex)
|
||||
EDELIB_NS_USING(alert)
|
||||
EDELIB_NS_USING(message)
|
||||
EDELIB_NS_USING(window_center_on_screen)
|
||||
EDELIB_NS_USING(RX_CASELESS)
|
||||
|
||||
#ifdef HAVE_CURL
|
||||
static Fl_Input *bug_title_input;
|
||||
static Fl_Input *email_input;
|
||||
static Fl_Text_Buffer *text_buf;
|
||||
static Fl_Check_Button *notify_reporter;
|
||||
|
||||
/* check if string has spaces */
|
||||
static bool empty_entry(const char *en) {
|
||||
|
@ -65,7 +69,7 @@ static bool valid_email(const char *e) {
|
|||
Regex r;
|
||||
|
||||
/* regex stolen from http://www.regular-expressions.info/email.html */
|
||||
if(!r.compile("\\b[A-Z0-9._%-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}\\b", RX_CASELESS)) {
|
||||
if(!r.compile("^\\b[A-Z0-9._%-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}\\b$", RX_CASELESS)) {
|
||||
E_WARNING(E_STRLOC ": Unable to properly compile regex pattern");
|
||||
return false;
|
||||
}
|
||||
|
@ -79,8 +83,8 @@ static void close_cb(Fl_Widget*, void *w) {
|
|||
}
|
||||
|
||||
static void send_cb(Fl_Widget*, void *w) {
|
||||
const char *txt;
|
||||
String title, content;
|
||||
const char *txt, *cc = NULL;
|
||||
String title, content;
|
||||
|
||||
if(empty_entry(bug_title_input->value())) {
|
||||
alert(_("Report title is missing"));
|
||||
|
@ -100,7 +104,7 @@ static void send_cb(Fl_Widget*, void *w) {
|
|||
}
|
||||
|
||||
if(!valid_email(email_input->value())) {
|
||||
alert(_("Email address is invalid. Please use the valid email address"));
|
||||
alert(_("Email address is invalid. Please use the valid email address so developers can contact you in case more details are needed"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -124,7 +128,10 @@ static void send_cb(Fl_Widget*, void *w) {
|
|||
|
||||
free((void *) txt);
|
||||
|
||||
if(bugzilla_send_with_progress(title.c_str(), content.c_str()))
|
||||
if(notify_reporter->value())
|
||||
cc = email_input->value();
|
||||
|
||||
if(bugzilla_send_with_progress(title.c_str(), content.c_str(), cc))
|
||||
close_cb(0, w);
|
||||
}
|
||||
#endif /* HAVE_CURL */
|
||||
|
@ -156,7 +163,7 @@ int main(int argc, char** argv) {
|
|||
|
||||
Fl_Box *description_box = new Fl_Box(80, 45, 390, 95, _("To help us to improve the future EDE versions, "
|
||||
"please describe the problem with much details as possible.\n\nNote: valid email address is required, so "
|
||||
"developers could contact you for more informations if necessary."));
|
||||
"developers can contact you for more informations if necessary."));
|
||||
|
||||
description_box->align(133|FL_ALIGN_INSIDE);
|
||||
|
||||
|
@ -182,6 +189,10 @@ int main(int argc, char** argv) {
|
|||
E_WARNING(E_STRLOC ": Unable to read '%s' as debugger output. Continuing...\n");
|
||||
}
|
||||
|
||||
notify_reporter = new Fl_Check_Button(10, 330, 265, 25, _("Receive notifications"));
|
||||
notify_reporter->tooltip(_("Receive notifications when developers updates or comments this issue. You have to create EDE Bugzilla account first to get notifications."));
|
||||
notify_reporter->down_box(FL_DOWN_BOX);
|
||||
|
||||
/* resizable box */
|
||||
Fl_Box *rbox = new Fl_Box(180, 273, 55, 37);
|
||||
|
||||
|
@ -193,8 +204,9 @@ int main(int argc, char** argv) {
|
|||
|
||||
Fl_Group::current()->resizable(rbox);
|
||||
win->window_icon(bug_xpm);
|
||||
/* win->show(argc, argv); */
|
||||
win->show();
|
||||
|
||||
window_center_on_screen(win);
|
||||
win->show(argc, argv);
|
||||
return Fl::run();
|
||||
#endif /* HAVE_CURL */
|
||||
}
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
# data file for the Fltk User Interface Designer (fluid)
|
||||
version 1.0108
|
||||
version 1.0300
|
||||
header_name {.h}
|
||||
code_name {.cxx}
|
||||
Function {} {open
|
||||
} {
|
||||
Fl_Window {} {
|
||||
label {EDE Bug Reporting Tool} open
|
||||
xywh {357 193 480 365} type Double resizable visible
|
||||
xywh {353 189 480 365} type Double resizable visible
|
||||
} {
|
||||
Fl_Box {} {
|
||||
image {../icons/bug.png} xywh {10 10 60 59}
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {EDE Bug Reporting Tool}
|
||||
xywh {80 10 390 30} labelfont 1 labelsize 14 align 20
|
||||
xywh {80 10 390 30} labelfont 1 align 20
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {To help us to improve the future EDE versions, please describe the problem with much details as possible.
|
||||
|
||||
Note: valid email address is required, so developers could contact you for more informations if necessary.}
|
||||
Note: valid email address is required, so developers can contact you for more informations if necessary.}
|
||||
xywh {80 45 390 95} align 149
|
||||
}
|
||||
Fl_Input {} {
|
||||
|
@ -33,6 +33,10 @@ Note: valid email address is required, so developers could contact you for more
|
|||
label {Detail description of the problem:}
|
||||
xywh {10 215 460 105} align 5
|
||||
}
|
||||
Fl_Check_Button {} {
|
||||
label {Receive notifications} selected
|
||||
tooltip {Receive notifications when developers updates or comments this issue} xywh {10 330 265 25} down_box DOWN_BOX
|
||||
}
|
||||
Fl_Button {} {
|
||||
label {&Send}
|
||||
xywh {285 330 90 25}
|
||||
|
@ -41,8 +45,8 @@ Note: valid email address is required, so developers could contact you for more
|
|||
label {&Cancel}
|
||||
xywh {380 330 90 25}
|
||||
}
|
||||
Fl_Box {} {selected
|
||||
xywh {180 273 55 37} labelsize 14 resizable
|
||||
Fl_Box {} {
|
||||
xywh {180 273 55 37} resizable
|
||||
code0 {/* resizable box */}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ void
|
|||
xmlrpc_set_fault_formatted_v(xmlrpc_env * const envP,
|
||||
int const code,
|
||||
const char * const format,
|
||||
va_list const args) {
|
||||
va_list args) {
|
||||
|
||||
const char * faultDescription;
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#define _XOPEN_SOURCE 600 /* Get pselect() in <sys/select.h> */
|
||||
#if !defined(__SVR4) && !defined(__svr4__)
|
||||
# define _XOPEN_SOURCE 600 /* Get pselect() in <sys/select.h> */
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock.h>
|
||||
|
@ -7,13 +9,14 @@
|
|||
in others, from <sys/select.h>, and other from both. Including both
|
||||
in this order appears to work on all.
|
||||
*/
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "xmlrpc_config.h"
|
||||
|
||||
#include "xmlrpc-c/select_int.h"
|
||||
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ extern const char * const xmlrpc_strsol;
|
|||
void
|
||||
xmlrpc_vasprintf(const char ** const retvalP,
|
||||
const char * const fmt,
|
||||
va_list varargs);
|
||||
va_list varargs);
|
||||
|
||||
void GNU_PRINTF_ATTR(2,3)
|
||||
xmlrpc_asprintf(const char ** const retvalP, const char * const fmt, ...);
|
||||
|
|
|
@ -140,7 +140,7 @@ void
|
|||
xmlrpc_set_fault_formatted_v(xmlrpc_env * const envP,
|
||||
int const code,
|
||||
const char * const format,
|
||||
va_list const args);
|
||||
va_list args);
|
||||
|
||||
/* The same as the above, but using a printf-style format string. */
|
||||
void
|
||||
|
|
|
@ -29,8 +29,9 @@
|
|||
/* We hope to replace xmlrpc_amconfig.h some day with something that
|
||||
doesn't require a whole special set of software to build, to make
|
||||
Xmlrpc-c approachable by dumber developers.
|
||||
*/
|
||||
|
||||
#include "xmlrpc_amconfig.h"
|
||||
*/
|
||||
|
||||
/* EDE top config file */
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
|
|
@ -14,11 +14,12 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/utsname.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
|
@ -26,6 +27,7 @@
|
|||
#include <FL/Fl_Text_Display.H>
|
||||
#include <FL/Fl_Text_Buffer.H>
|
||||
#include <FL/Fl_File_Chooser.H>
|
||||
#include <FL/x.H>
|
||||
|
||||
#include <edelib/Nls.h>
|
||||
#include <edelib/Window.h>
|
||||
|
@ -44,6 +46,12 @@
|
|||
#define WIN_H_NORMAL 130
|
||||
#define WIN_H_EXPANDED 340
|
||||
|
||||
/* two levels of expansion to expand values and then to stringfy them */
|
||||
#define BUILD_VERSION_STR(maj, min, patch) STRINGFY(maj) "." STRINGFY(min) "." STRINGFY(patch)
|
||||
#define STRINGFY(s) #s
|
||||
|
||||
#define FLTK_VERSION BUILD_VERSION_STR(FL_MAJOR_VERSION, FL_MINOR_VERSION, FL_PATCH_VERSION)
|
||||
|
||||
EDELIB_NS_USING(String)
|
||||
EDELIB_NS_USING(TempFile)
|
||||
EDELIB_NS_USING(alert)
|
||||
|
@ -65,8 +73,7 @@ static void close_cb(Fl_Widget*, void*) {
|
|||
|
||||
static void save_as_cb(Fl_Widget*, void*) {
|
||||
const char *p = fl_file_chooser(_("Save details to..."), "Text Files (*.txt)\tAll Files(*)", "dump.txt");
|
||||
if(!p)
|
||||
return;
|
||||
if(!p) return;
|
||||
|
||||
/* so we can have EOL */
|
||||
txt_buf->append("\n");
|
||||
|
@ -77,14 +84,19 @@ static void save_as_cb(Fl_Widget*, void*) {
|
|||
|
||||
static void write_host_info(void) {
|
||||
txt_buf->append("---------- short summary ----------\n");
|
||||
|
||||
/* make first X version */
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf), "\nX version: %s %i %i.%i", XServerVendor(fl_display), XVendorRelease(fl_display), XProtocolVersion(fl_display), XProtocolRevision(fl_display));
|
||||
txt_buf->append(buf);
|
||||
|
||||
txt_buf->append("\nFLTK version: " FLTK_VERSION);
|
||||
txt_buf->append("\nEDE version: " PACKAGE_VERSION);
|
||||
txt_buf->append("\nedelib version: " EDELIB_VERSION);
|
||||
|
||||
struct utsname ut;
|
||||
if(uname(&ut) == 0) {
|
||||
char buf[1024];
|
||||
snprintf(buf, sizeof(buf), "%s %s %s %s %s", ut.sysname, ut.nodename, ut.release, ut.version, ut.machine);
|
||||
|
||||
txt_buf->append("\nSystem info: ");
|
||||
txt_buf->append(buf);
|
||||
}
|
||||
|
@ -125,7 +137,11 @@ static void collect_info_once(void) {
|
|||
TempFile tmp;
|
||||
tmp.set_auto_delete(true);
|
||||
|
||||
if(gdb_output_generate(pdetails->path, tmp))
|
||||
int pid = -1;
|
||||
if(pdetails->pid)
|
||||
pid = atoi(pdetails->pid);
|
||||
|
||||
if(gdb_output_generate(pdetails->path, tmp, pid))
|
||||
txt_buf->appendfile(tmp.name());
|
||||
|
||||
info_was_collected = true;
|
||||
|
@ -166,7 +182,6 @@ static void report_cb(Fl_Widget*, void*) {
|
|||
|
||||
/* close it since we need the file name */
|
||||
tmp.close();
|
||||
|
||||
txt_buf->savefile(tmp.name());
|
||||
|
||||
run_async("%s --gdb-dump %s", bug_tool.c_str(), tmp.name());
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include "GdbOutput.h"
|
||||
|
||||
/* assume core is placed in current directory */
|
||||
#define CORE_FILE "core"
|
||||
|
||||
EDELIB_NS_USING(String)
|
||||
|
@ -37,7 +36,7 @@ static int write_str(int fd, const char *str) {
|
|||
return ::write(fd, str, len);
|
||||
}
|
||||
|
||||
bool gdb_output_generate(const char *path, TempFile &t) {
|
||||
bool gdb_output_generate(const char *path, TempFile &t, int pid) {
|
||||
E_RETURN_VAL_IF_FAIL(path != NULL, false);
|
||||
|
||||
int tfd = -1;
|
||||
|
@ -71,18 +70,37 @@ bool gdb_output_generate(const char *path, TempFile &t) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if(!file_test(CORE_FILE, FILE_TEST_IS_REGULAR)) {
|
||||
write_str(tfd, "Unable to find '"CORE_FILE"'. Backtrace will not be done.");
|
||||
/*
|
||||
* to find core file, we will try these strategies: first try to open 'core.PID' if
|
||||
* we got PID (default on linux); if does not exists, try to open 'core'; everything is
|
||||
* assumed current folder, whatever it was set
|
||||
*/
|
||||
bool core_found = false;
|
||||
String core_path;
|
||||
if(pid > -1) {
|
||||
core_path.printf("%s.%i", CORE_FILE, pid);
|
||||
if(file_test(core_path.c_str(), FILE_TEST_IS_REGULAR))
|
||||
core_found = true;
|
||||
}
|
||||
|
||||
if(!core_found) {
|
||||
core_path = CORE_FILE;
|
||||
if(file_test(core_path.c_str(), FILE_TEST_IS_REGULAR))
|
||||
core_found = true;
|
||||
}
|
||||
|
||||
if(!core_found) {
|
||||
write_str(tfd, "Unable to find core file. Backtrace will not be done.");
|
||||
/* see it as valid, so dialog could be shown */
|
||||
return true;
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
pid_t gdb_pid = fork();
|
||||
|
||||
if(pid == -1) {
|
||||
if(gdb_pid == -1) {
|
||||
E_WARNING(E_STRLOC ": Unable to fork the process\n");
|
||||
return false;
|
||||
} else if(pid == 0) {
|
||||
} else if(gdb_pid == 0) {
|
||||
/* child; redirect to the file */
|
||||
dup2(tfd, 1);
|
||||
t.close();
|
||||
|
@ -96,7 +114,7 @@ bool gdb_output_generate(const char *path, TempFile &t) {
|
|||
argv[3] = (char*)"-x";
|
||||
argv[4] = (char*)scr.name();
|
||||
argv[5] = (char*)path;
|
||||
argv[6] = (char*)CORE_FILE;
|
||||
argv[6] = (char*)core_path.c_str();
|
||||
argv[7] = 0;
|
||||
|
||||
execvp(argv[0], argv);
|
||||
|
@ -104,12 +122,12 @@ bool gdb_output_generate(const char *path, TempFile &t) {
|
|||
} else {
|
||||
int status;
|
||||
|
||||
if(waitpid(pid, &status, 0) != pid) {
|
||||
if(waitpid(gdb_pid, &status, 0) != gdb_pid) {
|
||||
E_WARNING(E_STRLOC ": Failed to execute waitpid() properly\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
file_remove(CORE_FILE);
|
||||
file_remove(core_path.c_str());
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
#ifndef __GDBOUTPUT_H__
|
||||
#define __GDBOUTPUT_H__
|
||||
|
||||
bool gdb_output_generate(const char *path, edelib::TempFile &t);
|
||||
bool gdb_output_generate(const char *path, edelib::TempFile &t, int pid = -1);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Desktop configuration tool
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2007-2008 EDE Authors.
|
||||
* Copyright (c) 2007-2014 EDE Authors.
|
||||
*
|
||||
* This program is licensed under terms of the
|
||||
* GNU General Public License version 2 or newer.
|
||||
|
@ -29,7 +29,6 @@
|
|||
#include <FL/Fl_Color_Chooser.H>
|
||||
#include <FL/Fl_File_Chooser.H>
|
||||
#include <FL/Fl_Shared_Image.H>
|
||||
#include <FL/Fl_Tiled_Image.H>
|
||||
#include <FL/Fl_Menu_Button.H>
|
||||
#include <FL/x.H>
|
||||
|
||||
|
@ -43,6 +42,9 @@
|
|||
#include <edelib/Directory.h>
|
||||
#include <edelib/ForeignCallback.h>
|
||||
#include <edelib/Ede.h>
|
||||
#include <edelib/Netwm.h>
|
||||
|
||||
EDELIB_NS_USING(netwm_workarea_get_size)
|
||||
|
||||
#define EDE_DESKTOP_CONFIG "ede-desktop"
|
||||
|
||||
|
@ -53,7 +55,7 @@ Fl_Menu_Item mode_menu[] = {
|
|||
{0}
|
||||
};
|
||||
|
||||
// make sure this part matches array positions in mode_menu[]
|
||||
/* make sure this part matches array positions in mode_menu[] */
|
||||
#define IMG_CENTER 0
|
||||
#define IMG_STRETCH 1
|
||||
#define IMG_TILE 2
|
||||
|
@ -79,7 +81,79 @@ Fl_Input* icon_font_txt;
|
|||
|
||||
Fl_Check_Button* engage_with_one_click;
|
||||
|
||||
void set_wallpaper(const char* path) {
|
||||
#define PIXEL_POS(x, y, w, d) ((((y) * (w)) + (x)) * (d))
|
||||
|
||||
/* TODO: the same function exists in ede-desktop: move this to edelib */
|
||||
static Fl_RGB_Image* create_tile(Fl_Image *orig, int X, int Y, int W, int H) {
|
||||
/* don't tile large image */
|
||||
if(orig->w() >= W && orig->h() >= H)
|
||||
return (Fl_RGB_Image*)orig;
|
||||
|
||||
int iw = orig->w();
|
||||
int ih = orig->h();
|
||||
int idepth = orig->d();
|
||||
int tx = X - (X % iw);
|
||||
int ty = Y - (Y % ih);
|
||||
int tw = W + tx;
|
||||
int th = H + ty;
|
||||
|
||||
unsigned char* dest = new unsigned char[tw * th * orig->d()];
|
||||
unsigned char* destptr = dest;
|
||||
unsigned char* src = (unsigned char*)orig->data()[0];
|
||||
int ppos = 0;
|
||||
/* for bounds checks */
|
||||
int imax = iw * ih * idepth;
|
||||
|
||||
if(idepth == 3 || idepth == 4) {
|
||||
for(int j = 0, cj = 0; j < th; j++, cj++) {
|
||||
if(cj > ih) cj = 0;
|
||||
|
||||
for(int i = 0, ci = 0; i < tw; i++, ci++) {
|
||||
if(ci > iw) ci = 0;
|
||||
ppos = PIXEL_POS(ci, cj, iw, idepth);
|
||||
if(ppos > imax) ppos = imax;
|
||||
|
||||
*destptr++ = src[ppos];
|
||||
*destptr++ = src[ppos + 1];
|
||||
*destptr++ = src[ppos + 2];
|
||||
|
||||
if(idepth == 4)
|
||||
*destptr++ = src[ppos + 3];
|
||||
}
|
||||
}
|
||||
} else if(idepth == 2) {
|
||||
for(int j = 0, cj = 0; j < th; j++, cj++) {
|
||||
if(cj > ih) cj = 0;
|
||||
|
||||
for(int i = 0, ci = 0; i < tw; i++, ci++) {
|
||||
if(ci > iw) ci = 0;
|
||||
ppos = PIXEL_POS(ci, cj, iw, idepth);
|
||||
if(ppos > imax) ppos = imax;
|
||||
|
||||
*destptr++ = src[ppos];
|
||||
*destptr++ = src[ppos + 1];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(int j = 0, cj = 0; j < th; j++, cj++) {
|
||||
if(cj > ih) cj = 0;
|
||||
|
||||
for(int i = 0, ci = 0; i < tw; i++, ci++) {
|
||||
if(ci > iw) ci = 0;
|
||||
ppos = PIXEL_POS(ci, cj, iw, idepth);
|
||||
if(ppos > imax) ppos = imax;
|
||||
|
||||
*destptr++ = src[ppos];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Fl_RGB_Image* c = new Fl_RGB_Image(dest, tw, th, idepth, orig->ld());
|
||||
c->alloc_array = 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
static void set_wallpaper(const char* path) {
|
||||
if(!path)
|
||||
return;
|
||||
|
||||
|
@ -101,19 +175,12 @@ void set_wallpaper(const char* path) {
|
|||
* Before doing anything with the image, first scale it relative to wallpaper box,
|
||||
* which is relative to the screen sizes.
|
||||
*/
|
||||
int display_w = DisplayWidth(fl_display, fl_screen);
|
||||
int display_h = DisplayHeight(fl_display, fl_screen);
|
||||
int scale_w_factor, scale_h_factor;
|
||||
int X, Y, W, H;
|
||||
if(!netwm_workarea_get_size(X, Y, W, H))
|
||||
Fl::screen_xywh(X, Y, W, H);
|
||||
|
||||
if(display_w > area_w)
|
||||
scale_w_factor = display_w / area_w;
|
||||
else
|
||||
scale_w_factor = 1;
|
||||
|
||||
if(display_h > area_h)
|
||||
scale_h_factor = display_h / area_h;
|
||||
else
|
||||
scale_h_factor = 1;
|
||||
int scale_w_factor = (W > area_w) ? W / area_w : 1;
|
||||
int scale_h_factor = (H > area_h) ? H / area_h : 1;
|
||||
|
||||
Fl_Image* rel_img = img->copy(img->w() / scale_w_factor, img->h() / scale_h_factor);
|
||||
|
||||
|
@ -134,9 +201,8 @@ void set_wallpaper(const char* path) {
|
|||
}
|
||||
|
||||
case IMG_TILE: {
|
||||
Fl_Tiled_Image* tiled = new Fl_Tiled_Image(rel_img, area_w, area_h);
|
||||
wallpaper_img->size(area_w, area_h);
|
||||
wallpaper_img->image(tiled);
|
||||
wallpaper_img->image(create_tile(rel_img, 0, 0, area_w, area_h));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -168,7 +234,7 @@ void set_wallpaper(const char* path) {
|
|||
}
|
||||
}
|
||||
|
||||
void disable_wallpaper(bool doit) {
|
||||
static void disable_wallpaper(bool doit) {
|
||||
if(doit) {
|
||||
desk_use_wallpaper->value(0);
|
||||
desk_background_mode->deactivate();
|
||||
|
@ -191,17 +257,12 @@ void disable_wallpaper(bool doit) {
|
|||
wallpaper->redraw();
|
||||
}
|
||||
|
||||
void set_rgb_color(Fl_Button* btn, unsigned char r, unsigned char g, unsigned char b) {
|
||||
Fl_Color c = (Fl_Color)edelib::color_rgb_to_fltk(r, g, b);
|
||||
btn->color(c);
|
||||
}
|
||||
|
||||
void close_cb(Fl_Widget*, void* w) {
|
||||
static void close_cb(Fl_Widget*, void* w) {
|
||||
edelib::Window* win = (edelib::Window*)w;
|
||||
win->hide();
|
||||
}
|
||||
|
||||
void color_cb(Fl_Widget* btn, void*) {
|
||||
static void color_cb(Fl_Widget* btn, void*) {
|
||||
unsigned char r, g, b;
|
||||
|
||||
edelib::color_fltk_to_rgb(btn->color(), r, g, b);
|
||||
|
@ -212,7 +273,7 @@ void color_cb(Fl_Widget* btn, void*) {
|
|||
}
|
||||
}
|
||||
|
||||
void wallpaper_color_cb(Fl_Widget*, void* w) {
|
||||
static void wallpaper_color_cb(Fl_Widget*, void* w) {
|
||||
unsigned char r, g, b;
|
||||
|
||||
edelib::color_fltk_to_rgb(desk_background_color->color(), r, g, b);
|
||||
|
@ -227,7 +288,7 @@ void wallpaper_color_cb(Fl_Widget*, void* w) {
|
|||
}
|
||||
}
|
||||
|
||||
void browse_cb(Fl_Widget*, void*) {
|
||||
static void browse_cb(Fl_Widget*, void*) {
|
||||
char* ret = fl_file_chooser(_("Background image"), "*.jpg\t*.png", desk_background->value());
|
||||
if(!ret)
|
||||
return;
|
||||
|
@ -237,7 +298,7 @@ void browse_cb(Fl_Widget*, void*) {
|
|||
wallpaper->redraw();
|
||||
}
|
||||
|
||||
void wallpaper_use_cb(Fl_Widget*, void*) {
|
||||
static void wallpaper_use_cb(Fl_Widget*, void*) {
|
||||
if(desk_use_wallpaper->value()) {
|
||||
disable_wallpaper(false);
|
||||
set_wallpaper(desk_background->value());
|
||||
|
@ -245,13 +306,13 @@ void wallpaper_use_cb(Fl_Widget*, void*) {
|
|||
disable_wallpaper(true);
|
||||
}
|
||||
|
||||
void choice_cb(Fl_Widget*, void*) {
|
||||
static void choice_cb(Fl_Widget*, void*) {
|
||||
set_wallpaper(desk_background->value());
|
||||
wallpaper_img->redraw();
|
||||
wallpaper->redraw();
|
||||
}
|
||||
|
||||
void apply_cb(Fl_Widget*, void* w) {
|
||||
static void apply_cb(Fl_Widget*, void* w) {
|
||||
edelib::Resource conf;
|
||||
conf.set("Desktop", "color", (int)desk_background_color->color());
|
||||
conf.set("Desktop", "wallpaper_use", desk_use_wallpaper->value());
|
||||
|
@ -273,7 +334,7 @@ void apply_cb(Fl_Widget*, void* w) {
|
|||
edelib::foreign_callback_call("ede-desktop");
|
||||
}
|
||||
|
||||
void ok_cb(Fl_Widget*, void* w) {
|
||||
static void ok_cb(Fl_Widget*, void* w) {
|
||||
edelib::Window* win = (edelib::Window*)w;
|
||||
apply_cb(0, win);
|
||||
/* a hack so ede-desktop-conf can send a message before it was closed */
|
||||
|
@ -281,7 +342,7 @@ void ok_cb(Fl_Widget*, void* w) {
|
|||
win->hide();
|
||||
}
|
||||
|
||||
void browse_fonts_cb(Fl_Widget*, void* w) {
|
||||
static void browse_fonts_cb(Fl_Widget*, void* w) {
|
||||
Fl_Input* in = (Fl_Input*)w;
|
||||
int retsz;
|
||||
const char* font_name = Fl::get_font_name((Fl_Font)icon_font, 0);
|
||||
|
@ -296,7 +357,7 @@ void browse_fonts_cb(Fl_Widget*, void* w) {
|
|||
icon_font_size = retsz;
|
||||
}
|
||||
|
||||
void load_settings(void) {
|
||||
static void load_settings(void) {
|
||||
int b_mode = 0;
|
||||
bool d_wp_use = false;
|
||||
int d_background_color = fl_rgb_color(73, 64, 102); /* keep it in sync with default color in ede-desktop */
|
||||
|
@ -376,13 +437,11 @@ int main(int argc, char** argv) {
|
|||
g1->hide();
|
||||
|
||||
g1->begin();
|
||||
/*
|
||||
Fl_Box* b1 = new Fl_Box(85, 196, 100, 15);
|
||||
b1->box(FL_BORDER_BOX);
|
||||
b1->box(FL_THIN_UP_BOX);
|
||||
|
||||
Fl_Box* b2 = new Fl_Box(30, 43, 210, 158);
|
||||
b2->box(FL_THIN_UP_BOX);
|
||||
*/
|
||||
|
||||
/* box size is intentionaly odd so preserve aspect ratio */
|
||||
wallpaper = new Fl_Box(43, 53, 184, 138);
|
||||
|
|
871
ede-desktop/Desktop.cpp
Normal file
871
ede-desktop/Desktop.cpp
Normal file
|
@ -0,0 +1,871 @@
|
|||
/*
|
||||
* $Id: ede-panel.cpp 3463 2012-12-17 15:49:33Z karijes $
|
||||
*
|
||||
* Copyright (C) 2006-2013 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <edelib/Debug.h>
|
||||
#include <edelib/Netwm.h>
|
||||
#include <edelib/WindowUtils.h>
|
||||
#include <edelib/ForeignCallback.h>
|
||||
#include <edelib/MenuItem.h>
|
||||
#include <edelib/Nls.h>
|
||||
#include <edelib/StrUtil.h>
|
||||
#include <edelib/Directory.h>
|
||||
#include <edelib/Util.h>
|
||||
#include <edelib/Run.h>
|
||||
#include <edelib/MessageBox.h>
|
||||
#include <edelib/IconLoader.h>
|
||||
#include <edelib/FontCache.h>
|
||||
#include <edelib/FileTest.h>
|
||||
#include <edelib/File.h>
|
||||
|
||||
#include "Desktop.h"
|
||||
#include "DesktopIcon.h"
|
||||
#include "Wallpaper.h"
|
||||
#include "Utils.h"
|
||||
#include "IconDialog.h"
|
||||
|
||||
EDELIB_NS_USING(MenuButton)
|
||||
EDELIB_NS_USING(MenuItem)
|
||||
EDELIB_NS_USING(String)
|
||||
EDELIB_NS_USING(DesktopFile)
|
||||
EDELIB_NS_USING(IconLoader)
|
||||
EDELIB_NS_USING(window_xid_create)
|
||||
EDELIB_NS_USING(netwm_window_set_type)
|
||||
EDELIB_NS_USING(netwm_workarea_get_size)
|
||||
EDELIB_NS_USING(netwm_callback_add)
|
||||
EDELIB_NS_USING(foreign_callback_add)
|
||||
EDELIB_NS_USING(str_ends)
|
||||
EDELIB_NS_USING(dir_home)
|
||||
EDELIB_NS_USING(dir_empty)
|
||||
EDELIB_NS_USING(dir_remove)
|
||||
EDELIB_NS_USING(build_filename)
|
||||
EDELIB_NS_USING(run_async)
|
||||
EDELIB_NS_USING(input)
|
||||
EDELIB_NS_USING(alert)
|
||||
EDELIB_NS_USING(dir_create)
|
||||
EDELIB_NS_USING(file_test)
|
||||
EDELIB_NS_USING(file_remove)
|
||||
EDELIB_NS_USING(font_cache_find)
|
||||
EDELIB_NS_USING(FILE_TEST_IS_DIR)
|
||||
EDELIB_NS_USING(FILE_TEST_IS_REGULAR)
|
||||
EDELIB_NS_USING(FILE_TEST_IS_SYMLINK)
|
||||
EDELIB_NS_USING(NETWM_WINDOW_TYPE_DESKTOP)
|
||||
EDELIB_NS_USING(NETWM_CHANGED_CURRENT_WORKAREA)
|
||||
EDELIB_NS_USING(DESK_FILE_TYPE_UNKNOWN)
|
||||
EDELIB_NS_USING(ICON_SIZE_TINY)
|
||||
|
||||
#define DOT_OR_DOTDOT(base) (base[0] == '.' && (base[1] == '\0' || (base[1] == '.' && base[2] == '\0')))
|
||||
#define NOT_SELECTABLE(widget) ((widget == this) || (widget == wallpaper) || (widget == dmenu))
|
||||
|
||||
#define SELECTION_SINGLE (Fl::event_button() == 1)
|
||||
#define SELECTION_MULTI (Fl::event_button() == 1 && (Fl::event_key(FL_Shift_L) || Fl::event_key(FL_Shift_R)))
|
||||
|
||||
#undef MIN
|
||||
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
||||
#undef MAX
|
||||
#define MAX(x,y) ((x) > (y) ? (x) : (y))
|
||||
|
||||
#define ICONS_POS_FILE "ede-desktop-icons"
|
||||
|
||||
static void background_conf_cb(Fl_Widget*, void*);
|
||||
static void icons_conf_cb(Fl_Widget*, void*);
|
||||
static void folder_create_cb(Fl_Widget*, void*);
|
||||
static void launcher_create_cb(Fl_Widget*, void*);
|
||||
static void arrange_icons_cb(Fl_Widget*, void*);
|
||||
|
||||
struct SelectionOverlay {
|
||||
int x, y, w, h;
|
||||
bool show;
|
||||
SelectionOverlay() : x(0), y(0), w(0), h(0), show(false) { }
|
||||
};
|
||||
|
||||
static MenuItem desktop_menu[] = {
|
||||
{_("Create &launcher..."), 0, launcher_create_cb},
|
||||
{_("Create &folder..."), 0, folder_create_cb, 0, FL_MENU_DIVIDER},
|
||||
{_("A&rrange icons"), 0, arrange_icons_cb, 0, FL_MENU_DIVIDER},
|
||||
{_("&Icons settings..."), 0, icons_conf_cb, 0},
|
||||
{_("&Background..."), 0, background_conf_cb, 0},
|
||||
{0}
|
||||
};
|
||||
|
||||
inline bool intersects(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) {
|
||||
return (MAX(x1, x2) <= MIN(w1, w2) &&
|
||||
MAX(y1, y2) <= MIN(h1, h2));
|
||||
}
|
||||
|
||||
static void make_me_desktop(Fl_Window *win) {
|
||||
netwm_window_set_type(fl_xid(win), NETWM_WINDOW_TYPE_DESKTOP);
|
||||
}
|
||||
|
||||
static void settings_changed_cb(Fl_Window *win, void *data) {
|
||||
Desktop *d = (Desktop*)win;
|
||||
d->read_config();
|
||||
}
|
||||
|
||||
static void desktop_message_handler(int action, Window xid, void *data) {
|
||||
Desktop *d = (Desktop*)data;
|
||||
|
||||
switch(action) {
|
||||
case NETWM_CHANGED_CURRENT_WORKAREA:
|
||||
d->update_workarea();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void background_conf_cb(Fl_Widget*, void*) {
|
||||
run_async("ede-launch ede-desktop-conf");
|
||||
}
|
||||
|
||||
static void icons_conf_cb(Fl_Widget*, void*) {
|
||||
run_async("ede-launch ede-desktop-conf --icons");
|
||||
}
|
||||
|
||||
static void launcher_create_cb(Fl_Widget*, void* d) {
|
||||
Desktop *self = (Desktop*)d;
|
||||
icon_dialog_icon_create(self);
|
||||
}
|
||||
|
||||
static void arrange_icons_cb(Fl_Widget*, void *d) {
|
||||
E_RETURN_IF_FAIL(d != NULL);
|
||||
|
||||
Desktop *self = (Desktop*)d;
|
||||
self->arrange_icons();
|
||||
self->redraw();
|
||||
}
|
||||
|
||||
static void folder_create_cb(Fl_Widget*, void *d) {
|
||||
E_RETURN_IF_FAIL(d != NULL);
|
||||
|
||||
const char *n = input(_("Create a new folder with the name"));
|
||||
if(!n) return;
|
||||
|
||||
Desktop *self = (Desktop*)d;
|
||||
self->create_folder(n);
|
||||
}
|
||||
|
||||
Desktop::Desktop() : EDE_DESKTOP_WINDOW(0, 0, 100, 100, EDE_DESKTOP_APP) {
|
||||
end();
|
||||
|
||||
/* use nice darker blue color as default for background */
|
||||
color(fl_rgb_color(73, 64, 102));
|
||||
|
||||
conf = NULL;
|
||||
selbox = new SelectionOverlay;
|
||||
icon_opts = NULL;
|
||||
|
||||
wallpaper = NULL;
|
||||
dmenu = NULL;
|
||||
|
||||
selection_x = selection_y = 0;
|
||||
last_px = last_py = -1;
|
||||
|
||||
moving = false;
|
||||
|
||||
/*
|
||||
* first update workarea _then_ read configuration, as it will have correct size for
|
||||
* wallpaper which will prevent wallpaper load and scalle image twice
|
||||
*/
|
||||
update_workarea();
|
||||
read_config();
|
||||
read_desktop_folder(desktop_path());
|
||||
|
||||
foreign_callback_add(this, EDE_DESKTOP_APP, settings_changed_cb);
|
||||
|
||||
dmenu = new MenuButton(0, 0, 500, 0);
|
||||
dmenu->menu(desktop_menu);
|
||||
desktop_menu[1].image((Fl_Image*)IconLoader::get("folder", ICON_SIZE_TINY));
|
||||
desktop_menu[0].user_data(this);
|
||||
desktop_menu[1].user_data(this);
|
||||
desktop_menu[2].user_data(this);
|
||||
add(dmenu);
|
||||
}
|
||||
|
||||
Desktop::~Desktop() {
|
||||
E_DEBUG("Desktop::~Desktop()\n");
|
||||
|
||||
delete conf;
|
||||
delete icon_opts;
|
||||
delete selbox;
|
||||
}
|
||||
|
||||
const char *Desktop::desktop_path(void) {
|
||||
if(dpath.empty())
|
||||
dpath = build_filename(dir_home().c_str(), "Desktop");
|
||||
return dpath.c_str();
|
||||
}
|
||||
|
||||
void Desktop::show(void) {
|
||||
if(shown()) {
|
||||
EDE_DESKTOP_WINDOW::show();
|
||||
return;
|
||||
}
|
||||
|
||||
window_xid_create(this, make_me_desktop);
|
||||
netwm_callback_add(desktop_message_handler, this);
|
||||
}
|
||||
|
||||
void Desktop::update_workarea(void) {
|
||||
int X, Y, W, H;
|
||||
|
||||
if(!netwm_workarea_get_size(X, Y, W, H))
|
||||
Fl::screen_xywh(X, Y, W, H);
|
||||
|
||||
update_workarea(X, Y, W, H);
|
||||
}
|
||||
|
||||
void Desktop::update_workarea(int X, int Y, int W, int H) {
|
||||
/* prevent multiple calls with the same values */
|
||||
if(X == x() && Y == y() && W == w() && H == h())
|
||||
return;
|
||||
|
||||
E_DEBUG(E_STRLOC ": resizing to %i %i %i %i (was: %i %i %i %i)\n",
|
||||
X, Y, W, H, x(), y(), w(), h());
|
||||
|
||||
/*
|
||||
* Check if wallpaper needs resizing. Sometimes, while screen size is updated
|
||||
* X11 can change x/y, but keep w/h; here, wallpaper size update is not needed.
|
||||
*/
|
||||
bool resize_wallpaper = !(W == w() && H == h());
|
||||
|
||||
resize(X, Y, W, H);
|
||||
|
||||
/* also resize wallpaper if given */
|
||||
if(wallpaper && wallpaper->visible() && resize_wallpaper) {
|
||||
E_DEBUG(E_STRLOC ": resizing wallpaper to %i %i\n", W, H);
|
||||
wallpaper->resize(0, 0, W, H);
|
||||
}
|
||||
}
|
||||
|
||||
void Desktop::read_config(void) {
|
||||
E_DEBUG(E_STRLOC ": Reading desktop config...\n");
|
||||
|
||||
if(!conf) conf = new DesktopConfig();
|
||||
conf->load(EDE_DESKTOP_APP);
|
||||
|
||||
char buf[PATH_MAX];
|
||||
bool wp_use = true;
|
||||
int bcolor;
|
||||
|
||||
if(conf->get("Desktop", "color", bcolor, color()))
|
||||
color(bcolor);
|
||||
|
||||
conf->get("Desktop", "wallpaper_use", wp_use, wp_use);
|
||||
|
||||
/* get wallpaper */
|
||||
if(wp_use) {
|
||||
if(conf->get("Desktop", "wallpaper", buf, sizeof(buf))) {
|
||||
if(!wallpaper)
|
||||
wallpaper = new Wallpaper(0, 0, w(), h());
|
||||
|
||||
int s;
|
||||
bool rootpmap_use;
|
||||
conf->get("Desktop", "wallpaper_mode", s, WALLPAPER_CENTER);
|
||||
conf->get("Desktop", "wallpaper_rootpmap", rootpmap_use, true);
|
||||
wallpaper->load(buf, s, rootpmap_use);
|
||||
|
||||
/*
|
||||
* wallpaper is another widget, but we add it to the bottom of the list
|
||||
* to preserve stacking order
|
||||
*/
|
||||
if(find(*wallpaper) == children())
|
||||
insert(*wallpaper, 0);
|
||||
|
||||
/* show it in case it got hidden before */
|
||||
wallpaper->show();
|
||||
}
|
||||
} else {
|
||||
if(wallpaper) wallpaper->hide();
|
||||
}
|
||||
|
||||
if(!icon_opts) icon_opts = new IconOptions;
|
||||
|
||||
#define ICON_CONF_GET(var) conf->get("Icons", #var, icon_opts->var, icon_opts->var)
|
||||
ICON_CONF_GET(label_background);
|
||||
ICON_CONF_GET(label_foreground);
|
||||
ICON_CONF_GET(label_maxwidth);
|
||||
ICON_CONF_GET(label_transparent);
|
||||
ICON_CONF_GET(label_visible);
|
||||
ICON_CONF_GET(one_click_exec);
|
||||
|
||||
if(ICON_CONF_GET(label_font) && ICON_CONF_GET(label_fontsize))
|
||||
E_WARNING(E_STRLOC ": 'label_font' && 'label_fontsize' are deprecated. Use 'label_fontname' with full font name and size instead (e.g 'sans 12')\n");
|
||||
|
||||
/* if found new 'label_fontname' variable, overwrite 'label_font' && 'label_fontsize' */
|
||||
if(conf->get("Icons", "label_fontname", buf, sizeof(buf))) {
|
||||
if(!font_cache_find(buf, (Fl_Font&)icon_opts->label_font, icon_opts->label_fontsize))
|
||||
E_WARNING(E_STRLOC ": Unable to find '%s' font. Using default values...\n", buf);
|
||||
}
|
||||
|
||||
icon_opts->sanitize_font();
|
||||
|
||||
/* doing this will redraw _all_ children, and they will in turn read modified 'icon_opts' */
|
||||
if(visible()) redraw();
|
||||
}
|
||||
|
||||
void Desktop::read_desktop_folder(const char *dpath) {
|
||||
E_RETURN_IF_FAIL(dpath != NULL);
|
||||
String path;
|
||||
|
||||
DIR *dir = opendir(dpath);
|
||||
E_RETURN_IF_FAIL(dir != NULL);
|
||||
|
||||
DesktopConfig pos;
|
||||
pos.load(ICONS_POS_FILE);
|
||||
|
||||
dirent *d;
|
||||
while((d = readdir(dir)) != NULL) {
|
||||
if(DOT_OR_DOTDOT(d->d_name))
|
||||
continue;
|
||||
|
||||
if(d->d_type > 0) {
|
||||
if(d->d_type != DT_REG && d->d_type != DT_LNK && d->d_type != DT_DIR)
|
||||
continue;
|
||||
|
||||
path = dpath;
|
||||
path += E_DIR_SEPARATOR;
|
||||
path += d->d_name;
|
||||
} else {
|
||||
/*
|
||||
* If we got here, it means d_type isn't set and we must do it via file_test() which could be much slower.
|
||||
* By POSIX standard, only d_name must be set, but many modern *nixes set all dirent members correctly. Except Slackware ;)
|
||||
*/
|
||||
path = dpath;
|
||||
path += E_DIR_SEPARATOR;
|
||||
path += d->d_name;
|
||||
|
||||
if(!(file_test(path.c_str(), FILE_TEST_IS_REGULAR) ||
|
||||
file_test(path.c_str(), FILE_TEST_IS_DIR) ||
|
||||
file_test(path.c_str(), FILE_TEST_IS_SYMLINK)))
|
||||
continue;
|
||||
}
|
||||
|
||||
DesktopIcon *o = read_desktop_file(path.c_str(), (const char*)d->d_name, &pos);
|
||||
if(o) add(o);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
DesktopIcon *Desktop::read_desktop_file(const char *path, const char *base, DesktopConfig *pos) {
|
||||
DesktopIcon *ret = NULL;
|
||||
|
||||
if(file_test(path, FILE_TEST_IS_DIR)) {
|
||||
ret = new DesktopIcon(_("No Name"));
|
||||
ret->set_icon_type(DESKTOP_ICON_TYPE_FOLDER);
|
||||
/* hardcoded */
|
||||
ret->set_image("folder");
|
||||
|
||||
/* copy label explicitly, as DesktopIcon() will only store a pointer */
|
||||
ret->copy_label(base);
|
||||
} else {
|
||||
/*
|
||||
* try to load it as plain .desktop file by looking only at extension
|
||||
* TODO: MimeType can be used here too
|
||||
*/
|
||||
if(!str_ends(path, EDE_DESKTOP_DESKTOP_EXT))
|
||||
return ret;
|
||||
|
||||
DesktopFile df;
|
||||
char buf[PATH_MAX];
|
||||
|
||||
E_RETURN_VAL_IF_FAIL(df.load(path), ret);
|
||||
E_RETURN_VAL_IF_FAIL(df.type() != DESK_FILE_TYPE_UNKNOWN, ret);
|
||||
|
||||
ret = new DesktopIcon(_("No Name"));
|
||||
ret->set_icon_type(DESKTOP_ICON_TYPE_NORMAL);
|
||||
|
||||
if(df.name(buf, sizeof(buf))) ret->copy_label(buf);
|
||||
ret->set_image(df.icon(buf, sizeof(buf)) ? buf : NULL);
|
||||
if(df.comment(buf, sizeof(buf))) ret->set_tooltip(buf);
|
||||
}
|
||||
|
||||
/* try to put random icon position in the middle of the desktop, so it is easier to notice */
|
||||
int X = (rand() % (w() / 4)) + (w() / 4);
|
||||
int Y = (rand() % (h() / 4)) + (h() / 4);
|
||||
|
||||
/* lookup icons locations if possible */
|
||||
if(base && pos && *pos) {
|
||||
pos->get(base, "X", X, X);
|
||||
pos->get(base, "Y", Y, Y);
|
||||
}
|
||||
|
||||
E_DEBUG("Setting icon '%s' (%i,%i)\n", base, X, Y);
|
||||
ret->position(X, Y);
|
||||
|
||||
/* use loaded icon options */
|
||||
ret->set_options(icon_opts);
|
||||
ret->set_path(path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Desktop::arrange_icons(void) {
|
||||
int lw = icon_opts ? icon_opts->label_maxwidth : 75;
|
||||
int X = (lw / 5) + 10;
|
||||
int Y = 10;
|
||||
int H = h();
|
||||
DesktopIcon *o;
|
||||
|
||||
for(int i = 0; i < children(); i++) {
|
||||
if(NOT_SELECTABLE(child(i))) continue;
|
||||
|
||||
o = (DesktopIcon*)child(i);
|
||||
o->position(X, Y);
|
||||
Y += o->h() + (o->h() / 2);
|
||||
|
||||
if(Y + (o->h() / 2) > H) {
|
||||
Y = 10;
|
||||
X += lw + (o->w() / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Desktop::remove_icon(DesktopIcon *di, bool real_delete) {
|
||||
bool ret = true;
|
||||
|
||||
if(real_delete) {
|
||||
if(di->get_icon_type() == DESKTOP_ICON_TYPE_FOLDER) {
|
||||
if(!dir_empty(di->get_path())) {
|
||||
alert(_("This folder is not empty. Recursive removal of not empty folders is not yet supported"));
|
||||
return false;
|
||||
}
|
||||
ret = dir_remove(di->get_path());
|
||||
} else {
|
||||
ret = file_remove(di->get_path());
|
||||
}
|
||||
}
|
||||
|
||||
remove(di);
|
||||
redraw();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Desktop::rename_icon(DesktopIcon *di, const char *name) {
|
||||
di->copy_label(name);
|
||||
di->update_label_font_and_size();
|
||||
di->fast_redraw();
|
||||
|
||||
/* open file and try to change the name */
|
||||
DesktopFile df;
|
||||
E_RETURN_VAL_IF_FAIL(df.load(di->get_path()) == true, false);
|
||||
|
||||
df.set_name(name);
|
||||
return df.save(di->get_path());
|
||||
}
|
||||
|
||||
void Desktop::edit_icon(DesktopIcon *di) {
|
||||
icon_dialog_icon_edit(this, di);
|
||||
}
|
||||
|
||||
bool Desktop::save_icons_positions(void) {
|
||||
DesktopConfig pos;
|
||||
DesktopIcon *o;
|
||||
char *base;
|
||||
|
||||
for(int i = 0; i < children(); i++) {
|
||||
if(NOT_SELECTABLE(child(i))) continue;
|
||||
|
||||
o = (DesktopIcon*)child(i);
|
||||
base = get_basename(o->get_path());
|
||||
pos.set(base, "X", o->x());
|
||||
pos.set(base, "Y", o->y());
|
||||
}
|
||||
|
||||
return pos.save(ICONS_POS_FILE);
|
||||
}
|
||||
|
||||
bool Desktop::create_folder(const char *name) {
|
||||
String path = desktop_path();
|
||||
path += E_DIR_SEPARATOR;
|
||||
path += name;
|
||||
|
||||
if(!dir_create(path.c_str())) {
|
||||
alert(_("Unable to create directory '%s'! Please check if directory already exists or you have enough permissions to create it"), path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
DesktopIcon *ic = read_desktop_file(path.c_str(), name);
|
||||
if(ic) {
|
||||
/* use mouse position so folder icon gets created where was clicked */
|
||||
ic->position(last_px, last_py);
|
||||
add(ic);
|
||||
redraw();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Desktop::unfocus_all(void) {
|
||||
DesktopIcon *o;
|
||||
for(int i = 0; i < children(); i++) {
|
||||
if(NOT_SELECTABLE(child(i))) continue;
|
||||
|
||||
o = (DesktopIcon*)child(i);
|
||||
o->do_unfocus();
|
||||
o->fast_redraw();
|
||||
}
|
||||
}
|
||||
|
||||
void Desktop::select(DesktopIcon *ic, bool do_redraw) {
|
||||
E_ASSERT(ic != NULL);
|
||||
|
||||
if(in_selection(ic)) return;
|
||||
selectionbuf.push_back(ic);
|
||||
|
||||
if(!ic->is_focused()) {
|
||||
ic->do_focus();
|
||||
if(do_redraw) ic->fast_redraw();
|
||||
}
|
||||
}
|
||||
|
||||
void Desktop::select_only(DesktopIcon *ic) {
|
||||
E_ASSERT(ic != NULL);
|
||||
|
||||
unfocus_all();
|
||||
selectionbuf.clear();
|
||||
selectionbuf.push_back(ic);
|
||||
|
||||
ic->do_focus();
|
||||
ic->fast_redraw();
|
||||
}
|
||||
|
||||
bool Desktop::in_selection(const DesktopIcon* ic) {
|
||||
E_ASSERT(ic != NULL);
|
||||
|
||||
if(selectionbuf.empty())
|
||||
return false;
|
||||
|
||||
for(DesktopIconListIt it = selectionbuf.begin(), ite = selectionbuf.end(); it != ite; ++it) {
|
||||
if((*it) == ic)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Desktop::move_selection(int x, int y, bool apply) {
|
||||
if(selectionbuf.empty()) return;
|
||||
|
||||
int prev_x, prev_y, tmp_x, tmp_y;
|
||||
DesktopIcon *ic;
|
||||
|
||||
for(DesktopIconListIt it = selectionbuf.begin(), ite = selectionbuf.end(); it != ite; ++it) {
|
||||
ic = (*it);
|
||||
|
||||
prev_x = ic->drag_icon_x();
|
||||
prev_y = ic->drag_icon_y();
|
||||
|
||||
tmp_x = x - selection_x;
|
||||
tmp_y = y - selection_y;
|
||||
|
||||
ic->drag(prev_x + tmp_x, prev_y + tmp_y, apply);
|
||||
}
|
||||
|
||||
selection_x = x;
|
||||
selection_y = y;
|
||||
|
||||
/*
|
||||
* move the last moved icon on the top of the stack, so it be drawn the top most; also
|
||||
* when called arrange_icons(), last moved icon will be placed last in the list
|
||||
*/
|
||||
ic = selectionbuf.back();
|
||||
insert(*ic, children());
|
||||
|
||||
if(apply) {
|
||||
redraw();
|
||||
save_icons_positions();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tries to figure out icon below mouse. It is alternative to Fl::belowmouse() since with this we hunt
|
||||
* only icons, not other childs (wallpaper, menu), which can be returned by Fl::belowmouse() and bad
|
||||
* things be hapened.
|
||||
*/
|
||||
DesktopIcon* Desktop::below_mouse(int px, int py) {
|
||||
DesktopIcon *o;
|
||||
|
||||
for(int i = 0; i < children(); i++) {
|
||||
if(NOT_SELECTABLE(child(i))) continue;
|
||||
|
||||
o = (DesktopIcon*)child(i);
|
||||
if(o->x() < px && o->y() < py && px < (o->x() + o->h()) && py < (o->y() + o->h()))
|
||||
return o;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Desktop::select_in_area(void) {
|
||||
if(!selbox->show) return;
|
||||
|
||||
int ax = selbox->x;
|
||||
int ay = selbox->y;
|
||||
int aw = selbox->w;
|
||||
int ah = selbox->h;
|
||||
|
||||
if(aw < 0) {
|
||||
ax += aw;
|
||||
aw = -aw;
|
||||
} else if(!aw)
|
||||
aw = 1;
|
||||
|
||||
if(ah < 0) {
|
||||
ay += ah;
|
||||
ah = -ah;
|
||||
} else if(!ah)
|
||||
ah = 1;
|
||||
|
||||
/*
|
||||
* XXX: This function can fail since icon coordinates are absolute (event_x_root)
|
||||
* but selbox use relative (event_root). It will work as expected if desktop is at x=0 y=0.
|
||||
* This should be checked further.
|
||||
*/
|
||||
DesktopIcon* o;
|
||||
for(int i = 0; i < children(); i++) {
|
||||
if(NOT_SELECTABLE(child(i))) continue;
|
||||
o = (DesktopIcon*)child(i);
|
||||
|
||||
if(intersects(ax, ay, ax+aw, ay+ah, o->x(), o->y(), o->w()+o->x(), o->h()+o->y())) {
|
||||
if(!o->is_focused()) {
|
||||
o->do_focus();
|
||||
/* updated from Desktop::draw() */
|
||||
o->damage(EDE_DESKTOP_DAMAGE_CHILD_LABEL);
|
||||
}
|
||||
} else {
|
||||
if(o->is_focused()) {
|
||||
o->do_unfocus();
|
||||
o->fast_redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Desktop::draw(void) {
|
||||
if(!damage()) return;
|
||||
|
||||
if(damage() & (FL_DAMAGE_ALL | FL_DAMAGE_EXPOSE)) {
|
||||
/*
|
||||
* If any overlay was previously visible during full redraw, it will not be cleared because of fast flip.
|
||||
* This will assure that does not happened.
|
||||
*/
|
||||
fl_overlay_clear();
|
||||
EDE_DESKTOP_WINDOW::draw();
|
||||
//E_DEBUG(E_STRLOC ": REDRAW ALL\n");
|
||||
}
|
||||
|
||||
if(damage() & EDE_DESKTOP_DAMAGE_OVERLAY) {
|
||||
if(selbox->show)
|
||||
fl_overlay_rect(selbox->x, selbox->y, selbox->w, selbox->h);
|
||||
else
|
||||
fl_overlay_clear();
|
||||
|
||||
/*
|
||||
* now scan all icons and see if they needs redraw, and if do
|
||||
* just update their label since it is indicator of selection
|
||||
*/
|
||||
for(int i = 0; i < children(); i++) {
|
||||
if(child(i)->damage() == EDE_DESKTOP_DAMAGE_CHILD_LABEL) {
|
||||
update_child(*child(i));
|
||||
child(i)->clear_damage();
|
||||
//E_DEBUG(E_STRLOC ": ICON REDRAW \n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clear_damage();
|
||||
}
|
||||
|
||||
int Desktop::handle(int event) {
|
||||
switch(event) {
|
||||
case FL_FOCUS:
|
||||
case FL_UNFOCUS:
|
||||
case FL_SHORTCUT:
|
||||
return 1;
|
||||
|
||||
case FL_PUSH: {
|
||||
/*
|
||||
* First check where we clicked. If we do it on desktop unfocus any possible focused childs, and handle
|
||||
* specific clicks. Otherwise, do rest for childs.
|
||||
*/
|
||||
Fl_Widget* clicked = Fl::belowmouse();
|
||||
|
||||
if(NOT_SELECTABLE(clicked)) {
|
||||
//E_DEBUG(E_STRLOC ": DESKTOP CLICK !!!\n");
|
||||
if(!selectionbuf.empty()) {
|
||||
/*
|
||||
* Only focused are in selectionbuf, so this is fine to do; also will prevent
|
||||
* full redraw when is clicked on desktop
|
||||
*/
|
||||
unfocus_all();
|
||||
selectionbuf.clear();
|
||||
}
|
||||
|
||||
/* track position so moving can be deduced */
|
||||
if(Fl::event_button() == 1) {
|
||||
selbox->x = Fl::event_x();
|
||||
selbox->y = Fl::event_y();
|
||||
} else if(Fl::event_button() == 3) {
|
||||
last_px = Fl::event_x();
|
||||
last_py = Fl::event_y();
|
||||
|
||||
damage(EDE_DESKTOP_DAMAGE_OVERLAY);
|
||||
const edelib::MenuItem* item = dmenu->menu()->popup(Fl::event_x(), Fl::event_y());
|
||||
dmenu->picked(item);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* from here, all events are managed for icons */
|
||||
DesktopIcon* tmp_icon = (DesktopIcon*)clicked;
|
||||
|
||||
/* do no use assertion on this, since fltk::belowmouse() can miss our icon */
|
||||
if(!tmp_icon) return 1;
|
||||
|
||||
if(SELECTION_MULTI) {
|
||||
Fl::event_is_click(0);
|
||||
select(tmp_icon);
|
||||
return 1;
|
||||
} else if(SELECTION_SINGLE) {
|
||||
if(!in_selection(tmp_icon)) {
|
||||
select_only(tmp_icon);
|
||||
}
|
||||
} else if(Fl::event_button() == 3) {
|
||||
select_only(tmp_icon);
|
||||
}
|
||||
|
||||
/*
|
||||
* Let child handle the rest.
|
||||
* Also prevent click on other mouse buttons during move.
|
||||
*/
|
||||
if(!moving)
|
||||
tmp_icon->handle(FL_PUSH);
|
||||
|
||||
//E_DEBUG(E_STRLOC ": FL_PUSH from desktop\n");
|
||||
selection_x = Fl::event_x_root();
|
||||
selection_y = Fl::event_y_root();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
case FL_DRAG:
|
||||
moving = true;
|
||||
if(!selectionbuf.empty()) {
|
||||
//E_DEBUG(E_STRLOC ": DRAG icon from desktop\n");
|
||||
move_selection(Fl::event_x_root(), Fl::event_y_root(), false);
|
||||
} else {
|
||||
//E_DEBUG(E_STRLOC ": DRAG from desktop\n");
|
||||
/*
|
||||
* Moving is started with pushed button.
|
||||
* From this point selection box is created and is rolled until release
|
||||
*/
|
||||
if(selbox->x != 0 || selbox->y != 0) {
|
||||
selbox->w = Fl::event_x() - selbox->x;
|
||||
selbox->h = Fl::event_y() - selbox->y;
|
||||
|
||||
selbox->show = true;
|
||||
|
||||
/* see if there some icons inside selection area */
|
||||
select_in_area();
|
||||
|
||||
/* redraw selection box */
|
||||
damage(EDE_DESKTOP_DAMAGE_OVERLAY);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
case FL_RELEASE:
|
||||
//E_DEBUG(E_STRLOC ": RELEASE from desktop\n");
|
||||
//E_DEBUG(E_STRLOC ": clicks: %i\n", Fl::event_is_click());
|
||||
|
||||
if(selbox->show) {
|
||||
selbox->x = selbox->y = selbox->w = selbox->h = 0;
|
||||
selbox->show = false;
|
||||
damage(EDE_DESKTOP_DAMAGE_OVERLAY);
|
||||
|
||||
/*
|
||||
* Now pickup those who are in is_focused() state.
|
||||
*
|
||||
* Possible flickers due overlay will be later removed when is called move_selection(), which
|
||||
* will in turn redraw icons again after position them.
|
||||
*/
|
||||
if(!selectionbuf.empty())
|
||||
selectionbuf.clear();
|
||||
|
||||
DesktopIcon *o;
|
||||
for(int i = 0; i < children(); i++) {
|
||||
if(NOT_SELECTABLE(child(i))) continue;
|
||||
|
||||
o = (DesktopIcon*)child(i);
|
||||
if(o->is_focused())
|
||||
select(o, false);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!selectionbuf.empty() && moving)
|
||||
move_selection(Fl::event_x_root(), Fl::event_y_root(), true);
|
||||
|
||||
/*
|
||||
* Do not send FL_RELEASE during move
|
||||
* TODO: should be alowed FL_RELEASE to multiple icons? (aka. run command for all selected icons)?
|
||||
*/
|
||||
if(selectionbuf.size() == 1 && !moving)
|
||||
selectionbuf.front()->handle(FL_RELEASE);
|
||||
|
||||
moving = false;
|
||||
return 1;
|
||||
|
||||
case FL_DND_ENTER:
|
||||
case FL_DND_DRAG:
|
||||
case FL_DND_LEAVE:
|
||||
return 1;
|
||||
|
||||
case FL_DND_RELEASE: {
|
||||
DesktopIcon* di = below_mouse(Fl::event_x(), Fl::event_y());
|
||||
if(di) return di->handle(event);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case FL_PASTE: {
|
||||
DesktopIcon* di = below_mouse(Fl::event_x(), Fl::event_y());
|
||||
if(di) return di->handle(event);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case FL_ENTER:
|
||||
case FL_LEAVE:
|
||||
case FL_MOVE:
|
||||
return EDE_DESKTOP_WINDOW::handle(event);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
101
ede-desktop/Desktop.h
Normal file
101
ede-desktop/Desktop.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* $Id: ede-panel.cpp 3463 2012-12-17 15:49:33Z karijes $
|
||||
*
|
||||
* Copyright (C) 2013 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __EDE_DESKTOP_H__
|
||||
#define __EDE_DESKTOP_H__
|
||||
|
||||
#include <edelib/MenuButton.h>
|
||||
#include <edelib/DesktopFile.h>
|
||||
#include <edelib/Config.h>
|
||||
#include <edelib/List.h>
|
||||
#include <edelib/String.h>
|
||||
|
||||
#ifdef USE_EDELIB_WINDOW
|
||||
# include <edelib/Window.h>
|
||||
# define EDE_DESKTOP_WINDOW EDELIB_NS_PREPEND(Window)
|
||||
#else
|
||||
# include <FL/Fl_Window.H>
|
||||
# define EDE_DESKTOP_WINDOW Fl_Window
|
||||
#endif
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
#define EDE_DESKTOP_APP "ede-desktop"
|
||||
|
||||
struct SelectionOverlay;
|
||||
struct IconOptions;
|
||||
class DesktopIcon;
|
||||
class Wallpaper;
|
||||
|
||||
typedef EDELIB_NS_PREPEND(list)<DesktopIcon*> DesktopIconList;
|
||||
typedef EDELIB_NS_PREPEND(list)<DesktopIcon*>::iterator DesktopIconListIt;
|
||||
|
||||
class Desktop : public EDE_DESKTOP_WINDOW {
|
||||
private:
|
||||
SelectionOverlay *selbox;
|
||||
DesktopConfig *conf;
|
||||
IconOptions *icon_opts;
|
||||
|
||||
EDELIB_NS_PREPEND(String) dpath;
|
||||
EDELIB_NS_PREPEND(MenuButton) *dmenu;
|
||||
Wallpaper *wallpaper;
|
||||
|
||||
int selection_x, selection_y;
|
||||
/* last recorded pointer position, so icon can be created at position where menu is clicked */
|
||||
int last_px, last_py;
|
||||
bool moving;
|
||||
|
||||
/* so we can track selected icons; one or multiselection */
|
||||
DesktopIconList selectionbuf;
|
||||
public:
|
||||
Desktop();
|
||||
~Desktop();
|
||||
|
||||
const char *desktop_path(void);
|
||||
|
||||
void show(void);
|
||||
void update_workarea(void);
|
||||
void update_workarea(int X, int Y, int W, int H);
|
||||
void read_config(void);
|
||||
|
||||
void read_desktop_folder(const char *dpath = NULL);
|
||||
DesktopIcon *read_desktop_file(const char *path, const char *base = 0, DesktopConfig *positions = 0);
|
||||
|
||||
void arrange_icons(void);
|
||||
bool remove_icon(DesktopIcon *di, bool real_delete);
|
||||
bool rename_icon(DesktopIcon *di, const char *name);
|
||||
void edit_icon(DesktopIcon *di);
|
||||
bool save_icons_positions(void);
|
||||
bool create_folder(const char *name);
|
||||
|
||||
void unfocus_all(void);
|
||||
void select(DesktopIcon *ic, bool do_redraw = true);
|
||||
void select_only(DesktopIcon *ic);
|
||||
bool in_selection(const DesktopIcon *ic);
|
||||
void move_selection(int x, int y, bool apply);
|
||||
|
||||
DesktopIcon *below_mouse(int px, int py);
|
||||
void select_in_area(void);
|
||||
|
||||
void draw(void);
|
||||
int handle(int event);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,13 +1,21 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ede-desktop, desktop and icon manager
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2006-2008 EDE Authors.
|
||||
*
|
||||
* This program is licensed under terms of the
|
||||
* GNU General Public License version 2 or newer.
|
||||
* See COPYING for details.
|
||||
* Copyright (C) 2006-2013 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
@ -18,20 +26,19 @@
|
|||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/Fl_Shared_Image.H>
|
||||
#include <FL/x.H>
|
||||
|
||||
#include <edelib/Debug.h>
|
||||
#include <edelib/IconLoader.h>
|
||||
#include <edelib/MenuItem.h>
|
||||
#include <edelib/MessageBox.h>
|
||||
#include <edelib/Nls.h>
|
||||
#include <edelib/Run.h>
|
||||
|
||||
#include "ede-desktop.h"
|
||||
#include "DesktopIcon.h"
|
||||
#include "IconDialog.h"
|
||||
#include "MovableIcon.h"
|
||||
#include "Utils.h"
|
||||
#include "Desktop.h"
|
||||
|
||||
/* label offset from icon y() + h(), so selection box can be drawn nicely */
|
||||
#define LABEL_OFFSET 2
|
||||
|
||||
/* minimal icon sizes */
|
||||
#define ICON_SIZE_MIN_W 48
|
||||
|
@ -41,181 +48,160 @@
|
|||
#define OFFSET_W 16
|
||||
#define OFFSET_H 16
|
||||
|
||||
/* label offset from icon y()+h(), so selection box can be drawn nicely */
|
||||
#define LABEL_OFFSET 2
|
||||
|
||||
EDELIB_NS_USING(String)
|
||||
EDELIB_NS_USING(IconLoader)
|
||||
EDELIB_NS_USING(MenuItem)
|
||||
EDELIB_NS_USING(String)
|
||||
EDELIB_NS_USING(MenuButton)
|
||||
EDELIB_NS_USING(ICON_SIZE_HUGE)
|
||||
EDELIB_NS_USING(ICON_SIZE_TINY)
|
||||
EDELIB_NS_USING(input)
|
||||
EDELIB_NS_USING(ask)
|
||||
EDELIB_NS_USING(MenuItem)
|
||||
EDELIB_NS_USING(run_async)
|
||||
EDELIB_NS_USING(ask)
|
||||
EDELIB_NS_USING(alert)
|
||||
EDELIB_NS_USING(input)
|
||||
EDELIB_NS_USING(ICON_SIZE_TINY)
|
||||
EDELIB_NS_USING(ICON_SIZE_HUGE)
|
||||
|
||||
static void open_cb(Fl_Widget*, void* d);
|
||||
static void rename_cb(Fl_Widget*, void* d);
|
||||
static void edit_cb(Fl_Widget*, void* d);
|
||||
static void delete_cb(Fl_Widget*, void* d);
|
||||
|
||||
static MenuItem icon_menu[] = {
|
||||
{_("&Open"), 0, open_cb, 0},
|
||||
{_("&Rename"), 0, rename_cb, 0},
|
||||
{_("&Edit"), 0, edit_cb, 0},
|
||||
{_("&Delete"), 0, delete_cb, 0},
|
||||
/* {_("&Properties"), 0, props_cb, 0}, */
|
||||
{0}
|
||||
};
|
||||
|
||||
#if 0
|
||||
static MenuItem icon_trash_menu[] = {
|
||||
{_("&Open"), 0, 0},
|
||||
{_("&Properties"), 0, 0, 0, FL_MENU_DIVIDER},
|
||||
{_("&Empty"), 0, 0},
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
static void open_cb(Fl_Widget*, void* d) {
|
||||
DesktopIcon* di = (DesktopIcon*)d;
|
||||
IconSettings* s = di->get_settings();
|
||||
|
||||
run_async("ede-launch %s", s->cmd.c_str());
|
||||
DesktopIcon *o = (DesktopIcon*)d;
|
||||
/* run .desktop file directly, since it can contain startup details */
|
||||
run_async("ede-launch %s", o->get_path());
|
||||
}
|
||||
|
||||
static void rename_cb(Fl_Widget*, void* d) {
|
||||
DesktopIcon* di = (DesktopIcon*)d;
|
||||
static void edit_cb(Fl_Widget*, void* d) {
|
||||
DesktopIcon *di = (DesktopIcon*)d;
|
||||
((Desktop*)di->parent())->edit_icon(di);
|
||||
}
|
||||
|
||||
const char* new_name = input(_("Change desktop icon name to:"), di->label());
|
||||
# if 0
|
||||
static void rename_cb(Fl_Widget*, void* d) {
|
||||
DesktopIcon *di = (DesktopIcon*)d;
|
||||
|
||||
const char *new_name = input(_("Change desktop icon name to:"), di->label());
|
||||
if(new_name) {
|
||||
di->rename(new_name);
|
||||
Desktop::instance()->rename_icon(di, new_name);
|
||||
bool saved = ((Desktop*)di->parent())->rename_icon(di, new_name);
|
||||
if(!saved)
|
||||
alert(_("Unable to rename this icon. Please check if you have enough permissions to do so"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void delete_cb(Fl_Widget*, void* d) {
|
||||
DesktopIcon* di = (DesktopIcon*)d;
|
||||
DesktopIcon *di = (DesktopIcon*)d;
|
||||
|
||||
if(ask(_("This icon will be permanently deleted. Proceed?")))
|
||||
Desktop::instance()->remove_icon(di, true);
|
||||
if(ask(_("This icon will be permanently deleted. Are you sure?")))
|
||||
((Desktop*)di->parent())->remove_icon(di, true);
|
||||
}
|
||||
|
||||
/*
|
||||
static void props_cb(Fl_Widget*, void* d) {
|
||||
DesktopIcon* di = (DesktopIcon*)d;
|
||||
icon_dialog_icon_property(di);
|
||||
}
|
||||
*/
|
||||
|
||||
DesktopIcon::DesktopIcon(GlobalIconSettings* gs, IconSettings* is, int bg) :
|
||||
Fl_Widget(is->x, is->y, ICON_SIZE_MIN_W, ICON_SIZE_MIN_H) {
|
||||
|
||||
E_ASSERT(gs != NULL);
|
||||
|
||||
lwidth = lheight = 0;
|
||||
focus = false;
|
||||
micon = NULL;
|
||||
darker_img = NULL;
|
||||
|
||||
gsettings = gs;
|
||||
settings = is;
|
||||
|
||||
label(settings->name.c_str());
|
||||
|
||||
imenu = new MenuButton(0, 0, 0, 0);
|
||||
if(settings->type == ICON_TRASH)
|
||||
imenu->menu(icon_trash_menu);
|
||||
else {
|
||||
icon_menu[2].image(IconLoader::get("edit-delete", ICON_SIZE_TINY));
|
||||
imenu->menu(icon_menu);
|
||||
}
|
||||
|
||||
load_icon(ICON_FACE_ONE);
|
||||
fix_position(x(), y());
|
||||
|
||||
/* use desktop color as color for icon background */
|
||||
color(bg);
|
||||
|
||||
DesktopIcon::DesktopIcon(const char *l, int W, int H) : Fl_Widget(1, 1, W, H, l) {
|
||||
box(FL_FLAT_BOX);
|
||||
color(FL_RED);
|
||||
label(l);
|
||||
align(FL_ALIGN_WRAP);
|
||||
update_label_font_and_size();
|
||||
|
||||
/* default values unless given explicitly */
|
||||
labelfont(FL_HELVETICA);
|
||||
labelsize(12);
|
||||
|
||||
darker_img = 0;
|
||||
micon = 0;
|
||||
lwidth = lheight = 0;
|
||||
focused = false;
|
||||
imenu = 0;
|
||||
|
||||
icon_menu[2].image((Fl_Image*)IconLoader::get("edit-delete", ICON_SIZE_TINY));
|
||||
}
|
||||
|
||||
DesktopIcon::~DesktopIcon() {
|
||||
E_DEBUG("DesktopIcon::~DesktopIcon()\n");
|
||||
|
||||
delete settings;
|
||||
delete micon;
|
||||
DesktopIcon::~DesktopIcon() {
|
||||
delete darker_img;
|
||||
delete micon;
|
||||
delete imenu;
|
||||
}
|
||||
|
||||
void DesktopIcon::load_icon(int face) {
|
||||
const char* ic = NULL;
|
||||
void DesktopIcon::set_image(const char *name) {
|
||||
E_RETURN_IF_FAIL(IconLoader::inited());
|
||||
|
||||
if(face != ICON_FACE_TWO) {
|
||||
if(!settings->icon.empty())
|
||||
ic = settings->icon.c_str();
|
||||
} else {
|
||||
if(!settings->icon2.empty())
|
||||
ic = settings->icon2.c_str();
|
||||
}
|
||||
|
||||
if(!ic)
|
||||
return;
|
||||
|
||||
if(!IconLoader::set(this, ic, ICON_SIZE_HUGE)) {
|
||||
E_DEBUG(E_STRLOC ": Unable to load %s icon\n", ic);
|
||||
return;
|
||||
}
|
||||
/* if not name give, use false name to trick IconLoader to use fallback icons */
|
||||
if(!name) name = "THIS-ICON-DOES-NOT-EXISTS";
|
||||
E_RETURN_IF_FAIL(IconLoader::set(this, name, ICON_SIZE_HUGE));
|
||||
|
||||
/* fetch image object for sizes */
|
||||
Fl_Image* img = image();
|
||||
Fl_Image *img = image();
|
||||
|
||||
int img_w = img->w();
|
||||
int img_h = img->h();
|
||||
int img_w = img->w(),
|
||||
img_h = img->h();
|
||||
|
||||
/* resize box if icon is larger */
|
||||
if(img_w > ICON_SIZE_MIN_W || img_h > ICON_SIZE_MIN_H)
|
||||
size(img_w + OFFSET_W, img_h + OFFSET_H);
|
||||
}
|
||||
|
||||
/* darker icon version for selection */
|
||||
delete darker_img;
|
||||
|
||||
darker_img = img->copy(img->w(), img->h());
|
||||
darker_img->color_average(FL_BLUE, 0.6);
|
||||
void DesktopIcon::set_tooltip(const char *tip) {
|
||||
#if (FL_MAJOR_VERSION >= 1) && (FL_MINOR_VERSION >= 3)
|
||||
copy_tooltip(tip);
|
||||
#else
|
||||
/*
|
||||
* in versions prior 1.3, copy_tooltip didn't exist and there wasn't any
|
||||
* way to store tooltip without manually managing the storage
|
||||
*/
|
||||
if(tip) {
|
||||
ttip = tip;
|
||||
tooltip(ttip.c_str());
|
||||
} else {
|
||||
tooltip(tip);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void DesktopIcon::update_label_font_and_size(void) {
|
||||
labelfont(gsettings->label_font);
|
||||
labelsize(gsettings->label_fontsize);
|
||||
lwidth = gsettings->label_maxwidth;
|
||||
lheight= 0;
|
||||
E_RETURN_IF_FAIL(opts != 0);
|
||||
|
||||
labelfont(opts->label_font);
|
||||
labelsize(opts->label_fontsize);
|
||||
lwidth = opts->label_maxwidth;
|
||||
lheight = 0;
|
||||
|
||||
/*
|
||||
* make sure current font size/type is set (internaly to fltk)
|
||||
* so fl_measure() can correctly calculate label width and height
|
||||
*/
|
||||
int old = fl_font();
|
||||
int old_sz = fl_size();
|
||||
int old = fl_font(), old_sz = fl_size();
|
||||
|
||||
fl_font(labelfont(), labelsize());
|
||||
|
||||
fl_measure(label(), lwidth, lheight, align());
|
||||
|
||||
fl_font(old, old_sz);
|
||||
|
||||
lwidth += 12;
|
||||
lwidth += 12;
|
||||
lheight += 5;
|
||||
}
|
||||
|
||||
void DesktopIcon::fix_position(int X, int Y) {
|
||||
int dx, dy, dw, dh;
|
||||
Desktop::instance()->area(dx, dy, dw, dh);
|
||||
int dx = parent()->x(),
|
||||
dy = parent()->y(),
|
||||
dw = parent()->w(),
|
||||
dh = parent()->h();
|
||||
|
||||
if(X < dx)
|
||||
X = dx;
|
||||
if(Y < dy)
|
||||
Y = dy;
|
||||
if(X + w() > dw)
|
||||
X = (dx + dw) - w();
|
||||
if(Y + h() > dh)
|
||||
Y = (dy + dh) - h();
|
||||
if(X < dx) X = dx;
|
||||
if(Y < dy) Y = dy;
|
||||
if(X + w() > dw) X = (dx + dw) - w();
|
||||
if(Y + h() > dh) Y = (dy + dh) - h();
|
||||
|
||||
position(X, Y);
|
||||
}
|
||||
|
@ -227,14 +213,17 @@ void DesktopIcon::drag(int x, int y, bool apply) {
|
|||
/*
|
||||
* This is used to calculate correct window startup/ending
|
||||
* position since icon is placed in the middle of the box.
|
||||
*
|
||||
* Opposite, window (shaped) will have small but noticeable 'jump off' and
|
||||
* dropped icon position will not be at the exact place where was dropped.
|
||||
*/
|
||||
int ix = 0, iy = 0;
|
||||
if(image()) {
|
||||
ix = (w()/2) - (image()->w()/2);
|
||||
iy = (h()/2) - (image()->h()/2);
|
||||
|
||||
/* include parent offset since x/y are absolute locations */
|
||||
if(parent()) {
|
||||
ix += parent()->x();
|
||||
iy += parent()->y();
|
||||
}
|
||||
}
|
||||
|
||||
micon->position(micon->x() + ix, micon->y() + iy);
|
||||
|
@ -251,7 +240,14 @@ void DesktopIcon::drag(int x, int y, bool apply) {
|
|||
if(image()) {
|
||||
ix = (w()/2) - (image()->w()/2);
|
||||
iy = (h()/2) - (image()->h()/2);
|
||||
|
||||
/* also take into account offsets, as below we subtract it */
|
||||
if(parent()) {
|
||||
ix += parent()->x();
|
||||
iy += parent()->y();
|
||||
}
|
||||
}
|
||||
|
||||
fix_position(micon->x() - ix, micon->y() - iy);
|
||||
#else
|
||||
fix_position(micon->x(), micon->y());
|
||||
|
@ -276,38 +272,7 @@ int DesktopIcon::drag_icon_y(void) {
|
|||
else
|
||||
return micon->y();
|
||||
}
|
||||
|
||||
void DesktopIcon::rename(const char* str) {
|
||||
if(!str ||(str[0] == '\0'))
|
||||
return;
|
||||
|
||||
if(settings->name == str)
|
||||
return;
|
||||
|
||||
settings->name = str;
|
||||
label(settings->name.c_str());
|
||||
update_label_font_and_size();
|
||||
redraw();
|
||||
}
|
||||
|
||||
const String& DesktopIcon::path(void) {
|
||||
return settings->full_path;
|
||||
}
|
||||
|
||||
int DesktopIcon::icon_type(void) {
|
||||
return settings->type;
|
||||
}
|
||||
|
||||
void DesktopIcon::use_icon1(void) {
|
||||
load_icon(ICON_FACE_ONE);
|
||||
fast_redraw();
|
||||
}
|
||||
|
||||
void DesktopIcon::use_icon2(void) {
|
||||
load_icon(ICON_FACE_TWO);
|
||||
fast_redraw();
|
||||
}
|
||||
|
||||
|
||||
void DesktopIcon::fast_redraw(void) {
|
||||
int wsz = w();
|
||||
int xpos = x();
|
||||
|
@ -321,11 +286,9 @@ void DesktopIcon::fast_redraw(void) {
|
|||
parent()->damage(FL_DAMAGE_ALL, xpos, y(), wsz, h() + lheight + LABEL_OFFSET + 2);
|
||||
}
|
||||
|
||||
void DesktopIcon::draw(void) {
|
||||
// draw_box(FL_UP_BOX, FL_BLACK);
|
||||
|
||||
void DesktopIcon::draw(void) {
|
||||
if(image() && (damage() & FL_DAMAGE_ALL)) {
|
||||
Fl_Image* im = image();
|
||||
Fl_Image *im = image();
|
||||
|
||||
/* center image in the box */
|
||||
int ix = (w()/2) - (im->w()/2);
|
||||
|
@ -333,23 +296,27 @@ void DesktopIcon::draw(void) {
|
|||
ix += x();
|
||||
iy += y();
|
||||
|
||||
/* darker_img is always present if image() is present */
|
||||
if(is_focused())
|
||||
if(is_focused()) {
|
||||
/* create darker image only when needed */
|
||||
if(!darker_img) {
|
||||
darker_img = im->copy(im->w(), im->h());
|
||||
darker_img->color_average(FL_BLUE, 0.6);
|
||||
}
|
||||
|
||||
darker_img->draw(ix, iy);
|
||||
else
|
||||
} else {
|
||||
im->draw(ix, iy);
|
||||
|
||||
E_DEBUG(E_STRLOC ": DesktopIcon icon redraw\n");
|
||||
}
|
||||
}
|
||||
|
||||
if(gsettings->label_draw && (damage() & (FL_DAMAGE_ALL | EDAMAGE_CHILD_LABEL))) {
|
||||
|
||||
if(opts && opts->label_visible && (damage() & (FL_DAMAGE_ALL | EDE_DESKTOP_DAMAGE_CHILD_LABEL))) {
|
||||
int X = x() + w()-(w()/2)-(lwidth/2);
|
||||
int Y = y() + h() + LABEL_OFFSET;
|
||||
|
||||
Fl_Color old = fl_color();
|
||||
|
||||
if(!gsettings->label_transparent) {
|
||||
fl_color(gsettings->label_background);
|
||||
if(!opts->label_transparent) {
|
||||
fl_color(opts->label_background);
|
||||
fl_rectf(X, Y, lwidth, lheight);
|
||||
}
|
||||
|
||||
|
@ -358,12 +325,12 @@ void DesktopIcon::draw(void) {
|
|||
|
||||
/* draw with icon's font */
|
||||
fl_font(labelfont(), labelsize());
|
||||
|
||||
|
||||
/* pseudo-shadow */
|
||||
fl_color(FL_BLACK);
|
||||
fl_draw(label(), X+1, Y+1, lwidth, lheight, align(), 0, 0);
|
||||
|
||||
fl_color(gsettings->label_foreground);
|
||||
fl_color(opts->label_foreground);
|
||||
fl_draw(label(), X, Y, lwidth, lheight, align(), 0, 0);
|
||||
|
||||
/* restore old font */
|
||||
|
@ -371,7 +338,7 @@ void DesktopIcon::draw(void) {
|
|||
|
||||
if(is_focused()) {
|
||||
/* draw focused box on our way so later this can be used to draw customised boxes */
|
||||
fl_color(gsettings->label_foreground);
|
||||
fl_color(opts->label_foreground);
|
||||
fl_line_style(FL_DOT);
|
||||
|
||||
fl_push_matrix();
|
||||
|
@ -390,7 +357,6 @@ void DesktopIcon::draw(void) {
|
|||
|
||||
/* revert to old color whatever that be */
|
||||
fl_color(old);
|
||||
E_DEBUG(E_STRLOC ": DesktopIcon label redraw\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,22 +366,34 @@ int DesktopIcon::handle(int event) {
|
|||
case FL_UNFOCUS:
|
||||
case FL_ENTER:
|
||||
case FL_LEAVE:
|
||||
return 1;
|
||||
/* We have to handle FL_MOVE too, if want to get only once FL_ENTER when entered or FL_LEAVE when leaved */
|
||||
case FL_MOVE:
|
||||
return 1;
|
||||
|
||||
case FL_PUSH:
|
||||
if(Fl::event_button() == 3) {
|
||||
/* MenuItem::popup() by default does not call callbacks */
|
||||
const MenuItem* m = imenu->menu()->popup(Fl::event_x(), Fl::event_y());
|
||||
/*
|
||||
* init icon specific menu only when needed
|
||||
* TODO: since menu for all icons is mostly the same, it can be shared; Desktop can
|
||||
* have menu instance seeded to all icons
|
||||
*/
|
||||
if(!imenu) {
|
||||
imenu = new MenuButton(0, 0, 0, 0);
|
||||
imenu->menu(icon_menu);
|
||||
}
|
||||
|
||||
/* MenuItem::popup() by default does not call callbacks */
|
||||
const MenuItem *m = imenu->menu()->popup(Fl::event_x(), Fl::event_y());
|
||||
|
||||
/* call menu callbacks, passing correct parameters */
|
||||
if(m && m->callback())
|
||||
m->do_callback(0, this);
|
||||
}
|
||||
return 1;
|
||||
|
||||
case FL_RELEASE:
|
||||
if(Fl::event_clicks() > 0)
|
||||
run_async("ede-launch %s", settings->cmd.c_str());
|
||||
if(Fl::event_clicks() > 0 && !path.empty())
|
||||
run_async("ede-launch %s", path.c_str());
|
||||
return 1;
|
||||
|
||||
case FL_DND_ENTER:
|
||||
|
|
|
@ -1,95 +1,139 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ede-desktop, desktop and icon manager
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2006-2008 EDE Authors.
|
||||
*
|
||||
* This program is licensed under terms of the
|
||||
* GNU General Public License version 2 or newer.
|
||||
* See COPYING for details.
|
||||
* Copyright (C) 2006-2013 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __DESKTOPICON_H__
|
||||
#define __DESKTOPICON_H__
|
||||
#ifndef __DESKTOP_ICON_H__
|
||||
#define __DESKTOP_ICON_H__
|
||||
|
||||
#include <FL/Fl_Widget.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Image.H>
|
||||
|
||||
#include <edelib/String.h>
|
||||
#include <edelib/MenuButton.h>
|
||||
#include <edelib/String.h>
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
enum {
|
||||
DESKTOP_ICON_TYPE_NORMAL,
|
||||
DESKTOP_ICON_TYPE_TRASH,
|
||||
DESKTOP_ICON_TYPE_LINK,
|
||||
DESKTOP_ICON_TYPE_FILE,
|
||||
DESKTOP_ICON_TYPE_FOLDER
|
||||
};
|
||||
|
||||
/* default icon sizes */
|
||||
#define DESKTOP_ICON_SIZE_W 48
|
||||
#define DESKTOP_ICON_SIZE_H 48
|
||||
|
||||
/*
|
||||
* Each DesktopIcon shares IconOptions, which is content of [Icons] section
|
||||
* from configuration file. With this, 'Desktop' needs only to update content so all
|
||||
* icons see it.
|
||||
*/
|
||||
struct IconOptions {
|
||||
int label_background;
|
||||
int label_foreground;
|
||||
int label_font;
|
||||
int label_fontsize;
|
||||
int label_maxwidth;
|
||||
int label_transparent;
|
||||
int label_visible;
|
||||
bool one_click_exec;
|
||||
|
||||
IconOptions() {
|
||||
label_background = FL_BLACK;
|
||||
label_foreground = FL_WHITE;
|
||||
label_maxwidth = 75;
|
||||
label_transparent = 1;
|
||||
label_visible = 1;
|
||||
label_font = FL_HELVETICA;
|
||||
label_fontsize = 12;
|
||||
one_click_exec = false;
|
||||
}
|
||||
|
||||
/* should be called only when values are assigned to fonts */
|
||||
void sanitize_font(void) {
|
||||
if(label_font < 0) label_font = FL_HELVETICA;
|
||||
if(label_fontsize < 8) label_fontsize = 12;
|
||||
if(label_maxwidth < 30) label_maxwidth = 75;
|
||||
}
|
||||
};
|
||||
|
||||
class GlobalIconSettings;
|
||||
class IconSettings;
|
||||
class MovableIcon;
|
||||
|
||||
class DesktopIcon : public Fl_Widget {
|
||||
private:
|
||||
IconSettings* settings;
|
||||
const GlobalIconSettings* gsettings;
|
||||
int icon_type;
|
||||
int lwidth, lheight;
|
||||
bool focused;
|
||||
|
||||
int lwidth;
|
||||
int lheight;
|
||||
bool focus;
|
||||
Fl_Image *darker_img;
|
||||
IconOptions *opts;
|
||||
MovableIcon *micon;
|
||||
|
||||
MovableIcon* micon;
|
||||
/* location of .desktop file */
|
||||
EDELIB_NS_PREPEND(String) path;
|
||||
EDELIB_NS_PREPEND(MenuButton) *imenu;
|
||||
|
||||
Fl_Image* darker_img;
|
||||
edelib::MenuButton* imenu;
|
||||
|
||||
void load_icon(int face);
|
||||
void update_label_font_and_size(void);
|
||||
void fix_position(int X, int Y);
|
||||
#if !((FL_MAJOR_VERSION >= 1) && (FL_MINOR_VERSION >= 3))
|
||||
EDELIB_NS_PREPEND(String) ttip;
|
||||
#endif
|
||||
|
||||
public:
|
||||
DesktopIcon(GlobalIconSettings* gisett, IconSettings* isett, int bg);
|
||||
DesktopIcon(const char *l, int W = DESKTOP_ICON_SIZE_W, int H = DESKTOP_ICON_SIZE_H);
|
||||
~DesktopIcon();
|
||||
|
||||
virtual void draw(void);
|
||||
virtual int handle(int event);
|
||||
void set_icon_type(int c) { icon_type = c; }
|
||||
int get_icon_type(void) { return icon_type;}
|
||||
void set_image(const char *name);
|
||||
void set_tooltip(const char *tip);
|
||||
|
||||
void update_label_font_and_size(void);
|
||||
|
||||
void set_options(IconOptions *o) {
|
||||
opts = o;
|
||||
update_label_font_and_size();
|
||||
}
|
||||
|
||||
/* Here is implemented localy focus schema avoiding messy fltk one. Focus/unfocus is handled from Desktop. */
|
||||
void do_focus(void) { focused = true; }
|
||||
void do_unfocus(void) { focused = false; }
|
||||
bool is_focused(void) { return focused; }
|
||||
|
||||
void set_path(const char *p) { path = p; }
|
||||
const char *get_path(void) { return path.c_str(); }
|
||||
|
||||
void fix_position(int X, int Y);
|
||||
void drag(int x, int y, bool apply);
|
||||
int drag_icon_x(void);
|
||||
int drag_icon_y(void);
|
||||
|
||||
IconSettings* get_settings(void) { return settings; }
|
||||
|
||||
/*
|
||||
* This is 'enhanced' (in some sense) redraw(). Redrawing
|
||||
* icon will not fully redraw label nor focus box, which laid outside
|
||||
* icon box. It will use damage() on given region, but called from
|
||||
* parent, so parent can redraw that region on itself (since label does
|
||||
* not laid on any box)
|
||||
* This is 'enhanced' (in some sense) redraw(). Redrawing icon will not fully redraw label nor
|
||||
* focus box, which laid outside icon box. It will use damage() on given region, but called from
|
||||
* parent, so parent can redraw that region on itself (since label does not laid on any box)
|
||||
*
|
||||
* Alternative way would be to redraw whole parent, but it is pretty unneeded
|
||||
* and slow.
|
||||
* Alternative way would be to redraw the whole parent, but it is pretty unneeded and slow.
|
||||
*/
|
||||
void fast_redraw(void);
|
||||
|
||||
/*
|
||||
* Here is implemented localy focus schema avoiding
|
||||
* messy fltk one. Focus/unfocus is handled from Desktop.
|
||||
*/
|
||||
void do_focus(void) { focus = true; }
|
||||
void do_unfocus(void) { focus = false; }
|
||||
bool is_focused(void) { return focus; }
|
||||
|
||||
Fl_Image* icon_image(void) { return image(); }
|
||||
|
||||
void rename(const char* str);
|
||||
|
||||
/*
|
||||
* make sure this returns String since operator== is
|
||||
* further used, especially in Desktop
|
||||
*/
|
||||
const edelib::String& path(void);
|
||||
|
||||
int icon_type(void);
|
||||
void use_icon1(void);
|
||||
void use_icon2(void);
|
||||
void draw(void);
|
||||
int handle(int event);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
35
ede-desktop/Globals.h
Normal file
35
ede-desktop/Globals.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* $Id: ede-panel.cpp 3463 2012-12-17 15:49:33Z karijes $
|
||||
*
|
||||
* Copyright (C) 2013 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __EDE_DESKTOP_GLOBAL_H__
|
||||
#define __EDE_DESKTOP_GLOBAL_H__
|
||||
|
||||
#include <edelib/Resource.h>
|
||||
|
||||
/* alias it so we don't have to use EDELIB_NS_PREPEND */
|
||||
EDELIB_NS_USING_AS(Resource, DesktopConfig)
|
||||
|
||||
#define EDE_DESKTOP_DAMAGE_CHILD_LABEL 0x10
|
||||
#define EDE_DESKTOP_DAMAGE_OVERLAY 0x20
|
||||
#define EDE_DESKTOP_DAMAGE_CLEAR_OVERLAY 0x30
|
||||
|
||||
#define EDE_DESKTOP_DESKTOP_EXT ".desktop"
|
||||
|
||||
#endif
|
|
@ -1,16 +1,25 @@
|
|||
/*
|
||||
* $Id: IconProperties.h 2366 2008-10-02 09:42:19Z karijes $
|
||||
* $Id: ede-panel.cpp 3463 2012-12-17 15:49:33Z karijes $
|
||||
*
|
||||
* ede-desktop, desktop and icon manager
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2006-2012 EDE Authors.
|
||||
*
|
||||
* This program is licensed under terms of the
|
||||
* GNU General Public License version 2 or newer.
|
||||
* See COPYING for details.
|
||||
* Copyright (C) 2006-2014 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/Fl.H>
|
||||
|
@ -20,6 +29,9 @@
|
|||
#include <FL/Fl_Menu_Item.H>
|
||||
#include <FL/Fl_Shared_Image.H>
|
||||
#include <FL/Fl_File_Chooser.H>
|
||||
#include <FL/Fl_Tabs.H>
|
||||
#include <FL/Fl_Group.H>
|
||||
#include <FL/Fl_Check_Button.H>
|
||||
|
||||
#include <edelib/Nls.h>
|
||||
#include <edelib/String.h>
|
||||
|
@ -35,19 +47,22 @@
|
|||
|
||||
#include "IconDialog.h"
|
||||
#include "DesktopIcon.h"
|
||||
#include "ede-desktop.h"
|
||||
#include "Desktop.h"
|
||||
#include "Globals.h"
|
||||
|
||||
EDELIB_NS_USING_LIST(10, (str_tolower, icon_chooser, dir_home, build_filename, alert,
|
||||
EDELIB_NS_USING_LIST(12, (str_tolower, icon_chooser, dir_home, build_filename, alert, ask, file_remove,
|
||||
ICON_SIZE_HUGE, String, IconLoader, DesktopFile, DESK_FILE_TYPE_APPLICATION))
|
||||
|
||||
#define DEFAULT_ICON "empty"
|
||||
|
||||
/* it is safe to be globals */
|
||||
static Fl_Window *win;
|
||||
static Fl_Button *img, *browse, *ok, *cancel;
|
||||
static Fl_Input *name, *comment, *execute;
|
||||
static Fl_Choice *icon_type;
|
||||
static String img_path;
|
||||
static Fl_Window *win;
|
||||
static Fl_Button *img, *browse, *ok, *cancel;
|
||||
static Fl_Input *name, *comment, *execute, *workdir;
|
||||
static Fl_Choice *icon_type;
|
||||
static Fl_Check_Button *run_in_terminal, *start_notify;
|
||||
static String img_path, old_desktop_path;
|
||||
static DesktopIcon *curr_icon;
|
||||
|
||||
/* the only supported type for now is application */
|
||||
static Fl_Menu_Item menu_items[] = {
|
||||
|
@ -59,8 +74,9 @@ static bool is_empty(const char *str) {
|
|||
if(!str) return true;
|
||||
const char *p = str;
|
||||
|
||||
while(*p++)
|
||||
while(*p++) {
|
||||
if(!isspace(*p)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -73,13 +89,15 @@ static void cancel_cb(Fl_Widget*, void*) {
|
|||
win->hide();
|
||||
}
|
||||
|
||||
static void ok_cb(Fl_Widget*, void*) {
|
||||
static void ok_cb(Fl_Widget*, void *d) {
|
||||
if(is_empty_input(name) || is_empty_input(execute) || !img->image()) {
|
||||
/* do nothing */
|
||||
win->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Desktop *self = (Desktop*)d;
|
||||
|
||||
DesktopFile df;
|
||||
df.create_new(DESK_FILE_TYPE_APPLICATION);
|
||||
df.set_name(name->value());
|
||||
|
@ -87,106 +105,170 @@ static void ok_cb(Fl_Widget*, void*) {
|
|||
if(comment->value())
|
||||
df.set_comment(comment->value());
|
||||
|
||||
if(!img_path.empty() && img_path.length() > 1) {
|
||||
/* figure out basename */
|
||||
const char *s;
|
||||
char *p, *e;
|
||||
|
||||
s = img_path.c_str();
|
||||
p = (char*)strrchr(s, E_DIR_SEPARATOR);
|
||||
|
||||
if(p && *p++) {
|
||||
/* now remove extension */
|
||||
e = (char*)strrchr((const char*)p, '.');
|
||||
if(e) *e = '\0';
|
||||
|
||||
df.set_icon(p);
|
||||
}
|
||||
} else {
|
||||
df.set_icon(DEFAULT_ICON);
|
||||
}
|
||||
|
||||
df.set_icon((img_path.length() > 1) ? img_path.c_str() : DEFAULT_ICON);
|
||||
df.set_exec(execute->value());
|
||||
|
||||
if(!is_empty_input(workdir))
|
||||
df.set_path(workdir->value());
|
||||
|
||||
df.set_startup_notify(start_notify->value());
|
||||
df.set_terminal(run_in_terminal->value());
|
||||
|
||||
/* determine filename and save it */
|
||||
String file = name->value();
|
||||
const char *fp = file.c_str();
|
||||
|
||||
str_tolower((unsigned char*)fp);
|
||||
file += ".desktop";
|
||||
file += EDE_DESKTOP_DESKTOP_EXT;
|
||||
|
||||
/* go through the file and replace spaces with '_' */
|
||||
for(char *p = (char*)file.c_str(); p && *p; p++)
|
||||
if(isspace(*p)) *p = '_';
|
||||
for(String::size_type i = 0; i < file.length(); i++)
|
||||
if(isspace(file[i])) file[i] = '_';
|
||||
|
||||
/* TODO: let 'Desktop' (class) returns full desktop path */
|
||||
String path = build_filename(Desktop::instance()->desktop_path(), file.c_str());
|
||||
|
||||
/*
|
||||
* disable watching on folder and explicitly add file (probably as notification will be fired up faster than
|
||||
* file will be available on that location)
|
||||
*/
|
||||
Desktop::instance()->dir_watch_off();
|
||||
String path = build_filename(self->desktop_path(), file.c_str());
|
||||
|
||||
int X = 0, Y = 0;
|
||||
if(curr_icon) {
|
||||
X = curr_icon->x();
|
||||
Y = curr_icon->y();
|
||||
/* try to remove icon from filesystem only when we can't overwrite old icon path */
|
||||
self->remove_icon(curr_icon, old_desktop_path != path);
|
||||
}
|
||||
|
||||
if(df.save(path.c_str())) {
|
||||
/* explictly add file path */
|
||||
Desktop::instance()->add_icon_by_path(path.c_str(), NULL);
|
||||
/*
|
||||
* wait a second; this would remove event from the queue so watched does not complain how filed
|
||||
* does not exists
|
||||
DesktopIcon *ic = self->read_desktop_file(path.c_str(), file.c_str());
|
||||
if(ic) {
|
||||
if(X > 0 || Y > 0) ic->position(X, Y);
|
||||
self->add(ic);
|
||||
}
|
||||
|
||||
self->redraw();
|
||||
|
||||
/*
|
||||
* In case when we rename icon, icon position will not be saved (because they are saved by icon basename). So
|
||||
* with different paths we are assured the name was changed and we proceed further.
|
||||
*/
|
||||
Fl::wait(1);
|
||||
Desktop::instance()->redraw();
|
||||
if(old_desktop_path != path) self->save_icons_positions();
|
||||
} else {
|
||||
alert(_("Unable to create '%s' file. Received error is: %s\n"), path.c_str(), df.strerror());
|
||||
}
|
||||
|
||||
Desktop::instance()->dir_watch_on();
|
||||
win->hide();
|
||||
}
|
||||
|
||||
static void img_browse_cb(Fl_Widget*, void*) {
|
||||
img_path = icon_chooser(ICON_SIZE_HUGE);
|
||||
if(img_path.empty()) return;
|
||||
|
||||
Fl_Image* im = Fl_Shared_Image::get(img_path.c_str());
|
||||
if(!im) return;
|
||||
|
||||
img->image(im);
|
||||
img->redraw();
|
||||
if(!img_path.empty())
|
||||
IconLoader::set(img, img_path.c_str(), ICON_SIZE_HUGE);
|
||||
}
|
||||
|
||||
static void file_browse_cb(Fl_Widget*, void*) {
|
||||
const char *p = fl_file_chooser(_("Choose program path to execute"), "*", 0, 0);
|
||||
if(!p) return;
|
||||
execute->value(p);
|
||||
if(p) execute->value(p);
|
||||
}
|
||||
|
||||
void icon_dialog_icon_create(void) {
|
||||
win = new Fl_Window(430, 170, _("Create desktop icon"));
|
||||
img = new Fl_Button(10, 10, 75, 75);
|
||||
img->callback(img_browse_cb);
|
||||
img->tooltip(_("Click to select icon"));
|
||||
IconLoader::set(img, DEFAULT_ICON, ICON_SIZE_HUGE);
|
||||
name = new Fl_Input(205, 10, 215, 25, _("Name:"));
|
||||
comment = new Fl_Input(205, 40, 215, 25, _("Comment:"));
|
||||
execute = new Fl_Input(205, 70, 185, 25, _("Execute:"));
|
||||
browse = new Fl_Button(395, 70, 25, 25, "...");
|
||||
browse->callback(file_browse_cb);
|
||||
icon_type = new Fl_Choice(205, 100, 215, 25, _("Type:"));
|
||||
icon_type->down_box(FL_BORDER_BOX);
|
||||
icon_type->menu(menu_items);
|
||||
static void dir_browse_cb(Fl_Widget*, void*) {
|
||||
const char *p = fl_dir_chooser(_("Choose directory"), "*", 0);
|
||||
if(p) workdir->value(p);
|
||||
}
|
||||
|
||||
#define BUFSIZE PATH_MAX
|
||||
|
||||
void icon_dialog_icon_edit(Desktop *self, DesktopIcon *d) {
|
||||
const char *lbl = d ? _("Edit desktop icon") : _("Create desktop icon");
|
||||
DesktopFile *df = NULL;
|
||||
char *buf = NULL;
|
||||
old_desktop_path = "";
|
||||
curr_icon = d;
|
||||
|
||||
if(d) {
|
||||
df = new DesktopFile();
|
||||
if(!df->load(d->get_path())) {
|
||||
delete df;
|
||||
df = NULL;
|
||||
|
||||
int ret = ask(_("Unable to load .desktop file for this icon. Would you like to create a new icon instead?"));
|
||||
if(!ret) return;
|
||||
|
||||
/* force NULL on icon, so we can run dialog in 'create' mode */
|
||||
d = NULL;
|
||||
}
|
||||
|
||||
buf = new char[BUFSIZE];
|
||||
old_desktop_path = d->get_path();
|
||||
}
|
||||
|
||||
win = new Fl_Window(450, 220, lbl);
|
||||
Fl_Tabs *tabs = new Fl_Tabs(10, 10, 430, 165);
|
||||
tabs->begin();
|
||||
Fl_Group *g1 = new Fl_Group(15, 30, 415, 140, _("Basic"));
|
||||
g1->begin();
|
||||
img = new Fl_Button(20, 45, 80, 75);
|
||||
img->callback(img_browse_cb);
|
||||
img->tooltip(_("Click to select icon"));
|
||||
|
||||
if(d) {
|
||||
E_ASSERT(df != NULL);
|
||||
if(df->icon(buf, BUFSIZE)) {
|
||||
IconLoader::set(img, buf, ICON_SIZE_HUGE);
|
||||
img_path = buf;
|
||||
}
|
||||
}
|
||||
|
||||
/* handles even the case when we are creating the new icon */
|
||||
if(!img->image()) {
|
||||
IconLoader::set(img, DEFAULT_ICON, ICON_SIZE_HUGE);
|
||||
img_path = DEFAULT_ICON;
|
||||
}
|
||||
|
||||
name = new Fl_Input(210, 45, 215, 25, _("Name:"));
|
||||
if(d && df->name(buf, BUFSIZE)) name->value(buf);
|
||||
|
||||
comment = new Fl_Input(210, 75, 215, 25, _("Comment:"));
|
||||
if(d && df->comment(buf, BUFSIZE)) comment->value(buf);
|
||||
|
||||
execute = new Fl_Input(210, 105, 185, 25, _("Execute:"));
|
||||
if(d && df->exec(buf, BUFSIZE)) execute->value(buf);
|
||||
|
||||
browse = new Fl_Button(400, 105, 25, 25, "...");
|
||||
browse->callback(file_browse_cb);
|
||||
|
||||
icon_type = new Fl_Choice(210, 135, 215, 25, _("Type:"));
|
||||
icon_type->down_box(FL_BORDER_BOX);
|
||||
icon_type->menu(menu_items);
|
||||
g1->end();
|
||||
|
||||
Fl_Group *g2 = new Fl_Group(15, 30, 420, 140, _("Details"));
|
||||
g2->hide();
|
||||
g2->begin();
|
||||
run_in_terminal = new Fl_Check_Button(195, 80, 235, 25, _("Run in terminal"));
|
||||
run_in_terminal->down_box(FL_DOWN_BOX);
|
||||
if(df) run_in_terminal->value(df->terminal());
|
||||
|
||||
workdir = new Fl_Input(195, 45, 205, 25, _("Working directory:"));
|
||||
if(df && df->path(buf, BUFSIZE)) workdir->value(buf);
|
||||
|
||||
Fl_Button *browsedir = new Fl_Button(405, 45, 25, 25, "...");
|
||||
browsedir->callback(dir_browse_cb);
|
||||
|
||||
start_notify = new Fl_Check_Button(195, 110, 235, 25, _("Use startup notification"));
|
||||
start_notify->down_box(FL_DOWN_BOX);
|
||||
if(df) start_notify->value(df->startup_notify());
|
||||
g2->end();
|
||||
tabs->end();
|
||||
|
||||
ok = new Fl_Button(255, 185, 90, 25, _("&OK"));
|
||||
ok->callback(ok_cb, self);
|
||||
cancel = new Fl_Button(350, 185, 90, 25, _("&Cancel"));
|
||||
cancel->callback(cancel_cb);
|
||||
|
||||
ok = new Fl_Button(235, 135, 90, 25, _("&OK"));
|
||||
ok->callback(ok_cb);
|
||||
cancel = new Fl_Button(330, 135, 90, 25, _("&Cancel"));
|
||||
cancel->callback(cancel_cb);
|
||||
win->end();
|
||||
win->set_modal();
|
||||
|
||||
delete df;
|
||||
delete buf;
|
||||
|
||||
Fl::focus(name);
|
||||
win->show();
|
||||
}
|
||||
|
||||
void icon_dialog_icon_property(DesktopIcon *d) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,30 @@
|
|||
/*
|
||||
* $Id: IconProperties.h 2366 2008-10-02 09:42:19Z karijes $
|
||||
* $Id: ede-panel.cpp 3463 2012-12-17 15:49:33Z karijes $
|
||||
*
|
||||
* ede-desktop, desktop and icon manager
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2006-2012 EDE Authors.
|
||||
*
|
||||
* This program is licensed under terms of the
|
||||
* GNU General Public License version 2 or newer.
|
||||
* See COPYING for details.
|
||||
* Copyright (C) 2006-2013 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ICONDIALOG_H__
|
||||
#define __ICONDIALOG_H__
|
||||
|
||||
class DesktopIcon;
|
||||
class Desktop;
|
||||
|
||||
void icon_dialog_icon_create(void);
|
||||
void icon_dialog_icon_property(DesktopIcon *d);
|
||||
void icon_dialog_icon_edit(Desktop *self, DesktopIcon *di);
|
||||
inline void icon_dialog_icon_create(Desktop *d) { icon_dialog_icon_edit(d, NULL); }
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,26 +1,34 @@
|
|||
#
|
||||
# $Id$
|
||||
#
|
||||
# Part of Equinox Desktop Environment (EDE).
|
||||
# Copyright (c) 2000-2007 EDE Authors.
|
||||
#
|
||||
# This program is licensed under terms of the
|
||||
# GNU General Public License version 2 or newer.
|
||||
# See COPYING for details.
|
||||
# Copyright (C) 2006-2013 Sanel Zukan
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
SubDir TOP ede-desktop ;
|
||||
|
||||
ObjectC++Flags ede-desktop.cpp : -DUSE_EDELIB_WINDOW ;
|
||||
|
||||
SOURCE = ede-desktop.cpp
|
||||
Utils.cpp
|
||||
Wallpaper.cpp
|
||||
DesktopIcon.cpp
|
||||
Wallpaper.cpp
|
||||
DesktopIcon.cpp
|
||||
MovableIcon.cpp
|
||||
IconDialog.cpp ;
|
||||
Utils.cpp
|
||||
IconDialog.cpp
|
||||
Desktop.cpp ;
|
||||
|
||||
ObjectC++Flags $(SOURCE) : $(EDELIB_DBUS_INCLUDE) ;
|
||||
|
||||
EdeProgram ede-desktop : $(SOURCE) ;
|
||||
LinkAgainst ede-desktop : $(EDELIB_DBUS_LIB) ;
|
||||
TranslationStrings locale : $(SOURCE) ;
|
||||
LinkAgainst ede-desktop : $(EDELIB_DBUS_LIB) $(XSHAPE_LIBS) $(PTHREAD_LIBS) ;
|
|
@ -1,13 +1,21 @@
|
|||
/*
|
||||
* $Id: DesktopIcon.cpp 3032 2011-08-03 12:20:37Z karijes $
|
||||
* $Id: ede-panel.cpp 3463 2012-12-17 15:49:33Z karijes $
|
||||
*
|
||||
* ede-desktop, desktop and icon manager
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2006-2011 EDE Authors.
|
||||
*
|
||||
* This program is licensed under terms of the
|
||||
* GNU General Public License version 2 or newer.
|
||||
* See COPYING for details.
|
||||
* Copyright (C) 2006-2013 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
@ -15,8 +23,9 @@
|
|||
#endif
|
||||
|
||||
#define FL_LIBRARY 1
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/x.H>
|
||||
#include <FL/Fl_Image.H>
|
||||
#include <edelib/Debug.h>
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
|
@ -27,7 +36,9 @@
|
|||
#include "DesktopIcon.h"
|
||||
#include "Utils.h"
|
||||
|
||||
MovableIcon::MovableIcon(DesktopIcon* ic) : Fl_Window(ic->x(), ic->y(), ic->w(), ic->h()), icon(ic), mask(0), opacity_atom(0) {
|
||||
MovableIcon::MovableIcon(DesktopIcon* ic) :
|
||||
Fl_Window(ic->x(), ic->y(), ic->w(), ic->h()), icon(ic), mask(0), opacity_atom(0)
|
||||
{
|
||||
E_ASSERT(icon != NULL);
|
||||
|
||||
set_override();
|
||||
|
@ -36,7 +47,7 @@ MovableIcon::MovableIcon(DesktopIcon* ic) : Fl_Window(ic->x(), ic->y(), ic->w(),
|
|||
begin();
|
||||
/* force box be same width/height as icon so it can fit inside masked window */
|
||||
#ifdef HAVE_SHAPE
|
||||
Fl_Image* img = ic->icon_image();
|
||||
Fl_Image* img = ic->image();
|
||||
if(img)
|
||||
icon_box = new Fl_Box(0, 0, img->w(), img->h());
|
||||
else
|
||||
|
@ -44,7 +55,7 @@ MovableIcon::MovableIcon(DesktopIcon* ic) : Fl_Window(ic->x(), ic->y(), ic->w(),
|
|||
#else
|
||||
icon_box = new Fl_Box(0, 0, w(), h());
|
||||
#endif
|
||||
icon_box->image(ic->icon_image());
|
||||
icon_box->image(ic->image());
|
||||
end();
|
||||
|
||||
opacity_atom = XInternAtom(fl_display, "_NET_WM_WINDOW_OPACITY", False);
|
||||
|
@ -60,8 +71,8 @@ void MovableIcon::show(void) {
|
|||
Fl_X::make_xid(this);
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
if(icon->icon_image()) {
|
||||
mask = create_mask(icon->icon_image());
|
||||
if(icon->image()) {
|
||||
mask = create_mask(icon->image());
|
||||
if(mask) {
|
||||
XShapeCombineMask(fl_display, fl_xid(this), ShapeBounding, 0, 0, mask, ShapeSet);
|
||||
|
||||
|
|
|
@ -1,21 +1,29 @@
|
|||
/*
|
||||
* $Id: DesktopIcon.h 2742 2009-07-09 13:59:51Z karijes $
|
||||
* $Id: ede-panel.cpp 3463 2012-12-17 15:49:33Z karijes $
|
||||
*
|
||||
* ede-desktop, desktop and icon manager
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2006-2011 EDE Authors.
|
||||
*
|
||||
* This program is licensed under terms of the
|
||||
* GNU General Public License version 2 or newer.
|
||||
* See COPYING for details.
|
||||
* Copyright (C) 2006-2013 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __MOVABLEICON_H__
|
||||
#define __MOVABLEICON_H__
|
||||
|
||||
#include <X11/Xlib.h> // Pixmap
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/x.H>
|
||||
|
||||
class DesktopIcon;
|
||||
|
||||
|
@ -25,6 +33,7 @@ private:
|
|||
Fl_Box* icon_box;
|
||||
Pixmap mask;
|
||||
Atom opacity_atom;
|
||||
|
||||
public:
|
||||
MovableIcon(DesktopIcon* i);
|
||||
~MovableIcon();
|
||||
|
|
|
@ -1,17 +1,24 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ede-desktop, desktop and icon manager
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2006-2008 EDE Authors.
|
||||
*
|
||||
* This program is licensed under terms of the
|
||||
* GNU General Public License version 2 or newer.
|
||||
* See COPYING for details.
|
||||
* Copyright (C) 2006-2013 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <FL/x.H>
|
||||
#include <edelib/Debug.h>
|
||||
|
||||
#include "Utils.h"
|
||||
|
@ -26,8 +33,7 @@ static Fl_Window* overlay_drawable = NULL;
|
|||
static char dash_list[] = {1};
|
||||
|
||||
void draw_overlay_rect(void) {
|
||||
if(overlay_w <= 0 || overlay_h <= 0)
|
||||
return;
|
||||
E_RETURN_IF_FAIL(overlay_w > 0 && overlay_h > 0);
|
||||
|
||||
XSetDashes(fl_display, fl_gc, 0, dash_list, 1);
|
||||
XSetLineAttributes(fl_display, fl_gc, 2, LineOnOffDash, CapButt, JoinMiter);
|
||||
|
@ -35,11 +41,7 @@ void draw_overlay_rect(void) {
|
|||
XSetFunction(fl_display, fl_gc, GXxor);
|
||||
XSetForeground(fl_display, fl_gc, 0xffffffff);
|
||||
|
||||
Window ow;
|
||||
if(overlay_drawable)
|
||||
ow = fl_xid(overlay_drawable);
|
||||
else
|
||||
ow = fl_window;
|
||||
Window ow = overlay_drawable ? fl_xid(overlay_drawable) : fl_window;
|
||||
XDrawRectangle(fl_display, ow, fl_gc, overlay_x, overlay_y, overlay_w-1, overlay_h-1);
|
||||
|
||||
XSetFunction(fl_display, fl_gc, GXcopy);
|
||||
|
|
|
@ -1,25 +1,31 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ede-desktop, desktop and icon manager
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2006-2008 EDE Authors.
|
||||
*
|
||||
* This program is licensed under terms of the
|
||||
* GNU General Public License version 2 or newer.
|
||||
* See COPYING for details.
|
||||
* Copyright (C) 2006-2013 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __UTILS_H__
|
||||
#define __UTILS_H__
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/Fl_Image.H>
|
||||
#include <FL/x.H>
|
||||
|
||||
void draw_xoverlay(int x, int y, int w, int h);
|
||||
void clear_xoverlay(void);
|
||||
void set_xoverlay_drawable(Fl_Window* win);
|
||||
|
||||
Pixmap create_mask(Fl_Image* img);
|
||||
|
||||
|
|
|
@ -1,52 +1,53 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ede-desktop, desktop and icon manager
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2006-2009 EDE Authors.
|
||||
*
|
||||
* This program is licensed under terms of the
|
||||
* GNU General Public License version 2 or newer.
|
||||
* See COPYING for details.
|
||||
* Copyright (C) 2006-2013 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <string.h> // memcpy
|
||||
#include <stdlib.h> // malloc
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <FL/Fl_Shared_Image.H>
|
||||
#include <FL/Fl_RGB_Image.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/x.H>
|
||||
|
||||
#include <edelib/Debug.h>
|
||||
|
||||
#include "Wallpaper.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#define CALC_PIXEL(tmp, rshift, rmask, gshift, gmask, bshift, bmask) \
|
||||
tmp = 0; \
|
||||
if(rshift >= 0) \
|
||||
tmp |= (((int)r << rshift) & rmask); \
|
||||
else \
|
||||
tmp |= (((int)r >> (-rshift)) & rmask); \
|
||||
\
|
||||
if(gshift >= 0) \
|
||||
tmp |= (((int)g << gshift) & gmask); \
|
||||
else \
|
||||
tmp |= (((int)g >> (-gshift)) & gmask); \
|
||||
\
|
||||
if(bshift >= 0) \
|
||||
tmp |= (((int)b << bshift) & bmask); \
|
||||
else \
|
||||
#define CALC_PIXEL(tmp, rshift, rmask, gshift, gmask, bshift, bmask) \
|
||||
tmp = 0; \
|
||||
if(rshift >= 0) \
|
||||
tmp |= (((int)r << rshift) & rmask); \
|
||||
else \
|
||||
tmp |= (((int)r >> (-rshift)) & rmask); \
|
||||
\
|
||||
if(gshift >= 0) \
|
||||
tmp |= (((int)g << gshift) & gmask); \
|
||||
else \
|
||||
tmp |= (((int)g >> (-gshift)) & gmask); \
|
||||
\
|
||||
if(bshift >= 0) \
|
||||
tmp |= (((int)b << bshift) & bmask); \
|
||||
else \
|
||||
tmp |= (((int)b >> (-bshift)) & bmask)
|
||||
|
||||
|
||||
static Pixmap create_xpixmap(Fl_Image* img, XImage** xim, Pixmap pix, int wp_w, int wp_h) {
|
||||
if(!img)
|
||||
return 0;
|
||||
|
||||
if(pix)
|
||||
XFreePixmap(fl_display, pix);
|
||||
if(!img) return 0;
|
||||
if(pix) XFreePixmap(fl_display, pix);
|
||||
|
||||
unsigned long rmask = fl_visual->visual->red_mask;
|
||||
unsigned long gmask = fl_visual->visual->green_mask;
|
||||
|
@ -108,15 +109,9 @@ static Pixmap create_xpixmap(Fl_Image* img, XImage** xim, Pixmap pix, int wp_w,
|
|||
int iw = img->w();
|
||||
int ih = img->h();
|
||||
int id = img->d();
|
||||
|
||||
bool msb = false;
|
||||
if(ImageByteOrder(fl_display) == MSBFirst)
|
||||
msb = true;
|
||||
else
|
||||
msb = false;
|
||||
bool msb = (ImageByteOrder(fl_display) == MSBFirst) ? true : false;
|
||||
|
||||
unsigned int r, g, b, tmp;
|
||||
//unsigned char* dest = (unsigned char*)malloc(sizeof(unsigned char) * iw * ih * id);
|
||||
unsigned char* dest = (unsigned char*)malloc(ih * (*xim)->bytes_per_line);
|
||||
unsigned char* destptr = dest;
|
||||
unsigned char* src = (unsigned char*)img->data()[0];
|
||||
|
@ -257,8 +252,8 @@ static Pixmap create_xpixmap(Fl_Image* img, XImage** xim, Pixmap pix, int wp_w,
|
|||
*
|
||||
* FIXME: drawable background should be the same color as wallpaper background
|
||||
*/
|
||||
Window drawable = XCreateSimpleWindow(fl_display, RootWindow(fl_display, fl_screen), 0, 0, wp_w,
|
||||
wp_h, 0, 0, BlackPixel(fl_display, fl_screen));
|
||||
Window drawable = XCreateSimpleWindow(fl_display, RootWindow(fl_display, fl_screen), 0, 0, wp_w, wp_h,
|
||||
0, 0, BlackPixel(fl_display, fl_screen));
|
||||
|
||||
pix = XCreatePixmap(fl_display, drawable, wp_w, wp_h, fl_visual->depth);
|
||||
|
||||
|
@ -349,23 +344,18 @@ static void create_tile(Fl_Image* orig, Fl_RGB_Image** copied, int X, int Y, int
|
|||
}
|
||||
|
||||
Wallpaper::~Wallpaper() {
|
||||
if(rootpmap_pixmap)
|
||||
XFreePixmap(fl_display, rootpmap_pixmap);
|
||||
|
||||
if(rootpmap_pixmap) XFreePixmap(fl_display, rootpmap_pixmap);
|
||||
delete stretched_alloc;
|
||||
}
|
||||
|
||||
void Wallpaper::set_rootpmap(void) {
|
||||
if(!image())
|
||||
return;
|
||||
E_RETURN_IF_FAIL(image() != NULL);
|
||||
|
||||
XImage* rootpmap_image = 0;
|
||||
XImage *rootpmap_image = 0;
|
||||
Atom _XA_XROOTPMAP_ID;
|
||||
|
||||
|
||||
rootpmap_pixmap = create_xpixmap(image(), &rootpmap_image, rootpmap_pixmap, w(), h());
|
||||
|
||||
if(!rootpmap_pixmap)
|
||||
return;
|
||||
E_RETURN_IF_FAIL(rootpmap_pixmap != 0);
|
||||
|
||||
/* XDestroyImage function calls frees both the image structure and the data pointed to by the image structure */
|
||||
if(rootpmap_image)
|
||||
|
@ -374,60 +364,63 @@ void Wallpaper::set_rootpmap(void) {
|
|||
_XA_XROOTPMAP_ID = XInternAtom(fl_display, "_XROOTPMAP_ID", False);
|
||||
|
||||
XChangeProperty(fl_display, RootWindow(fl_display, fl_screen),
|
||||
_XA_XROOTPMAP_ID, XA_PIXMAP, 32, PropModeReplace, (unsigned char *)&rootpmap_pixmap, 1);
|
||||
_XA_XROOTPMAP_ID, XA_PIXMAP, 32, PropModeReplace, (unsigned char *)&rootpmap_pixmap, 1);
|
||||
}
|
||||
|
||||
bool Wallpaper::load(const char* path, WallpaperState s) {
|
||||
bool Wallpaper::load(const char *path, int s, bool rootpmap) {
|
||||
E_ASSERT(path != NULL);
|
||||
|
||||
Fl_Shared_Image* i = Fl_Shared_Image::get(path);
|
||||
if(!i)
|
||||
return false;
|
||||
|
||||
|
||||
Fl_Shared_Image *img = Fl_Shared_Image::get(path);
|
||||
E_RETURN_VAL_IF_FAIL(img != NULL, false);
|
||||
|
||||
if(s != WALLPAPER_CENTER && s != WALLPAPER_TILE && s != WALLPAPER_STRETCH)
|
||||
s = WALLPAPER_CENTER;
|
||||
|
||||
if(s == WALLPAPER_TILE) {
|
||||
Fl_RGB_Image* tiled;
|
||||
Fl_RGB_Image *tiled;
|
||||
|
||||
create_tile((Fl_Image*)i, &tiled, x(), y(), w(), h());
|
||||
create_tile((Fl_Image*)img, &tiled, x(), y(), w(), h());
|
||||
image(tiled);
|
||||
} else if(s == WALLPAPER_STRETCH) {
|
||||
Fl_Image* stretched = NULL;
|
||||
Fl_Image *stretched = NULL;
|
||||
|
||||
if(i->w() == w() && i->h() == h())
|
||||
stretched = i;
|
||||
if(img->w() == w() && img->h() == h())
|
||||
stretched = img;
|
||||
else {
|
||||
/* valgrind reports it as possible lost, but FLTK should free it */
|
||||
delete stretched_alloc;
|
||||
|
||||
stretched = i->copy(w(), h());
|
||||
i->release();
|
||||
|
||||
stretched = img->copy(w(), h());
|
||||
img->release();
|
||||
stretched_alloc = stretched;
|
||||
}
|
||||
|
||||
image(stretched);
|
||||
} else {
|
||||
image(i);
|
||||
image(img);
|
||||
}
|
||||
|
||||
state = s;
|
||||
|
||||
/* set root pixmap for pseudo transparency */
|
||||
set_rootpmap();
|
||||
if(rootpmap) set_rootpmap();
|
||||
|
||||
state = s;
|
||||
use_rootpmap = rootpmap;
|
||||
/* prevent self assignment or bad things will happen */
|
||||
if(wpath != path) wpath = path;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Wallpaper::draw(void) {
|
||||
if(!image())
|
||||
return;
|
||||
E_RETURN_IF_FAIL(image() != NULL);
|
||||
|
||||
int ix, iy, iw, ih;
|
||||
Fl_Image* im = image();
|
||||
|
||||
iw = im->w();
|
||||
ih = im->h();
|
||||
|
||||
if(iw == 0 || ih == 0)
|
||||
return;
|
||||
|
||||
E_RETURN_IF_FAIL(iw > 0 && ih > 0);
|
||||
|
||||
if(state == WALLPAPER_CENTER) {
|
||||
ix = (w()/2) - (iw/2);
|
||||
|
@ -475,3 +468,20 @@ int Wallpaper::handle(int event) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Wallpaper::resize(int X, int Y, int W, int H) {
|
||||
if(X == x() && Y == y() && W == w() && H == h())
|
||||
return;
|
||||
|
||||
Fl_Box::resize(X, Y, W, H);
|
||||
if(image()) {
|
||||
/*
|
||||
* It is safe to call 'load()' again, as Fl_Shared_Image::get() will cache successfully loaded image.
|
||||
* Also benefit is that image transormations (scaling, tiling) will be done again on original image, so
|
||||
* there will be no lost data.
|
||||
*
|
||||
* TODO: Fl_Shared_Image will eat a memory; this needs some investigation.
|
||||
*/
|
||||
load(wpath.c_str(), state, use_rootpmap);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,31 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ede-desktop, desktop and icon manager
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2006-2009 EDE Authors.
|
||||
*
|
||||
* This program is licensed under terms of the
|
||||
* GNU General Public License version 2 or newer.
|
||||
* See COPYING for details.
|
||||
* Copyright (C) 2006-2013 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __WALLPAPER_H__
|
||||
#define __WALLPAPER_H__
|
||||
|
||||
#include <X11/Xlib.h> // XImage, Pixmap
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/x.H>
|
||||
#include <edelib/String.h>
|
||||
|
||||
enum WallpaperState {
|
||||
enum {
|
||||
WALLPAPER_CENTER,
|
||||
WALLPAPER_STRETCH,
|
||||
WALLPAPER_TILE
|
||||
|
@ -26,21 +35,23 @@ class Fl_Image;
|
|||
|
||||
class Wallpaper : public Fl_Box {
|
||||
private:
|
||||
Pixmap rootpmap_pixmap;
|
||||
WallpaperState state;
|
||||
Fl_Image* stretched_alloc; /* FLTK issue */
|
||||
Pixmap rootpmap_pixmap;
|
||||
int state;
|
||||
Fl_Image* stretched_alloc; /* FLTK issue */
|
||||
bool use_rootpmap;
|
||||
EDELIB_NS_PREPEND(String) wpath;
|
||||
|
||||
void set_rootpmap(void);
|
||||
public:
|
||||
Wallpaper(int X, int Y, int W, int H) : Fl_Box(X, Y, W, H),
|
||||
rootpmap_pixmap(0), state(WALLPAPER_CENTER), stretched_alloc(NULL) { }
|
||||
|
||||
Wallpaper(int X, int Y, int W, int H) : Fl_Box(X, Y, W, H),
|
||||
rootpmap_pixmap(0), state(WALLPAPER_CENTER), stretched_alloc(NULL), use_rootpmap(false) { }
|
||||
~Wallpaper();
|
||||
|
||||
bool load(const char* path, WallpaperState s);
|
||||
bool load(const char *path, int s, bool do_rootpmap = true);
|
||||
|
||||
virtual void draw(void);
|
||||
virtual int handle(int event);
|
||||
void draw(void);
|
||||
int handle(int event);
|
||||
void resize(int X, int Y, int W, int H);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,174 +0,0 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ede-desktop, desktop and icon manager
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2006-2009 EDE Authors.
|
||||
*
|
||||
* This program is licensed under terms of the
|
||||
* GNU General Public License version 2 or newer.
|
||||
* See COPYING for details.
|
||||
*/
|
||||
|
||||
#ifndef __EDE_DESKTOP_H__
|
||||
#define __EDE_DESKTOP_H__
|
||||
|
||||
#ifdef USE_EDELIB_WINDOW
|
||||
# include <edelib/Window.h>
|
||||
# define EDE_DESKTOP_WINDOW edelib::Window
|
||||
#else
|
||||
# include <FL/Fl_Window.H>
|
||||
# include <FL/Fl_Double_Window.H>
|
||||
# define EDE_DESKTOP_WINDOW Fl_Window
|
||||
#endif
|
||||
|
||||
#include <FL/Fl_Image.H>
|
||||
|
||||
#include <edelib/String.h>
|
||||
#include <edelib/Resource.h>
|
||||
#include <edelib/List.h>
|
||||
#include <edelib/EdbusConnection.h>
|
||||
#include <edelib/MenuButton.h>
|
||||
|
||||
#define EDAMAGE_CHILD_LABEL 0x10
|
||||
#define EDAMAGE_OVERLAY 0x20
|
||||
|
||||
#define ICON_NORMAL 1 // .desktop file
|
||||
#define ICON_TRASH 2 // trash.desktop (specific since have two icons for empty/full)
|
||||
#define ICON_FILE 3 // real file
|
||||
#define ICON_SYMLINK 4 // symbolic link
|
||||
|
||||
#define ICON_FACE_ONE 1 // use icon
|
||||
#define ICON_FACE_TWO 2 // use icon2
|
||||
|
||||
struct GlobalIconSettings {
|
||||
int label_background;
|
||||
int label_foreground;
|
||||
int label_font;
|
||||
int label_fontsize;
|
||||
int label_maxwidth;
|
||||
bool label_transparent;
|
||||
bool label_draw;
|
||||
bool one_click_exec;
|
||||
bool auto_arrange;
|
||||
bool same_size;
|
||||
};
|
||||
|
||||
/*
|
||||
* Settings representing related to icon on desktop. To complicate our lives
|
||||
* (and to, at least, simplify code) it can be:
|
||||
* - .desktop file content (normal or trash like)
|
||||
* - real file copied/moved inside ~/Desktop directory
|
||||
* - symlink in ~/Desktop directory pointing to the real file
|
||||
*/
|
||||
struct IconSettings {
|
||||
int x, y;
|
||||
int type; // ICON_NORMAL, ICON_TRASH,...
|
||||
bool cmd_is_url; // interpret cmd as url, like system:/,trash:/,$HOME
|
||||
|
||||
edelib::String name;
|
||||
edelib::String cmd;
|
||||
edelib::String icon;
|
||||
edelib::String icon2; // for stateable icons, like trash (empty/full)
|
||||
edelib::String key_name; // name used as key when storing positions
|
||||
edelib::String full_path; // for tracking changes
|
||||
};
|
||||
|
||||
/* selection overlay */
|
||||
struct SelectionOverlay {
|
||||
int x, y, w, h;
|
||||
bool show;
|
||||
};
|
||||
|
||||
class Wallpaper;
|
||||
class DesktopIcon;
|
||||
|
||||
typedef edelib::list<DesktopIcon*> DesktopIconList;
|
||||
typedef edelib::list<DesktopIcon*>::iterator DesktopIconListIter;
|
||||
|
||||
typedef edelib::list<edelib::String> StringList;
|
||||
typedef edelib::list<edelib::String>::iterator StringListIter;
|
||||
|
||||
class Desktop : public EDE_DESKTOP_WINDOW {
|
||||
private:
|
||||
static Desktop* pinstance;
|
||||
|
||||
int selection_x, selection_y;
|
||||
|
||||
/* last recorded pointer position, so icon can be created at position where menu is clicked */
|
||||
int last_px, last_py;
|
||||
|
||||
bool moving;
|
||||
bool do_dirwatch;
|
||||
|
||||
edelib::String desktop_dir_path;
|
||||
|
||||
SelectionOverlay* selbox;
|
||||
|
||||
GlobalIconSettings* gisett;
|
||||
|
||||
edelib::MenuButton* dmenu;
|
||||
Wallpaper* wallpaper;
|
||||
edelib::EdbusConnection* dbus;
|
||||
|
||||
DesktopIconList icons;
|
||||
DesktopIconList selectionbuf;
|
||||
|
||||
void init_internals(void);
|
||||
|
||||
void load_icons(const char* path);
|
||||
void save_icons_positions(void);
|
||||
IconSettings* read_desktop_file(const char* path);
|
||||
|
||||
void add_icon(DesktopIcon* ic);
|
||||
|
||||
DesktopIcon* find_icon_by_path(const char* path, DesktopIconListIter* pos);
|
||||
bool remove_icon_by_path(const char* path);
|
||||
|
||||
void auto_arrange(void);
|
||||
|
||||
void unfocus_all(void);
|
||||
|
||||
void select(DesktopIcon* ic, bool do_redraw = true);
|
||||
void select_only(DesktopIcon* ic);
|
||||
bool in_selection(const DesktopIcon* ic);
|
||||
void move_selection(int x, int y, bool apply);
|
||||
|
||||
void select_in_area(void);
|
||||
|
||||
//void dnd_drop_source(const char* src, int src_len, int x, int y);
|
||||
|
||||
DesktopIcon* below_mouse(int px, int py);
|
||||
|
||||
public:
|
||||
Desktop();
|
||||
~Desktop();
|
||||
|
||||
virtual void show(void);
|
||||
virtual void hide(void);
|
||||
virtual void draw(void);
|
||||
virtual int handle(int event);
|
||||
|
||||
static void init(void);
|
||||
static void shutdown(void);
|
||||
static Desktop* instance(void);
|
||||
|
||||
void read_config(void);
|
||||
|
||||
bool add_icon_by_path(const char* path, edelib::Resource* conf);
|
||||
bool remove_icon(DesktopIcon *d, bool real_delete);
|
||||
bool rename_icon(DesktopIcon *d, const char *n);
|
||||
|
||||
void update_workarea(void);
|
||||
void area(int& X, int& Y, int& W, int& H) { X = x(); Y = y(); W = w(); H = h(); }
|
||||
|
||||
void notify_desktop_changed(void);
|
||||
|
||||
void dir_watch(const char* dir, const char* changed, int flags);
|
||||
void dir_watch_on(void) { do_dirwatch = true; }
|
||||
void dir_watch_off(void) { do_dirwatch = false; }
|
||||
|
||||
const char *desktop_path(void) { return desktop_dir_path.c_str(); }
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,42 +1,72 @@
|
|||
# data file for the Fltk User Interface Designer (fluid)
|
||||
version 1.0300
|
||||
version 1.0302
|
||||
header_name {.h}
|
||||
code_name {.cxx}
|
||||
Function {} {open
|
||||
} {
|
||||
Fl_Window {} {open
|
||||
xywh {474 344 430 170} type Double visible
|
||||
xywh {426 288 450 220} type Double visible
|
||||
} {
|
||||
Fl_Button {} {
|
||||
xywh {10 10 75 75}
|
||||
}
|
||||
Fl_Input {} {
|
||||
label {Name:}
|
||||
xywh {205 10 215 25}
|
||||
}
|
||||
Fl_Input {} {
|
||||
label {Comment:}
|
||||
xywh {205 40 215 25}
|
||||
}
|
||||
Fl_Input {} {
|
||||
label {Execute:} selected
|
||||
xywh {205 70 185 25}
|
||||
}
|
||||
Fl_Button {} {
|
||||
label {...}
|
||||
xywh {395 70 25 25}
|
||||
}
|
||||
Fl_Choice {} {
|
||||
label {Type:} open
|
||||
xywh {205 100 215 25} down_box BORDER_BOX
|
||||
} {}
|
||||
Fl_Button {} {
|
||||
label {&OK}
|
||||
xywh {235 135 90 25}
|
||||
Fl_Tabs {} {open
|
||||
xywh {10 10 430 165}
|
||||
} {
|
||||
Fl_Group {} {
|
||||
label Basic open
|
||||
xywh {15 30 415 140}
|
||||
} {
|
||||
Fl_Button {} {selected
|
||||
xywh {20 45 80 75}
|
||||
}
|
||||
Fl_Input {} {
|
||||
label {Name:}
|
||||
xywh {210 45 215 25}
|
||||
}
|
||||
Fl_Input {} {
|
||||
label {Comment:}
|
||||
xywh {210 75 215 25}
|
||||
}
|
||||
Fl_Input {} {
|
||||
label {Execute:}
|
||||
xywh {210 105 185 25}
|
||||
}
|
||||
Fl_Button {} {
|
||||
label {...}
|
||||
xywh {400 105 25 25}
|
||||
}
|
||||
Fl_Choice {} {
|
||||
label {Type:} open
|
||||
xywh {210 135 215 25} down_box BORDER_BOX
|
||||
} {}
|
||||
}
|
||||
Fl_Group {} {
|
||||
label Details open
|
||||
xywh {15 30 420 140} hide
|
||||
} {
|
||||
Fl_Check_Button {} {
|
||||
label {Run in terminal}
|
||||
xywh {195 80 235 25} down_box DOWN_BOX
|
||||
}
|
||||
Fl_Input {} {
|
||||
label {Working directory:}
|
||||
xywh {195 45 205 25}
|
||||
}
|
||||
Fl_Button {} {
|
||||
label {...}
|
||||
xywh {405 45 25 25}
|
||||
}
|
||||
Fl_Check_Button {} {
|
||||
label {Use startup notification}
|
||||
xywh {195 110 235 25} down_box DOWN_BOX
|
||||
}
|
||||
}
|
||||
}
|
||||
Fl_Button {} {
|
||||
label {&Cancel}
|
||||
xywh {330 135 90 25}
|
||||
xywh {350 185 90 25}
|
||||
}
|
||||
Fl_Button {} {
|
||||
label {&OK}
|
||||
xywh {255 185 90 25}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,9 +125,17 @@ static void fetch_current_layout(String ¤t) {
|
|||
XFree(vd.variant);
|
||||
}
|
||||
|
||||
static int sort_cmp(const void *a, const void *b) {
|
||||
XkbRF_VarDescPtr first = (XkbRF_VarDescPtr)a;
|
||||
XkbRF_VarDescPtr second = (XkbRF_VarDescPtr)b;
|
||||
|
||||
return strcmp(first->desc, second->desc);
|
||||
}
|
||||
|
||||
static XkbRF_RulesPtr fetch_all_layouts(const String ¤t) {
|
||||
char buf[256];
|
||||
XkbRF_RulesPtr xkb_rules = NULL;
|
||||
char buf[256];
|
||||
XkbRF_RulesPtr xkb_rules = NULL;
|
||||
XkbRF_DescribeVarsPtr layouts = NULL;
|
||||
|
||||
/* try to locate rules file */
|
||||
for(int i = 0; x11_dirs[i]; i++) {
|
||||
|
@ -144,13 +152,18 @@ static XkbRF_RulesPtr fetch_all_layouts(const String ¤t) {
|
|||
E_WARNING(E_STRLOC ": Unable to load keyboard rules file\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
done:
|
||||
for(int i = 0; i < xkb_rules->layouts.num_desc; i++) {
|
||||
snprintf(buf, sizeof(buf), "%s\t%s", xkb_rules->layouts.desc[i].name, xkb_rules->layouts.desc[i].desc);
|
||||
layouts = &xkb_rules->layouts;
|
||||
|
||||
/* sort them */
|
||||
qsort(layouts->desc, layouts->num_desc, sizeof(XkbRF_VarDescRec), sort_cmp);
|
||||
|
||||
for(int i = 0; i < layouts->num_desc; i++) {
|
||||
snprintf(buf, sizeof(buf), "%s\t%s", layouts->desc[i].name, layouts->desc[i].desc);
|
||||
layout_browser->add(buf);
|
||||
|
||||
if(current == xkb_rules->layouts.desc[i].name) {
|
||||
if(current == layouts->desc[i].name) {
|
||||
/* Fl_Browser counts items from 1 */
|
||||
layout_browser->select(i + 1);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,21 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ede-launch, launch external application
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2008-2009 EDE Authors.
|
||||
*
|
||||
* This program is licensed under terms of the
|
||||
* GNU General Public License version 2 or newer.
|
||||
* See COPYING for details.
|
||||
* Copyright (C) 2012-2014 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
@ -46,7 +54,9 @@
|
|||
#include <edelib/DesktopFile.h>
|
||||
#include <edelib/StrUtil.h>
|
||||
#include <edelib/Debug.h>
|
||||
#include <edelib/Directory.h>
|
||||
#include <edelib/Regex.h>
|
||||
#include <edelib/Util.h>
|
||||
#include <edelib/Ede.h>
|
||||
#include "StartupNotify.h"
|
||||
|
||||
|
@ -58,22 +68,40 @@
|
|||
/* config name where all things are stored and read from */
|
||||
#define EDE_LAUNCH_CONFIG "ede-launch"
|
||||
|
||||
/* default 'Preferred' key in config file */
|
||||
#define KEY_PREFERRED "Preferred"
|
||||
|
||||
/* patterns for guessing user input */
|
||||
#define REGEX_PATTERN_MAIL "\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}\\b"
|
||||
#define REGEX_PATTERN_URL "((http|https|ftp|gopher|!file):\\/\\/|www)[a-zA-Z0-9\\-\\._]+\\/?[a-zA-Z0-9_\\.\\-\\?\\+\\/~=&#;,]*[a-zA-Z0-9\\/]{1}"
|
||||
|
||||
/* list of known terminals */
|
||||
static const char *known_terminals[] = {
|
||||
"xterm",
|
||||
"rxvt",
|
||||
"urxvt",
|
||||
"mrxvt",
|
||||
"st",
|
||||
"Terminal",
|
||||
"gnome-terminal",
|
||||
"konsole",
|
||||
0
|
||||
};
|
||||
|
||||
EDELIB_NS_USING_AS(Window, LaunchWindow)
|
||||
EDELIB_NS_USING_LIST(12, (Resource,
|
||||
EDELIB_NS_USING_LIST(14, (Resource,
|
||||
Regex,
|
||||
String,
|
||||
list,
|
||||
DesktopFile,
|
||||
RES_USER_ONLY,
|
||||
DESK_FILE_TYPE_APPLICATION,
|
||||
run_sync, run_async, alert, file_path, window_center_on_screen, str_ends))
|
||||
run_sync, run_async, alert, file_path, window_center_on_screen, str_ends, system_data_dirs))
|
||||
|
||||
static Fl_Pixmap image_run((const char**)run_xpm);
|
||||
static Fl_Input* dialog_input;
|
||||
static Fl_Check_Button* in_term;
|
||||
static Fl_Check_Button *in_term;
|
||||
static Resource launcher_resource; /* lazy loaded */
|
||||
|
||||
static void help(void) {
|
||||
puts("Usage: ede-launch [OPTIONS] [PROGRAM]");
|
||||
|
@ -103,34 +131,28 @@ static int re_match(const char *p, const char *str) {
|
|||
return re.match(str);
|
||||
}
|
||||
|
||||
static const char *resource_get(Resource &rc, const char *g, const char *k) {
|
||||
static char buf[64];
|
||||
static const char *resource_get(const char *g, const char *k) {
|
||||
if(!launcher_resource)
|
||||
launcher_resource.load(EDE_LAUNCH_CONFIG);
|
||||
|
||||
if(!rc) rc.load(EDE_LAUNCH_CONFIG);
|
||||
E_RETURN_VAL_IF_FAIL(rc != false, NULL);
|
||||
E_RETURN_VAL_IF_FAIL(launcher_resource != false, NULL);
|
||||
|
||||
if(rc.get(g, k, buf, sizeof(buf)))
|
||||
return (const char*)buf;
|
||||
|
||||
return NULL;
|
||||
static char buf[128];
|
||||
return launcher_resource.get(g, k, buf, sizeof(buf)) ? (const char*)buf : NULL;
|
||||
}
|
||||
|
||||
static char* get_basename(const char* path) {
|
||||
char *p = (char*)strrchr(path, '/');
|
||||
if(p)
|
||||
return (p + 1);
|
||||
|
||||
return (char*)p;
|
||||
static char *get_basename(const char* path) {
|
||||
char *p = (char*)strrchr(path, E_DIR_SEPARATOR);
|
||||
return p ? p + 1 : p;
|
||||
}
|
||||
|
||||
static char** cmd_split(const char* cmd) {
|
||||
int sz = 10;
|
||||
int i = 0;
|
||||
char* c = strdup(cmd);
|
||||
static char **cmd_split(const char* cmd) {
|
||||
int i = 0, sz = 10;
|
||||
char *c = strdup(cmd);
|
||||
|
||||
char** arr = (char**)malloc(sizeof(char*) * sz);
|
||||
char **arr = (char**)malloc(sizeof(char*) * sz);
|
||||
|
||||
for(char* p = strtok(c, " "); p; p = strtok(NULL, " ")) {
|
||||
for(char *p = strtok(c, " "); p; p = strtok(NULL, " ")) {
|
||||
if(i >= sz) {
|
||||
sz *= 2;
|
||||
arr = (char**)realloc(arr, sizeof(char*) * sz);
|
||||
|
@ -165,9 +187,34 @@ static bool allowed_launch_type(const char *t) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static void start_crasher(const char* cmd, int sig) {
|
||||
const char* base = get_basename(cmd);
|
||||
const char* ede_app_flag = "";
|
||||
#define RETURN_IF_VALID_TERM(t, r) \
|
||||
do { \
|
||||
if(t && ((strcmp(t, "linux") != 0) || (strcmp(t, "dumb") != 0))) { \
|
||||
r = file_path(t, false); \
|
||||
if(E_UNLIKELY(r.empty())) return true; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static bool find_terminal(String &ret) {
|
||||
const char *term = resource_get(KEY_PREFERRED, "terminal");
|
||||
if(term) {
|
||||
ret = term;
|
||||
return true;
|
||||
}
|
||||
|
||||
term = getenv("EDE_LAUNCH_TERMINAL");
|
||||
RETURN_IF_VALID_TERM(term, ret);
|
||||
|
||||
for(int i = 0; known_terminals[i]; i++) {
|
||||
term = known_terminals[i];
|
||||
RETURN_IF_VALID_TERM(term, ret);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void start_crasher(const char* cmd, int sig, int pid) {
|
||||
const char *ede_app_flag = "", *base = get_basename(cmd);
|
||||
|
||||
/* this means the app was called without full path */
|
||||
if(!base) base = cmd;
|
||||
|
@ -176,11 +223,11 @@ static void start_crasher(const char* cmd, int sig) {
|
|||
* determine is our app by checking the prefix; we don't want user to send bug reports about crashes
|
||||
* of foreign applications
|
||||
*/
|
||||
if(strncmp(base, "ede-", 4) == 0)
|
||||
if((strncmp(base, "ede-", 4) == 0) || (strncmp(base, "edelib-", 7) == 0))
|
||||
ede_app_flag = "--edeapp";
|
||||
|
||||
/* call edelib implementation instead start_child_process() to prevents loops if 'ede-crasher' crashes */
|
||||
run_sync(PREFIX "/bin/ede-crasher %s --appname %s --apppath %s --signal %i", ede_app_flag, base, cmd, sig);
|
||||
run_sync(PREFIX "/bin/ede-crasher %s --appname %s --apppath %s --signal %i --pid %i", ede_app_flag, base, cmd, sig, pid);
|
||||
}
|
||||
|
||||
static int start_child_process(const char* cmd) {
|
||||
|
@ -258,7 +305,7 @@ static int start_child_process(const char* cmd) {
|
|||
if(WIFEXITED(status)) {
|
||||
ret = WEXITSTATUS(status);
|
||||
} else if(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV) {
|
||||
start_crasher(cmd, SIGSEGV);
|
||||
start_crasher(cmd, SIGSEGV, pid);
|
||||
} else {
|
||||
E_WARNING(E_STRLOC ": child '%s' killed\n", cmd);
|
||||
}
|
||||
|
@ -267,6 +314,11 @@ static int start_child_process(const char* cmd) {
|
|||
}
|
||||
|
||||
static int start_child_process_with_core(const char* cmd) {
|
||||
#ifndef __minix
|
||||
/*
|
||||
* Minix does not have setrlimit() so we disable everything as by default it
|
||||
* will dump core.
|
||||
*/
|
||||
struct rlimit r;
|
||||
errno = 0;
|
||||
|
||||
|
@ -282,25 +334,29 @@ static int start_child_process_with_core(const char* cmd) {
|
|||
E_WARNING(E_STRLOC ": setrlimit() failed with '%s'\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
int ret = start_child_process(cmd);
|
||||
|
||||
#ifndef __minix
|
||||
r.rlim_cur = old;
|
||||
if(setrlimit(RLIMIT_CORE, &r) == -1) {
|
||||
E_WARNING(E_STRLOC ": setrlimit() failed with '%s'\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool start_child(const char* cmd) {
|
||||
static bool start_child(const char *cmd, bool notify = false) {
|
||||
E_DEBUG(E_STRLOC ": Starting '%s'\n", cmd);
|
||||
StartupNotify *n;
|
||||
|
||||
if(notify) n = startup_notify_start(cmd, "applications-order");
|
||||
|
||||
StartupNotify *n = startup_notify_start(cmd, "applications-order");
|
||||
int ret = start_child_process_with_core(cmd);
|
||||
|
||||
startup_notify_end(n);
|
||||
if(notify) startup_notify_end(n);
|
||||
|
||||
if(ret == 199) {
|
||||
alert(_("Program '%s' not found.\n\nPlease check if given path to the "
|
||||
|
@ -323,29 +379,56 @@ static bool start_child(const char* cmd) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool start_child_in_term(const char *cmd, bool notify = false) {
|
||||
String term;
|
||||
|
||||
if(!find_terminal(term)) {
|
||||
E_WARNING(E_STRLOC ": unable to find any suitable terminal\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* construct TERM -e cmd */
|
||||
term += " -e ";
|
||||
term += cmd;
|
||||
return start_child(term.c_str(), notify);
|
||||
}
|
||||
|
||||
static bool start_desktop_file(const char *cmd) {
|
||||
DesktopFile d;
|
||||
|
||||
if(!d.load(cmd)) {
|
||||
alert(_("Unable to load .desktop file '%s'. Got: %s"), cmd, d.strerror());
|
||||
goto FAIL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(d.type() != DESK_FILE_TYPE_APPLICATION) {
|
||||
alert(_("Starting other types of .desktop files except 'Application' is not supported now"));
|
||||
goto FAIL;
|
||||
return false;
|
||||
}
|
||||
|
||||
char buf[PATH_MAX];
|
||||
if(!d.exec(buf, PATH_MAX)) {
|
||||
alert(_("Unable to run '%s'.\nProbably this file is malformed or 'Exec' key has non-installed program"), cmd);
|
||||
goto FAIL;
|
||||
|
||||
/*
|
||||
* Determine working directory and set it first, to reuse buffer. Note that
|
||||
* it will override working directory path set from command line.
|
||||
*/
|
||||
if(d.path(buf, PATH_MAX)) {
|
||||
errno = 0;
|
||||
if(chdir(buf) < 0) {
|
||||
alert(_("Unable to change directory to '%s'. Got '%s' (%i)"), buf, strerror(errno), errno);
|
||||
}
|
||||
}
|
||||
|
||||
return start_child(buf);
|
||||
if(!d.exec(buf, PATH_MAX)) {
|
||||
alert(_("Unable to run '%s'.\nProbably the file is malformed or 'Exec' key has program which is not installed"), cmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
FAIL:
|
||||
return false;
|
||||
bool notify = d.startup_notify();
|
||||
if(d.terminal())
|
||||
return start_child_in_term(buf, notify);
|
||||
|
||||
return start_child(buf, notify);
|
||||
}
|
||||
|
||||
/* concat all arguments preparing it for start_child() */
|
||||
|
@ -398,48 +481,6 @@ static void cancel_cb(Fl_Widget*, void* w) {
|
|||
win->hide();
|
||||
}
|
||||
|
||||
#define RETURN_IF_VALID_TERM(t, r) \
|
||||
do { \
|
||||
if(t && ((strcmp(t, "linux") != 0) || (strcmp(t, "dumb") != 0))) { \
|
||||
r = file_path(t, false); \
|
||||
if(E_UNLIKELY(r.empty())) return true; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static bool find_terminal(String &ret) {
|
||||
/* before goint to list, try to read it from config file */
|
||||
Resource rc;
|
||||
const char *t = resource_get(rc, "Preferred", "terminal");
|
||||
if(t) {
|
||||
ret = t;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* list of known terminals */
|
||||
static const char *terms[] = {
|
||||
"xterm",
|
||||
"rxvt",
|
||||
"Terminal",
|
||||
"gnome-terminal",
|
||||
"konsole",
|
||||
0
|
||||
};
|
||||
|
||||
const char* term = getenv("TERM");
|
||||
|
||||
RETURN_IF_VALID_TERM(term, ret);
|
||||
|
||||
term = getenv("COLORTERM");
|
||||
RETURN_IF_VALID_TERM(term, ret);
|
||||
|
||||
for(int i = 0; terms[i]; i++) {
|
||||
term = terms[i];
|
||||
RETURN_IF_VALID_TERM(term, ret);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ok_cb(Fl_Widget*, void* w) {
|
||||
LaunchWindow* win = (LaunchWindow*)w;
|
||||
const char* cmd = dialog_input->value();
|
||||
|
@ -451,19 +492,7 @@ static void ok_cb(Fl_Widget*, void* w) {
|
|||
Fl::check();
|
||||
|
||||
/* TODO: is 'cmd' safe after hide? */
|
||||
if(in_term->value()) {
|
||||
char buf[128];
|
||||
String term;
|
||||
|
||||
if(find_terminal(term)) {
|
||||
snprintf(buf, sizeof(buf), "%s -e %s", term.c_str(), cmd);
|
||||
started = start_child(buf);
|
||||
} else {
|
||||
E_WARNING(E_STRLOC ": unable to find any suitable terminal\n");
|
||||
}
|
||||
} else {
|
||||
started = start_child(cmd);
|
||||
}
|
||||
started = (in_term->value()) ? start_child_in_term(cmd) : start_child(cmd);
|
||||
|
||||
if(!started) {
|
||||
/* show dialog again */
|
||||
|
@ -473,6 +502,7 @@ static void ok_cb(Fl_Widget*, void* w) {
|
|||
dialog_input->position(0, dialog_input->size());
|
||||
} else {
|
||||
Resource rc;
|
||||
|
||||
/* so could load previous content */
|
||||
rc.load(EDE_LAUNCH_CONFIG);
|
||||
rc.set("History", "open", cmd);
|
||||
|
@ -491,12 +521,9 @@ static int start_dialog(int argc, char** argv) {
|
|||
|
||||
dialog_input = new Fl_Input(70, 90, 290, 25, _("Open:"));
|
||||
|
||||
Resource rc;
|
||||
char buf[128];
|
||||
|
||||
if(rc.load(EDE_LAUNCH_CONFIG) && rc.get("History", "open", buf, sizeof(buf))) {
|
||||
dialog_input->value(buf);
|
||||
|
||||
const char *cmd = resource_get("History", "open");
|
||||
if(cmd) {
|
||||
dialog_input->value(cmd);
|
||||
/* make text appear selected */
|
||||
dialog_input->position(0, dialog_input->size());
|
||||
}
|
||||
|
@ -597,19 +624,18 @@ int main(int argc, char** argv) {
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* check if we have .desktop file */
|
||||
if(argv[ca] && str_ends(argv[ca], ".desktop"))
|
||||
return RETURN_FROM_BOOL(start_desktop_file(argv[ca]));
|
||||
|
||||
/* make arguments and exec program */
|
||||
String args;
|
||||
Resource rc;
|
||||
const char *prog = NULL;
|
||||
|
||||
if(launch_type) {
|
||||
/* explicitly launch what user requested */
|
||||
prog = resource_get(rc, "Preferred", launch_type);
|
||||
prog = resource_get(KEY_PREFERRED, launch_type);
|
||||
|
||||
if(!prog) {
|
||||
E_WARNING(E_STRLOC ": Unable to find out launch type\n");
|
||||
|
@ -625,7 +651,7 @@ int main(int argc, char** argv) {
|
|||
* Note however how this matching works on only one argument; other would be ignored
|
||||
*/
|
||||
if(re_match(REGEX_PATTERN_MAIL, argv[ca]) > 0) {
|
||||
prog = resource_get(rc, "Preferred", "mail");
|
||||
prog = resource_get(KEY_PREFERRED, "mail");
|
||||
if(!prog) {
|
||||
E_WARNING(E_STRLOC ": Unable to find mail agent\n");
|
||||
return 1;
|
||||
|
@ -636,7 +662,7 @@ int main(int argc, char** argv) {
|
|||
/* use only one argumet */
|
||||
argc = ca + 1;
|
||||
} else if(re_match(REGEX_PATTERN_URL, argv[ca]) > 0) {
|
||||
prog = resource_get(rc, "Preferred", "browser");
|
||||
prog = resource_get(KEY_PREFERRED, "browser");
|
||||
if(!prog) {
|
||||
E_WARNING(E_STRLOC ": Unable to find browser\n");
|
||||
return 1;
|
||||
|
|
|
@ -13,7 +13,7 @@ SubDir TOP ede-notify-daemon ;
|
|||
SOURCE = ede-notify-daemon.cpp NotifyWindow.cpp ;
|
||||
|
||||
EdeProgram ede-notify-daemon : $(SOURCE) ;
|
||||
LinkAgainst ede-notify-daemon : $(EDELIB_DBUS_LIB) ;
|
||||
LinkAgainst ede-notify-daemon : $(EDELIB_DBUS_LIB) $(PTHREAD_LIBS) ;
|
||||
|
||||
TranslationStrings locale : $(SOURCE) ;
|
||||
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
/*
|
||||
* $Id: ede-panel.cpp 3330 2012-05-28 10:57:50Z karijes $
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/x.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
@ -31,6 +51,8 @@ static void timeout_cb(void *w) {
|
|||
NotifyWindow::NotifyWindow() : Fl_Window(DEFAULT_W, DEFAULT_H) {
|
||||
FL_NORMAL_SIZE = 12;
|
||||
|
||||
timer_set = 0;
|
||||
|
||||
type(NOTIFYWINDOW_TYPE);
|
||||
color(FL_BACKGROUND2_COLOR);
|
||||
box(FL_BORDER_BOX);
|
||||
|
@ -67,6 +89,24 @@ NotifyWindow::NotifyWindow() : Fl_Window(DEFAULT_W, DEFAULT_H) {
|
|||
border(0);
|
||||
}
|
||||
|
||||
void NotifyWindow::add_timeout(void) {
|
||||
E_DEBUG(E_STRLOC ": adding timer\n");
|
||||
if(timer_set) return;
|
||||
|
||||
if(exp == -1) exp = DEFAULT_EXPIRE;
|
||||
Fl::add_timeout((double)exp / (double)1000, timeout_cb, this);
|
||||
|
||||
timer_set = 1;
|
||||
}
|
||||
|
||||
void NotifyWindow::remove_timeout(void) {
|
||||
E_DEBUG(E_STRLOC ": removing timer\n");
|
||||
if(!timer_set) return;
|
||||
|
||||
Fl::remove_timeout(timeout_cb);
|
||||
timer_set = 0;
|
||||
}
|
||||
|
||||
void NotifyWindow::set_icon(const char *img) {
|
||||
E_RETURN_IF_FAIL(IconLoader::inited());
|
||||
E_RETURN_IF_FAIL(img != NULL);
|
||||
|
@ -75,17 +115,17 @@ void NotifyWindow::set_icon(const char *img) {
|
|||
}
|
||||
|
||||
void NotifyWindow::set_body(const char *s) {
|
||||
summary->resize(summary->x(), summary->y() - (summary->h() / 2), summary->w(), summary->h());
|
||||
summary->resize(65, 10, 185, 25);
|
||||
//summary->resize(summary->x(), summary->y() - (summary->h() / 2), summary->w(), summary->h());
|
||||
|
||||
body->value(s);
|
||||
body->show();
|
||||
}
|
||||
|
||||
void NotifyWindow::show(void) {
|
||||
if(exp != 0) {
|
||||
if(exp == -1) exp = DEFAULT_EXPIRE;
|
||||
Fl::add_timeout((double)exp / (double)1000, timeout_cb, this);
|
||||
}
|
||||
/* the case when timer should not be added */
|
||||
if(exp != 0)
|
||||
add_timeout();
|
||||
|
||||
Fl_Window::show();
|
||||
netwm_window_set_type(fl_xid(this), NETWM_WINDOW_TYPE_NOTIFICATION);
|
||||
|
@ -98,7 +138,7 @@ void NotifyWindow::resize(int X, int Y, int W, int H) {
|
|||
* do not call further if window is shown: different strategy is needed as every time
|
||||
* window is re-configured, this will be called
|
||||
*/
|
||||
if(shown()) return;
|
||||
//if(shown()) return;
|
||||
|
||||
/* resize summary if needed */
|
||||
if(summary->size() > 0) {
|
||||
|
@ -161,3 +201,17 @@ void NotifyWindow::resize(int X, int Y, int W, int H) {
|
|||
|
||||
Fl_Window::resize(X, Y, W, H);
|
||||
}
|
||||
|
||||
int NotifyWindow::handle(int event) {
|
||||
switch(event) {
|
||||
case FL_ENTER:
|
||||
remove_timeout();
|
||||
goto done;
|
||||
case FL_LEAVE:
|
||||
add_timeout();
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
return Fl_Window::handle(event);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
/*
|
||||
* $Id: ede-panel.cpp 3330 2012-05-28 10:57:50Z karijes $
|
||||
*
|
||||
* Copyright (C) 2012-2014 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NOTIFYWINDOW_H__
|
||||
#define __NOTIFYWINDOW_H__
|
||||
|
||||
|
@ -11,16 +31,19 @@
|
|||
|
||||
class NotifyWindow : public Fl_Window {
|
||||
private:
|
||||
int id, exp;
|
||||
unsigned int id;
|
||||
int exp, timer_set;
|
||||
Fl_Button *closeb;
|
||||
Fl_Box *imgbox;
|
||||
Fl_Multiline_Output *summary, *body;
|
||||
|
||||
void add_timeout(void);
|
||||
void remove_timeout(void);
|
||||
public:
|
||||
NotifyWindow();
|
||||
|
||||
void set_id(int i) { id = i; }
|
||||
int get_id(void) { return id; }
|
||||
void set_id(unsigned int i) { id = i; }
|
||||
unsigned int get_id(void) { return id; }
|
||||
|
||||
void set_icon(const char *img);
|
||||
void set_summary(const char *s) { summary->value(s); }
|
||||
|
@ -30,10 +53,18 @@ public:
|
|||
* match to spec: if is -1, then we handle it, if is 0, then window will not be closed and
|
||||
* the rest is sender specific
|
||||
*/
|
||||
void set_expire(int t) { exp = t; }
|
||||
void set_expire(int t, bool update_timer) {
|
||||
exp = t;
|
||||
// if(update_timer) {
|
||||
// remove_timeout();
|
||||
// add_timeout();
|
||||
// }
|
||||
}
|
||||
|
||||
void show(void);
|
||||
|
||||
virtual void resize(int X, int Y, int W, int H);
|
||||
virtual int handle(int event);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
/*
|
||||
* $Id: ede-panel.cpp 3330 2012-05-28 10:57:50Z karijes $
|
||||
*
|
||||
* Copyright (C) 2012-2014 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
@ -6,11 +26,13 @@
|
|||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <edelib/Ede.h>
|
||||
#include <edelib/Debug.h>
|
||||
|
||||
#ifdef EDELIB_HAVE_DBUS
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Shared_Image.H>
|
||||
|
||||
#include <edelib/Ede.h>
|
||||
#include <edelib/Debug.h>
|
||||
#include <edelib/EdbusConnection.h>
|
||||
#include <edelib/EdbusMessage.h>
|
||||
#include <edelib/EdbusData.h>
|
||||
|
@ -25,7 +47,7 @@
|
|||
/* server info sent via GetServerInformation */
|
||||
#define EDE_NOTIFY_DAEMON_NAME "EDE Notification Daemon"
|
||||
#define EDE_NOTIFY_DAEMON_VENDOR "ede"
|
||||
#define EDE_NOTIFY_DAEMON_VERSION "0.1"
|
||||
#define EDE_NOTIFY_DAEMON_VERSION "0.2"
|
||||
#define EDE_NOTIFY_DAEMON_SPEC_VERSION "1.2"
|
||||
|
||||
#define NOTIFICATIONS_DBUS_PATH "/org/freedesktop/Notifications"
|
||||
|
@ -43,7 +65,6 @@
|
|||
#define WINDOWS_PADDING 10
|
||||
|
||||
#define IS_MEMBER(m, s1) (strcmp((m->member()), (s1)) == 0)
|
||||
#define CHECK_ARGV(argv, pshort, plong) ((strcmp(argv, pshort) == 0) || (strcmp(argv, plong) == 0))
|
||||
|
||||
EDELIB_NS_USING(EdbusConnection)
|
||||
EDELIB_NS_USING(EdbusMessage)
|
||||
|
@ -62,7 +83,8 @@ static bool server_running;
|
|||
* list of server capabilities
|
||||
* check all available on: http://people.gnome.org/~mccann/docs/notification-spec/notification-spec-latest.html
|
||||
*/
|
||||
static const char *server_caps[] = {"actions", "body", "icon-static", 0};
|
||||
// static const char *server_caps[] = {"actions", "body", "icon-static", 0};
|
||||
static const char *server_caps[] = {"body", "icon-static", 0};
|
||||
|
||||
/* increased every time new notification window is shown; must be less than UINT_MAX */
|
||||
static unsigned int notify_id;
|
||||
|
@ -107,22 +129,40 @@ static bool get_int_coordinate(const char *n, EdbusDict &hints, int &c) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void show_window(unsigned int id,
|
||||
const char *app_name,
|
||||
const char *app_icon,
|
||||
const char *summary,
|
||||
const char *body,
|
||||
int expire_timeout,
|
||||
EdbusDict &hints)
|
||||
static void show_or_update_window(bool update_only,
|
||||
unsigned int id,
|
||||
const char *app_name,
|
||||
const char *app_icon,
|
||||
const char *summary,
|
||||
const char *body,
|
||||
int expire_timeout,
|
||||
EdbusDict &hints)
|
||||
{
|
||||
byte_t u = get_urgency_level(hints);
|
||||
NotifyWindow *win = NULL;
|
||||
|
||||
NotifyWindow *win = new NotifyWindow();
|
||||
if(update_only) {
|
||||
E_DEBUG(E_STRLOC ": Requesting update\n");
|
||||
/* try to find existing window with given id */
|
||||
Fl_Window *wi;
|
||||
NotifyWindow *tmp;
|
||||
|
||||
if(!empty_str(summary))
|
||||
win->set_summary(summary);
|
||||
if(!empty_str(body))
|
||||
win->set_body(body);
|
||||
for(wi = Fl::first_window(); wi; wi = Fl::next_window(wi)) {
|
||||
if(wi->type() != NOTIFYWINDOW_TYPE) continue;
|
||||
tmp = (NotifyWindow*)wi;
|
||||
if(tmp->get_id() == id) {
|
||||
E_DEBUG(E_STRLOC ": Requesting update - win found\n");
|
||||
win = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* window not found or new window requested */
|
||||
if(!win) win = new NotifyWindow();
|
||||
|
||||
if(!empty_str(summary)) win->set_summary(summary);
|
||||
if(!empty_str(body)) win->set_body(body);
|
||||
if(empty_str(app_icon)) {
|
||||
switch(u) {
|
||||
case URGENCY_CRITICAL:
|
||||
|
@ -137,7 +177,7 @@ static void show_window(unsigned int id,
|
|||
|
||||
win->set_icon(app_icon);
|
||||
win->set_id(id);
|
||||
win->set_expire(expire_timeout);
|
||||
win->set_expire(expire_timeout, update_only);
|
||||
|
||||
/* according to spec, both coordinates must exist so window can be positioned as desired */
|
||||
int X, Y;
|
||||
|
@ -155,11 +195,11 @@ static void show_window(unsigned int id,
|
|||
px = sw - WINDOWS_PADDING - win->w();
|
||||
py = sh - WINDOWS_PADDING - win->h();
|
||||
|
||||
Fl::lock();
|
||||
|
||||
/*
|
||||
* iterate through shown windows and find position where to put our one
|
||||
* FIXME: this is quite primitive window position deducing facility
|
||||
*
|
||||
* TODO: add locking here
|
||||
*/
|
||||
Fl_Window *wi;
|
||||
for(wi = Fl::first_window(); wi; wi = Fl::next_window(wi)) {
|
||||
|
@ -173,12 +213,12 @@ static void show_window(unsigned int id,
|
|||
}
|
||||
}
|
||||
|
||||
Fl::unlock();
|
||||
win->position(px, py);
|
||||
}
|
||||
|
||||
/* we are already running loop, so window will handle events */
|
||||
win->show();
|
||||
if(!win->shown())
|
||||
win->show();
|
||||
}
|
||||
|
||||
static int handle_notify(EdbusConnection *dbus, const EdbusMessage *m) {
|
||||
|
@ -189,7 +229,7 @@ static int handle_notify(EdbusConnection *dbus, const EdbusMessage *m) {
|
|||
|
||||
const char *app_name, *app_icon, *summary, *body;
|
||||
app_name = app_icon = summary = body = NULL;
|
||||
unsigned int replaces_id;
|
||||
unsigned int replaces_id, id;
|
||||
int expire_timeout;
|
||||
|
||||
EdbusMessage::const_iterator it = m->begin();
|
||||
|
@ -226,19 +266,33 @@ static int handle_notify(EdbusConnection *dbus, const EdbusMessage *m) {
|
|||
E_RETURN_VAL_IF_FAIL(it->is_int32(), 0);
|
||||
expire_timeout = it->to_int32();
|
||||
|
||||
/* specification dumb stuff: what if we got UINT_MAX?? here we will reverse to first ID */
|
||||
if(++notify_id == UINT_MAX) notify_id = 1;
|
||||
|
||||
if(replaces_id) {
|
||||
//replaces_id == notify_id;
|
||||
if(replaces_id > 0) {
|
||||
id = replaces_id;
|
||||
} else {
|
||||
show_window(notify_id, app_name, app_icon, summary, body, expire_timeout, hints);
|
||||
/* by the spec, if we got MAX, reversing will be just fine */
|
||||
if(++notify_id == UINT_MAX) notify_id = 1;
|
||||
id = notify_id;
|
||||
}
|
||||
|
||||
/* reply sent to client */
|
||||
/* this should never happen */
|
||||
E_RETURN_VAL_IF_FAIL(id != 0, 0);
|
||||
|
||||
show_or_update_window(replaces_id > 0, id,
|
||||
app_name, app_icon, summary, body, expire_timeout, hints);
|
||||
#if 0
|
||||
if(replaces_id) {
|
||||
update_window(replaces_id, app_name, app_icon, summary, body, expire_timeout, hints);
|
||||
sent_id = replaces_id;
|
||||
} else {
|
||||
show_window(notify_id, app_name, app_icon, summary, body, expire_timeout, hints);
|
||||
sent_id = notify_id;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* reply sent to client, with used window id */
|
||||
EdbusMessage reply;
|
||||
reply.create_reply(*m);
|
||||
reply << EdbusData::from_uint32(replaces_id);
|
||||
reply << EdbusData::from_uint32(id);
|
||||
dbus->send(reply);
|
||||
|
||||
return 1;
|
||||
|
@ -279,6 +333,8 @@ static int notifications_dbus_method_cb(const EdbusMessage *m, void *d) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
#endif /* EDELIB_HAVE_DBUS */
|
||||
|
||||
#if 0
|
||||
static int notifications_dbus_signal_cb(const EdbusMessage *m, void *d) {
|
||||
E_DEBUG("+=> %s\n", m->member());
|
||||
|
@ -294,6 +350,8 @@ static void help(void) {
|
|||
puts(" -n, --no-daemon do not run in background");
|
||||
}
|
||||
|
||||
#define CHECK_ARGV(argv, pshort, plong) ((strcmp(argv, pshort) == 0) || (strcmp(argv, plong) == 0))
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
/* daemon behaves as GUI app, as will use icon theme and etc. */
|
||||
EDE_APPLICATION("ede-notify-daemon");
|
||||
|
@ -310,6 +368,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef EDELIB_HAVE_DBUS
|
||||
server_running = false;
|
||||
notify_id = 0;
|
||||
EdbusConnection dbus;
|
||||
|
@ -332,7 +391,6 @@ int main(int argc, char **argv) {
|
|||
|
||||
dbus.register_object(NOTIFICATIONS_DBUS_PATH);
|
||||
dbus.method_callback(notifications_dbus_method_cb, &dbus);
|
||||
//dbus.signal_callback(notifications_dbus_signal_cb, &dbus);
|
||||
dbus.setup_listener_with_fltk();
|
||||
server_running = true;
|
||||
|
||||
|
@ -340,5 +398,8 @@ int main(int argc, char **argv) {
|
|||
Fl::wait(FOREVER);
|
||||
|
||||
IconLoader::shutdown();
|
||||
#else
|
||||
E_WARNING(E_STRLOC ": edelib is compiled without DBus so notification daemon is not able to receive notification messages\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3,8 +3,64 @@
|
|||
|
||||
N_EVENTS=5
|
||||
|
||||
notify_cmd="notify-send --expire-time=10000"
|
||||
#notify_cmd="notify-send --expire-time=3000"
|
||||
#
|
||||
#for((i=0;i<$N_EVENTS;i++)) do
|
||||
# $notify_cmd "title $i" "this is content"
|
||||
#done
|
||||
|
||||
for((i=0;i<$N_EVENTS;i++)) do
|
||||
$notify_cmd "title $i" "this is content"
|
||||
done
|
||||
#method call sender=:1.798 -> dest=org.freedesktop.Notifications serial=116 path=/org/freedesktop/Notifications; interface=org.freedesktop.Notifications; member=Notify
|
||||
# string "Mumble"
|
||||
# uint32 1
|
||||
# string "gtk-dialog-info"
|
||||
# string "User Joined Channel"
|
||||
# string "<a href='clientid://df93eabe004245bd18dd38cf9a07bd5242b2f522' class='log-user log-target'>madamova</a> entered channel."
|
||||
# array [
|
||||
# ]
|
||||
# array [
|
||||
# dict entry(
|
||||
# string "desktop-entry"
|
||||
# variant string "mumble"
|
||||
# )
|
||||
# ]
|
||||
# int32 -1
|
||||
|
||||
dbus-send --type=method_call \
|
||||
--dest=org.freedesktop.Notifications \
|
||||
/org/freedesktop/Notifications org.freedesktop.Notifications.Notify \
|
||||
string:"Mumble" \
|
||||
uint32:1 \
|
||||
string:"gtk-dialog-info" \
|
||||
string:"User Joined Channel" \
|
||||
string:"<a href='clientid://df93eabe004245bd18dd38cf9a07bd5242b2f522' class='log-user log-target'>madamova</a> entered channel." \
|
||||
array:string:'' \
|
||||
dict:string:string:'','' \
|
||||
int32:-1
|
||||
|
||||
sleep 1
|
||||
|
||||
dbus-send --type=method_call \
|
||||
--dest=org.freedesktop.Notifications \
|
||||
/org/freedesktop/Notifications org.freedesktop.Notifications.Notify \
|
||||
string:"Mumble 2" \
|
||||
uint32:1 \
|
||||
string:"gtk-dialog-info" \
|
||||
string:"User Joined Channel #2" \
|
||||
string:"<a href='clientid://df93eabe004245bd18dd38cf9a07bd5242b2f522' class='log-user log-target'>madamova</a> entered channel. asdasd asdasdsa asdasd asdasd asdasdsa" \
|
||||
array:string:'' \
|
||||
dict:string:string:'','' \
|
||||
int32:-1
|
||||
|
||||
sleep 1
|
||||
|
||||
dbus-send --type=method_call \
|
||||
--dest=org.freedesktop.Notifications \
|
||||
/org/freedesktop/Notifications org.freedesktop.Notifications.Notify \
|
||||
string:"Mumble 2" \
|
||||
uint32:1 \
|
||||
string:"gtk-dialog-info" \
|
||||
string:"User Joined Channel #2 dasdasd asdasfdsa fsdfsdfa sdfsdfasdf asdfsdfasdfasdfasdfa asdfasdfdsafasdfasdfdsafdsaf sadfsdafds" \
|
||||
string:"doh!" \
|
||||
array:string:'' \
|
||||
dict:string:string:'','' \
|
||||
int32:-1
|
||||
|
|
|
@ -1,10 +1,41 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __APPLET_H__
|
||||
#define __APPLET_H__
|
||||
|
||||
#define EDE_PANEL_APPLET_INTERFACE_VERSION 0x01
|
||||
#include <edelib/Resource.h>
|
||||
|
||||
EDELIB_NS_USING_AS(Resource, PanelResource)
|
||||
class Fl_Widget;
|
||||
|
||||
/* stored version in each applet shared library in case interface get changed */
|
||||
#define EDE_PANEL_APPLET_INTERFACE_VERSION 0x01
|
||||
|
||||
/* random number (must be less than FL_WINDOW) so panel could know it is AppletWidget<> */
|
||||
#define EDE_PANEL_APPLET_TYPE 0x27
|
||||
|
||||
/*
|
||||
* Options assigned to each applet: how it will be resizable (horizontally or vertically)
|
||||
* and how it will be aligned. Each applet is by default aligned left without resizing ability.
|
||||
*/
|
||||
enum {
|
||||
EDE_PANEL_APPLET_OPTION_RESIZABLE_H = (1 << 1),
|
||||
EDE_PANEL_APPLET_OPTION_RESIZABLE_V = (1 << 2),
|
||||
|
@ -12,6 +43,26 @@ enum {
|
|||
EDE_PANEL_APPLET_OPTION_ALIGN_RIGHT = (1 << 4)
|
||||
};
|
||||
|
||||
/*
|
||||
* each applet want to inherit this class if would like to exchange data with panel
|
||||
* NOTE: new things could be added in future, but that will be reflected through EDE_PANEL_APPLET_INTERFACE_VERSION
|
||||
*/
|
||||
template <typename T>
|
||||
class AppletWidget : public T {
|
||||
public:
|
||||
AppletWidget(int X, int Y, int W, int H, const char *l = 0) : T(X, Y, W, H, l) {
|
||||
T::type(EDE_PANEL_APPLET_TYPE);
|
||||
}
|
||||
|
||||
virtual ~AppletWidget() { }
|
||||
|
||||
/*
|
||||
* Override this method to access panel configuration. Note that 'PanelResource' object
|
||||
* will be destroyed after applets are loaded, so do not hold reference to this address.
|
||||
*/
|
||||
virtual void configure(PanelResource *conf) { }
|
||||
};
|
||||
|
||||
struct AppletInfo {
|
||||
const char *name;
|
||||
const char *klass_name;
|
||||
|
@ -21,6 +72,7 @@ struct AppletInfo {
|
|||
unsigned long options;
|
||||
};
|
||||
|
||||
/* module stuff */
|
||||
typedef Fl_Widget* (*applet_create_t)(void);
|
||||
typedef void (*applet_destroy_t)(Fl_Widget *);
|
||||
|
||||
|
@ -29,11 +81,13 @@ typedef void (*applet_destroy_info_t)(AppletInfo *a);
|
|||
|
||||
typedef float (*applet_version_t)(void);
|
||||
|
||||
/* the main macro each applet library must implement */
|
||||
|
||||
/*
|
||||
* The main macro each applet library must implement. It will assign apropriate values
|
||||
* so applet loader can use them to load applet class with some common metadata.
|
||||
*/
|
||||
#define EDE_PANEL_APPLET_EXPORT(klass, aoptions, aname, aversion, aicon, aauthor) \
|
||||
extern "C" Fl_Widget *ede_panel_applet_create(void) { \
|
||||
return new klass; \
|
||||
return new klass; \
|
||||
} \
|
||||
\
|
||||
extern "C" void ede_panel_applet_destroy(Fl_Widget *w) { \
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <string.h>
|
||||
#include <edelib/Debug.h>
|
||||
|
@ -13,10 +33,10 @@ struct AppletData {
|
|||
Fl_Widget *awidget; /* widget from the applet */
|
||||
AppletInfo *ainfo; /* applet informations */
|
||||
|
||||
applet_create_t create_func;
|
||||
applet_destroy_t destroy_func;
|
||||
applet_create_t create_func;
|
||||
applet_destroy_t destroy_func;
|
||||
|
||||
applet_destroy_info_t destroy_info_func;
|
||||
applet_destroy_info_t destroy_info_func;
|
||||
};
|
||||
|
||||
static void clear_applet(AppletData *a) {
|
||||
|
@ -35,10 +55,6 @@ static void clear_applet(AppletData *a) {
|
|||
delete a;
|
||||
}
|
||||
|
||||
AppletManager::~AppletManager() {
|
||||
clear();
|
||||
}
|
||||
|
||||
bool AppletManager::load(const char *path) {
|
||||
dlerror();
|
||||
const char *dl_err = NULL;
|
||||
|
@ -46,7 +62,7 @@ bool AppletManager::load(const char *path) {
|
|||
void *a = dlopen(path, RTLD_LAZY);
|
||||
if(!a) {
|
||||
dl_err = dlerror();
|
||||
E_WARNING(E_STRLOC ": Unable to load '%s' : '%s'\n", path, dl_err);
|
||||
E_WARNING(E_STRLOC ": Unable to load '%s': '%s'\n", path, dl_err);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -92,7 +108,6 @@ bool AppletManager::load(const char *path) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
AppletData *data = new AppletData;
|
||||
data->dl = a;
|
||||
data->awidget = NULL;
|
||||
|
@ -111,12 +126,12 @@ bool AppletManager::load(const char *path) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void AppletManager::clear(void) {
|
||||
if(applet_list.empty())
|
||||
return;
|
||||
void AppletManager::clear(Panel *p) {
|
||||
E_RETURN_IF_FAIL(applet_list.size() > 0);
|
||||
|
||||
AListIter it = applet_list.begin(), it_end = applet_list.end();
|
||||
while(it != it_end) {
|
||||
AListIter it = applet_list.begin(), ite = applet_list.end();
|
||||
while(it != ite) {
|
||||
p->remove((*it)->awidget);
|
||||
clear_applet(*it);
|
||||
it = applet_list.erase(it);
|
||||
}
|
||||
|
@ -126,30 +141,39 @@ void AppletManager::clear(void) {
|
|||
* Must be called so widget can actually be added to FLTK parent. Widgets will be created and
|
||||
* added to the group.
|
||||
*/
|
||||
void AppletManager::fill_group(Panel *p) {
|
||||
AListIter it = applet_list.begin(), it_end = applet_list.end();
|
||||
void AppletManager::fill_group(Panel *p, PanelResource *res) {
|
||||
AListIter it = applet_list.begin(), ite = applet_list.end();
|
||||
AppletData *applet;
|
||||
|
||||
for(; it != it_end; ++it) {
|
||||
for(; it != ite; ++it) {
|
||||
applet = *it;
|
||||
|
||||
/* allocate memory for widget and append it to group */
|
||||
/* allocate memory for widget and append it to the group */
|
||||
applet->awidget = applet->create_func();
|
||||
|
||||
/* call configuration function if needed */
|
||||
if(res && applet->awidget->type() == EDE_PANEL_APPLET_TYPE) {
|
||||
/* a hackery to make compiler happy */
|
||||
typedef AppletWidget<Fl_Widget> AW;
|
||||
AW *tmp = (AW*)(applet->awidget);
|
||||
tmp->configure(res);
|
||||
}
|
||||
|
||||
p->add(applet->awidget);
|
||||
}
|
||||
}
|
||||
|
||||
void AppletManager::unfill_group(Panel *p) {
|
||||
AListIter it = applet_list.begin(), it_end = applet_list.end();
|
||||
AListIter it = applet_list.begin(), ite = applet_list.end();
|
||||
|
||||
for(; it != it_end; ++it)
|
||||
for(; it != ite; ++it)
|
||||
p->remove((*it)->awidget);
|
||||
}
|
||||
|
||||
bool AppletManager::get_applet_options(Fl_Widget *o, unsigned long &opts) {
|
||||
AListIter it = applet_list.begin(), it_end = applet_list.end();
|
||||
AListIter it = applet_list.begin(), ite = applet_list.end();
|
||||
|
||||
for(; it != it_end; ++it) {
|
||||
for(; it != ite; ++it) {
|
||||
if(o == (*it)->awidget) {
|
||||
opts = (*it)->ainfo->options;
|
||||
return true;
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __APPLETMANAGER_H__
|
||||
#define __APPLETMANAGER_H__
|
||||
|
||||
|
@ -9,17 +29,16 @@ class Panel;
|
|||
class Fl_Widget;
|
||||
struct AppletData;
|
||||
|
||||
typedef edelib::list<AppletData*> AList;
|
||||
typedef edelib::list<AppletData*>::iterator AListIter;
|
||||
typedef EDELIB_NS_PREPEND(list<AppletData*>) AList;
|
||||
typedef EDELIB_NS_PREPEND(list<AppletData*>::iterator) AListIter;
|
||||
|
||||
class AppletManager {
|
||||
private:
|
||||
AList applet_list;
|
||||
public:
|
||||
~AppletManager();
|
||||
bool load(const char *path);
|
||||
void clear(void);
|
||||
void fill_group(Panel *p);
|
||||
void clear(Panel *p);
|
||||
void fill_group(Panel *p, PanelResource *res);
|
||||
void unfill_group(Panel *p);
|
||||
|
||||
bool get_applet_options(Fl_Widget *o, unsigned long &opts);
|
||||
|
|
|
@ -1,49 +1,41 @@
|
|||
#include "Applet.h"
|
||||
#include "Panel.h"
|
||||
/*
|
||||
* $Id: ede-panel.cpp 3463 2012-12-17 15:49:33Z karijes $
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/x.H>
|
||||
#include <edelib/Nls.h>
|
||||
#include <edelib/Debug.h>
|
||||
|
||||
#include <FL/x.H>
|
||||
#include "Hider.h"
|
||||
#include "Panel.h"
|
||||
|
||||
/* delay in secs */
|
||||
#define PANEL_MOVE_DELAY 0.0015
|
||||
/* how fast we will move X axis */
|
||||
#define PANEL_ANIM_SPEED 50
|
||||
|
||||
static void hide_cb(Fl_Widget*, void *h);
|
||||
|
||||
class Hider : public Fl_Button {
|
||||
private:
|
||||
int old_x, old_y, is_hidden, old_px, stop_x;
|
||||
public:
|
||||
Hider() : Fl_Button(0, 0, 10, 25, "@>"), old_x(0), old_y(0), is_hidden(0), old_px(0), stop_x(0) {
|
||||
labelsize(8);
|
||||
box(FL_FLAT_BOX);
|
||||
tooltip(_("Hide panel"));
|
||||
callback(hide_cb, this);
|
||||
}
|
||||
|
||||
int panel_hidden(void) { return is_hidden; }
|
||||
void panel_hidden(int s) { is_hidden = s; }
|
||||
|
||||
void panel_show(void);
|
||||
void panel_hide(void);
|
||||
void post_show(void);
|
||||
void post_hide(void);
|
||||
void animate(void);
|
||||
};
|
||||
|
||||
static void hide_cb(Fl_Widget*, void *h) {
|
||||
Hider *hh = (Hider*)h;
|
||||
if(hh->panel_hidden())
|
||||
hh->panel_show();
|
||||
else
|
||||
hh->panel_hide();
|
||||
hh->panel_hidden() ? hh->panel_show() : hh->panel_hide();
|
||||
}
|
||||
|
||||
static void animate_cb(void *h) {
|
||||
|
@ -51,8 +43,15 @@ static void animate_cb(void *h) {
|
|||
hh->animate();
|
||||
}
|
||||
|
||||
Hider::Hider() : Fl_Button(0, 0, 10, 25, "@>"), old_x(0), old_y(0), is_hidden(0), old_px(0), stop_x(0) {
|
||||
labelsize(8);
|
||||
box(FL_FLAT_BOX);
|
||||
tooltip(_("Hide panel"));
|
||||
callback(hide_cb, this);
|
||||
}
|
||||
|
||||
void Hider::animate(void) {
|
||||
Panel *p = EDE_PANEL_GET_PANEL_OBJECT(this);
|
||||
Panel *p = (Panel*)parent();
|
||||
|
||||
if(!panel_hidden()) {
|
||||
/* hide */
|
||||
|
@ -76,7 +75,8 @@ void Hider::animate(void) {
|
|||
}
|
||||
|
||||
void Hider::panel_hide(void) {
|
||||
Panel *p = EDE_PANEL_GET_PANEL_OBJECT(this);
|
||||
Panel *p = (Panel*)parent();
|
||||
|
||||
int X, Y, W, H;
|
||||
|
||||
p->screen_size(X, Y, W, H);
|
||||
|
@ -87,7 +87,7 @@ void Hider::panel_hide(void) {
|
|||
}
|
||||
|
||||
void Hider::post_hide(void) {
|
||||
Panel *p = EDE_PANEL_GET_PANEL_OBJECT(this);
|
||||
Panel *p = (Panel*)parent();
|
||||
|
||||
/* align to bounds */
|
||||
p->position(stop_x, p->y());
|
||||
|
@ -116,7 +116,7 @@ void Hider::panel_show(void) {
|
|||
}
|
||||
|
||||
void Hider::post_show(void) {
|
||||
Panel *p = EDE_PANEL_GET_PANEL_OBJECT(this);
|
||||
Panel *p = (Panel*)parent();
|
||||
|
||||
/* align to bounds */
|
||||
p->position(old_px, p->y());
|
||||
|
@ -136,12 +136,3 @@ void Hider::post_show(void) {
|
|||
panel_hidden(0);
|
||||
tooltip(_("Hide panel"));
|
||||
}
|
||||
|
||||
EDE_PANEL_APPLET_EXPORT (
|
||||
Hider,
|
||||
EDE_PANEL_APPLET_OPTION_ALIGN_RIGHT,
|
||||
"Hide-panel applet",
|
||||
"0.1",
|
||||
"empty",
|
||||
"Sanel Zukan"
|
||||
)
|
41
ede-panel/Hider.h
Normal file
41
ede-panel/Hider.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* $Id: ede-panel.cpp 3463 2012-12-17 15:49:33Z karijes $
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <FL/Fl_Button.H>
|
||||
|
||||
#ifndef __HIDER_H__
|
||||
#define __HIDER_H__
|
||||
|
||||
class Hider : public Fl_Button {
|
||||
private:
|
||||
int old_x, old_y, is_hidden, old_px, stop_x;
|
||||
public:
|
||||
Hider();
|
||||
int panel_hidden(void) { return is_hidden; }
|
||||
void panel_hidden(int s) { is_hidden = s; }
|
||||
|
||||
void panel_show(void);
|
||||
void panel_hide(void);
|
||||
void post_show(void);
|
||||
void post_hide(void);
|
||||
void animate(void);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
SubDir TOP ede-panel ;
|
||||
|
||||
EdeProgram ede-panel : Panel.cpp AppletManager.cpp ede-panel.cpp ;
|
||||
EdeProgram ede-panel : Hider.cpp Panel.cpp AppletManager.cpp ede-panel.cpp ;
|
||||
LinkAgainst ede-panel : -ldl ;
|
||||
#ObjectC++Flags Panel.cpp : -DEDE_PANEL_LOCAL_APPLETS ;
|
||||
|
||||
if $(OS) != "SOLARIS" {
|
||||
|
@ -30,13 +31,13 @@ rule PanelApplet
|
|||
}
|
||||
|
||||
# append default extension
|
||||
target = $(<:S=$(SUFLIB_SHARED)) ;
|
||||
target = $(1:S=$(SUFLIB_SHARED)) ;
|
||||
|
||||
Main $(target) : $(>) ;
|
||||
ObjectC++Flags $(>) : $(GLOBALFLAGS) -fPIC $(FLTKINCLUDE) -I [ FDirName $(TOP) ede-panel ] $(EDELIBINCLUDE) ;
|
||||
Main $(target) : $(2) ;
|
||||
ObjectC++Flags $(2) : $(GLOBALFLAGS) -fPIC $(FLTKINCLUDE) -I [ FDirName $(TOP) ede-panel ] $(EDELIBINCLUDE) ;
|
||||
|
||||
LinkAgainst $(target) : $(3) $(EDELIBLIB) $(EDELIB_GUI_LIB) $(FLTKLIB) $(STDLIB) ;
|
||||
LINKFLAGS on $(target) = $(linker_stuff) [ on $(target) return $(LINKFLAGS) ] ;
|
||||
LINKFLAGS on $(target) = $(linker_stuff) [ on $(target) return $(LINKFLAGS) ] $(3) ;
|
||||
|
||||
InstallProgram $(EDE_PANEL_APPLETS_DIR) : $(target) ;
|
||||
|
||||
|
|
|
@ -1,17 +1,40 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012-2014 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/x.H>
|
||||
#include <X11/Xproto.h>
|
||||
|
||||
#include <edelib/Debug.h>
|
||||
#include <edelib/List.h>
|
||||
#include <edelib/WindowXid.h>
|
||||
#include <edelib/Resource.h>
|
||||
#include <edelib/Util.h>
|
||||
#include <edelib/Netwm.h>
|
||||
#include <edelib/Directory.h>
|
||||
#include <edelib/StrUtil.h>
|
||||
|
||||
#include "Panel.h"
|
||||
#include "Hider.h"
|
||||
|
||||
/* empty space from left and right panel border */
|
||||
#define INITIAL_SPACING 5
|
||||
|
@ -22,25 +45,30 @@
|
|||
/* default panel height */
|
||||
#define DEFAULT_PANEL_H 35
|
||||
|
||||
#define APPLET_EXTENSION ".so"
|
||||
|
||||
#undef MIN
|
||||
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
||||
#undef MAX
|
||||
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
||||
#define MAX(x,y) ((x) > (y) ? (x) : (y))
|
||||
|
||||
EDELIB_NS_USING_LIST(10, (list,
|
||||
Resource,
|
||||
String,
|
||||
window_xid_create,
|
||||
build_filename,
|
||||
str_trim,
|
||||
netwm_window_set_strut,
|
||||
netwm_window_remove_strut,
|
||||
netwm_window_set_type,
|
||||
netwm_workarea_get_size,
|
||||
NETWM_WINDOW_TYPE_DOCK))
|
||||
NETWM_WINDOW_TYPE_DOCK))
|
||||
|
||||
typedef list<Fl_Widget*> WidgetList;
|
||||
typedef list<Fl_Widget*>::iterator WidgetListIt;
|
||||
|
||||
/* used only insid x_events */
|
||||
static Panel *gpanel;
|
||||
|
||||
inline bool intersects(Fl_Widget *o1, Fl_Widget *o2) {
|
||||
return (MAX(o1->x(), o2->x()) <= MIN(o1->x() + o1->w(), o2->x() + o2->w()) &&
|
||||
MAX(o1->y(), o2->y()) <= MIN(o1->y() + o1->h(), o2->y() + o2->h()));
|
||||
|
@ -50,14 +78,14 @@ static int xerror_handler(Display *d, XErrorEvent *e) {
|
|||
if(e->request_code == X_GetImage)
|
||||
return 0;
|
||||
|
||||
char buf[128];
|
||||
/* keep it static as no multiple panels will be run */
|
||||
static char buf[128];
|
||||
|
||||
/*
|
||||
* construct the similar message format like X11 is using by default, but again, little
|
||||
* bit different so we knows it comes from here
|
||||
*/
|
||||
|
||||
sprintf(buf, "%d", e->request_code);
|
||||
snprintf(buf, sizeof(buf), "%d", e->request_code);
|
||||
|
||||
XGetErrorDatabaseText(d, "XRequest", buf, "%d", buf, sizeof(buf));
|
||||
fprintf(stderr, "%s: ", buf);
|
||||
|
@ -77,20 +105,39 @@ static void make_me_dock(Fl_Window *win) {
|
|||
netwm_window_set_type(fl_xid(win), NETWM_WINDOW_TYPE_DOCK);
|
||||
}
|
||||
|
||||
static int x_events(int ev) {
|
||||
/*
|
||||
* This is quite stupid to do, but hopefully very reliable. When screen is resized
|
||||
* root window was resized too and using those sizes, panel is placed. Tracking workarea changes
|
||||
* isn't much of use, as setting struts dimensions will affect workarea dimension too.
|
||||
*/
|
||||
if(fl_xevent->type == ConfigureNotify &&
|
||||
(fl_xevent->xconfigure.window == RootWindow(fl_display, fl_screen))) {
|
||||
gpanel->update_size_and_pos(false, false,
|
||||
fl_xevent->xconfigure.x,
|
||||
fl_xevent->xconfigure.y,
|
||||
fl_xevent->xconfigure.width,
|
||||
fl_xevent->xconfigure.height);
|
||||
}
|
||||
|
||||
/* let others receive the same event */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* horizontaly centers widget in the panel */
|
||||
static void center_widget_h(Fl_Widget *o, Panel *self) {
|
||||
int ph, wy;
|
||||
static void fix_widget_h(Fl_Widget *o, Panel *self) {
|
||||
int ph, wy, H = self->h() - 10;
|
||||
|
||||
ph = self->panel_h() / 2;
|
||||
wy = ph - (o->h() / 2);
|
||||
o->position(o->x(), wy);
|
||||
wy = ph - (H / 2);
|
||||
o->resize(o->x(), wy, o->w(), H);
|
||||
}
|
||||
|
||||
static void add_from_list(WidgetList &lst, Panel *self, int &X, bool inc) {
|
||||
WidgetListIt it = lst.begin(), it_end = lst.end();
|
||||
WidgetListIt it = lst.begin(), ite = lst.end();
|
||||
Fl_Widget *o;
|
||||
|
||||
while(it != it_end) {
|
||||
while(it != ite) {
|
||||
o = *it;
|
||||
|
||||
/* 'inc == false' means we are going from right to left */
|
||||
|
@ -174,14 +221,17 @@ static void move_widget(Panel *self, Fl_Widget *o, int &sx, int &sy) {
|
|||
}
|
||||
#endif
|
||||
|
||||
Panel::Panel() : PanelWindow(300, 30) {
|
||||
Panel::Panel() : PanelWindow(300, 30, "ede-panel") {
|
||||
gpanel = this;
|
||||
hider = NULL;
|
||||
|
||||
clicked = 0;
|
||||
sx = sy = 0;
|
||||
vpos = PANEL_POSITION_BOTTOM;
|
||||
screen_x = screen_y = screen_w = screen_h = screen_h_half = 0;
|
||||
width_perc = 100;
|
||||
can_move_widgets = false;
|
||||
can_drag = true;
|
||||
can_drag = false;
|
||||
|
||||
box(FL_UP_BOX);
|
||||
read_config();
|
||||
|
@ -189,8 +239,7 @@ Panel::Panel() : PanelWindow(300, 30) {
|
|||
|
||||
void Panel::read_config(void) {
|
||||
Resource r;
|
||||
if(!r.load("ede-panel"))
|
||||
return;
|
||||
r.load("ede-panel");
|
||||
|
||||
int tmp;
|
||||
if(r.get("Panel", "position", tmp, PANEL_POSITION_BOTTOM)) {
|
||||
|
@ -205,6 +254,26 @@ void Panel::read_config(void) {
|
|||
|
||||
width_perc = tmp;
|
||||
}
|
||||
|
||||
/* small button on the right edge for panel sliding */
|
||||
r.get("Panel", "hider", tmp, 1);
|
||||
if(tmp) {
|
||||
if(!hider) {
|
||||
hider = new Hider();
|
||||
add(hider);
|
||||
}
|
||||
|
||||
/* in case was hidden before */
|
||||
hider->show();
|
||||
} else {
|
||||
if(hider) hider->hide();
|
||||
}
|
||||
|
||||
char buf[128];
|
||||
if(r.get("Panel", "applets", buf, sizeof(buf)))
|
||||
load_applets(buf, &r);
|
||||
else
|
||||
load_applets(0, &r);
|
||||
}
|
||||
|
||||
void Panel::save_config(void) {
|
||||
|
@ -217,7 +286,7 @@ void Panel::save_config(void) {
|
|||
}
|
||||
|
||||
void Panel::do_layout(void) {
|
||||
E_RETURN_IF_FAIL(mgr.napplets() > 0);
|
||||
E_RETURN_IF_FAIL(children() > 0);
|
||||
|
||||
Fl_Widget *o;
|
||||
unsigned long opts;
|
||||
|
@ -229,8 +298,14 @@ void Panel::do_layout(void) {
|
|||
for(int i = 0; i < children(); i++) {
|
||||
o = child(i);
|
||||
|
||||
/* first center it vertically */
|
||||
center_widget_h(o, this);
|
||||
/* first resize it to some reasonable height and center it vertically */
|
||||
fix_widget_h(o, this);
|
||||
|
||||
/* manage hider specifically */
|
||||
if(hider && o == hider) {
|
||||
right.push_back(o);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* could be slow, but I'm relaying how number of loaded applets will not be that large */
|
||||
if(!mgr.get_applet_options(o, opts)) {
|
||||
|
@ -297,11 +372,11 @@ void Panel::do_layout(void) {
|
|||
* since add_from_list() will already reserve some space by current child width and default spacing,
|
||||
* those values will be used again or holes will be made
|
||||
*/
|
||||
WidgetListIt it = resizable_h.begin(), it_end = resizable_h.end();
|
||||
WidgetListIt it = resizable_h.begin(), ite = resizable_h.end();
|
||||
o = resizable_h.front();
|
||||
X = o->x();
|
||||
|
||||
while(it != it_end) {
|
||||
while(it != ite) {
|
||||
o = *it;
|
||||
|
||||
W = o->w() + free_w;
|
||||
|
@ -312,26 +387,63 @@ void Panel::do_layout(void) {
|
|||
}
|
||||
}
|
||||
|
||||
void Panel::set_strut(short state) {
|
||||
if(state & PANEL_STRUT_REMOVE)
|
||||
netwm_window_remove_strut(fl_xid(this));
|
||||
|
||||
/* no other flags */
|
||||
if(state == PANEL_STRUT_REMOVE) return;
|
||||
|
||||
int sizes[4] = {0, 0, 0, 0};
|
||||
sizes[state & PANEL_STRUT_BOTTOM ? 3 : 2] = h();
|
||||
|
||||
/* TODO: netwm_window_set_strut_partial() */
|
||||
netwm_window_set_strut(fl_xid(this), sizes[0], sizes[1], sizes[2], sizes[3]);
|
||||
}
|
||||
|
||||
void Panel::show(void) {
|
||||
if(shown()) {
|
||||
Fl_Window::show();
|
||||
return;
|
||||
}
|
||||
|
||||
int X, Y, W, H;
|
||||
|
||||
fl_open_display();
|
||||
if(shown()) return;
|
||||
|
||||
/*
|
||||
* hush known FLTK bug with XGetImage; a lot of errors will be print when menu icons goes
|
||||
* outside screen; this also make ede-panel, at some point, unresponsible
|
||||
* hush known FLTK bug with XGetImage; a lot of errors will be printed when menu icons goes
|
||||
* outside screen; this can stuck ede-panel at some point
|
||||
*/
|
||||
XSetErrorHandler((XErrorHandler) xerror_handler);
|
||||
update_size_and_pos(true, true);
|
||||
|
||||
/* position it */
|
||||
/* collect messages */
|
||||
Fl::add_handler(x_events);
|
||||
}
|
||||
|
||||
void Panel::hide(void) {
|
||||
Fl::remove_handler(x_events);
|
||||
set_strut(PANEL_STRUT_REMOVE);
|
||||
|
||||
/* clear loaded widgets */
|
||||
mgr.clear(this);
|
||||
|
||||
/* clear whatever was left out, but was not part of applet manager */
|
||||
clear();
|
||||
|
||||
save_config();
|
||||
Fl_Window::hide();
|
||||
}
|
||||
|
||||
void Panel::update_size_and_pos(bool create_xid, bool update_strut) {
|
||||
int X, Y, W, H;
|
||||
|
||||
/* figure out screen dimensions */
|
||||
if(!netwm_workarea_get_size(X, Y, W, H))
|
||||
Fl::screen_xywh(X, Y, W, H);
|
||||
|
||||
update_size_and_pos(create_xid, update_strut, X, Y, W, H);
|
||||
}
|
||||
|
||||
void Panel::update_size_and_pos(bool create_xid, bool update_strut, int X, int Y, int W, int H) {
|
||||
/* do not update ourself if we screen sizes are the same */
|
||||
if(screen_x == X && screen_y == Y && screen_w == W && screen_h == H)
|
||||
return;
|
||||
|
||||
screen_x = X;
|
||||
screen_y = Y;
|
||||
screen_w = W;
|
||||
|
@ -348,33 +460,37 @@ void Panel::show(void) {
|
|||
size(W, DEFAULT_PANEL_H);
|
||||
|
||||
do_layout();
|
||||
window_xid_create(this, make_me_dock);
|
||||
|
||||
if(create_xid) window_xid_create(this, make_me_dock);
|
||||
|
||||
/* position it, this is done after XID was created */
|
||||
if(vpos == PANEL_POSITION_BOTTOM) {
|
||||
position(X, screen_h - h());
|
||||
if(width_perc >= 100)
|
||||
netwm_window_set_strut(fl_xid(this), 0, 0, 0, h());
|
||||
if(width_perc >= 100 && update_strut)
|
||||
set_strut(PANEL_STRUT_REMOVE | PANEL_STRUT_BOTTOM);
|
||||
} else {
|
||||
/* FIXME: this does not work well with edewm (nor pekwm). kwin do it correctly. */
|
||||
position(X, Y);
|
||||
if(width_perc >= 100)
|
||||
netwm_window_set_strut(fl_xid(this), 0, 0, h(), 0);
|
||||
/*
|
||||
* I'm not sure what the hell is going on here; if 'y == 0', X will
|
||||
* move panel few pixels down, even if FLTK is reporting y() == 0.
|
||||
* Seems like 1 will solve this.
|
||||
*/
|
||||
position(X, Y == 0 ? 1 : Y);
|
||||
if(width_perc >= 100 && update_strut)
|
||||
set_strut(PANEL_STRUT_REMOVE | PANEL_STRUT_TOP);
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::hide(void) {
|
||||
save_config();
|
||||
}
|
||||
|
||||
int Panel::handle(int e) {
|
||||
return Fl_Window::handle(e);
|
||||
|
||||
#if 0
|
||||
switch(e) {
|
||||
case FL_PUSH:
|
||||
clicked = Fl::belowmouse();
|
||||
|
||||
if(clicked == this)
|
||||
clicked = 0;
|
||||
else if(clicked && clicked->takesevents())
|
||||
else if(clicked && Fl::event_inside(clicked) && clicked->takesevents())
|
||||
clicked->handle(e);
|
||||
|
||||
/* record push position for possible child drag */
|
||||
|
@ -383,27 +499,32 @@ int Panel::handle(int e) {
|
|||
return 1;
|
||||
|
||||
case FL_DRAG: {
|
||||
if(!can_drag) return 1;
|
||||
/* send drag events to children and do not drag panel in the mean time */
|
||||
if(clicked && clicked != this && Fl::event_inside(clicked) && clicked->takesevents()) {
|
||||
cursor(FL_CURSOR_MOVE);
|
||||
return clicked->handle(e);
|
||||
} else {
|
||||
printf("XXXy %p %p\n", clicked, this);
|
||||
if(!can_drag) return 1;
|
||||
cursor(FL_CURSOR_MOVE);
|
||||
|
||||
/* are moving the panel; only vertical moving is supported */
|
||||
cursor(FL_CURSOR_MOVE);
|
||||
/* snap it to the top or bottom, depending on pressed mouse location */
|
||||
if(Fl::event_y_root() <= screen_h_half && y() > screen_h_half) {
|
||||
position(x(), screen_y);
|
||||
if(width_perc >= 100)
|
||||
set_strut(PANEL_STRUT_TOP);
|
||||
vpos = PANEL_POSITION_TOP;
|
||||
}
|
||||
|
||||
/* snap it to the top or bottom, depending on pressed mouse location */
|
||||
if(Fl::event_y_root() <= screen_h_half && y() > screen_h_half) {
|
||||
position(x(), screen_y);
|
||||
if(width_perc >= 100)
|
||||
netwm_window_set_strut(fl_xid(this), 0, 0, h(), 0);
|
||||
vpos = PANEL_POSITION_TOP;
|
||||
}
|
||||
|
||||
if(Fl::event_y_root() > screen_h_half && y() < screen_h_half) {
|
||||
position(x(), screen_h - h());
|
||||
if(width_perc >= 100)
|
||||
netwm_window_set_strut(fl_xid(this), 0, 0, 0, h());
|
||||
vpos = PANEL_POSITION_BOTTOM;
|
||||
if(Fl::event_y_root() > screen_h_half && y() < screen_h_half) {
|
||||
position(x(), screen_h - h());
|
||||
if(width_perc >= 100)
|
||||
set_strut(PANEL_STRUT_BOTTOM);
|
||||
vpos = PANEL_POSITION_BOTTOM;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
case FL_RELEASE:
|
||||
|
@ -422,53 +543,68 @@ int Panel::handle(int e) {
|
|||
return 1;
|
||||
/* fallthrough */
|
||||
}
|
||||
|
||||
return Fl_Window::handle(e);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Panel::load_applets(void) {
|
||||
void Panel::load_applets(const char *applets, PanelResource *res) {
|
||||
mgr.clear(this);
|
||||
|
||||
/*
|
||||
* Hardcoded order, unless configuration file was found. For easier and uniform parsing
|
||||
* (similar string is expected from configuration), fallback is plain string.
|
||||
*/
|
||||
static const char *fallback =
|
||||
#ifndef EDE_PANEL_LOCAL_APPLETS
|
||||
/* FIXME: hardcoded order */
|
||||
static const char *applets[] = {
|
||||
"start_menu.so",
|
||||
"quick_launch.so",
|
||||
"pager.so",
|
||||
"hider.so",
|
||||
"clock.so",
|
||||
"taskbar.so",
|
||||
"keyboard_layout.so",
|
||||
"cpu_monitor.so",
|
||||
#ifdef __linux__
|
||||
"mem_monitor.so",
|
||||
#endif
|
||||
"system_tray.so",
|
||||
0
|
||||
};
|
||||
|
||||
"start_menu,"
|
||||
"quick_launch,"
|
||||
"pager,"
|
||||
"clock,"
|
||||
"taskbar,"
|
||||
"keyboard_layout,"
|
||||
"battery_monitor,"
|
||||
"cpu_monitor,"
|
||||
# ifdef __linux__
|
||||
"mem_monitor,"
|
||||
# endif
|
||||
"system_tray"
|
||||
#else /* EDE_PANEL_LOCAL_APPLETS */
|
||||
"./applets/start-menu/start_menu,"
|
||||
"./applets/quick-launch/quick_launch,"
|
||||
"./applets/pager/pager,"
|
||||
"./applets/clock/clock,"
|
||||
"./applets/taskbar/taskbar,"
|
||||
"./applets/keyboard-layout/keyboard_layout,"
|
||||
"./applets/battery-monitor/battery_monitor,"
|
||||
"./applets/cpu-monitor/cpu_monitor,"
|
||||
# ifdef __linux__
|
||||
"./applets/mem-monitor/mem_monitor,"
|
||||
# endif
|
||||
"./applets/system-tray/system_tray"
|
||||
#endif /* EDE_PANEL_LOCAL_APPLETS */
|
||||
;
|
||||
|
||||
String dir = Resource::find_data("panel-applets");
|
||||
if(dir.empty())
|
||||
return;
|
||||
E_RETURN_IF_FAIL(!dir.empty());
|
||||
|
||||
char *dup = strdup(applets ? applets : fallback);
|
||||
E_RETURN_IF_FAIL(dup != NULL);
|
||||
|
||||
String tmp;
|
||||
for(int i = 0; applets[i]; i++) {
|
||||
tmp = build_filename(dir.c_str(), applets[i]);
|
||||
mgr.load(tmp.c_str());
|
||||
char path[PATH_MAX];
|
||||
for(char *tok = strtok(dup, ","); tok; tok = strtok(NULL, ",")) {
|
||||
tok = str_trim(tok);
|
||||
|
||||
#ifndef EDE_PANEL_LOCAL_APPLETS
|
||||
snprintf(path, sizeof(path), "%s" E_DIR_SEPARATOR_STR "%s" APPLET_EXTENSION, dir.c_str(), tok);
|
||||
#else
|
||||
/* only for testing, so path separator is hardcoded */
|
||||
snprintf(path, sizeof(path), "%s" APPLET_EXTENSION, tok);
|
||||
#endif
|
||||
mgr.load(path);
|
||||
}
|
||||
|
||||
mgr.fill_group(this);
|
||||
#else
|
||||
mgr.load("./applets/start-menu/start_menu.so");
|
||||
mgr.load("./applets/quick-launch/quick_launch.so");
|
||||
mgr.load("./applets/pager/pager.so");
|
||||
mgr.load("./applets/hider/hider.so");
|
||||
mgr.load("./applets/clock/clock.so");
|
||||
mgr.load("./applets/taskbar/taskbar.so");
|
||||
mgr.load("./applets/keyboard-layout/keyboard_layout.so");
|
||||
mgr.load("./applets/cpu-monitor/cpu_monitor.so");
|
||||
mgr.load("./applets/mem-monitor/mem_monitor.so");
|
||||
mgr.load("./applets/system-tray/system_tray.so");
|
||||
mgr.fill_group(this);
|
||||
#endif
|
||||
free(dup);
|
||||
mgr.fill_group(this, res);
|
||||
}
|
||||
|
||||
/* TODO: can be better */
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PANEL_H__
|
||||
#define __PANEL_H__
|
||||
|
||||
|
@ -14,9 +34,20 @@ enum {
|
|||
PANEL_POSITION_BOTTOM
|
||||
};
|
||||
|
||||
/* combination of what to do with strut data */
|
||||
enum {
|
||||
PANEL_STRUT_REMOVE = (1 << 1),
|
||||
PANEL_STRUT_BOTTOM = (1 << 2),
|
||||
PANEL_STRUT_TOP = (1 << 3)
|
||||
};
|
||||
|
||||
class Hider;
|
||||
|
||||
class Panel : public PanelWindow {
|
||||
private:
|
||||
Fl_Widget *clicked;
|
||||
Hider *hider;
|
||||
|
||||
int vpos;
|
||||
int sx, sy;
|
||||
int screen_x, screen_y, screen_w, screen_h, screen_h_half;
|
||||
|
@ -28,14 +59,16 @@ private:
|
|||
void read_config(void);
|
||||
void save_config(void);
|
||||
void do_layout(void);
|
||||
|
||||
void set_strut(short state);
|
||||
public:
|
||||
Panel();
|
||||
|
||||
void show(void);
|
||||
void hide(void);
|
||||
void update_size_and_pos(bool create_xid, bool update_strut);
|
||||
void update_size_and_pos(bool create_xid, bool update_strut, int X, int Y, int W, int H);
|
||||
int handle(int e);
|
||||
void load_applets(void);
|
||||
void load_applets(const char *applets, PanelResource *res = 0);
|
||||
|
||||
int panel_w(void) { return w(); }
|
||||
int panel_h(void) { return h(); }
|
||||
|
|
|
@ -13,8 +13,8 @@ SubDir TOP ede-panel applets ;
|
|||
# SubInclude TOP ede-panel applets demo ;
|
||||
SubInclude TOP ede-panel applets clock ;
|
||||
SubInclude TOP ede-panel applets cpu-monitor ;
|
||||
SubInclude TOP ede-panel applets hider ;
|
||||
SubInclude TOP ede-panel applets mem-monitor ;
|
||||
SubInclude TOP ede-panel applets battery-monitor ;
|
||||
SubInclude TOP ede-panel applets keyboard-layout ;
|
||||
SubInclude TOP ede-panel applets pager ;
|
||||
SubInclude TOP ede-panel applets quick-launch ;
|
||||
|
|
302
ede-panel/applets/battery-monitor/BatteryMonitor.cpp
Normal file
302
ede-panel/applets/battery-monitor/BatteryMonitor.cpp
Normal file
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2016 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <edelib/Nls.h>
|
||||
#include "Applet.h"
|
||||
|
||||
#ifdef EDELIB_HAVE_DBUS
|
||||
#include <edelib/EdbusConnection.h>
|
||||
#include <edelib/EdbusMessage.h>
|
||||
#include <edelib/EdbusList.h>
|
||||
#include <edelib/EdbusObjectPath.h>
|
||||
#include <edelib/EdbusData.h>
|
||||
#include <edelib/List.h>
|
||||
#include <edelib/Debug.h>
|
||||
#include <edelib/IconLoader.h>
|
||||
|
||||
EDELIB_NS_USING(EdbusConnection)
|
||||
EDELIB_NS_USING(EdbusMessage)
|
||||
EDELIB_NS_USING(EdbusList)
|
||||
EDELIB_NS_USING(EdbusObjectPath)
|
||||
EDELIB_NS_USING(EdbusData)
|
||||
EDELIB_NS_USING(EdbusVariant)
|
||||
EDELIB_NS_USING(IconLoader)
|
||||
EDELIB_NS_USING(ICON_SIZE_SMALL)
|
||||
EDELIB_NS_USING(list)
|
||||
EDELIB_NS_USING(EDBUS_SYSTEM)
|
||||
|
||||
#define UPOWER_TYPE_BATTERY 2
|
||||
|
||||
#define UPOWER_STATE_CHARGING 1
|
||||
#define UPOWER_STATE_DISCHARGING 2
|
||||
#define UPOWER_STATE_EMPTY 3
|
||||
#define UPOWER_STATE_CHARGED 4
|
||||
|
||||
#define UPOWER_SERVICE "org.freedesktop.UPower"
|
||||
#define UPOWER_INTERFACE "org.freedesktop.UPower.Device"
|
||||
#define UPOWER_PATH "/org/freedesktop/UPower"
|
||||
|
||||
#define BATTERY_MIN 10 /* minimal time before icon to BATTERY_CAUTION_IMG was changed */
|
||||
#define BATTERY_IMG "battery"
|
||||
#define BATTERY_CAUTION_IMG "battery-caution"
|
||||
#define BATTERY_NO_CONNECTION "dialog-warning"
|
||||
|
||||
typedef list<EdbusObjectPath> BatteryList;
|
||||
typedef list<EdbusObjectPath>::iterator BatteryListIt;
|
||||
|
||||
/*
|
||||
* For now all query-ing is done via UPower. Applet is support multiple batteries, but
|
||||
* status will be reported as cumulative state all of them.
|
||||
|
||||
* TODO: add support for other methods, like DeviceKit (is this obsolete??)
|
||||
*/
|
||||
class BatteryMonitor : public Fl_Box {
|
||||
private:
|
||||
const char *bimg;
|
||||
char tip[128];
|
||||
|
||||
EdbusConnection con;
|
||||
BatteryList batts;
|
||||
|
||||
public:
|
||||
BatteryMonitor() : Fl_Box(0, 0, 30, 25), bimg(0) {
|
||||
box(FL_FLAT_BOX);
|
||||
if(!scan_and_init()) {
|
||||
set_icon(0, true);
|
||||
tooltip(_("Failed to query battery status"));
|
||||
}
|
||||
}
|
||||
|
||||
EdbusConnection &connection() { return con; }
|
||||
|
||||
void tooltip_printf(const char *fmt, ...);
|
||||
int scan_and_init(void);
|
||||
int update_icon_and_tooltip(void);
|
||||
void set_icon(double percentage, bool failure = false);
|
||||
|
||||
BatteryList &get_batteries(void);
|
||||
};
|
||||
|
||||
static bool bus_property_get(EdbusConnection &con,
|
||||
const char *service,
|
||||
const char *path,
|
||||
const char *iface,
|
||||
const char *prop,
|
||||
EdbusMessage *ret)
|
||||
{
|
||||
EdbusMessage msg;
|
||||
msg.create_method_call(service, path, "org.freedesktop.DBus.Properties", "Get");
|
||||
msg << EdbusData::from_string(iface);
|
||||
msg << EdbusData::from_string(prop);
|
||||
|
||||
E_RETURN_VAL_IF_FAIL(con.send_with_reply_and_block(msg, 1000, *ret), false);
|
||||
E_RETURN_VAL_IF_FAIL(ret->size() == 1, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_battery(EdbusConnection &con, const char *path) {
|
||||
EdbusMessage reply;
|
||||
E_RETURN_VAL_IF_FAIL(bus_property_get(con, UPOWER_SERVICE, path, UPOWER_INTERFACE, "Type", &reply), false);
|
||||
|
||||
EdbusMessage::const_iterator it = reply.begin();
|
||||
E_RETURN_VAL_IF_FAIL(it->is_variant(), false);
|
||||
|
||||
EdbusVariant v = it->to_variant();
|
||||
E_RETURN_VAL_IF_FAIL(v.value.is_uint32(), false);
|
||||
|
||||
return v.value.to_uint32() == UPOWER_TYPE_BATTERY;
|
||||
}
|
||||
|
||||
static bool get_percentage(EdbusConnection &con, const char *path, double *ret) {
|
||||
EdbusMessage reply;
|
||||
E_RETURN_VAL_IF_FAIL(bus_property_get(con, UPOWER_SERVICE, path, UPOWER_INTERFACE, "Percentage", &reply), false);
|
||||
|
||||
EdbusMessage::const_iterator it = reply.begin();
|
||||
E_RETURN_VAL_IF_FAIL(it->is_variant(), false);
|
||||
|
||||
EdbusVariant v = it->to_variant();
|
||||
E_RETURN_VAL_IF_FAIL(v.value.is_double(), false);
|
||||
|
||||
*ret = v.value.to_double();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool get_state(EdbusConnection &con, const char *path, int *ret) {
|
||||
EdbusMessage reply;
|
||||
E_RETURN_VAL_IF_FAIL(bus_property_get(con, UPOWER_SERVICE, path, UPOWER_INTERFACE, "State", &reply), false);
|
||||
|
||||
EdbusMessage::const_iterator it = reply.begin();
|
||||
E_RETURN_VAL_IF_FAIL(it->is_variant(), false);
|
||||
|
||||
EdbusVariant v = it->to_variant();
|
||||
E_RETURN_VAL_IF_FAIL(v.value.is_uint32(), false);
|
||||
|
||||
*ret = v.value.to_uint32();
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *get_state_str(EdbusConnection &con, const char *path) {
|
||||
const char * fallback = _("unknown");
|
||||
int ret;
|
||||
E_RETURN_VAL_IF_FAIL(get_state(con, path, &ret), fallback);
|
||||
|
||||
switch(ret) {
|
||||
case UPOWER_STATE_CHARGED: return _("charged");
|
||||
case UPOWER_STATE_CHARGING: return _("charging");
|
||||
case UPOWER_STATE_DISCHARGING: return _("discharging");
|
||||
case UPOWER_STATE_EMPTY: return _("empty");
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
static int signal_cb(const EdbusMessage *msg, void *data) {
|
||||
/* in case some org.freedesktop.DBus (like NameAcquired) received */
|
||||
if(strcmp(msg->interface(), UPOWER_INTERFACE) != 0)
|
||||
return 0;
|
||||
BatteryMonitor *self = (BatteryMonitor*)data;
|
||||
return self->update_icon_and_tooltip();
|
||||
}
|
||||
|
||||
void BatteryMonitor::tooltip_printf(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(tip, sizeof(tip), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
tooltip(tip);
|
||||
}
|
||||
|
||||
int BatteryMonitor::scan_and_init(void) {
|
||||
if(con.connected()) return 1;
|
||||
E_RETURN_VAL_IF_FAIL(con.connect(EDBUS_SYSTEM), 0);
|
||||
|
||||
/* get battery devices */
|
||||
EdbusMessage msg, reply;
|
||||
msg.create_method_call(UPOWER_SERVICE, UPOWER_PATH, UPOWER_SERVICE, "EnumerateDevices");
|
||||
|
||||
E_RETURN_VAL_IF_FAIL(con.send_with_reply_and_block(msg, 1000, reply), 0);
|
||||
E_RETURN_VAL_IF_FAIL(reply.size() == 1, 0);
|
||||
|
||||
EdbusMessage::const_iterator it = reply.begin();
|
||||
E_RETURN_VAL_IF_FAIL(it->is_array(), 0);
|
||||
|
||||
EdbusList arr = it->to_array();
|
||||
it = arr.begin();
|
||||
EdbusMessage::const_iterator ite = arr.end();
|
||||
|
||||
for(; it != ite; ++it) {
|
||||
if(!it->is_object_path()) continue;
|
||||
|
||||
EdbusObjectPath p = it->to_object_path();
|
||||
|
||||
if(is_battery(con, p.path())) {
|
||||
/* filters so signal_cb() doesn't get clobbered with uninterested dbus signals */
|
||||
con.add_signal_match(p.path(), UPOWER_INTERFACE, "Changed");
|
||||
//con.add_signal_match(p.path(), UPOWER_SERVICE, "DeviceChanged");
|
||||
batts.push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
update_icon_and_tooltip();
|
||||
|
||||
/* ready to receive signals */
|
||||
con.signal_callback(signal_cb, this);
|
||||
con.setup_listener_with_fltk();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BatteryMonitor::update_icon_and_tooltip(void) {
|
||||
/* in case connection failed somehow */
|
||||
if(!con.connected()) {
|
||||
label("0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
E_RETURN_VAL_IF_FAIL(batts.size() > 0, 0);
|
||||
double p = 0, ret = 0;
|
||||
|
||||
if(batts.size() == 1) {
|
||||
E_RETURN_VAL_IF_FAIL(get_percentage(con, batts.front().path(), &ret), 0);
|
||||
p = ret;
|
||||
tooltip_printf(_("Battery %s: %i%%"), get_state_str(con, batts.front().path()), (int)ret);
|
||||
} else {
|
||||
for(BatteryListIt it = batts.begin(), ite = batts.end(); it != ite; ++it) {
|
||||
if(!get_percentage(con, it->path(), &ret)) continue;
|
||||
p += ret;
|
||||
}
|
||||
|
||||
p /= batts.size();
|
||||
tooltip_printf(_("%i batteries: %i%%"), batts.size(), (int)p);
|
||||
}
|
||||
|
||||
set_icon(p);
|
||||
/* returning state is mainly for signal_cb() */
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define BATTERY_MIN 10
|
||||
|
||||
void BatteryMonitor::set_icon(double percentage, bool failure) {
|
||||
if(E_UNLIKELY(IconLoader::inited() == false)) {
|
||||
char buf[8];
|
||||
snprintf(buf, sizeof(buf), "%i%%", (int)percentage);
|
||||
copy_label(buf);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const char *icon;
|
||||
|
||||
if(failure)
|
||||
icon = BATTERY_NO_CONNECTION;
|
||||
else
|
||||
icon = (percentage >= BATTERY_MIN) ? BATTERY_IMG : BATTERY_CAUTION_IMG;
|
||||
|
||||
/* small check to prevent image loading when not needed */
|
||||
if(icon == bimg) return;
|
||||
|
||||
IconLoader::set(this, icon, ICON_SIZE_SMALL);
|
||||
bimg = icon;
|
||||
}
|
||||
|
||||
#else /* EDELIB_HAVE_DBUS */
|
||||
class BatteryMonitor : public Fl_Box {
|
||||
public:
|
||||
BatteryMonitor() : Fl_Box(0, 0, 30, 25) {
|
||||
tooltip(_("Battery status not available"));
|
||||
label("bat");
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
EDE_PANEL_APPLET_EXPORT (
|
||||
BatteryMonitor,
|
||||
EDE_PANEL_APPLET_OPTION_ALIGN_RIGHT,
|
||||
"Battery monitor",
|
||||
"0.1",
|
||||
"empty",
|
||||
"Sanel Zukan"
|
||||
)
|
13
ede-panel/applets/battery-monitor/Jamfile
Normal file
13
ede-panel/applets/battery-monitor/Jamfile
Normal file
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# $Id: Jamfile 3515 2013-01-09 16:01:35Z karijes $
|
||||
#
|
||||
# Part of Equinox Desktop Environment (EDE).
|
||||
# Copyright (c) 2013 EDE Authors.
|
||||
#
|
||||
# This program is licensed under terms of the
|
||||
# GNU General Public License version 2 or newer.
|
||||
# See COPYING for details.
|
||||
|
||||
SubDir TOP ede-panel applets battery-monitor ;
|
||||
|
||||
PanelApplet battery_monitor : BatteryMonitor.cpp : $(EDELIB_DBUS_LIB) ;
|
|
@ -9,6 +9,10 @@
|
|||
* For ede-panel by Sanel Zukan 2009
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -26,22 +30,27 @@
|
|||
# include <sys/sysinfo.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_KSTAT_H
|
||||
#ifdef HAVE_KSTAT
|
||||
# include <kstat.h>
|
||||
# include <sys/sysinfo.h>
|
||||
# include <string.h> /* strncmp */
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
# include <sys/param.h>
|
||||
# include <sys/sysctl.h>
|
||||
# if __FreeBSD_version < 500101
|
||||
# include <sys/dkstat.h>
|
||||
# if defined(__OpenBSD__)
|
||||
# include <sys/sched.h>
|
||||
# else
|
||||
# include <sys/resource.h>
|
||||
# if __FreeBSD_version < 500101
|
||||
# include <sys/dkstat.h>
|
||||
# else
|
||||
# include <sys/resource.h>
|
||||
# endif
|
||||
# endif
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include "Applet.h"
|
||||
#include "CpuMonitor.h"
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
@ -149,9 +158,9 @@ void CPUMonitor::clear()
|
|||
if(!cpu) return;
|
||||
|
||||
for (int i = 0; i < samples(); i++)
|
||||
delete cpu[i];
|
||||
delete [] cpu[i];
|
||||
|
||||
delete cpu;
|
||||
delete [] cpu;
|
||||
cpu = 0;
|
||||
|
||||
m_old_samples = -1;
|
||||
|
@ -336,11 +345,10 @@ void CPUMonitor::get_cpu_info() {
|
|||
|
||||
#endif /* linux */
|
||||
|
||||
#ifdef HAVE_KSTAT_H
|
||||
#ifdef HAVE_KSTAT
|
||||
# ifdef HAVE_OLD_KSTAT
|
||||
# define ui32 ul
|
||||
#endif
|
||||
|
||||
static kstat_ctl_t *kc = NULL;
|
||||
static kid_t kcid;
|
||||
kid_t new_kcid;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define __CPUMONITOR_H__
|
||||
|
||||
#include <FL/Fl_Box.H>
|
||||
#include "Applet.h"
|
||||
|
||||
/*
|
||||
#ifdef HAVE_KSTAT_H
|
||||
|
|
|
@ -10,4 +10,4 @@
|
|||
|
||||
SubDir TOP ede-panel applets cpu-monitor ;
|
||||
|
||||
PanelApplet cpu_monitor : CpuMonitor.cpp ;
|
||||
PanelApplet cpu_monitor : CpuMonitor.cpp : $(KSTAT_LIBS) ;
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
#
|
||||
# $Id: Jamfile 2864 2009-10-03 07:49:30Z karijes $
|
||||
#
|
||||
# Part of Equinox Desktop Environment (EDE).
|
||||
# Copyright (c) 2012 EDE Authors.
|
||||
#
|
||||
# This program is licensed under terms of the
|
||||
# GNU General Public License version 2 or newer.
|
||||
# See COPYING for details.
|
||||
|
||||
SubDir TOP ede-panel applets hider ;
|
||||
|
||||
PanelApplet hider : Hider.cpp ;
|
|
@ -1,3 +1,23 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2011-2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "Applet.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
@ -10,6 +30,7 @@
|
|||
#include <FL/Fl.H>
|
||||
|
||||
#include <stdio.h> /* needed for XKBrules.h */
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_XKBRULES
|
||||
# include <X11/XKBlib.h>
|
||||
|
@ -61,11 +82,12 @@ static KeyLayoutList keylayout_objects;
|
|||
#ifdef HAVE_XKBRULES
|
||||
/* Xkb does not provide this */
|
||||
static void xkbrf_names_prop_free(XkbRF_VarDefsRec &vd, char *tmp) {
|
||||
XFree(tmp);
|
||||
XFree(vd.model);
|
||||
XFree(vd.layout);
|
||||
XFree(vd.options);
|
||||
XFree(vd.variant);
|
||||
if(tmp) free(tmp);
|
||||
if(vd.model) XFree(vd.model);
|
||||
if(vd.layout) XFree(vd.layout);
|
||||
if(vd.options) XFree(vd.options);
|
||||
if(vd.variant) XFree(vd.variant);
|
||||
if(vd.extra_names) XFree(vd.extra_names);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -172,8 +194,10 @@ void KeyLayout::do_key_layout(void) {
|
|||
|
||||
if(XkbRF_GetNamesProp(fl_display, &tmp, &vd)) {
|
||||
/* do nothing if layout do not exists or the same was catched */
|
||||
if(!vd.layout || (curr_layout == vd.layout))
|
||||
if(!vd.layout || (curr_layout == vd.layout)) {
|
||||
xkbrf_names_prop_free(vd, tmp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* just store it, so update_flag() can do the rest */
|
||||
curr_layout = vd.layout;
|
||||
|
|
|
@ -1,72 +1,79 @@
|
|||
/*
|
||||
* $Id: Panel.cpp 3512 2013-01-09 13:45:49Z karijes $
|
||||
*
|
||||
* Copyright (C) 2012-2013 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <FL/Fl_Box.H>
|
||||
#include "Applet.h"
|
||||
#include <edelib/Nls.h>
|
||||
|
||||
#if defined(linux)
|
||||
#include <sys/sysinfo.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <edelib/Color.h>
|
||||
#include <edelib/Missing.h>
|
||||
#include "Applet.h"
|
||||
#include "MemMonitor.h"
|
||||
|
||||
EDELIB_NS_USING(color_rgb_to_fltk)
|
||||
|
||||
#define UPDATE_INTERVAL 1.0f
|
||||
#define UPDATE_INTERVAL 2.0f
|
||||
#define STR_CMP(first, second, n) (strncmp(first, second, n) == 0)
|
||||
|
||||
static int height_from_perc(int perc, int h) {
|
||||
class MemMonitor : public Fl_Box {
|
||||
private:
|
||||
int mem_usedp, swap_usedp;
|
||||
public:
|
||||
MemMonitor() : Fl_Box(0, 0, 45, 25), mem_usedp(0), swap_usedp(0) {
|
||||
box(FL_THIN_DOWN_BOX);
|
||||
update_status();
|
||||
}
|
||||
|
||||
void update_status(void);
|
||||
void draw(void);
|
||||
int handle(int e);
|
||||
};
|
||||
|
||||
inline int height_from_perc(int perc, int h) {
|
||||
return (perc * h) / 100;
|
||||
}
|
||||
|
||||
static long get_number(const char *ln) {
|
||||
char *s = edelib_strndup(ln, 128);
|
||||
int i = 1;
|
||||
|
||||
for(char *p = strtok(s, " "); p; p = strtok(NULL, " "), i++) {
|
||||
if(i == 2) {
|
||||
long ret = atol(p);
|
||||
free(s);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
free(s);
|
||||
return 0;
|
||||
}
|
||||
static void mem_timeout_cb(void *d) {
|
||||
((MemMonitor*)d)->update_status();
|
||||
Fl::repeat_timeout(UPDATE_INTERVAL, mem_timeout_cb, d);
|
||||
}
|
||||
|
||||
MemMonitor::MemMonitor() : Fl_Box(0, 0, 45, 25), mem_usedp(0), swap_usedp(0) {
|
||||
box(FL_THIN_DOWN_BOX);
|
||||
}
|
||||
|
||||
void MemMonitor::update_status(void) {
|
||||
FILE *fd = fopen("/proc/meminfo", "r");
|
||||
if(!fd) return;
|
||||
struct sysinfo sys;
|
||||
if(sysinfo(&sys) != 0) return;
|
||||
|
||||
long mem_total, mem_free, swap_total, swap_free;
|
||||
mem_total = mem_free = swap_total = swap_free = 0;
|
||||
|
||||
char buf[128];
|
||||
while(fgets(buf, 128, fd) != 0) {
|
||||
if(STR_CMP(buf, "MemTotal:", 9))
|
||||
mem_total = get_number(buf);
|
||||
else if(STR_CMP(buf, "MemFree:", 8))
|
||||
mem_free = get_number(buf);
|
||||
else if(STR_CMP(buf, "SwapTotal:", 10))
|
||||
swap_total = get_number(buf);
|
||||
else if(STR_CMP(buf, "SwapFree:", 9))
|
||||
swap_free = get_number(buf);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
mem_total = (float)sys.totalram * (float)sys.mem_unit / 1048576.0f;
|
||||
mem_free = (float)sys.freeram * (float)sys.mem_unit / 1048576.0f;
|
||||
swap_total = (float)sys.totalswap * (float)sys.mem_unit / 1048576.0f;
|
||||
swap_free = (float)sys.freeswap * (float)sys.mem_unit / 1048576.0f;
|
||||
|
||||
mem_usedp = 100 - (int)(((float)mem_free / (float)mem_total) * 100);
|
||||
swap_usedp = 100 - (int)(((float)swap_total / (float)swap_free) * 100);
|
||||
swap_usedp = 100 - (int)(((float)swap_free / (float)swap_total) * 100);
|
||||
|
||||
static char tip[100];
|
||||
snprintf(tip, sizeof(tip), "Memory used: %i%%\nSwap used: %i%%", mem_usedp, swap_usedp);
|
||||
snprintf(tip, sizeof(tip), _("Memory used: %i%%\nSwap used: %i%%"), mem_usedp, swap_usedp);
|
||||
tooltip(tip);
|
||||
|
||||
redraw();
|
||||
|
@ -105,11 +112,24 @@ int MemMonitor::handle(int e) {
|
|||
return Fl_Box::handle(e);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
class MemMonitor : public Fl_Box {
|
||||
public:
|
||||
MemMonitor() : Fl_Box(0, 0, 45, 25) {
|
||||
box(FL_THIN_DOWN_BOX);
|
||||
label("n/a");
|
||||
tooltip(_("Memory information not available for this platform"));
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* linux */
|
||||
|
||||
EDE_PANEL_APPLET_EXPORT (
|
||||
MemMonitor,
|
||||
EDE_PANEL_APPLET_OPTION_ALIGN_RIGHT,
|
||||
"Memory monitor",
|
||||
"0.1",
|
||||
"0.2",
|
||||
"empty",
|
||||
"Sanel Zukan"
|
||||
)
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
#ifndef __MEMMONITOR_H__
|
||||
#define __MEMMONITOR_H__
|
||||
|
||||
#include <FL/Fl_Box.H>
|
||||
|
||||
class MemMonitor : public Fl_Box {
|
||||
private:
|
||||
int mem_usedp, swap_usedp;
|
||||
|
||||
public:
|
||||
MemMonitor();
|
||||
void update_status(void);
|
||||
void draw(void);
|
||||
int handle(int e);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,3 +1,23 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "Applet.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
|
|
@ -84,9 +84,10 @@ public:
|
|||
const char *get_id(void) { return id ? id->c_str() : NULL; }
|
||||
unsigned int get_age(void) { return age; }
|
||||
|
||||
const char *get_name(void) { return name ? name->c_str() : NULL; }
|
||||
const char *get_icon(void) { return icon ? icon->c_str() : NULL; }
|
||||
const char *get_exec(void) { return exec_cmd ? exec_cmd->c_str() : NULL; }
|
||||
const char *get_name(void) { return name ? name->c_str() : NULL; }
|
||||
const char *get_icon(void) { return icon ? icon->c_str() : NULL; }
|
||||
const char *get_exec(void) { return exec_cmd ? exec_cmd->c_str() : NULL; }
|
||||
const char *get_comment(void) { return comment ? comment->c_str() : NULL; }
|
||||
};
|
||||
|
||||
/* remove duplicate items in the list, by looking at DesktopEntry id */
|
||||
|
|
|
@ -12,10 +12,14 @@ SubDir TOP ede-panel applets start-menu ;
|
|||
|
||||
MENU_SRC = XdgMenuReader.cpp DesktopEntry.cpp MenuRules.cpp ;
|
||||
|
||||
Library libmenu : $(MENU_SRC) ;
|
||||
ObjectC++Flags $(MENU_SRC) : -fPIC $(FLTKINCLUDE) -I [ FDirName $(TOP) ede-panel ] $(EDELIBINCLUDE) ;
|
||||
if $(MENU_TESTS) {
|
||||
Library libmenu : $(MENU_SRC) ;
|
||||
ObjectC++Flags $(MENU_SRC) : -fPIC $(FLTKINCLUDE) -I [ FDirName $(TOP) ede-panel ] $(EDELIBINCLUDE) ;
|
||||
|
||||
PanelApplet start_menu : StartMenu.cpp : -L$(SUBDIR) -lmenu ;
|
||||
|
||||
PanelApplet start_menu : StartMenu.cpp : -L$(SUBDIR) -lmenu ;
|
||||
|
||||
EdeProgram ede-menu-spec-test : ede-menu-spec-test.cpp ;
|
||||
LinkAgainstAsFirst ede-menu-spec-test : -L$(SUBDIR) -lmenu ;
|
||||
EdeProgram ede-menu-spec-test : ede-menu-spec-test.cpp ;
|
||||
LinkAgainstAsFirst ede-menu-spec-test : -L$(SUBDIR) -lmenu ;
|
||||
} else {
|
||||
PanelApplet start_menu : StartMenu.cpp $(MENU_SRC) ;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __MENURULES_H__
|
||||
#define __MENURULES_H__
|
||||
|
||||
|
@ -8,7 +28,7 @@ EDELIB_NS_USING(list)
|
|||
EDELIB_NS_USING(String)
|
||||
|
||||
struct MenuRules;
|
||||
struct DesktopEntry;
|
||||
class DesktopEntry;
|
||||
|
||||
typedef list<MenuRules*> MenuRulesList;
|
||||
typedef list<MenuRules*>::iterator MenuRulesListIt;
|
||||
|
|
|
@ -1,21 +1,64 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "Applet.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <edelib/MenuBase.h>
|
||||
#include <edelib/Debug.h>
|
||||
#include <edelib/Nls.h>
|
||||
#include <edelib/Debug.h>
|
||||
#include <edelib/StrUtil.h>
|
||||
|
||||
#include "XdgMenuReader.h"
|
||||
#include "ede-icon.h"
|
||||
|
||||
/* by default is enabled */
|
||||
#define EDE_PANEL_MENU_AUTOUPDATE 1
|
||||
|
||||
#ifdef EDE_PANEL_MENU_AUTOUPDATE
|
||||
# include <edelib/DirWatch.h>
|
||||
EDELIB_NS_USING(DirWatch)
|
||||
EDELIB_NS_USING_LIST(4, (DW_CREATE, DW_MODIFY, DW_DELETE, DW_REPORT_RENAME))
|
||||
|
||||
/* when menu needs to be update, after how long to do real update */
|
||||
# define MENU_UPDATE_TIMEOUT 5.0
|
||||
|
||||
/* elapsed seconds between changes reports from DirWatch; to prevent event throttling */
|
||||
# define MENU_UPDATE_DIFF 5
|
||||
#endif
|
||||
|
||||
EDELIB_NS_USING(MenuBase)
|
||||
EDELIB_NS_USING(str_ends)
|
||||
|
||||
/* some of this code was ripped from Fl_Menu_Button.cxx */
|
||||
|
||||
class StartMenu : public MenuBase {
|
||||
private:
|
||||
MenuItem *mcontent;
|
||||
XdgMenuContent *mcontent, *mcontent_pending;
|
||||
|
||||
time_t last_reload;
|
||||
bool menu_opened;
|
||||
|
||||
void setup_menu(XdgMenuContent *m);
|
||||
public:
|
||||
StartMenu();
|
||||
~StartMenu();
|
||||
|
@ -23,9 +66,35 @@ public:
|
|||
void popup(void);
|
||||
void draw(void);
|
||||
int handle(int e);
|
||||
|
||||
void reload_menu(void);
|
||||
bool can_reload(void);
|
||||
};
|
||||
|
||||
StartMenu::StartMenu() : MenuBase(0, 0, 80, 25, "EDE"), mcontent(NULL) {
|
||||
#ifdef EDE_PANEL_MENU_AUTOUPDATE
|
||||
static void menu_update_cb(void *data) {
|
||||
StartMenu *m = (StartMenu*)data;
|
||||
m->reload_menu();
|
||||
E_DEBUG(E_STRLOC ": Scheduled menu update done\n");
|
||||
}
|
||||
|
||||
static void folder_changed_cb(const char *dir, const char *w, int flags, void *data) {
|
||||
StartMenu *m = (StartMenu*)data;
|
||||
|
||||
/* skip file renaming */
|
||||
if(flags == DW_REPORT_RENAME) return;
|
||||
|
||||
if(w == NULL) w = "<none>";
|
||||
|
||||
/* add timeout for update so all filesystem changes gets applied */
|
||||
if(str_ends(w, ".desktop") && m->can_reload()) {
|
||||
E_DEBUG(E_STRLOC ": Scheduled menu update due changes inside inside '%s' folder ('%s':%i) in %i secs.\n", dir, w, flags, MENU_UPDATE_TIMEOUT);
|
||||
Fl::add_timeout(MENU_UPDATE_TIMEOUT, menu_update_cb, m);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
StartMenu::StartMenu() : MenuBase(0, 0, 80, 25, "EDE"), mcontent(NULL), mcontent_pending(NULL), last_reload(0), menu_opened(false) {
|
||||
down_box(FL_NO_BOX);
|
||||
labelfont(FL_HELVETICA_BOLD);
|
||||
labelsize(14);
|
||||
|
@ -33,21 +102,51 @@ StartMenu::StartMenu() : MenuBase(0, 0, 80, 25, "EDE"), mcontent(NULL) {
|
|||
|
||||
tooltip(_("Click here to choose and start common programs"));
|
||||
|
||||
/* load menu */
|
||||
mcontent = xdg_menu_load();
|
||||
setup_menu(mcontent);
|
||||
|
||||
if(mcontent) {
|
||||
/* skip the first item, since it often contains only one submenu */
|
||||
if(mcontent->submenu()) {
|
||||
MenuItem *mc = mcontent + 1;
|
||||
menu(mc);
|
||||
} else {
|
||||
menu(mcontent);
|
||||
}
|
||||
}
|
||||
#ifdef EDE_PANEL_MENU_AUTOUPDATE
|
||||
/*
|
||||
* setup listeners on menu folders
|
||||
* TODO: this list is constructed twice: the first time when menu was loaded and now
|
||||
*/
|
||||
StrList lst;
|
||||
xdg_menu_applications_location(lst);
|
||||
|
||||
DirWatch::init();
|
||||
|
||||
StrListIt it = lst.begin(), ite = lst.end();
|
||||
for(; it != ite; ++it)
|
||||
DirWatch::add(it->c_str(), DW_CREATE | DW_MODIFY | DW_DELETE);
|
||||
|
||||
DirWatch::callback(folder_changed_cb, this);
|
||||
#endif
|
||||
}
|
||||
|
||||
StartMenu::~StartMenu() {
|
||||
xdg_menu_delete(mcontent);
|
||||
if(mcontent) xdg_menu_delete(mcontent);
|
||||
if(mcontent_pending) xdg_menu_delete(mcontent_pending);
|
||||
|
||||
#ifdef EDE_PANEL_MENU_AUTOUPDATE
|
||||
DirWatch::shutdown();
|
||||
#endif
|
||||
}
|
||||
|
||||
void StartMenu::setup_menu(XdgMenuContent *m) {
|
||||
if(m == NULL) {
|
||||
menu(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
MenuItem *item = xdg_menu_to_fltk_menu(m);
|
||||
|
||||
/* skip the first item, since it often contains only one submenu */
|
||||
if(item && item->submenu()) {
|
||||
menu(item + 1);
|
||||
} else {
|
||||
menu(item);
|
||||
}
|
||||
}
|
||||
|
||||
static StartMenu *pressed_menu_button = 0;
|
||||
|
@ -78,13 +177,18 @@ void StartMenu::draw(void) {
|
|||
}
|
||||
|
||||
void StartMenu::popup(void) {
|
||||
menu_opened = true;
|
||||
|
||||
const MenuItem *m;
|
||||
|
||||
pressed_menu_button = this;
|
||||
redraw();
|
||||
|
||||
#if (FL_MAJOR_VERSION >= 1) && (FL_MINOR_VERSION >= 3)
|
||||
Fl_Widget *mb = this;
|
||||
Fl::watch_widget_pointer(mb);
|
||||
#endif
|
||||
|
||||
if(!box() || type())
|
||||
m = menu()->popup(Fl::event_x(), Fl::event_y(), label(), mvalue(), this);
|
||||
else
|
||||
|
@ -92,7 +196,25 @@ void StartMenu::popup(void) {
|
|||
|
||||
picked(m);
|
||||
pressed_menu_button = 0;
|
||||
|
||||
#if (FL_MAJOR_VERSION >= 1) && (FL_MINOR_VERSION >= 3)
|
||||
Fl::release_widget_pointer(mb);
|
||||
#endif
|
||||
|
||||
menu_opened = false;
|
||||
#ifdef EDE_PANEL_MENU_AUTOUPDATE
|
||||
/* if we have menu that wants to be updated, swap them as soon as menu window was closed */
|
||||
if(mcontent_pending) {
|
||||
XdgMenuContent *tmp = mcontent;
|
||||
|
||||
mcontent = mcontent_pending;
|
||||
setup_menu(mcontent);
|
||||
|
||||
mcontent_pending = tmp;
|
||||
xdg_menu_delete(mcontent_pending);
|
||||
mcontent_pending = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int StartMenu::handle(int e) {
|
||||
|
@ -158,11 +280,39 @@ int StartMenu::handle(int e) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* to prevent throttling of dirwatch events */
|
||||
bool StartMenu::can_reload(void) {
|
||||
#ifdef EDE_PANEL_MENU_AUTOUPDATE
|
||||
time_t c, diff;
|
||||
|
||||
c = time(NULL);
|
||||
diff = (time_t)difftime(c, last_reload);
|
||||
last_reload = c;
|
||||
|
||||
if(diff >= MENU_UPDATE_DIFF) return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void StartMenu::reload_menu(void) {
|
||||
#ifdef EDE_PANEL_MENU_AUTOUPDATE
|
||||
if(menu_opened) {
|
||||
mcontent_pending = xdg_menu_load();
|
||||
} else {
|
||||
xdg_menu_delete(mcontent);
|
||||
|
||||
mcontent = xdg_menu_load();
|
||||
setup_menu(mcontent);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
EDE_PANEL_APPLET_EXPORT (
|
||||
StartMenu,
|
||||
EDE_PANEL_APPLET_OPTION_ALIGN_LEFT,
|
||||
"Main menu",
|
||||
"0.1",
|
||||
"0.2",
|
||||
"empty",
|
||||
"Sanel Zukan"
|
||||
)
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
|
@ -6,9 +26,7 @@
|
|||
#include <FL/Fl_Shared_Image.H>
|
||||
#include <edelib/TiXml.h>
|
||||
#include <edelib/Debug.h>
|
||||
#include <edelib/String.h>
|
||||
#include <edelib/StrUtil.h>
|
||||
#include <edelib/List.h>
|
||||
#include <edelib/Util.h>
|
||||
#include <edelib/FileTest.h>
|
||||
#include <edelib/Directory.h>
|
||||
|
@ -21,9 +39,7 @@
|
|||
#include "MenuRules.h"
|
||||
#include "XdgMenuReader.h"
|
||||
|
||||
EDELIB_NS_USING(String)
|
||||
EDELIB_NS_USING(DesktopFile)
|
||||
EDELIB_NS_USING(list)
|
||||
EDELIB_NS_USING(IconLoader)
|
||||
EDELIB_NS_USING(system_config_dirs)
|
||||
EDELIB_NS_USING(system_data_dirs)
|
||||
|
@ -204,25 +220,11 @@ static void menu_parse_context_append_desktop_files(MenuParseContext *ctx, const
|
|||
|
||||
static void menu_parse_context_append_desktop_files_from_xdg_data_dirs(MenuParseContext *ctx) {
|
||||
StrList lst;
|
||||
if(system_data_dirs(lst) < 1)
|
||||
return;
|
||||
xdg_menu_applications_location(lst);
|
||||
|
||||
StrListIt it = lst.begin(), it_end = lst.end();
|
||||
String tmp;
|
||||
|
||||
for(; it != it_end; ++it) {
|
||||
tmp = build_filename((*it).c_str(), "applications");
|
||||
menu_parse_context_append_desktop_files(ctx, tmp.c_str(), tmp.c_str());
|
||||
}
|
||||
|
||||
/*
|
||||
* Add user directory too; the spec is unclear about this, but official menu spec tests
|
||||
* requires it. Also, users will be able to add menu items without superuser permissions.
|
||||
*/
|
||||
String user_dir = user_data_dir();
|
||||
|
||||
tmp = build_filename(user_dir.c_str(), "applications");
|
||||
menu_parse_context_append_desktop_files(ctx, tmp.c_str(), tmp.c_str());
|
||||
for(; it != it_end; ++it)
|
||||
menu_parse_context_append_desktop_files(ctx, it->c_str(), it->c_str());
|
||||
}
|
||||
|
||||
static void scan_include_exclude_tag(TiXmlNode *elem, MenuRulesList &rules) {
|
||||
|
@ -547,8 +549,8 @@ static MenuContext *menu_parse_context_to_menu_context(MenuParseContext *m,
|
|||
* figure out the name first; if returns false, either menu should not be displayed, or something
|
||||
* went wrong
|
||||
*/
|
||||
String *n, *ic;
|
||||
bool should_be_displayed;
|
||||
String *n = NULL, *ic = NULL;
|
||||
bool should_be_displayed = false;
|
||||
|
||||
if(!menu_context_construct_name_and_get_icon(m, top, &n, &ic, &should_be_displayed))
|
||||
return NULL;
|
||||
|
@ -568,7 +570,6 @@ static MenuContext *menu_parse_context_to_menu_context(MenuParseContext *m,
|
|||
ctx->name = n;
|
||||
ctx->icon = ic;
|
||||
ctx->display_it = should_be_displayed;
|
||||
|
||||
//E_DEBUG("+ Menu: %s %i\n", ctx->name->c_str(), m->include_rules.size());
|
||||
|
||||
/* fill MenuContext items, depending on what list was passed */
|
||||
|
@ -799,7 +800,7 @@ static TiXmlNode *load_menu_file(TiXmlDocument &doc) {
|
|||
String tmp;
|
||||
StrListIt it = paths.begin(), it_end = paths.end();
|
||||
|
||||
for(; it != paths.end(); ++it) {
|
||||
for(; it != it_end; ++it) {
|
||||
tmp = build_filename((*it).c_str(), "menus", menu_file.c_str());
|
||||
|
||||
if(doc.LoadFile(tmp.c_str()))
|
||||
|
@ -868,9 +869,18 @@ void xdg_menu_dump_for_test_suite(void) {
|
|||
menu_all_parse_lists_clear(pl, cl);
|
||||
}
|
||||
|
||||
/* used only for xdg_menu_load() and xdg_menu_delete() */
|
||||
static MenuParseList global_parse_list;
|
||||
static MenuContextList global_context_list;
|
||||
/* public API */
|
||||
|
||||
struct XdgMenuContent {
|
||||
MenuItem *fltk_menu;
|
||||
|
||||
/*
|
||||
* We are keeping them as fltk_menu references some objects, like text.
|
||||
* This is since FLTK menu can't free label strings as MenuItem is plain struct.
|
||||
*/
|
||||
MenuParseList parse_list;
|
||||
MenuContextList context_list;
|
||||
};
|
||||
|
||||
static void item_cb(Fl_Widget*, void *en) {
|
||||
DesktopEntry *entry = (DesktopEntry*)en;
|
||||
|
@ -916,7 +926,7 @@ static unsigned int construct_edelib_menu(MenuContextList &lst, MenuItem *mi, un
|
|||
mi[pos].labelsize_ = FL_NORMAL_SIZE;
|
||||
mi[pos].labelcolor_ = FL_BLACK;
|
||||
|
||||
mi[pos].image(NULL);
|
||||
MenuItem::init_extensions(&mi[pos]);
|
||||
|
||||
/* set image for menu */
|
||||
if(cc->icon && IconLoader::inited()) {
|
||||
|
@ -952,13 +962,16 @@ static unsigned int construct_edelib_menu(MenuContextList &lst, MenuItem *mi, un
|
|||
mi[pos].labelfont_ = FL_HELVETICA;
|
||||
mi[pos].labelsize_ = FL_NORMAL_SIZE;
|
||||
mi[pos].labelcolor_ = FL_BLACK;
|
||||
mi[pos].image(NULL);
|
||||
MenuItem::init_extensions(&mi[pos]);
|
||||
|
||||
/* set image for menu item*/
|
||||
if((*ds)->get_icon() && IconLoader::inited()) {
|
||||
Fl_Image *img = IconLoader::get((*ds)->get_icon(), ICON_SIZE_SMALL);
|
||||
mi[pos].image(img);
|
||||
}
|
||||
|
||||
/* set tooltip if we have; it is actually a comment from .desktop file */
|
||||
mi[pos].tooltip((*ds)->get_comment());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -973,11 +986,11 @@ static unsigned int construct_edelib_menu(MenuContextList &lst, MenuItem *mi, un
|
|||
|
||||
mi[pos].flags = 0;
|
||||
mi[pos].shortcut_ = 0;
|
||||
mi[pos].image(NULL);
|
||||
mi[pos].labeltype_ = FL_NORMAL_LABEL;
|
||||
mi[pos].labelfont_ = FL_HELVETICA;
|
||||
mi[pos].labelsize_ = FL_NORMAL_SIZE;
|
||||
mi[pos].labelcolor_ = FL_BLACK;
|
||||
MenuItem::init_extensions(&mi[pos]);
|
||||
|
||||
/* set callback and callback data to be current entry */
|
||||
mi[pos].callback_ = logout_cb;
|
||||
|
@ -993,7 +1006,7 @@ static unsigned int construct_edelib_menu(MenuContextList &lst, MenuItem *mi, un
|
|||
|
||||
/* end this menu */
|
||||
mi[pos].text = NULL;
|
||||
mi[pos].image(NULL);
|
||||
MenuItem::init_extensions(&mi[pos]);
|
||||
|
||||
//E_DEBUG("{0}\n");
|
||||
|
||||
|
@ -1006,33 +1019,60 @@ static unsigned int construct_edelib_menu(MenuContextList &lst, MenuItem *mi, un
|
|||
return pos;
|
||||
}
|
||||
|
||||
MenuItem *xdg_menu_load(void) {
|
||||
/* assure they are empty */
|
||||
E_RETURN_VAL_IF_FAIL(global_parse_list.empty() == true, NULL);
|
||||
E_RETURN_VAL_IF_FAIL(global_context_list.empty() == true, NULL);
|
||||
void xdg_menu_applications_location(StrList &lst) {
|
||||
lst.clear();
|
||||
|
||||
if(system_data_dirs(lst) < 1)
|
||||
return;
|
||||
|
||||
StrListIt it = lst.begin(), it_end = lst.end();
|
||||
|
||||
for(; it != it_end; ++it)
|
||||
*it = build_filename(it->c_str(), "applications");
|
||||
|
||||
/*
|
||||
* Add user directory too; the spec is unclear about this, but official menu spec tests
|
||||
* requires it. Also, users will be able to add menu items without superuser permissions.
|
||||
*/
|
||||
String user_dir = user_data_dir();
|
||||
lst.push_back(build_filename(user_dir.c_str(), "applications"));
|
||||
}
|
||||
|
||||
XdgMenuContent *xdg_menu_load(void) {
|
||||
XdgMenuContent *content = new XdgMenuContent();
|
||||
|
||||
/* load everything */
|
||||
menu_all_parse_lists_load(global_parse_list, global_context_list);
|
||||
menu_all_parse_lists_load(content->parse_list, content->context_list);
|
||||
|
||||
unsigned int sz = menu_context_list_count(global_context_list);
|
||||
unsigned int sz = menu_context_list_count(content->context_list);
|
||||
E_RETURN_VAL_IF_FAIL(sz > 0, NULL);
|
||||
|
||||
MenuItem *mi = new MenuItem[sz + 2]; /* plus logout + ending NULL */
|
||||
|
||||
unsigned int pos = construct_edelib_menu(global_context_list, mi, 0);
|
||||
unsigned int pos = construct_edelib_menu(content->context_list, mi, 0);
|
||||
mi[pos].text = NULL;
|
||||
|
||||
/*
|
||||
* MenuItem does not have constructor, so everywhere where we access MenuItem object, image
|
||||
* member must be NULL-ed too
|
||||
*/
|
||||
mi[pos].image(NULL);
|
||||
MenuItem::init_extensions(&mi[pos]);
|
||||
|
||||
E_ASSERT(pos <= sz + 2);
|
||||
return mi;
|
||||
|
||||
content->fltk_menu = mi;
|
||||
return content;
|
||||
}
|
||||
|
||||
void xdg_menu_delete(MenuItem *m) {
|
||||
delete [] m;
|
||||
menu_all_parse_lists_clear(global_parse_list, global_context_list);
|
||||
void xdg_menu_delete(XdgMenuContent *m) {
|
||||
E_RETURN_IF_FAIL(m != NULL);
|
||||
|
||||
delete [] m->fltk_menu;
|
||||
menu_all_parse_lists_clear(m->parse_list, m->context_list);
|
||||
delete m;
|
||||
}
|
||||
|
||||
MenuItem *xdg_menu_to_fltk_menu(XdgMenuContent *m) {
|
||||
E_RETURN_VAL_IF_FAIL(m != NULL, NULL);
|
||||
return m->fltk_menu;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,45 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __XDGMENUREADER_H__
|
||||
#define __XDGMENUREADER_H__
|
||||
|
||||
#include <edelib/MenuItem.h>
|
||||
#include <edelib/List.h>
|
||||
#include <edelib/String.h>
|
||||
|
||||
EDELIB_NS_USING(MenuItem)
|
||||
EDELIB_NS_USING(String)
|
||||
EDELIB_NS_USING(list)
|
||||
|
||||
typedef list<String> StrList;
|
||||
typedef list<String>::iterator StrListIt;
|
||||
|
||||
void xdg_menu_dump_for_test_suite(void);
|
||||
/* all locations where menu files are stored */
|
||||
void xdg_menu_applications_location(StrList &lst);
|
||||
|
||||
MenuItem *xdg_menu_load(void);
|
||||
void xdg_menu_delete(MenuItem *it);
|
||||
struct XdgMenuContent;
|
||||
|
||||
XdgMenuContent *xdg_menu_load(void);
|
||||
void xdg_menu_delete(XdgMenuContent *c);
|
||||
MenuItem *xdg_menu_to_fltk_menu(XdgMenuContent *c);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <FL/Fl_Window.H>
|
||||
#include <edelib/Debug.h>
|
||||
|
||||
#include "Applet.h"
|
||||
#include "Panel.h"
|
||||
#include "Tray.h"
|
||||
|
||||
|
@ -45,6 +44,7 @@ static int handle_xevent(int e) {
|
|||
}
|
||||
} else if(fl_xevent->type == DestroyNotify) {
|
||||
XDestroyWindowEvent xev = fl_xevent->xdestroywindow;
|
||||
E_DEBUG(E_STRLOC ": Unock request for %i\n", fl_xevent->xclient.data.l[2]);
|
||||
curr_tray->unembed_window(xev.window);
|
||||
return false;
|
||||
} else if(fl_xevent->type == ConfigureNotify) {
|
||||
|
@ -88,6 +88,7 @@ void Tray::distribute_children(void) {
|
|||
Y = y();
|
||||
for(int i = 0; i < children(); i++) {
|
||||
child(i)->position(X, Y);
|
||||
E_DEBUG(E_STRLOC ": child %i at %i %i\n", i, child(i)->x(), child(i)->y());
|
||||
X += child(i)->w() + TRAY_ICONS_SPACE;
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +204,8 @@ void Tray::add_to_tray(Fl_Widget *win) {
|
|||
w(w() + win->w() + TRAY_ICONS_SPACE);
|
||||
|
||||
distribute_children();
|
||||
redraw();
|
||||
|
||||
//redraw();
|
||||
EDE_PANEL_GET_PANEL_OBJECT(this)->relayout();
|
||||
}
|
||||
|
||||
|
@ -211,10 +213,13 @@ void Tray::remove_from_tray(Fl_Widget *win) {
|
|||
remove(win);
|
||||
w(w() - win->w() - TRAY_ICONS_SPACE);
|
||||
|
||||
win->hide();
|
||||
delete win;
|
||||
|
||||
distribute_children();
|
||||
|
||||
redraw();
|
||||
EDE_PANEL_GET_PANEL_OBJECT(this)->relayout();
|
||||
EDE_PANEL_GET_PANEL_OBJECT(this)->redraw();
|
||||
}
|
||||
|
||||
int Tray::handle(int e) {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <FL/Fl_Group.H>
|
||||
#include <FL/x.H>
|
||||
#include <edelib/List.h>
|
||||
#include "Applet.h"
|
||||
|
||||
EDELIB_NS_USING(list)
|
||||
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <FL/Fl.H>
|
||||
|
@ -24,10 +44,12 @@ EDELIB_NS_USING(IconLoader)
|
|||
EDELIB_NS_USING(ICON_SIZE_TINY)
|
||||
EDELIB_NS_USING(netwm_window_close)
|
||||
EDELIB_NS_USING(netwm_window_set_active)
|
||||
EDELIB_NS_USING(netwm_window_maximize)
|
||||
EDELIB_NS_USING(netwm_window_get_title)
|
||||
EDELIB_NS_USING(wm_window_ede_restore)
|
||||
EDELIB_NS_USING(wm_window_get_state)
|
||||
EDELIB_NS_USING(netwm_window_get_icon)
|
||||
EDELIB_NS_USING(netwm_window_set_state)
|
||||
EDELIB_NS_USING(NETWM_STATE_ACTION_TOGGLE)
|
||||
EDELIB_NS_USING(NETWM_STATE_MAXIMIZED)
|
||||
|
||||
EDELIB_NS_USING(wm_window_set_state)
|
||||
EDELIB_NS_USING(WM_WINDOW_STATE_ICONIC)
|
||||
|
||||
|
@ -60,32 +82,32 @@ static void close_cb(Fl_Widget*, void *b) {
|
|||
|
||||
static void restore_cb(Fl_Widget*, void *b) {
|
||||
TaskButton *bb = (TaskButton*)b;
|
||||
wm_window_ede_restore(bb->get_window_xid());
|
||||
|
||||
netwm_window_set_active(bb->get_window_xid());
|
||||
netwm_window_set_active(bb->get_window_xid(), 1);
|
||||
redraw_whole_panel(bb);
|
||||
}
|
||||
|
||||
static void minimize_cb(Fl_Widget*, void *b) {
|
||||
TaskButton *bb = (TaskButton*)b;
|
||||
|
||||
if(wm_window_get_state(bb->get_window_xid()) != WM_WINDOW_STATE_ICONIC)
|
||||
wm_window_set_state(bb->get_window_xid(), WM_WINDOW_STATE_ICONIC);
|
||||
|
||||
redraw_whole_panel(bb);
|
||||
/* WM_WINDOW_STATE_ICONIC is safer on other window managers than NETWM_STATE_HIDDEN */
|
||||
wm_window_set_state(bb->get_window_xid(), WM_WINDOW_STATE_ICONIC);
|
||||
}
|
||||
|
||||
static void maximize_cb(Fl_Widget*, void *b) {
|
||||
TaskButton *bb = (TaskButton*)b;
|
||||
|
||||
netwm_window_set_active(bb->get_window_xid());
|
||||
netwm_window_maximize(bb->get_window_xid());
|
||||
netwm_window_set_active(bb->get_window_xid(), 1);
|
||||
netwm_window_set_state(bb->get_window_xid(), NETWM_STATE_MAXIMIZED, NETWM_STATE_ACTION_TOGGLE);
|
||||
|
||||
redraw_whole_panel(bb);
|
||||
}
|
||||
|
||||
TaskButton::TaskButton(int X, int Y, int W, int H, const char *l) : Fl_Button(X, Y, W, H, l), xid(0), image_alloc(false) {
|
||||
TaskButton::TaskButton(int X, int Y, int W, int H, const char *l) : Fl_Button(X, Y, W, H, l),
|
||||
xid(0), wspace(0), old_value(0), image_alloc(false), dragged(false), net_wm_icon(0)
|
||||
{
|
||||
box(FL_UP_BOX);
|
||||
|
||||
align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT | FL_ALIGN_CLIP);
|
||||
|
||||
if(IconLoader::inited()) {
|
||||
|
@ -181,64 +203,13 @@ void TaskButton::update_title_from_xid(void) {
|
|||
}
|
||||
}
|
||||
|
||||
/* stolen from pekwm */
|
||||
void TaskButton::update_image_from_xid(void) {
|
||||
E_RETURN_IF_FAIL(xid >= 0);
|
||||
|
||||
Atom real;
|
||||
int format;
|
||||
unsigned long n, extra;
|
||||
unsigned char *prop = 0;
|
||||
long len = 2;
|
||||
|
||||
int status = XGetWindowProperty(fl_display, xid,
|
||||
net_wm_icon , 0L, len, False, XA_CARDINAL, &real, &format, &n, &extra, (unsigned char**)&prop);
|
||||
|
||||
if((status != Success) || (real != XA_CARDINAL)) {
|
||||
if(prop) XFree(prop);
|
||||
return;
|
||||
}
|
||||
|
||||
long *data = (long*)prop;
|
||||
unsigned int width, height;
|
||||
|
||||
width = data[0];
|
||||
height = data[1];
|
||||
XFree(prop);
|
||||
|
||||
len += width * height;
|
||||
|
||||
format = 0;
|
||||
prop = 0;
|
||||
real = 0;
|
||||
|
||||
status = XGetWindowProperty(fl_display, xid,
|
||||
net_wm_icon , 0L, len, False, XA_CARDINAL, &real, &format, &n, &extra, (unsigned char**)&prop);
|
||||
|
||||
if((status != Success) || (real != XA_CARDINAL)) {
|
||||
if(prop) XFree(prop);
|
||||
return;
|
||||
}
|
||||
|
||||
data = (long*)prop;
|
||||
|
||||
unsigned char *img_data = new unsigned char[width * height * 4];
|
||||
unsigned char *ptr = img_data;
|
||||
int pixel;
|
||||
|
||||
for(int i = 2; i < len; i++) {
|
||||
pixel = data[i];
|
||||
|
||||
*ptr++ = pixel >> 16 & 0xff;
|
||||
*ptr++ = pixel >> 8 & 0xff;
|
||||
*ptr++ = pixel & 0xff;
|
||||
*ptr++ = pixel >> 24 & 0xff;
|
||||
}
|
||||
|
||||
XFree(prop);
|
||||
|
||||
Fl_RGB_Image *img = new Fl_RGB_Image(img_data, width, height, 4);
|
||||
img->alloc_array = 1;
|
||||
Fl_RGB_Image *img = netwm_window_get_icon(xid, TASKBUTTON_ICON_W);
|
||||
if(!img) return;
|
||||
|
||||
int width = img->w(), height = img->h();
|
||||
|
||||
/* some safety, scale it if needed */
|
||||
if((width > TASKBUTTON_ICON_W) || (height > TASKBUTTON_ICON_H)) {
|
||||
|
@ -256,3 +227,30 @@ void TaskButton::update_image_from_xid(void) {
|
|||
image(img);
|
||||
image_alloc = true;
|
||||
}
|
||||
|
||||
int TaskButton::handle(int e) {
|
||||
switch(e) {
|
||||
case FL_PUSH:
|
||||
/*
|
||||
* Remember old value, as value() result affect will box be drawn as FL_UP_BOX or FL_DOWN_BOX.
|
||||
* This trick should return box to the old state in case of dragging.
|
||||
*/
|
||||
old_value = value();
|
||||
return Fl_Button::handle(e);
|
||||
case FL_DRAG:
|
||||
dragged = true;
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if(dragged) {
|
||||
Taskbar *taskbar = (Taskbar*)parent();
|
||||
taskbar->try_dnd(this, Fl::event_x(), Fl::event_y());
|
||||
dragged = false;
|
||||
|
||||
value(old_value);
|
||||
return 1;
|
||||
}
|
||||
/* fallthrough */
|
||||
}
|
||||
|
||||
return Fl_Button::handle(e);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __TASKBUTTON_H__
|
||||
#define __TASKBUTTON_H__
|
||||
|
||||
|
@ -8,11 +28,13 @@ class TaskButton : public Fl_Button {
|
|||
private:
|
||||
/* window ID this button handles */
|
||||
Window xid;
|
||||
int wspace;
|
||||
char old_value; /* for storing value() as it affects boxtype */
|
||||
bool image_alloc;
|
||||
bool dragged;
|
||||
Atom net_wm_icon;
|
||||
|
||||
void clear_image(void);
|
||||
|
||||
public:
|
||||
TaskButton(int X, int Y, int W, int H, const char *l = 0);
|
||||
~TaskButton();
|
||||
|
@ -25,6 +47,11 @@ public:
|
|||
|
||||
void update_title_from_xid(void);
|
||||
void update_image_from_xid(void);
|
||||
|
||||
void set_workspace(int s) { wspace = s; }
|
||||
int get_workspace(void) { return wspace; }
|
||||
|
||||
int handle(int e);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,22 @@
|
|||
#include "Applet.h"
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012-2014 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
|
@ -7,7 +25,6 @@
|
|||
|
||||
#include "TaskButton.h"
|
||||
#include "Taskbar.h"
|
||||
#include "Panel.h"
|
||||
|
||||
#define DEFAULT_CHILD_W 175
|
||||
#define DEFAULT_SPACING 5
|
||||
|
@ -19,6 +36,7 @@ EDELIB_NS_USING(netwm_window_is_manageable)
|
|||
EDELIB_NS_USING(netwm_window_get_workspace)
|
||||
EDELIB_NS_USING(netwm_window_get_active)
|
||||
EDELIB_NS_USING(netwm_window_set_active)
|
||||
EDELIB_NS_USING(netwm_window_set_state)
|
||||
EDELIB_NS_USING(netwm_workspace_get_current)
|
||||
EDELIB_NS_USING(wm_window_set_state)
|
||||
EDELIB_NS_USING(wm_window_get_state)
|
||||
|
@ -27,7 +45,10 @@ EDELIB_NS_USING(NETWM_CHANGED_CURRENT_WORKSPACE)
|
|||
EDELIB_NS_USING(NETWM_CHANGED_WINDOW_LIST)
|
||||
EDELIB_NS_USING(NETWM_CHANGED_WINDOW_NAME)
|
||||
EDELIB_NS_USING(NETWM_CHANGED_WINDOW_ICON)
|
||||
EDELIB_NS_USING(NETWM_CHANGED_WINDOW_DESKTOP)
|
||||
EDELIB_NS_USING(WM_WINDOW_STATE_ICONIC)
|
||||
EDELIB_NS_USING(NETWM_STATE_ACTION_TOGGLE)
|
||||
EDELIB_NS_USING(NETWM_STATE_HIDDEN)
|
||||
|
||||
static void button_cb(TaskButton *b, void *t) {
|
||||
Taskbar *tt = (Taskbar*)t;
|
||||
|
@ -40,10 +61,23 @@ static void button_cb(TaskButton *b, void *t) {
|
|||
|
||||
static void net_event_cb(int action, Window xid, void *data) {
|
||||
E_RETURN_IF_FAIL(data != NULL);
|
||||
|
||||
if(action == NETWM_CHANGED_CURRENT_WORKSPACE || action == NETWM_CHANGED_WINDOW_LIST) {
|
||||
|
||||
/* this is a message, so property is not changed and netwm_window_get_active() must be called */
|
||||
if(action == NETWM_CHANGED_ACTIVE_WINDOW) {
|
||||
Taskbar *tt = (Taskbar*)data;
|
||||
tt->create_task_buttons();
|
||||
tt->update_active_button();
|
||||
return;
|
||||
}
|
||||
|
||||
if(action == NETWM_CHANGED_CURRENT_WORKSPACE) {
|
||||
Taskbar *tt = (Taskbar*)data;
|
||||
tt->update_workspace_change();
|
||||
return;
|
||||
}
|
||||
|
||||
if(action == NETWM_CHANGED_WINDOW_LIST) {
|
||||
Taskbar *tt = (Taskbar*)data;
|
||||
tt->update_task_buttons();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -53,25 +87,27 @@ static void net_event_cb(int action, Window xid, void *data) {
|
|||
return;
|
||||
}
|
||||
|
||||
/* this is a message, so property is not changed and netwm_window_get_active() must be called */
|
||||
if(action == NETWM_CHANGED_ACTIVE_WINDOW) {
|
||||
Taskbar *tt = (Taskbar*)data;
|
||||
tt->update_active_button();
|
||||
return;
|
||||
}
|
||||
|
||||
if(action == NETWM_CHANGED_WINDOW_ICON) {
|
||||
Taskbar *tt = (Taskbar*)data;
|
||||
tt->update_child_icon(xid);
|
||||
return;
|
||||
}
|
||||
|
||||
if(action == NETWM_CHANGED_WINDOW_DESKTOP) {
|
||||
Taskbar *tt = (Taskbar*)data;
|
||||
tt->update_child_workspace(xid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Taskbar::Taskbar() : Fl_Group(0, 0, 40, 25), curr_active(NULL), prev_active(NULL), panel(NULL) {
|
||||
Taskbar::Taskbar() : WidgetGroup(0, 0, 40, 25), curr_active(NULL), prev_active(NULL) {
|
||||
end();
|
||||
fixed_layout = false;
|
||||
ignore_workspace_value = false;
|
||||
|
||||
panel = EDE_PANEL_GET_PANEL_OBJECT(this);
|
||||
create_task_buttons();
|
||||
current_workspace = netwm_workspace_get_current();
|
||||
|
||||
update_task_buttons();
|
||||
netwm_callback_add(net_event_cb, this);
|
||||
}
|
||||
|
||||
|
@ -79,64 +115,124 @@ Taskbar::~Taskbar() {
|
|||
netwm_callback_remove(net_event_cb);
|
||||
}
|
||||
|
||||
void Taskbar::create_task_buttons(void) {
|
||||
/* erase all current elements */
|
||||
if(children())
|
||||
clear();
|
||||
void Taskbar::configure(Resource *res) {
|
||||
E_RETURN_IF_FAIL(res != NULL);
|
||||
|
||||
res->get("Taskbar", "fixed_layout", fixed_layout, false);
|
||||
res->get("Taskbar", "all_desktops", ignore_workspace_value, false);
|
||||
|
||||
/* also current/prev storage */
|
||||
curr_active = prev_active = NULL;
|
||||
if(visible()) update_task_buttons();
|
||||
}
|
||||
|
||||
/* redraw it, in case no windows exists in this workspace */
|
||||
panel_redraw();
|
||||
void Taskbar::update_task_buttons(void) {
|
||||
Window *wins;
|
||||
int ws, nwins = netwm_window_get_all_mapped(&wins);
|
||||
|
||||
Window *wins, transient_prop_win;
|
||||
int nwins = netwm_window_get_all_mapped(&wins);
|
||||
if(nwins < 1) {
|
||||
if(children() > 0) clear();
|
||||
return;
|
||||
}
|
||||
|
||||
TaskButton *b;
|
||||
bool need_full_redraw = false;
|
||||
|
||||
for(int i = 0, found; i < children(); i++) {
|
||||
found = 0;
|
||||
b = (TaskButton*)child(i);
|
||||
|
||||
if(nwins > 0) {
|
||||
TaskButton *b;
|
||||
int curr_workspace = netwm_workspace_get_current();
|
||||
for(int j = 0; j < nwins; j++) {
|
||||
if(b->get_window_xid() == wins[j]) {
|
||||
/* assure this window is on current workspace */
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < nwins; i++) {
|
||||
transient_prop_win = None;
|
||||
if(!found) {
|
||||
/* FLTK since 1.3 optimized Fl_Group::remove() */
|
||||
#if (FL_MAJOR_VERSION >= 1) && (FL_MINOR_VERSION >= 3)
|
||||
remove(i);
|
||||
#else
|
||||
remove(b);
|
||||
#endif
|
||||
/* Fl_Group does not call delete on remove() */
|
||||
delete b;
|
||||
need_full_redraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!netwm_window_is_manageable(wins[i]))
|
||||
continue;
|
||||
/* now see which one needs to be created */
|
||||
for(int i = 0, found; i < nwins; i++) {
|
||||
found = 0;
|
||||
|
||||
/*
|
||||
* see if it has WM_TRANSIENT_FOR hint set; transient_prop_win would point to parent window, but
|
||||
* parent should not be root window for this screen
|
||||
*/
|
||||
if(XGetTransientForHint(fl_display, wins[i], &transient_prop_win)
|
||||
&& (transient_prop_win != None)
|
||||
&& (transient_prop_win != RootWindow(fl_display, fl_screen)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for(int j = 0; j < children(); j++) {
|
||||
b = (TaskButton*)child(j);
|
||||
|
||||
/*
|
||||
* show window per workspace
|
||||
* TODO: allow showing all windows in each workspace
|
||||
*/
|
||||
if(curr_workspace == netwm_window_get_workspace(wins[i])) {
|
||||
b = new TaskButton(0, 0, DEFAULT_CHILD_W, 25);
|
||||
b->set_window_xid(wins[i]);
|
||||
b->update_title_from_xid();
|
||||
b->update_image_from_xid();
|
||||
|
||||
/* catch the name changes */
|
||||
XSelectInput(fl_display, wins[i], PropertyChangeMask | StructureNotifyMask);
|
||||
|
||||
b->callback((Fl_Callback*)button_cb, this);
|
||||
add(b);
|
||||
if(b->get_window_xid() == wins[i]) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
XFree(wins);
|
||||
if(found || !netwm_window_is_manageable(wins[i]))
|
||||
continue;
|
||||
|
||||
Window transient_prop_win = None;
|
||||
|
||||
/*
|
||||
* see if it has WM_TRANSIENT_FOR hint set; transient_prop_win would point to parent window, but
|
||||
* parent should not be root window for this screen
|
||||
*/
|
||||
if(XGetTransientForHint(fl_display, wins[i], &transient_prop_win)
|
||||
&& (transient_prop_win != None)
|
||||
&& (transient_prop_win != RootWindow(fl_display, fl_screen)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* create button */
|
||||
ws = netwm_window_get_workspace(wins[i]);
|
||||
|
||||
b = new TaskButton(0, 0, DEFAULT_CHILD_W, 25);
|
||||
b->set_window_xid(wins[i]);
|
||||
b->update_title_from_xid();
|
||||
b->update_image_from_xid();
|
||||
b->set_workspace(ws);
|
||||
/* mark it hidden by default */
|
||||
b->hide();
|
||||
|
||||
/* catch the name changes */
|
||||
XSelectInput(fl_display, wins[i], PropertyChangeMask | StructureNotifyMask);
|
||||
b->callback((Fl_Callback*)button_cb, this);
|
||||
|
||||
/* add it to our list */
|
||||
add(b);
|
||||
|
||||
if(visible_on_current_workspace(ws)) {
|
||||
//need_full_redraw = true;
|
||||
b->show();
|
||||
}
|
||||
}
|
||||
|
||||
XFree(wins);
|
||||
layout_children();
|
||||
update_active_button();
|
||||
update_active_button(!need_full_redraw);
|
||||
|
||||
if(need_full_redraw) panel_redraw();
|
||||
}
|
||||
|
||||
void Taskbar::update_workspace_change(void) {
|
||||
if(!children()) return;
|
||||
current_workspace = netwm_workspace_get_current();
|
||||
|
||||
TaskButton *b;
|
||||
for(int i = 0; i < children(); i++) {
|
||||
b = (TaskButton*)child(i);
|
||||
visible_on_current_workspace(b->get_workspace()) ? b->show() : b->hide();
|
||||
}
|
||||
|
||||
layout_children();
|
||||
redraw();
|
||||
}
|
||||
|
||||
void Taskbar::resize(int X, int Y, int W, int H) {
|
||||
|
@ -145,37 +241,50 @@ void Taskbar::resize(int X, int Y, int W, int H) {
|
|||
}
|
||||
|
||||
void Taskbar::layout_children(void) {
|
||||
if(!children())
|
||||
return;
|
||||
if(!children()) return;
|
||||
|
||||
Fl_Widget *o;
|
||||
int X = x() + Fl::box_dx(box());
|
||||
int Y = y() + Fl::box_dy(box());
|
||||
int W = w() - Fl::box_dw(box());
|
||||
int X, Y, W, child_h, reduce = 0, sz = 0, all_buttons_w = 0;
|
||||
|
||||
int child_w = DEFAULT_CHILD_W;
|
||||
int sz = children();
|
||||
int all_buttons_w = 0;
|
||||
X = x() + Fl::box_dx(box());
|
||||
Y = y() + Fl::box_dy(box());
|
||||
W = w() - Fl::box_dw(box());
|
||||
child_h = parent()->h() - 10; /* same sizes as in panel */
|
||||
|
||||
/* figure out the bounds */
|
||||
for(int i = 0; i < sz; i++)
|
||||
all_buttons_w += child(i)->w() + DEFAULT_SPACING;
|
||||
for(int i = 0; i < children(); i++) {
|
||||
o = child(i);
|
||||
if(!o->visible()) continue;
|
||||
|
||||
if(all_buttons_w > W) {
|
||||
int reduce = (all_buttons_w - W) / sz;
|
||||
child_w -= reduce;
|
||||
sz++;
|
||||
|
||||
/* resize every child to default size so we can calculate total length */
|
||||
o->resize(o->x(), o->y(), (fixed_layout ? DEFAULT_CHILD_W : W), child_h);
|
||||
all_buttons_w += o->w();
|
||||
|
||||
/* do not include ending spaces */
|
||||
if(i != children() - 1)
|
||||
all_buttons_w += DEFAULT_SPACING;
|
||||
}
|
||||
|
||||
/* now, position each child and resize it if needed */
|
||||
for(int i = 0; i < sz; i++) {
|
||||
o = child(i);
|
||||
/* find reduction size */
|
||||
if(all_buttons_w > W)
|
||||
reduce = (all_buttons_w - W) / sz;
|
||||
|
||||
o->resize(X, Y, child_w, o->h());
|
||||
/* now, position each child and resize it if needed */
|
||||
for(int i = 0; i < children(); i++) {
|
||||
o = child(i);
|
||||
if(!o->visible()) continue;
|
||||
|
||||
/*
|
||||
* I'm putting -1 here to leave a small space at the end of group; this will also
|
||||
* make children adaptive to not overflow group in case too many of them was created
|
||||
*/
|
||||
o->resize(X, Y, o->w() - reduce - 1, child_h);
|
||||
X += o->w() + DEFAULT_SPACING;
|
||||
}
|
||||
}
|
||||
|
||||
void Taskbar::update_active_button(int xid) {
|
||||
void Taskbar::update_active_button(bool do_redraw, int xid) {
|
||||
if(!children())
|
||||
return;
|
||||
|
||||
|
@ -187,14 +296,17 @@ void Taskbar::update_active_button(int xid) {
|
|||
TaskButton *o;
|
||||
for(int i = 0; i < children(); i++) {
|
||||
o = (TaskButton*)child(i);
|
||||
if(!o->visible()) continue;
|
||||
|
||||
if(o->get_window_xid() == (Window)xid)
|
||||
if(o->get_window_xid() == (Window)xid) {
|
||||
o->box(FL_DOWN_BOX);
|
||||
else
|
||||
curr_active = o;
|
||||
} else {
|
||||
o->box(FL_UP_BOX);
|
||||
}
|
||||
}
|
||||
|
||||
redraw();
|
||||
if(do_redraw) redraw();
|
||||
}
|
||||
|
||||
void Taskbar::activate_window(TaskButton *b) {
|
||||
|
@ -210,6 +322,7 @@ void Taskbar::activate_window(TaskButton *b) {
|
|||
|
||||
if(prev_active &&
|
||||
prev_active != b &&
|
||||
prev_active->get_workspace() == b->get_workspace() &&
|
||||
wm_window_get_state(prev_active->get_window_xid()) != WM_WINDOW_STATE_ICONIC)
|
||||
{
|
||||
xid = prev_active->get_window_xid();
|
||||
|
@ -221,10 +334,9 @@ void Taskbar::activate_window(TaskButton *b) {
|
|||
}
|
||||
|
||||
/* active or restore minimized */
|
||||
netwm_window_set_active(xid);
|
||||
update_active_button(xid);
|
||||
netwm_window_set_active(xid, 1);
|
||||
update_active_button(false, xid);
|
||||
|
||||
/* TODO: use stack for this (case when this can't handle: minimize three window, out of four on the workspace) */
|
||||
prev_active = curr_active;
|
||||
curr_active = b;
|
||||
}
|
||||
|
@ -236,7 +348,7 @@ void Taskbar::update_child_title(Window xid) {
|
|||
for(int i = 0; i < children(); i++) {
|
||||
o = (TaskButton*)child(i);
|
||||
|
||||
if(o->get_window_xid() == xid) {
|
||||
if(o->visible() && o->get_window_xid() == xid) {
|
||||
o->update_title_from_xid();
|
||||
break;
|
||||
}
|
||||
|
@ -250,7 +362,7 @@ void Taskbar::update_child_icon(Window xid) {
|
|||
for(int i = 0; i < children(); i++) {
|
||||
o = (TaskButton*)child(i);
|
||||
|
||||
if(o->get_window_xid() == xid) {
|
||||
if(o->visible() && o->get_window_xid() == xid) {
|
||||
o->update_image_from_xid();
|
||||
o->redraw();
|
||||
break;
|
||||
|
@ -258,11 +370,71 @@ void Taskbar::update_child_icon(Window xid) {
|
|||
}
|
||||
}
|
||||
|
||||
void Taskbar::panel_redraw(void) {
|
||||
E_RETURN_IF_FAIL(panel != NULL);
|
||||
panel->redraw();
|
||||
void Taskbar::update_child_workspace(Window xid) {
|
||||
if(!children()) return;
|
||||
|
||||
TaskButton *o;
|
||||
for(int i = 0; i < children(); i++) {
|
||||
o = (TaskButton*)child(i);
|
||||
|
||||
if(o->get_window_xid() == xid) {
|
||||
int ws = netwm_window_get_workspace(xid);
|
||||
o->set_workspace(ws);
|
||||
visible_on_current_workspace(ws) ? o->show() : o->hide();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
layout_children();
|
||||
redraw();
|
||||
}
|
||||
|
||||
void Taskbar::panel_redraw(void) {
|
||||
parent()->redraw();
|
||||
}
|
||||
|
||||
void Taskbar::try_dnd(TaskButton *b, int xpos, int ypos) {
|
||||
if(!children()) return;
|
||||
|
||||
/*
|
||||
* try to find position of incoming child, as the child, when is moved
|
||||
* forward, has to go on 'target_pos + 1' instead only 'target_pos'
|
||||
*/
|
||||
int child_pos = find(b);
|
||||
E_RETURN_IF_FAIL(child_pos != children());
|
||||
|
||||
TaskButton *o;
|
||||
for(int i = 0; i < children(); i++) {
|
||||
o = (TaskButton*)child(i);
|
||||
if(o == b) continue;
|
||||
|
||||
if((xpos > b->x() && xpos < b->x() + b->w()) &&
|
||||
(ypos > b->y() && ypos < b->y() + b->h()))
|
||||
{
|
||||
/* not moved outside child range */
|
||||
return;
|
||||
}
|
||||
|
||||
if((xpos > o->x() && xpos < o->x() + o->w()) &&
|
||||
(ypos > o->y() && ypos < o->y() + o->h()))
|
||||
{
|
||||
/* Try to find widget position in array. Widgets in array are not sorted in any order. */
|
||||
int pos = find(o);
|
||||
if(pos == children()) {
|
||||
/* not found, proceed with the search */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* increase just in case target position is in front */
|
||||
pos += (pos > child_pos) ? 1 : 0;
|
||||
insert(*b, pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
layout_children();
|
||||
redraw();
|
||||
}
|
||||
|
||||
EDE_PANEL_APPLET_EXPORT (
|
||||
Taskbar,
|
||||
|
|
|
@ -1,31 +1,71 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __TASKBAR_H__
|
||||
#define __TASKBAR_H__
|
||||
|
||||
#include <FL/Fl_Group.H>
|
||||
#include <edelib/Resource.h>
|
||||
#include "Applet.h"
|
||||
|
||||
EDELIB_NS_USING(Resource)
|
||||
|
||||
/* if button should be on visible on all workspaces */
|
||||
#define ALL_WORKSPACES -1
|
||||
|
||||
class TaskButton;
|
||||
class Panel;
|
||||
typedef AppletWidget<Fl_Group> WidgetGroup;
|
||||
|
||||
class Taskbar : public Fl_Group {
|
||||
class Taskbar : public WidgetGroup {
|
||||
public:
|
||||
TaskButton *curr_active, *prev_active;
|
||||
Panel *panel;
|
||||
bool fixed_layout; /* fixed or streched layout of buttons */
|
||||
bool ignore_workspace_value; /* should all windows be shown ignoring workspace value */
|
||||
int current_workspace;
|
||||
|
||||
bool visible_on_current_workspace(int ws) {
|
||||
return (ignore_workspace_value == true) || (ws == ALL_WORKSPACES) || (ws == current_workspace);
|
||||
}
|
||||
|
||||
public:
|
||||
Taskbar();
|
||||
~Taskbar();
|
||||
|
||||
void configure(Resource *res);
|
||||
|
||||
void create_task_buttons(void);
|
||||
void update_task_buttons(void);
|
||||
void update_workspace_change(void);
|
||||
|
||||
void resize(int X, int Y, int W, int H);
|
||||
void layout_children(void);
|
||||
|
||||
void update_active_button(int xid = -1);
|
||||
void update_active_button(bool do_redraw = true, int xid = -1);
|
||||
void activate_window(TaskButton *b);
|
||||
void update_child_title(Window xid);
|
||||
void update_child_icon(Window xid);
|
||||
void update_child_workspace(Window xid);
|
||||
|
||||
void panel_redraw(void);
|
||||
|
||||
/* try to move child on place of other child, but only if it falls within x,y range */
|
||||
void try_dnd(TaskButton *b, int x, int y);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,38 +1,48 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012 Sanel Zukan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <edelib/Ede.h>
|
||||
|
||||
#include "Panel.h"
|
||||
#include "AppletManager.h"
|
||||
|
||||
static bool running;
|
||||
static Panel *panel;
|
||||
|
||||
static void exit_signal(int signum) {
|
||||
running = false;
|
||||
if(panel) panel->hide();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
EDE_APPLICATION("ede-panel");
|
||||
panel = NULL;
|
||||
|
||||
signal(SIGTERM, exit_signal);
|
||||
signal(SIGKILL, exit_signal);
|
||||
signal(SIGINT, exit_signal);
|
||||
|
||||
Panel *panel = new Panel();
|
||||
panel->load_applets();
|
||||
panel = new Panel();
|
||||
panel->show();
|
||||
running = true;
|
||||
|
||||
while(running)
|
||||
Fl::wait();
|
||||
|
||||
/* so Panel::hide() can be called */
|
||||
panel->hide();
|
||||
return 0;
|
||||
return Fl::run();
|
||||
}
|
||||
|
|
|
@ -40,7 +40,9 @@ static KnownApp app_filemanagers[] = {
|
|||
static KnownApp app_terminals[] = {
|
||||
{"X11 terminal", "xterm"},
|
||||
{"Rxvt", "rxvt"},
|
||||
{"Rxvt Unicode", "urxvt"},
|
||||
{"Mrxvt", "mrxvt"},
|
||||
{"Small Terminal", "st"},
|
||||
{"Xfce Terminal", "xfterm4"},
|
||||
{"GNOME Terminal", "gnome-terminal"},
|
||||
KNOWN_APP_END
|
||||
|
|
|
@ -43,6 +43,10 @@ static Fl_Spinner* timeout_val;
|
|||
static Fl_Double_Window* main_win;
|
||||
static Fl_Double_Window* preview_win;
|
||||
|
||||
static bool hacks_sorter(SaverHack* const& a, SaverHack* const& b) {
|
||||
return a->name < b->name;
|
||||
}
|
||||
|
||||
static void dpms_enable_cb(Fl_Widget* w, void* s) {
|
||||
Fl_Check_Button* o = (Fl_Check_Button*)w;
|
||||
SaverPrefs* sp = (SaverPrefs*)s;
|
||||
|
@ -170,6 +174,7 @@ int main(int argc, char **argv) {
|
|||
if(sp->curr_hack >= sp->hacks.size())
|
||||
sp->curr_hack = 0;
|
||||
|
||||
sp->hacks.sort(hacks_sorter);
|
||||
HackListIter it = sp->hacks.begin(), it_end = sp->hacks.end();
|
||||
for(int i = 1; it != it_end; ++it, i++) {
|
||||
saver_list->add((*it)->name.c_str(), 0, 0);
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -215,12 +215,11 @@ int main(int argc, char **argv) {
|
|||
Fl_Button* close_button = new Fl_Button(435, 224, 90, 25, _("&Close"));
|
||||
close_button->callback(close_cb);
|
||||
|
||||
// check_button somehow steal focus
|
||||
close_button->take_focus();
|
||||
|
||||
win->end();
|
||||
window_center_on_screen(win);
|
||||
win->show(argc, argv);
|
||||
// check_button somehow steal focus
|
||||
close_button->take_focus();
|
||||
|
||||
Fl::run();
|
||||
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
#
|
||||
# $Id$
|
||||
#
|
||||
# Part of Equinox Desktop Environment (EDE).
|
||||
# Copyright (c) 2008 EDE Authors.
|
||||
#
|
||||
# This program is licensed under the terms of the
|
||||
# GNU General Public License version 2 or later.
|
||||
# See COPYING for the details.
|
||||
|
||||
SubDir TOP emountd ;
|
||||
|
||||
SOURCE = emountd.cpp ;
|
||||
|
||||
ObjectC++Flags $(SOURCE) : -Wno-long-long
|
||||
# libhal have a bug that fails on C++ with '-pedantic' flag
|
||||
[ RemoveFlag -pedantic : $(GLOBALFLAGS) ]
|
||||
$(EDELIBINCLUDE)
|
||||
$(HALINCLUDE) ;
|
||||
|
||||
Main emountd : $(SOURCE) ;
|
||||
LinkAgainst emountd : $(EDELIBLIB) $(HALLIB) $(STDLIB) $(LIBM) ;
|
||||
InstallEdeProgram emountd ;
|
||||
EdeManual emountd.txt ;
|
|
@ -1,469 +0,0 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* emountd, mount/unmount notifier
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2008 Sanel Zukan <karijes@equinox-project.org>
|
||||
*
|
||||
* This program is licensed under the terms of the
|
||||
* GNU General Public License version 2 or later.
|
||||
* See COPYING for the details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A bunch of this code is inspired from Thunar (http://thunar.xfce.org)
|
||||
* since HAL documentation pretty sucks.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_HAL
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <libhal-storage.h>
|
||||
#include <edelib/List.h>
|
||||
#include <edelib/Missing.h>
|
||||
|
||||
/* HAL can return NULL as error message if not checked */
|
||||
#define CHECK_STR(s) ((s != NULL) ? s : "<unknown>")
|
||||
|
||||
#define EMOUNTD_INTERFACE "org.equinoxproject.Emountd"
|
||||
#define EMOUNTD_OBJECT_PATH "/org/equinoxproject/Emountd"
|
||||
|
||||
#define EDE_SHUTDOWN_INTERFACE "org.equinoxproject.Shutdown"
|
||||
#define EDE_SHUTDOWN_MEMBER "Shutdown"
|
||||
|
||||
struct DeviceInfo {
|
||||
unsigned int udi_hash;
|
||||
const char* label;
|
||||
const char* mount_point;
|
||||
const char* device_file;
|
||||
|
||||
LibHalDriveType drive_type;
|
||||
LibHalVolumeDiscType cdrom_type; /* Valid only if drive_type == LIBHAL_DRIVE_TYPE_CDROM */
|
||||
|
||||
int read_only;
|
||||
};
|
||||
|
||||
/* audio CD are special */
|
||||
struct DeviceAudioInfo {
|
||||
unsigned int udi_hash;
|
||||
const char* label;
|
||||
const char* device_file;
|
||||
};
|
||||
|
||||
typedef edelib::list<unsigned int> UIntList;
|
||||
typedef edelib::list<unsigned int>::iterator UIntListIter;
|
||||
|
||||
static int quit_signaled = 0;
|
||||
static DBusConnection* bus_connection = NULL;
|
||||
static UIntList known_audio_udis;
|
||||
|
||||
void quit_signal(int sig) {
|
||||
quit_signaled = 1;
|
||||
}
|
||||
|
||||
/* A hash function from Dr.Dobbs Journal. */
|
||||
unsigned int do_hash(const char* key, int keylen) {
|
||||
unsigned hash ;
|
||||
int i;
|
||||
|
||||
for (i = 0, hash = 0; i < keylen ;i++) {
|
||||
hash += (long)key[i] ;
|
||||
hash += (hash<<10);
|
||||
hash ^= (hash>>6) ;
|
||||
}
|
||||
|
||||
hash += (hash <<3);
|
||||
hash ^= (hash >>11);
|
||||
hash += (hash <<15);
|
||||
|
||||
return hash ;
|
||||
}
|
||||
|
||||
void send_dbus_signal_mounted(DeviceInfo* info) {
|
||||
int vi;
|
||||
dbus_bool_t vb;
|
||||
const char* vs;
|
||||
|
||||
DBusMessage* msg = dbus_message_new_signal(EMOUNTD_OBJECT_PATH, EMOUNTD_INTERFACE, "Mounted");
|
||||
|
||||
DBusMessageIter it;
|
||||
dbus_message_iter_init_append(msg, &it);
|
||||
|
||||
/* open sub-iterator */
|
||||
DBusMessageIter sub;
|
||||
dbus_message_iter_open_container(&it, DBUS_TYPE_STRUCT, NULL, &sub);
|
||||
|
||||
/* hash UDI is first member*/
|
||||
dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &info->udi_hash);
|
||||
|
||||
vs = info->label;
|
||||
dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &vs);
|
||||
vs = info->mount_point;
|
||||
dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &vs);
|
||||
vs = info->device_file;
|
||||
dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &vs);
|
||||
|
||||
vb = (dbus_bool_t)info->read_only;
|
||||
dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &vb);
|
||||
|
||||
vi = (int)info->drive_type;
|
||||
dbus_message_iter_append_basic(&sub, DBUS_TYPE_INT32, &vi);
|
||||
|
||||
vi = (int)info->cdrom_type;
|
||||
dbus_message_iter_append_basic(&sub, DBUS_TYPE_INT32, &vi);
|
||||
|
||||
/* close sub-iterator */
|
||||
dbus_message_iter_close_container(&it, &sub);
|
||||
|
||||
dbus_uint32_t serial;
|
||||
if(!dbus_connection_send(bus_connection, msg, &serial))
|
||||
printf("Failed to send message (%i)\n", serial);
|
||||
|
||||
dbus_connection_flush(bus_connection);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
void send_dbus_signal_audio_cd_added(DeviceAudioInfo* info) {
|
||||
const char* vs;
|
||||
DBusMessage* msg = dbus_message_new_signal(EMOUNTD_OBJECT_PATH, EMOUNTD_INTERFACE, "AudioCDAdded");
|
||||
|
||||
DBusMessageIter it;
|
||||
dbus_message_iter_init_append(msg, &it);
|
||||
|
||||
/* open sub-iterator */
|
||||
DBusMessageIter sub;
|
||||
dbus_message_iter_open_container(&it, DBUS_TYPE_STRUCT, NULL, &sub);
|
||||
|
||||
/* hash UDI is first member*/
|
||||
dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &info->udi_hash);
|
||||
|
||||
vs = info->label;
|
||||
dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &vs);
|
||||
vs = info->device_file;
|
||||
dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &vs);
|
||||
|
||||
/* close sub-iterator */
|
||||
dbus_message_iter_close_container(&it, &sub);
|
||||
|
||||
dbus_uint32_t serial;
|
||||
if(!dbus_connection_send(bus_connection, msg, &serial))
|
||||
printf("Failed to send message (%i)\n", serial);
|
||||
|
||||
dbus_connection_flush(bus_connection);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
void send_dbus_signal_removed(unsigned int udi_hash, int is_audio) {
|
||||
const char* sig;
|
||||
if(is_audio)
|
||||
sig = "AudioCDRemoved";
|
||||
else
|
||||
sig = "Unmounted";
|
||||
|
||||
DBusMessage* msg = dbus_message_new_signal(EMOUNTD_OBJECT_PATH, EMOUNTD_INTERFACE, sig);
|
||||
DBusMessageIter it;
|
||||
|
||||
dbus_message_iter_init_append(msg, &it);
|
||||
dbus_message_iter_append_basic(&it, DBUS_TYPE_UINT32, &udi_hash);
|
||||
|
||||
dbus_uint32_t serial;
|
||||
if(!dbus_connection_send(bus_connection, msg, &serial))
|
||||
printf("Failed to send message (%i)\n", serial);
|
||||
|
||||
dbus_connection_flush(bus_connection);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
void device_info_init(DeviceInfo* i) {
|
||||
i->udi_hash = 0;
|
||||
i->label = 0;
|
||||
i->mount_point = 0;
|
||||
i->device_file = 0;
|
||||
|
||||
i->drive_type = (LibHalDriveType)-1; /* 0 is LIBHAL_DRIVE_TYPE_REMOVABLE_DISK */
|
||||
i->cdrom_type = (LibHalVolumeDiscType)-1;
|
||||
i->read_only = 0;
|
||||
}
|
||||
|
||||
void device_audio_info_init(DeviceAudioInfo* i) {
|
||||
i->udi_hash = 0;
|
||||
i->label = 0;
|
||||
i->device_file = 0;
|
||||
}
|
||||
|
||||
void device_info_send(LibHalContext* ctx, const char* udi) {
|
||||
/* spec said devices with this property should be ignored */
|
||||
if(libhal_device_get_property_bool(ctx, udi, "volume.ignore", 0))
|
||||
return;
|
||||
|
||||
/* check volume */
|
||||
LibHalVolume* vol = libhal_volume_from_udi(ctx, udi);
|
||||
if(!vol)
|
||||
return;
|
||||
|
||||
/* determine udi of the drive this volume belongs to */
|
||||
const char* drive_udi = libhal_volume_get_storage_device_udi(vol);
|
||||
if(drive_udi) {
|
||||
/* determine the drive for the volume */
|
||||
LibHalDrive* drive = libhal_drive_from_udi(ctx, drive_udi);
|
||||
if(drive) {
|
||||
const char* label = libhal_device_get_property_string(ctx, udi, "volume.label", 0);
|
||||
const char* dev = libhal_drive_get_device_file(drive);
|
||||
unsigned int udi_hash = do_hash(udi, strlen(udi));
|
||||
|
||||
/* for audio CD's we send special signals */
|
||||
if(libhal_volume_disc_has_audio(vol) && !libhal_volume_disc_has_data(vol)) {
|
||||
DeviceAudioInfo d;
|
||||
device_audio_info_init(&d);
|
||||
|
||||
d.udi_hash = udi_hash;
|
||||
d.label = label;
|
||||
d.device_file = dev;
|
||||
|
||||
/*
|
||||
* register hash so when Audio CD is ejected (device_removed() will be called)
|
||||
* we knows should we send AudioCDRemoved signal
|
||||
*/
|
||||
known_audio_udis.push_back(udi_hash);
|
||||
|
||||
/* send signal about Audio CD */
|
||||
send_dbus_signal_audio_cd_added(&d);
|
||||
} else {
|
||||
/*
|
||||
* Check if volume is mounted, since device_info_send() is called at emountd startup
|
||||
* and collects known volumes. Also, this function is called from device_property_modified()
|
||||
* and that will be when device mounts/unmounts. In either case, we send unmount signal
|
||||
*/
|
||||
if(!libhal_device_get_property_bool(ctx, udi, "volume.is_mounted", 0)) {
|
||||
send_dbus_signal_removed(udi_hash, 0); /* TODO: or to send drive_udi? */
|
||||
} else {
|
||||
DeviceInfo d;
|
||||
device_info_init(&d);
|
||||
|
||||
d.udi_hash = udi_hash;
|
||||
d.label = label;
|
||||
d.device_file = dev;
|
||||
d.mount_point = libhal_device_get_property_string(ctx, udi, "volume.mount_point", 0);
|
||||
d.read_only = (int)libhal_device_get_property_bool(ctx, udi, "volume.is_mounted_read_only", 0);
|
||||
d.drive_type = libhal_drive_get_type(drive);
|
||||
|
||||
/* determine CD type if we got it */
|
||||
if(d.drive_type == LIBHAL_DRIVE_TYPE_CDROM)
|
||||
d.cdrom_type = libhal_volume_get_disc_type(vol);
|
||||
|
||||
/* send signal about mounted device*/
|
||||
send_dbus_signal_mounted(&d);
|
||||
|
||||
libhal_free_string((char*)d.mount_point);
|
||||
}
|
||||
}
|
||||
|
||||
libhal_free_string((char*)label);
|
||||
libhal_drive_free(drive);
|
||||
}
|
||||
}
|
||||
|
||||
libhal_volume_free(vol);
|
||||
}
|
||||
|
||||
void device_added(LibHalContext* ctx, const char* udi) {
|
||||
/* only used for Audio CD's */
|
||||
device_info_send(ctx, udi);
|
||||
}
|
||||
|
||||
void device_removed(LibHalContext* ctx, const char* udi) {
|
||||
unsigned int udi_hash = do_hash(udi, strlen(udi));
|
||||
|
||||
/* signal audio CD removal if udi match ours */
|
||||
UIntListIter it = known_audio_udis.begin(), it_end = known_audio_udis.end();
|
||||
for(; it != it_end; ++it) {
|
||||
if((*it) == udi_hash) {
|
||||
send_dbus_signal_removed(udi_hash, 1);
|
||||
known_audio_udis.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void device_property_modified(LibHalContext* ctx, const char* udi, const char* key, dbus_bool_t is_rem, dbus_bool_t is_added) {
|
||||
/*
|
||||
* we watch only 'volume.mount_point' property;
|
||||
* it is always set after 'volue.is_mounted' property so we can check it manualy
|
||||
*/
|
||||
if(strcmp(key, "volume.mount_point") == 0)
|
||||
device_info_send(ctx, udi);
|
||||
}
|
||||
|
||||
#endif // HAVE_HAL
|
||||
|
||||
void help(void) {
|
||||
puts("Usage: emountd [--no-daemon]");
|
||||
puts("EDE mount/unmount notify manager");
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int go_daemon = 1;
|
||||
if(argc > 1) {
|
||||
if(strcmp(argv[1], "--no-daemon") == 0)
|
||||
go_daemon = 0;
|
||||
else {
|
||||
help();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HAVE_HAL
|
||||
printf("HAL support not enabled!\n");
|
||||
printf("Make sure you have system supporting HAL and installed HAL package and libraries\n");
|
||||
printf("For more details, please visit: 'http://freedesktop.org/HAL'\n");
|
||||
return 1;
|
||||
#else
|
||||
/* run in background */
|
||||
if(go_daemon)
|
||||
edelib_daemon(0, 0);
|
||||
|
||||
DBusError err;
|
||||
DBusConnection* conn = NULL, *session_conn = NULL;
|
||||
DBusMessage* down_msg = NULL;
|
||||
|
||||
LibHalContext* ctx = NULL;
|
||||
LibHalDrive* hd;
|
||||
|
||||
char** drive_udis;
|
||||
int n_drive_udis;
|
||||
|
||||
char** udis;
|
||||
int n_udis;
|
||||
|
||||
signal(SIGINT, quit_signal);
|
||||
signal(SIGTERM, quit_signal);
|
||||
signal(SIGKILL, quit_signal);
|
||||
signal(SIGQUIT, quit_signal);
|
||||
|
||||
ctx = libhal_ctx_new();
|
||||
if(!ctx) {
|
||||
puts("Unable to get libhal context");
|
||||
goto error;
|
||||
}
|
||||
|
||||
dbus_error_init(&err);
|
||||
|
||||
/* open system bus for HAL */
|
||||
conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
|
||||
if(dbus_error_is_set(&err)) {
|
||||
printf("Unable to connect to system bus %s : %s\n", err.name, err.message);
|
||||
dbus_error_free(&err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* open session bus for EDE */
|
||||
session_conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
|
||||
if(dbus_error_is_set(&err)) {
|
||||
printf("Unable to connect to session bus %s : %s\n", err.name, err.message);
|
||||
dbus_error_free(&err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
bus_connection = session_conn;
|
||||
|
||||
/*
|
||||
* make sure we are running only one instance; this is done by requesting ownership
|
||||
* of the interface name
|
||||
*/
|
||||
if(dbus_bus_request_name(bus_connection, EMOUNTD_INTERFACE, 0, 0) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
|
||||
printf("One instance of emountd is already running! Balling out...\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* let libhal use our system bus connection */
|
||||
libhal_ctx_set_dbus_connection(ctx, conn);
|
||||
|
||||
if(!libhal_ctx_init(ctx, &err)) {
|
||||
printf("Unable to init libhal context %s : %s\n", CHECK_STR(err.name), CHECK_STR(err.message));
|
||||
printf("Does hald daemon is running?\n");
|
||||
dbus_error_free(&err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
libhal_ctx_set_device_added(ctx, device_added);
|
||||
libhal_ctx_set_device_removed(ctx, device_removed);
|
||||
libhal_ctx_set_device_property_modified(ctx, device_property_modified);
|
||||
|
||||
/* explicitly state to watch all properties or nothing will be received */
|
||||
if(!libhal_device_property_watch_all(ctx, &err)) {
|
||||
printf("Unable to watch properties %s : %s\n", CHECK_STR(err.name), CHECK_STR(err.message));
|
||||
dbus_error_free(&err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* now lookup storage devices already known by HAL */
|
||||
drive_udis = libhal_find_device_by_capability(ctx, "storage", &n_drive_udis, &err);
|
||||
if(drive_udis) {
|
||||
for(int i = 0; i < n_drive_udis; i++) {
|
||||
hd = libhal_drive_from_udi(ctx, drive_udis[i]);
|
||||
if(!hd)
|
||||
continue;
|
||||
|
||||
/* check for floppy since it does not have volumes */
|
||||
if(libhal_drive_get_type(hd) == LIBHAL_DRIVE_TYPE_FLOPPY) {
|
||||
device_info_send(ctx, drive_udis[i]);
|
||||
} else {
|
||||
/* determine all volumes for the given drive */
|
||||
udis = libhal_drive_find_all_volumes(ctx, hd, &n_udis);
|
||||
if(udis) {
|
||||
for(int j = 0; j < n_udis; j++) {
|
||||
device_info_send(ctx, udis[j]);
|
||||
/* HAL bug #5279 */
|
||||
free(udis[j]);
|
||||
}
|
||||
/* HAL bug #5279 */
|
||||
free(udis);
|
||||
}
|
||||
}
|
||||
|
||||
libhal_drive_free(hd);
|
||||
}
|
||||
|
||||
libhal_free_string_array(drive_udis);
|
||||
}
|
||||
|
||||
/* add matcher for quit dbus signal */
|
||||
dbus_bus_add_match(bus_connection, "type='signal',interface='"EDE_SHUTDOWN_INTERFACE"'", 0);
|
||||
|
||||
/*
|
||||
* Now handle both system and session bus messages: system messages
|
||||
* are to receive HAL notifications and bus messages are to dispatch them to EDE clients
|
||||
* and to receive Shutdown signal
|
||||
*/
|
||||
while(1) {
|
||||
if(quit_signaled)
|
||||
break;
|
||||
|
||||
/* fetch and dispatch system bus messages */
|
||||
dbus_connection_read_write_dispatch(conn, 10);
|
||||
|
||||
/* but only fetch session bus messages; they are processed here */
|
||||
dbus_connection_read_write(bus_connection, 10);
|
||||
|
||||
down_msg = dbus_connection_pop_message(bus_connection);
|
||||
if(down_msg && dbus_message_is_signal(down_msg, EDE_SHUTDOWN_INTERFACE, EDE_SHUTDOWN_MEMBER))
|
||||
break;
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
error:
|
||||
if(!ctx)
|
||||
libhal_ctx_free(ctx);
|
||||
|
||||
return 0;
|
||||
#endif // HAVE_HAL
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
Emountd documentation
|
||||
=====================
|
||||
|
||||
Emountd is EDE service responsible for reporting when storage
|
||||
devices get mounted or unmounted. Reporting is done via D-BUS protocol and
|
||||
interested applications should listen certain signals.
|
||||
|
||||
Specific emountd signals can be found at link:dbus-usage.html[D-BUS usage] page.
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
--no-daemon::
|
||||
Do not run in background. Emountd will by default run in background.
|
|
@ -26,8 +26,13 @@
|
|||
#include <edelib/MessageBox.h>
|
||||
#include <edelib/Nls.h>
|
||||
#include <edelib/Run.h>
|
||||
|
||||
#include <FL/Fl.H>
|
||||
|
||||
#if EDELIB_HAVE_DBUS
|
||||
#include <edelib/EdbusMessage.h>
|
||||
#include <edelib/EdbusConnection.h>
|
||||
#endif
|
||||
|
||||
#include "EvokeService.h"
|
||||
#include "Splash.h"
|
||||
|
@ -37,12 +42,6 @@
|
|||
|
||||
EDELIB_NS_USING(Config)
|
||||
EDELIB_NS_USING(Resource)
|
||||
EDELIB_NS_USING(EdbusMessage)
|
||||
EDELIB_NS_USING(EdbusConnection)
|
||||
EDELIB_NS_USING(EdbusError)
|
||||
EDELIB_NS_USING(EDBUS_SESSION)
|
||||
EDELIB_NS_USING(EDBUS_SYSTEM)
|
||||
EDELIB_NS_USING(RES_SYS_ONLY)
|
||||
EDELIB_NS_USING(file_remove)
|
||||
EDELIB_NS_USING(file_test)
|
||||
EDELIB_NS_USING(str_trim)
|
||||
|
@ -51,16 +50,23 @@ EDELIB_NS_USING(alert)
|
|||
EDELIB_NS_USING(ask)
|
||||
EDELIB_NS_USING(FILE_TEST_IS_REGULAR)
|
||||
|
||||
#ifdef USE_LOCAL_CONFIG
|
||||
# define CONFIG_GET_STRVAL(object, section, key, buff) object.get(section, key, buff, sizeof(buff))
|
||||
#else
|
||||
# define CONFIG_GET_STRVAL(object, section, key, buff) object.get(section, key, buff, sizeof(buff), RES_SYS_ONLY)
|
||||
#if EDELIB_HAVE_DBUS
|
||||
EDELIB_NS_USING(EdbusMessage)
|
||||
EDELIB_NS_USING(EdbusConnection)
|
||||
EDELIB_NS_USING(EdbusError)
|
||||
EDELIB_NS_USING(EDBUS_SESSION)
|
||||
EDELIB_NS_USING(EDBUS_SYSTEM)
|
||||
#endif
|
||||
|
||||
#define CONFIG_GET_STRVAL(object, section, key, buff) object.get(section, key, buff, sizeof(buff))
|
||||
|
||||
/* stolen from xfce's xfsm-shutdown-helper */
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
# define POWEROFF_CMD "/sbin/shutdown -p now"
|
||||
# define REBOOT_CMD "/sbin/shutdown -r now"
|
||||
#elif defined(__OpenBSD__)
|
||||
# define POWEROFF_CMD "/sbin/shutdown -hp now"
|
||||
# define REBOOT_CMD "/sbin/shutdown -r now"
|
||||
#elif defined(sun) || defined(__sun)
|
||||
# define POWEROFF_CMD "/usr/sbin/shutdown -i 5 -g 0 -y"
|
||||
# define REBOOT_CMD "/usr/sbin/shutdown -i 6 -g 0 -y"
|
||||
|
@ -90,35 +96,46 @@ static int get_int_property_value(Atom at) {
|
|||
}
|
||||
|
||||
static void send_dbus_ede_quit(void) {
|
||||
#ifdef EDELIB_HAVE_DBUS
|
||||
EdbusConnection c;
|
||||
E_RETURN_IF_FAIL(c.connect(EDBUS_SESSION));
|
||||
|
||||
EdbusMessage msg;
|
||||
msg.create_signal("/org/equinoxproject/Shutdown", "org.equinoxproject.Shutdown", "Shutdown");
|
||||
c.send(msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool do_shutdown_or_restart(bool restart) {
|
||||
#define CONSOLEKIT_SERVICE "org.freedesktop.ConsoleKit"
|
||||
#define CONSOLEKIT_PATH "/org/freedesktop/ConsoleKit/Manager"
|
||||
#define CONSOLEKIT_INTERFACE "org.freedesktop.ConsoleKit.Manager"
|
||||
|
||||
static bool do_shutdown_or_restart(bool restart, void (*x_shutdown_func)(void)) {
|
||||
const char *action;
|
||||
int r = 1;
|
||||
|
||||
#ifdef EDELIB_HAVE_DBUS
|
||||
const char *can_do_action;
|
||||
|
||||
EdbusConnection c;
|
||||
if(!c.connect(EDBUS_SYSTEM)) {
|
||||
alert(_("Unable to connect to HAL daemon. Make sure both D-BUS and HAL daemons are running"));
|
||||
alert(_("Unable to connect to DBus daemon. Make sure system DBus daemon is running and have permissions to access it"));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* determine what to check first; ConsoleKit shutdown action calls 'Stop' */
|
||||
action = restart ? "Restart" : "Stop";
|
||||
can_do_action = restart ? "CanRestart" : "CanStop";
|
||||
action = restart ? "Restart" : "Stop";
|
||||
|
||||
EdbusMessage msg, ret;
|
||||
msg.create_method_call("org.freedesktop.ConsoleKit",
|
||||
"/org/freedesktop/ConsoleKit/Manager",
|
||||
"org.freedesktop.ConsoleKit.Manager",
|
||||
action);
|
||||
msg.create_method_call(CONSOLEKIT_SERVICE,
|
||||
CONSOLEKIT_PATH,
|
||||
CONSOLEKIT_INTERFACE,
|
||||
can_do_action);
|
||||
|
||||
if(!c.send_with_reply_and_block(msg, 100, ret)) {
|
||||
EdbusError *err = c.error();
|
||||
alert(_("Unable to complete this action. Got '%s' (%s)"), err->name(), err->message());
|
||||
alert(_("Unable to communicate with DBus properly. Got '%s' (%s)"), err->name(), err->message());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -128,25 +145,36 @@ static bool do_shutdown_or_restart(bool restart) {
|
|||
}
|
||||
|
||||
EdbusMessage::iterator it = ret.begin();
|
||||
if((*it).to_bool() == true)
|
||||
return true;
|
||||
if(it->is_bool() && it->to_bool() == true) {
|
||||
/* first close all X children */
|
||||
x_shutdown_func();
|
||||
|
||||
int r = ask(_("You are not allowed to execute this command. Please consult ConsoleKit documentation on how to allow privileged actions. "
|
||||
"Would you like to try to execute system commands?"));
|
||||
/* call action */
|
||||
msg.create_method_call(CONSOLEKIT_SERVICE,
|
||||
CONSOLEKIT_PATH,
|
||||
CONSOLEKIT_INTERFACE,
|
||||
action);
|
||||
c.send(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
r = ask(_("You are not allowed to execute this command. Please consult ConsoleKit documentation on how to allow privileged actions. "
|
||||
"Would you like to try to execute system commands?"));
|
||||
#endif /* EDELIB_HAVE_DBUS */
|
||||
|
||||
/* try to do things manually */
|
||||
if(!r) return false;
|
||||
const char *cmd = _("restart");
|
||||
action = _("restart");
|
||||
|
||||
if(restart) {
|
||||
r = run_sync(REBOOT_CMD);
|
||||
} else {
|
||||
r = run_sync(POWEROFF_CMD);
|
||||
cmd = _("shutdown");
|
||||
action = _("shutdown");
|
||||
}
|
||||
|
||||
if(r) {
|
||||
alert(_("Unable to %s the computer. Probably you do not have enough permissions to do that"), cmd);
|
||||
alert(_("Unable to %s the computer. Probably you do not have enough permissions to do that"), action);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -171,12 +199,11 @@ EvokeService* EvokeService::instance(void) {
|
|||
}
|
||||
|
||||
bool EvokeService::setup_lock(const char* name) {
|
||||
if(file_test(name, FILE_TEST_IS_REGULAR))
|
||||
return false;
|
||||
E_RETURN_VAL_IF_FAIL(file_test(name, FILE_TEST_IS_REGULAR) == false, false);
|
||||
|
||||
FILE* f = fopen(name, "w");
|
||||
if(!f)
|
||||
return false;
|
||||
E_RETURN_VAL_IF_FAIL(f != NULL, false);
|
||||
|
||||
fclose(f);
|
||||
|
||||
lock_name = strdup(name);
|
||||
|
@ -184,8 +211,7 @@ bool EvokeService::setup_lock(const char* name) {
|
|||
}
|
||||
|
||||
void EvokeService::remove_lock(void) {
|
||||
if(!lock_name)
|
||||
return;
|
||||
E_RETURN_IF_FAIL(lock_name != NULL);
|
||||
|
||||
file_remove(lock_name);
|
||||
free(lock_name);
|
||||
|
@ -193,14 +219,13 @@ void EvokeService::remove_lock(void) {
|
|||
}
|
||||
|
||||
void EvokeService::clear_startup_items(void) {
|
||||
if(startup_items.empty())
|
||||
return;
|
||||
E_RETURN_IF_FAIL(startup_items.size() > 0);
|
||||
|
||||
StartupItemListIter it = startup_items.begin(), it_end = startup_items.end();
|
||||
for(; it != it_end; ++it)
|
||||
StartupItemListIter it = startup_items.begin(), ite = startup_items.end();
|
||||
while(it != ite) {
|
||||
delete *it;
|
||||
|
||||
startup_items.clear();
|
||||
it = startup_items.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void EvokeService::read_startup(void) {
|
||||
|
@ -221,40 +246,37 @@ void EvokeService::read_startup(void) {
|
|||
return;
|
||||
}
|
||||
|
||||
char tok_buff[256], buff[256];
|
||||
|
||||
char tokbuf[128], buf[128];
|
||||
/* if nothing found, exit */
|
||||
if(!CONFIG_GET_STRVAL(c, "Startup", "start_order", tok_buff))
|
||||
return;
|
||||
E_RETURN_IF_FAIL(CONFIG_GET_STRVAL(c, "Startup", "start_order", tokbuf));
|
||||
|
||||
if(CONFIG_GET_STRVAL(c, "Startup", "splash_theme", buff))
|
||||
splash_theme = buff;
|
||||
if(CONFIG_GET_STRVAL(c, "Startup", "splash_theme", buf))
|
||||
splash_theme = buf;
|
||||
|
||||
for(const char* sect = strtok(tok_buff, ","); sect; sect = strtok(NULL, ",")) {
|
||||
for(const char* sect = strtok(tokbuf, ","); sect; sect = strtok(NULL, ",")) {
|
||||
/* remove leading/ending spaces, if exists */
|
||||
str_trim(buff);
|
||||
str_trim(buf);
|
||||
|
||||
/* assure each startup item has 'exec' key */
|
||||
if(!CONFIG_GET_STRVAL(c, sect, "exec", buff)) {
|
||||
if(!CONFIG_GET_STRVAL(c, sect, "exec", buf)) {
|
||||
E_WARNING(E_STRLOC ": Startup item '%s' does not have anything to execute. Skipping...\n", sect);
|
||||
continue;
|
||||
}
|
||||
|
||||
StartupItem *s = new StartupItem;
|
||||
s->exec = buff;
|
||||
s->exec = buf;
|
||||
|
||||
if(CONFIG_GET_STRVAL(c, sect, "icon", buff))
|
||||
s->icon = buff;
|
||||
if(CONFIG_GET_STRVAL(c, sect, "description", buff))
|
||||
s->description = buff;
|
||||
if(CONFIG_GET_STRVAL(c, sect, "icon", buf))
|
||||
s->icon = buf;
|
||||
if(CONFIG_GET_STRVAL(c, sect, "description", buf))
|
||||
s->description = buf;
|
||||
|
||||
startup_items.push_back(s);
|
||||
}
|
||||
}
|
||||
|
||||
void EvokeService::run_startup(bool splash, bool dryrun) {
|
||||
if(startup_items.empty())
|
||||
return;
|
||||
E_RETURN_IF_FAIL(startup_items.size() > 0);
|
||||
|
||||
Splash s(startup_items, splash_theme, splash, dryrun);
|
||||
s.run();
|
||||
|
@ -265,7 +287,7 @@ void EvokeService::start_xsettings_manager(void) {
|
|||
xsm = new Xsm;
|
||||
|
||||
if(Xsm::manager_running(fl_display, fl_screen)) {
|
||||
int ret = edelib::ask(_("XSETTINGS manager already running on this screen. Would you like to replace it?"));
|
||||
int ret = ask(_("XSETTINGS manager already running on this screen. Would you like to replace it?"));
|
||||
if(ret < 1) {
|
||||
stop_xsettings_manager(false);
|
||||
return;
|
||||
|
@ -273,19 +295,16 @@ void EvokeService::start_xsettings_manager(void) {
|
|||
}
|
||||
|
||||
if(!xsm->init(fl_display, fl_screen)) {
|
||||
edelib::alert(_("Unable to load XSETTINGS manager properly :-("));
|
||||
alert(_("Unable to load XSETTINGS manager properly"));
|
||||
stop_xsettings_manager(false);
|
||||
}
|
||||
|
||||
E_RETURN_IF_FAIL(xsm);
|
||||
|
||||
if(xsm->load_serialized())
|
||||
xsm->notify();
|
||||
}
|
||||
|
||||
void EvokeService::stop_xsettings_manager(bool serialize) {
|
||||
if(!xsm)
|
||||
return;
|
||||
E_RETURN_IF_FAIL(xsm != NULL);
|
||||
|
||||
if(serialize)
|
||||
xsm->save_serialized();
|
||||
|
@ -310,10 +329,12 @@ int EvokeService::handle(const XEvent* xev) {
|
|||
if(xev->xproperty.atom == XA_EDE_EVOKE_SHUTDOWN_ALL) {
|
||||
int val = get_int_property_value(XA_EDE_EVOKE_SHUTDOWN_ALL);
|
||||
if(val == 1) {
|
||||
int dw = DisplayWidth(fl_display, fl_screen);
|
||||
int dh = DisplayHeight(fl_display, fl_screen);
|
||||
int dw, dh, ret;
|
||||
|
||||
int ret = logout_dialog_show(dw, dh, LOGOUT_OPT_SHUTDOWN | LOGOUT_OPT_RESTART);
|
||||
dw = DisplayWidth(fl_display, fl_screen);
|
||||
dh = DisplayHeight(fl_display, fl_screen);
|
||||
|
||||
ret = logout_dialog_show(dw, dh, LOGOUT_OPT_SHUTDOWN | LOGOUT_OPT_RESTART);
|
||||
if(ret == LOGOUT_RET_CANCEL)
|
||||
return 1;
|
||||
|
||||
|
@ -321,12 +342,10 @@ int EvokeService::handle(const XEvent* xev) {
|
|||
|
||||
switch(ret) {
|
||||
case LOGOUT_RET_RESTART:
|
||||
if(!do_shutdown_or_restart(true))
|
||||
return 1;
|
||||
if(!do_shutdown_or_restart(true, x_shutdown)) return 1;
|
||||
break;
|
||||
case LOGOUT_RET_SHUTDOWN:
|
||||
if(!do_shutdown_or_restart(false))
|
||||
return 1;
|
||||
if(!do_shutdown_or_restart(false, x_shutdown)) return 1;
|
||||
break;
|
||||
case LOGOUT_RET_LOGOUT:
|
||||
default:
|
||||
|
|
|
@ -27,7 +27,7 @@ ObjectC++Flags Splash.cpp : -DEDEWM_HAVE_NET_SPLASH ;
|
|||
ObjectC++Flags evoke.cpp : -DUSE_SIGHUP ;
|
||||
|
||||
ObjectC++Flags EvokeService.cpp : $(EDELIB_DBUS_INCLUDE) ;
|
||||
LinkAgainstAsFirst evoke : $(EDELIB_DBUS_LIB) ;
|
||||
LinkAgainstAsFirst evoke : $(EDELIB_DBUS_LIB) $(PTHREAD_LIBS) ;
|
||||
|
||||
EdeProgram evoke : $(SOURCE) ;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*/
|
||||
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Return_Button.H>
|
||||
#include <FL/Fl_Choice.H>
|
||||
#include <FL/Fl.H>
|
||||
#include <edelib/Window.h>
|
||||
|
@ -78,7 +78,7 @@ int logout_dialog_show(int screen_w, int screen_h, int opt) {
|
|||
c->value(0);
|
||||
description->label(logout_options[0].opt_long);
|
||||
|
||||
Fl_Button* ok = new Fl_Button(140, 145, 90, 25, _("&OK"));
|
||||
Fl_Return_Button* ok = new Fl_Return_Button(140, 145, 90, 25, _("&OK"));
|
||||
ok->callback(ok_cb, c);
|
||||
Fl_Button* cancel = new Fl_Button(235, 145, 90, 25, _("&Cancel"));
|
||||
cancel->callback(cancel_cb);
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
* See COPYING for details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Shared_Image.H>
|
||||
#include <edelib/Debug.h>
|
||||
|
@ -20,6 +19,7 @@
|
|||
#include <edelib/FileTest.h>
|
||||
#include <edelib/Resource.h>
|
||||
#include <edelib/Run.h>
|
||||
#include <edelib/Netwm.h>
|
||||
|
||||
#include "Splash.h"
|
||||
|
||||
|
@ -31,8 +31,10 @@ EDELIB_NS_USING(Resource)
|
|||
EDELIB_NS_USING(build_filename)
|
||||
EDELIB_NS_USING(file_test)
|
||||
EDELIB_NS_USING(run_async)
|
||||
EDELIB_NS_USING(netwm_window_set_type)
|
||||
EDELIB_NS_USING(RES_SYS_ONLY)
|
||||
EDELIB_NS_USING(FILE_TEST_IS_DIR)
|
||||
EDELIB_NS_USING(NETWM_WINDOW_TYPE_SPLASH)
|
||||
|
||||
#ifndef EDEWM_HAVE_NET_SPLASH
|
||||
static Splash* global_splash = NULL;
|
||||
|
@ -54,17 +56,10 @@ static int splash_xmessage_handler(int e) {
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* repeatedly call runner() until all clients are
|
||||
* started then hide splash window
|
||||
*/
|
||||
/* repeatedly call runner() until all clients are started then hide splash window */
|
||||
static void runner_cb(void* s) {
|
||||
Splash* sp = (Splash*)s;
|
||||
|
||||
if(sp->next_client())
|
||||
Fl::repeat_timeout(TIMEOUT_CONTINUE, runner_cb, sp);
|
||||
else
|
||||
sp->hide();
|
||||
sp->next_client() ? Fl::repeat_timeout(TIMEOUT_CONTINUE, runner_cb, sp) : sp->hide();
|
||||
}
|
||||
|
||||
Splash::Splash(StartupItemList& s, String& theme, bool show_it, bool dr) : Fl_Double_Window(480, 365) {
|
||||
|
@ -77,46 +72,35 @@ Splash::Splash(StartupItemList& s, String& theme, bool show_it, bool dr) : Fl_Do
|
|||
|
||||
box(FL_BORDER_BOX);
|
||||
}
|
||||
|
||||
|
||||
Splash::~Splash() {
|
||||
E_DEBUG(E_STRLOC ": Cleaning splash data\n");
|
||||
|
||||
/* elements of icons cleans Fl_Group */
|
||||
delete [] icons;
|
||||
Fl::remove_timeout(runner_cb);
|
||||
}
|
||||
|
||||
|
||||
/* after edewm got _NET_WM_WINDOW_TYPE_SPLASH support */
|
||||
/* for wm's with _NET_WM_WINDOW_TYPE_SPLASH support */
|
||||
#if EDEWM_HAVE_NET_SPLASH
|
||||
void Splash::show(void) {
|
||||
if(shown())
|
||||
return;
|
||||
if(shown()) return;
|
||||
|
||||
Fl_X::make_xid(this);
|
||||
/*
|
||||
* Edewm does not implement this for now. Alternative, working solution
|
||||
* is used via register_top()/unregister_top(); also looks like later
|
||||
* is working on othe wm's too.
|
||||
*/
|
||||
Atom win_type = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE", False);
|
||||
Atom win_splash = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_SPLASH", False);
|
||||
XChangeProperty(fl_display, fl_xid(this), win_type, XA_ATOM, 32, PropModeReplace,
|
||||
(unsigned char*)&win_splash, sizeof(Atom));
|
||||
netwm_window_set_type(fl_xid(this), NETWM_WINDOW_TYPE_SPLASH);
|
||||
}
|
||||
#endif
|
||||
|
||||
void Splash::run(void) {
|
||||
E_ASSERT(slist != NULL);
|
||||
|
||||
if(!show_splash) {
|
||||
if(!show_splash || (splash_theme && (strcasecmp(splash_theme->c_str(), "none") == 0))) {
|
||||
while(next_client_nosplash())
|
||||
;
|
||||
return;
|
||||
}
|
||||
|
||||
fl_register_images();
|
||||
|
||||
String path, splash_theme_path;
|
||||
|
||||
#ifdef USE_LOCAL_CONFIG
|
||||
|
@ -128,12 +112,12 @@ void Splash::run(void) {
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
splash_theme_path += E_DIR_SEPARATOR;
|
||||
splash_theme_path += *splash_theme;
|
||||
|
||||
if(!file_test(splash_theme_path.c_str(), FILE_TEST_IS_DIR)) {
|
||||
E_WARNING(E_STRLOC ": Unable to locate '%s' in '%s' theme directory\n",
|
||||
splash_theme->c_str(), splash_theme_path.c_str());
|
||||
E_WARNING(E_STRLOC ": Unable to locate '%s' in '%s' theme directory\n", splash_theme->c_str(), splash_theme_path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -155,10 +139,7 @@ void Splash::run(void) {
|
|||
bimg->image(splash_img);
|
||||
}
|
||||
|
||||
/*
|
||||
* place message box at the bottom with
|
||||
* nice offset (10 px) from window borders
|
||||
*/
|
||||
/* place message box at the bottom with nice offset (10 px) from window borders */
|
||||
msgbox = new Fl_Box(10, h() - 25 - 10, w() - 20, 25);
|
||||
|
||||
/*
|
||||
|
@ -218,21 +199,18 @@ void Splash::run(void) {
|
|||
|
||||
clear_border();
|
||||
|
||||
/*
|
||||
* If set_override() is used, message boxes will be
|
||||
* popped behind splash. Using it or not ???
|
||||
*/
|
||||
/* If set_override() is used, message boxes will be popped behind splash. Using it or not ??? */
|
||||
set_override();
|
||||
|
||||
// make sure window is centered
|
||||
/* make sure window is centered */
|
||||
int sw = DisplayWidth(fl_display, fl_screen);
|
||||
int sh = DisplayHeight(fl_display, fl_screen);
|
||||
position(sw/2 - w()/2, sh/2 - h()/2);
|
||||
position(sw / 2 - w() / 2, sh / 2 - h() / 2);
|
||||
|
||||
show();
|
||||
Fl::add_timeout(TIMEOUT_START, runner_cb, this);
|
||||
|
||||
// to keep splash at the top
|
||||
/* to keep splash at the top */
|
||||
#ifndef EDEWM_HAVE_NET_SPLASH
|
||||
global_splash = this;
|
||||
XSelectInput(fl_display, RootWindow(fl_display, fl_screen), SubstructureNotifyMask);
|
||||
|
@ -249,8 +227,7 @@ void Splash::run(void) {
|
|||
|
||||
/* called when splash option is on */
|
||||
bool Splash::next_client(void) {
|
||||
if(slist->empty())
|
||||
return false;
|
||||
E_RETURN_VAL_IF_FAIL(slist->size() > 0, false);
|
||||
|
||||
if(counter == 0)
|
||||
slist_it = slist->begin();
|
||||
|
@ -260,11 +237,11 @@ bool Splash::next_client(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
E_ASSERT(counter < slist->size() && "Internal error; 'counter' out of bounds");
|
||||
|
||||
const char* msg = (*slist_it)->description.c_str();
|
||||
const char* cmd = (*slist_it)->exec.c_str();
|
||||
const char *msg, *cmd;
|
||||
msg = (*slist_it)->description.c_str();
|
||||
cmd = (*slist_it)->exec.c_str();
|
||||
|
||||
icons[counter]->show();
|
||||
msgbox->label(msg);
|
||||
|
@ -281,8 +258,7 @@ bool Splash::next_client(void) {
|
|||
|
||||
/* called when splash option is off */
|
||||
bool Splash::next_client_nosplash(void) {
|
||||
if(slist->empty())
|
||||
return false;
|
||||
E_RETURN_VAL_IF_FAIL(slist->size() > 0, false);
|
||||
|
||||
if(counter == 0)
|
||||
slist_it = slist->begin();
|
||||
|
@ -297,7 +273,7 @@ bool Splash::next_client_nosplash(void) {
|
|||
const char* msg = (*slist_it)->description.c_str();
|
||||
const char* cmd = (*slist_it)->exec.c_str();
|
||||
|
||||
printf("%s\n", msg);
|
||||
E_DEBUG(E_STRLOC ": Starting '%s'...\n", msg);
|
||||
|
||||
/* run command */
|
||||
if(!dryrun)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user