Merging new panel in the trunk.

This commit is contained in:
Sanel Zukan 2009-10-03 07:33:08 +00:00
parent 0b3662910f
commit 1f96f833d9
146 changed files with 7482 additions and 0 deletions

63
ede-panel/Applet.h Normal file
View File

@ -0,0 +1,63 @@
#ifndef __APPLET_H__
#define __APPLET_H__
#define EDE_PANEL_APPLET_INTERFACE_VERSION 0x01
class Fl_Widget;
enum {
EDE_PANEL_APPLET_OPTION_RESIZABLE_H = (1 << 1),
EDE_PANEL_APPLET_OPTION_RESIZABLE_V = (1 << 2),
EDE_PANEL_APPLET_OPTION_ALIGN_LEFT = (1 << 3),
EDE_PANEL_APPLET_OPTION_ALIGN_RIGHT = (1 << 4)
};
struct AppletInfo {
const char *name;
const char *klass_name;
const char *version;
const char *icon;
const char *author;
unsigned long options;
};
typedef Fl_Widget* (*applet_create_t)(void);
typedef void (*applet_destroy_t)(Fl_Widget *);
typedef AppletInfo* (*applet_get_info_t)(void);
typedef void (*applet_destroy_info_t)(AppletInfo *a);
typedef float (*applet_version_t)(void);
/* the main macro each applet library must implement */
#define EDE_PANEL_APPLET_EXPORT(klass, aoptions, aname, aversion, aicon, aauthor) \
extern "C" Fl_Widget *ede_panel_applet_create(void) { \
return new klass; \
} \
\
extern "C" void ede_panel_applet_destroy(Fl_Widget *w) { \
klass *k = (klass*)w; \
delete k; \
} \
\
extern "C" AppletInfo *ede_panel_applet_get_info(void) { \
AppletInfo *a = new AppletInfo; \
a->name = aname; \
a->klass_name = #klass; \
a->version = aversion; \
a->icon = aicon; \
a->author = aauthor; \
a->options = aoptions; \
return a; \
} \
\
extern "C" void ede_panel_applet_destroy_info(AppletInfo *a) { \
delete a; \
} \
\
extern "C" int ede_panel_applet_get_iface_version(void) { \
return EDE_PANEL_APPLET_INTERFACE_VERSION; \
}
#endif

160
ede-panel/AppletManager.cpp Normal file
View File

@ -0,0 +1,160 @@
#include <dlfcn.h>
#include <string.h>
#include <edelib/Debug.h>
#include "AppletManager.h"
#include "Panel.h"
EDELIB_NS_USING(String)
EDELIB_NS_USING(list)
struct AppletData {
void *dl;
Fl_Widget *awidget; /* widget from the applet */
AppletInfo *ainfo; /* applet informations */
applet_create_t create_func;
applet_destroy_t destroy_func;
applet_destroy_info_t destroy_info_func;
};
static void clear_applet(AppletData *a) {
E_RETURN_IF_FAIL(a != NULL);
/* clear applet information first */
if(a->ainfo) {
E_DEBUG(E_STRLOC ": Cleaning class %s\n", a->ainfo->klass_name);
(a->destroy_info_func)(a->ainfo);
}
/* clear applet specific suff */
(a->destroy_func)(a->awidget);
dlclose(a->dl);
delete a;
}
AppletManager::~AppletManager() {
clear();
}
bool AppletManager::load(const char *path) {
dlerror();
const char *dl_err = NULL;
void *a = dlopen(path, RTLD_LAZY);
if(!a) {
dl_err = dlerror();
E_WARNING(E_STRLOC ": Unable to load '%s' : '%s'\n", path, dl_err);
return false;
}
/* first check if we have valid plugin by requesting version function */
void *av = (applet_version_t*)dlsym(a, "ede_panel_applet_get_iface_version");
if(!av) {
dl_err = dlerror();
E_WARNING(E_STRLOC ": Invalid ede-panel plugin. The plugin will not be loaded\n");
return false;
}
applet_version_t avf = (applet_version_t)av;
if((avf)() > EDE_PANEL_APPLET_INTERFACE_VERSION) {
E_WARNING(E_STRLOC ": This plugin requries newer ede-panel version\n");
return false;
}
void *ac = (applet_create_t*)dlsym(a, "ede_panel_applet_create");
if(!ac) {
dl_err = dlerror();
E_WARNING(E_STRLOC ": Unable to find 'create' function in ede-panel plugin: '%s'\n", dl_err);
return false;
}
void *ad = (applet_destroy_t*)dlsym(a, "ede_panel_applet_destroy");
if(!ad) {
dl_err = dlerror();
E_WARNING(E_STRLOC ": Unable to find 'destroy' function in ede-plugin plugin: '%s'\n", dl_err);
return false;
}
void *agi = (applet_get_info_t*)dlsym(a, "ede_panel_applet_get_info");
if(!agi) {
dl_err = dlerror();
E_WARNING(E_STRLOC ": Don't know how to fetch applet information: '%s'\n", dl_err);
return false;
}
void *adi = (applet_destroy_info_t*)dlsym(a, "ede_panel_applet_destroy_info");
if(!adi) {
dl_err = dlerror();
E_WARNING(E_STRLOC ": Don't know how to clean applet information: '%s'\n", dl_err);
return false;
}
AppletData *data = new AppletData;
data->dl = a;
data->awidget = NULL;
data->create_func = (applet_create_t)ac;
data->destroy_func = (applet_destroy_t)ad;
data->destroy_info_func = (applet_destroy_info_t)adi;
applet_get_info_t get_info_func = (applet_get_info_t)agi;
/* load applet info first, so we can even use it when widget wasn't created yet */
data->ainfo = (get_info_func)();
E_DEBUG(E_STRLOC ": Loading class %s\n", data->ainfo->klass_name);
applet_list.push_back(data);
return true;
}
void AppletManager::clear(void) {
if(applet_list.empty())
return;
AListIter it = applet_list.begin(), it_end = applet_list.end();
while(it != it_end) {
clear_applet(*it);
it = applet_list.erase(it);
}
}
/*
* 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();
AppletData *applet;
for(; it != it_end; ++it) {
applet = *it;
/* allocate memory for widget and append it to group */
applet->awidget = applet->create_func();
p->add(applet->awidget);
}
}
void AppletManager::unfill_group(Panel *p) {
AListIter it = applet_list.begin(), it_end = applet_list.end();
for(; it != it_end; ++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();
for(; it != it_end; ++it) {
if(o == (*it)->awidget) {
opts = (*it)->ainfo->options;
return true;
}
}
return false;
}

29
ede-panel/AppletManager.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef __APPLETMANAGER_H__
#define __APPLETMANAGER_H__
#include <edelib/List.h>
#include <edelib/String.h>
#include "Applet.h"
class Panel;
class Fl_Widget;
struct AppletData;
typedef edelib::list<AppletData*> AList;
typedef edelib::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 unfill_group(Panel *p);
bool get_applet_options(Fl_Widget *o, unsigned long &opts);
unsigned int napplets(void) const { return applet_list.size(); }
};
#endif

43
ede-panel/Jamfile Normal file
View File

@ -0,0 +1,43 @@
#
# $Id$
#
# Part of Equinox Desktop Environment (EDE).
# Copyright (c) 2009 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-new ;
# make it as library, so applets can use it too
ObjectC++Flags Netwm.cpp : -g3 -fPIC $(EDELIBINCLUDE) ;
StaticLibrary libnetwm : Netwm.cpp ;
NETWMLIB = -L$(SUBDIR) -lnetwm ;
EdeProgram ede-panel : Panel.cpp AppletManager.cpp ede-panel.cpp ;
LinkAgainst ede-panel : $(NETWMLIB) ;
# also must use this flag or program will crash
LINKFLAGS on ede-panel = -rdynamic ;
rule PanelApplet
{
local target ;
# append default extension
target = $(<:S=$(SUFLIB_SHARED)) ;
Main $(target) : $(>) ;
ObjectC++Flags $(>) : -fPIC -I [ FDirName $(TOP) ede-panel-new ] $(EDELIBINCLUDE) ;
LinkAgainst $(target) : $(NETWMLIB) $(EDELIBLIB) $(EDELIB_GUI_LIB) $(FLTKLIB) $(STDLIB) ;
LINKFLAGS on $(target) = -shared -rdynamic [ on $(target) return $(LINKFLAGS) ] ;
LINKLIBS on $(target) = [ on $(target) return $(LINKLIBS) ] $(3) ;
InstallData $(EDE_PANEL_APPLETS_DIR) : $(target) ;
Clean clean : $(target) ;
}
SubInclude TOP ede-panel-new applets ;

564
ede-panel/Netwm.cpp Normal file
View File

@ -0,0 +1,564 @@
#include <string.h>
#include <X11/Xproto.h>
#include <FL/Fl.H>
#include <FL/x.H>
#include <FL/Fl_Window.H>
#include <edelib/Debug.h>
#include <edelib/List.h>
#include "Netwm.h"
EDELIB_NS_USING(list)
struct NetwmCallbackData {
NetwmCallback cb;
void *data;
};
typedef list<NetwmCallbackData> CbList;
typedef list<NetwmCallbackData>::iterator CbListIt;
static CbList callback_list;
static bool input_selected = false;
static Atom _XA_NET_WORKAREA;
static Atom _XA_NET_WM_WINDOW_TYPE;
static Atom _XA_NET_WM_WINDOW_TYPE_DOCK;
static Atom _XA_NET_WM_WINDOW_TYPE_DESKTOP;
static Atom _XA_NET_WM_WINDOW_TYPE_SPLASH;
static Atom _XA_NET_WM_STRUT;
static Atom _XA_NET_NUMBER_OF_DESKTOPS;
static Atom _XA_NET_CURRENT_DESKTOP;
static Atom _XA_NET_DESKTOP_NAMES;
static Atom _XA_NET_CLIENT_LIST;
static Atom _XA_NET_WM_DESKTOP;
static Atom _XA_NET_WM_NAME;
static Atom _XA_NET_WM_VISIBLE_NAME;
static Atom _XA_NET_ACTIVE_WINDOW;
static Atom _XA_NET_CLOSE_WINDOW;
static Atom _XA_WM_STATE;
static Atom _XA_NET_WM_STATE;
static Atom _XA_NET_WM_STATE_MAXIMIZED_HORZ;
static Atom _XA_NET_WM_STATE_MAXIMIZED_VERT;
static Atom _XA_EDE_WM_ACTION;
static Atom _XA_EDE_WM_RESTORE_SIZE;
/* this macro is set in xlib when X-es provides UTF-8 extension (since XFree86 4.0.2) */
#if X_HAVE_UTF8_STRING
static Atom _XA_UTF8_STRING;
#else
# define _XA_UTF8_STRING XA_STRING
#endif
static short atoms_inited = 0;
static void init_atoms_once(void) {
if(atoms_inited)
return;
_XA_NET_WORKAREA = XInternAtom(fl_display, "_NET_WORKAREA", False);
_XA_NET_WM_WINDOW_TYPE = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE", False);
_XA_NET_WM_WINDOW_TYPE_DOCK = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_DOCK", False);
_XA_NET_WM_WINDOW_TYPE_SPLASH = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_SPLASH", False);
_XA_NET_WM_WINDOW_TYPE_DESKTOP = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
_XA_NET_WM_STRUT = XInternAtom(fl_display, "_NET_WM_STRUT", False);
_XA_NET_NUMBER_OF_DESKTOPS = XInternAtom(fl_display, "_NET_NUMBER_OF_DESKTOPS", False);
_XA_NET_CURRENT_DESKTOP = XInternAtom(fl_display, "_NET_CURRENT_DESKTOP", False);
_XA_NET_DESKTOP_NAMES = XInternAtom(fl_display, "_NET_DESKTOP_NAMES", False);
_XA_NET_CLIENT_LIST = XInternAtom(fl_display, "_NET_CLIENT_LIST", False);
_XA_NET_WM_DESKTOP = XInternAtom(fl_display, "_NET_WM_DESKTOP", False);
_XA_NET_WM_NAME = XInternAtom(fl_display, "_NET_WM_NAME", False);
_XA_NET_WM_VISIBLE_NAME = XInternAtom(fl_display, "_NET_WM_VISIBLE_NAME", False);
_XA_NET_ACTIVE_WINDOW = XInternAtom(fl_display, "_NET_ACTIVE_WINDOW", False);
_XA_NET_CLOSE_WINDOW = XInternAtom(fl_display, "_NET_CLOSE_WINDOW", False);
_XA_WM_STATE = XInternAtom(fl_display, "WM_STATE", False);
_XA_NET_WM_STATE = XInternAtom(fl_display, "_NET_WM_STATE", False);
_XA_NET_WM_STATE_MAXIMIZED_HORZ = XInternAtom(fl_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
_XA_NET_WM_STATE_MAXIMIZED_VERT = XInternAtom(fl_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
_XA_EDE_WM_ACTION = XInternAtom(fl_display, "_EDE_WM_ACTION", False);
_XA_EDE_WM_RESTORE_SIZE = XInternAtom(fl_display, "_EDE_WM_RESTORE_SIZE", False);
#ifdef X_HAVE_UTF8_STRING
_XA_UTF8_STRING = XInternAtom(fl_display, "UTF8_STRING", False);
#endif
atoms_inited = 1;
}
static int xevent_handler(int e) {
if(fl_xevent->type == PropertyNotify) {
int action = -1;
E_DEBUG("==> %s\n", XGetAtomName(fl_display, fl_xevent->xproperty.atom));
if(fl_xevent->xproperty.atom == _XA_NET_NUMBER_OF_DESKTOPS)
action = NETWM_CHANGED_WORKSPACE_COUNT;
else if(fl_xevent->xproperty.atom == _XA_NET_DESKTOP_NAMES)
action = NETWM_CHANGED_WORKSPACE_NAMES;
else if(fl_xevent->xproperty.atom == _XA_NET_CURRENT_DESKTOP)
action = NETWM_CHANGED_CURRENT_WORKSPACE;
else if(fl_xevent->xproperty.atom == _XA_NET_WORKAREA)
action = NETWM_CHANGED_CURRENT_WORKAREA;
else if(fl_xevent->xproperty.atom == _XA_NET_ACTIVE_WINDOW)
action = NETWM_CHANGED_ACTIVE_WINDOW;
else if(fl_xevent->xproperty.atom == _XA_NET_WM_NAME || fl_xevent->xproperty.atom == XA_WM_NAME)
action = NETWM_CHANGED_WINDOW_NAME;
else if(fl_xevent->xproperty.atom == _XA_NET_WM_VISIBLE_NAME)
action = NETWM_CHANGED_WINDOW_VISIBLE_NAME;
else if(fl_xevent->xproperty.atom == _XA_NET_WM_DESKTOP)
action = NETWM_CHANGED_WINDOW_DESKTOP;
else if(fl_xevent->xproperty.atom == _XA_NET_CLIENT_LIST)
action = NETWM_CHANGED_WINDOW_LIST;
else
action = -1;
if(action >= 0 && !callback_list.empty()) {
Window xid = fl_xevent->xproperty.window;
/* TODO: locking here */
CbListIt it = callback_list.begin(), it_end = callback_list.end();
for(; it != it_end; ++it) {
/* execute callback */
(*it).cb(action, xid, (*it).data);
}
}
}
return 0;
}
void netwm_callback_add(NetwmCallback cb, void *data) {
E_RETURN_IF_FAIL(cb != NULL);
fl_open_display();
init_atoms_once();
/* to catch _XA_NET_CURRENT_DESKTOP and such events */
if(!input_selected) {
XSelectInput(fl_display, RootWindow(fl_display, fl_screen), PropertyChangeMask | StructureNotifyMask);
input_selected = true;
}
NetwmCallbackData cb_data;
cb_data.cb = cb;
cb_data.data = data;
callback_list.push_back(cb_data);
Fl::remove_handler(xevent_handler);
Fl::add_handler(xevent_handler);
}
void netwm_callback_remove(NetwmCallback cb) {
if(callback_list.empty())
return;
CbListIt it = callback_list.begin(), it_end = callback_list.end();
while(it != it_end) {
if(cb == (*it).cb) {
it = callback_list.erase(it);
} else {
/* continue, in case the same callback is put multiple times */
++it;
}
}
}
bool netwm_get_workarea(int& x, int& y, int& w, int &h) {
init_atoms_once();
Atom real;
int format;
unsigned long n, extra;
unsigned char* prop;
x = y = w = h = 0;
int status = XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
_XA_NET_WORKAREA, 0L, 0x7fffffff, False, XA_CARDINAL, &real, &format, &n, &extra, (unsigned char**)&prop);
if(status != Success)
return false;
CARD32* val = (CARD32*)prop;
if(val) {
x = val[0];
y = val[1];
w = val[2];
h = val[3];
XFree((char*)val);
return true;
}
return false;
}
void netwm_make_me_dock(Fl_Window *win) {
init_atoms_once();
XChangeProperty(fl_display, fl_xid(win), _XA_NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace,
(unsigned char*)&_XA_NET_WM_WINDOW_TYPE_DOCK, sizeof(Atom));
}
void netwm_set_window_strut(Fl_Window *win, int left, int right, int top, int bottom) {
init_atoms_once();
CARD32 strut[4] = { left, right, top, bottom };
XChangeProperty(fl_display, fl_xid(win), _XA_NET_WM_STRUT, XA_CARDINAL, 32,
PropModeReplace, (unsigned char*)&strut, sizeof(CARD32) * 4);
}
int netwm_get_workspace_count(void) {
init_atoms_once();
Atom real;
int format;
unsigned long n, extra;
unsigned char* prop;
int status = XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
_XA_NET_NUMBER_OF_DESKTOPS, 0L, 0x7fffffff, False, XA_CARDINAL, &real, &format, &n, &extra,
(unsigned char**)&prop);
if(status != Success || !prop)
return -1;
int ns = int(*(long*)prop);
XFree(prop);
return ns;
}
/* change current workspace */
void netwm_change_workspace(int n) {
init_atoms_once();
XEvent xev;
Window root_win = RootWindow(fl_display, fl_screen);
memset(&xev, 0, sizeof(xev));
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = root_win;
xev.xclient.display = fl_display;
xev.xclient.message_type = _XA_NET_CURRENT_DESKTOP;
xev.xclient.format = 32;
xev.xclient.data.l[0] = (long)n;
xev.xclient.data.l[1] = CurrentTime;
XSendEvent (fl_display, root_win, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
XSync(fl_display, True);
}
int netwm_get_current_workspace(void) {
init_atoms_once();
Atom real;
int format;
unsigned long n, extra;
unsigned char* prop;
int status = XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
_XA_NET_CURRENT_DESKTOP, 0L, 0x7fffffff, False, XA_CARDINAL, &real, &format, &n, &extra,
(unsigned char**)&prop);
if(status != Success || !prop)
return -1;
int ns = int(*(long*)prop);
XFree(prop);
return ns;
}
int netwm_get_workspace_names(char**& names) {
init_atoms_once();
/* FIXME: add _NET_SUPPORTING_WM_CHECK and _NET_SUPPORTED ??? */
XTextProperty wnames;
XGetTextProperty(fl_display, RootWindow(fl_display, fl_screen), &wnames, _XA_NET_DESKTOP_NAMES);
/* if wm does not understainds _NET_DESKTOP_NAMES this is not set */
if(!wnames.nitems || !wnames.value)
return 0;
int nsz;
/*
* FIXME: Here should as alternative Xutf8TextPropertyToTextList since
* many wm's set UTF8_STRING property. Below is XA_STRING and for UTF8_STRING
* will fail.
*/
if(!XTextPropertyToStringList(&wnames, &names, &nsz)) {
XFree(wnames.value);
return 0;
}
XFree(wnames.value);
return nsz;
}
int netwm_get_mapped_windows(Window **windows) {
init_atoms_once();
Atom real;
int format;
unsigned long n, extra;
unsigned char* prop = 0;
int status = XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
_XA_NET_CLIENT_LIST, 0L, 0x7fffffff, False, XA_WINDOW, &real, &format, &n, &extra,
(unsigned char**)&prop);
if(status != Success || !prop)
return -1;
*windows = (Window*)prop;
return n;
}
int netwm_get_window_workspace(Window win) {
E_RETURN_VAL_IF_FAIL(win >= 0, -1);
init_atoms_once();
Atom real;
int format;
unsigned long n, extra;
unsigned char* prop = 0;
int status = XGetWindowProperty(fl_display, win,
_XA_NET_WM_DESKTOP, 0L, 0x7fffffff, False, XA_CARDINAL, &real, &format, &n, &extra,
(unsigned char**)&prop);
if(status != Success || !prop)
return -1;
//int ns = int(*(long*)prop);
unsigned long desk = (unsigned long)(*(long*)prop);
XFree(prop);
/* sticky */
if(desk == 0xFFFFFFFF || desk == 0xFFFFFFFE)
return -1;
return desk;
}
int netwm_manageable_window(Window win) {
init_atoms_once();
Atom real;
int format;
unsigned long n, extra;
unsigned char* prop = 0;
int status = XGetWindowProperty(fl_display, win,
_XA_NET_WM_WINDOW_TYPE, 0L, sizeof(Atom), False, XA_ATOM, &real, &format, &n, &extra,
(unsigned char**)&prop);
if(status != Success || !prop)
return -1;
Atom type = *(Atom*)prop;
XFree(prop);
if(type == _XA_NET_WM_WINDOW_TYPE_DESKTOP ||
type == _XA_NET_WM_WINDOW_TYPE_SPLASH ||
type == _XA_NET_WM_WINDOW_TYPE_DOCK)
{
return 0;
}
return 1;
}
char *netwm_get_window_title(Window win) {
init_atoms_once();
XTextProperty xtp;
char *title = NULL, *ret = NULL;
Atom real;
int format;
unsigned long n, extra;
unsigned char* prop = 0;
int status = XGetWindowProperty(fl_display, win,
_XA_NET_WM_NAME, 0L, 0x7fffffff, False, _XA_UTF8_STRING , &real, &format, &n, &extra,
(unsigned char**)&prop);
if(status == Success && prop) {
title = (char *)prop;
ret = strdup(title);
XFree(prop);
} else {
/* try WM_NAME */
if(!XGetWMName(fl_display, win, &xtp))
return NULL;
if(xtp.encoding == XA_STRING) {
ret = strdup((const char*)xtp.value);
} else {
#if X_HAVE_UTF8_STRING
char **lst;
int lst_sz;
status = Xutf8TextPropertyToTextList(fl_display, &xtp, &lst, &lst_sz);
if(status == Success && lst_sz > 0) {
ret = strdup((const char*)*lst);
XFreeStringList(lst);
} else {
ret = strdup((const char*)xtp.value);
}
#else
ret = strdup((const char*)tp.value);
#endif
}
XFree(xtp.value);
}
return ret;
}
Window netwm_get_active_window(void) {
init_atoms_once();
Atom real;
int format;
unsigned long n, extra;
unsigned char* prop = 0;
int status = XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
_XA_NET_ACTIVE_WINDOW, 0L, sizeof(Atom), False, XA_WINDOW, &real, &format, &n, &extra,
(unsigned char**)&prop);
if(status != Success || !prop)
return -1;
int ret = int(*(long*)prop);
XFree(prop);
return (Window)ret;
}
void netwm_set_active_window(Window win) {
init_atoms_once();
XEvent xev;
memset(&xev, 0, sizeof(xev));
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = win;
xev.xclient.display = fl_display;
xev.xclient.message_type = _XA_NET_ACTIVE_WINDOW;
xev.xclient.format = 32;
xev.xclient.data.l[0] = (long)win;
xev.xclient.data.l[1] = CurrentTime;
XSendEvent (fl_display, RootWindow(fl_display, fl_screen), False,
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
XSync(fl_display, True);
}
void netwm_maximize_window(Window win) {
init_atoms_once();
XEvent xev;
memset(&xev, 0, sizeof(xev));
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = win;
xev.xclient.display = fl_display;
xev.xclient.message_type = _XA_NET_WM_STATE;
xev.xclient.format = 32;
xev.xclient.data.l[0] = 0;
xev.xclient.data.l[1] = _XA_NET_WM_STATE_MAXIMIZED_HORZ;
xev.xclient.data.l[2] = _XA_NET_WM_STATE_MAXIMIZED_VERT;
XSendEvent (fl_display, RootWindow(fl_display, fl_screen), False,
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
XSync(fl_display, True);
}
void netwm_close_window(Window win) {
init_atoms_once();
XEvent xev;
memset(&xev, 0, sizeof(xev));
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = win;
xev.xclient.display = fl_display;
xev.xclient.message_type = _XA_NET_CLOSE_WINDOW;
xev.xclient.format = 32;
xev.xclient.data.l[0] = (long)win;
xev.xclient.data.l[1] = CurrentTime;
XSendEvent (fl_display, RootWindow(fl_display, fl_screen), False,
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
XSync(fl_display, True);
}
void wm_ede_restore_window(Window win) {
init_atoms_once();
XEvent xev;
memset(&xev, 0, sizeof(xev));
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = win;
xev.xclient.display = fl_display;
xev.xclient.message_type = _XA_EDE_WM_ACTION;
xev.xclient.format = 32;
xev.xclient.data.l[0] = _XA_EDE_WM_RESTORE_SIZE;
xev.xclient.data.l[1] = CurrentTime;
XSendEvent (fl_display, RootWindow(fl_display, fl_screen), False,
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
XSync(fl_display, True);
}
WmStateValue wm_get_window_state(Window win) {
init_atoms_once();
Atom real;
int format;
unsigned long n, extra;
unsigned char* prop = 0;
int status = XGetWindowProperty(fl_display, win,
_XA_WM_STATE, 0L, sizeof(Atom), False, _XA_WM_STATE, &real, &format, &n, &extra,
(unsigned char**)&prop);
if(status != Success || !prop)
return WM_STATE_NONE;
WmStateValue ret = WmStateValue(*(long*)prop);
XFree(prop);
return ret;
}
void wm_set_window_state(Window win, WmStateValue state) {
E_RETURN_IF_FAIL((int)state > 0);
if(state == WM_STATE_WITHDRAW) {
XWithdrawWindow(fl_display, win, fl_screen);
XSync(fl_display, True);
} else if(state == WM_STATE_ICONIC) {
XIconifyWindow(fl_display, win, fl_screen);
XSync(fl_display, True);
}
/* nothing for WM_STATE_NORMAL */
}

89
ede-panel/Netwm.h Normal file
View File

@ -0,0 +1,89 @@
#ifndef __NETWM_H__
#define __NETWM_H__
#include <X11/Xlib.h>
/* NETWM helpers for panel and applets */
class Fl_Window;
enum {
NETWM_CHANGED_WORKSPACE_COUNT,
NETWM_CHANGED_WORKSPACE_NAMES,
NETWM_CHANGED_CURRENT_WORKSPACE,
NETWM_CHANGED_CURRENT_WORKAREA,
NETWM_CHANGED_ACTIVE_WINDOW,
NETWM_CHANGED_WINDOW_NAME,
NETWM_CHANGED_WINDOW_VISIBLE_NAME,
NETWM_CHANGED_WINDOW_DESKTOP,
NETWM_CHANGED_WINDOW_LIST
};
enum WmStateValue {
WM_STATE_NONE = -1,
WM_STATE_WITHDRAW = 0,
WM_STATE_NORMAL = 1,
WM_STATE_ICONIC = 3
};
typedef void (*NetwmCallback)(int action, Window xid, void *data);
/* register callback for NETWM_* changes */
void netwm_callback_add(NetwmCallback cb, void *data = 0);
/* remove callback if exists */
void netwm_callback_remove(NetwmCallback cb);
/* get current workare set by window manager; return false if fails */
bool netwm_get_workarea(int& x, int& y, int& w, int &h);
/* make 'dock' type from given window */
void netwm_make_me_dock(Fl_Window *win);
/* resize area by setting offsets to each side; 'win' will be outside that area */
void netwm_set_window_strut(Fl_Window *win, int left, int right, int top, int bottom);
/* return number of workspaces */
int netwm_get_workspace_count(void);
/* change current workspace */
void netwm_change_workspace(int n);
/* current visible workspace; workspaces are starting from 0 */
int netwm_get_current_workspace(void);
/* workspace names; return number of allocated ones; call on this XFreeStringList(names) */
int netwm_get_workspace_names(char**& names);
/* get a list of mapped windows; returns number in the list, or -1 if fails; call XFree when done */
int netwm_get_mapped_windows(Window **windows);
/* returns -2 on error, -1 on sticky, else is desktop */
int netwm_get_window_workspace(Window win);
/* return 1 if given window is manageable (desktop/dock/splash types are not manageable) */
int netwm_manageable_window(Window win);
/* return window title or NULL if fails; call free() on returned string */
char *netwm_get_window_title(Window win);
/* return ID of currently focused window; if fails, return -1 */
Window netwm_get_active_window(void);
/* try to focus given window */
void netwm_set_active_window(Window win);
/* maximize window */
void netwm_maximize_window(Window win);
/* close window */
void netwm_close_window(Window win);
/* edewm specific: restore window to previous state */
void wm_ede_restore_window(Window win);
/* not part of NETWM, but helpers until _NET_WM_STATE_* is implemented */
WmStateValue wm_get_window_state(Window win);
void wm_set_window_state(Window win, WmStateValue state);
#endif

357
ede-panel/Panel.cpp Normal file
View File

@ -0,0 +1,357 @@
#include <FL/Fl.H>
#include <FL/fl_draw.H>
#include <FL/x.H>
#include <edelib/Debug.h>
#include <edelib/List.h>
#include <edelib/WindowXid.h>
#include <edelib/Resource.h>
#include <edelib/Util.h>
#include "Panel.h"
#include "Netwm.h"
/* empty space from left and right panel border */
#define INITIAL_SPACING 5
/* space between each applet */
#define DEFAULT_SPACING 5
/* default panel height */
#define DEFAULT_PANEL_H 35
#undef MIN
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#undef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
EDELIB_NS_USING(list)
EDELIB_NS_USING(Resource)
EDELIB_NS_USING(String)
EDELIB_NS_USING(window_xid_create)
EDELIB_NS_USING(build_filename)
typedef list<Fl_Widget*> WidgetList;
typedef list<Fl_Widget*>::iterator WidgetListIt;
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()));
}
/* horizontaly centers widget in the panel */
static void center_widget_h(Fl_Widget *o, Panel *self) {
int ph, wy;
ph = self->panel_h() / 2;
wy = ph - (o->h() / 2);
o->position(o->x(), wy);
}
static void add_from_list(WidgetList &lst, Panel *self, int &X, bool inc) {
WidgetListIt it = lst.begin(), it_end = lst.end();
Fl_Widget *o;
while(it != it_end) {
o = *it;
/* 'inc == false' means we are going from right to left */
if(!inc)
X -= o->w();
/* place it correctly */
o->position(X, o->y());
self->add(o);
if(inc) {
X += DEFAULT_SPACING;
X += o->w();
} else {
X -= DEFAULT_SPACING;
}
it = lst.erase(it);
}
}
static void move_widget(Panel *self, Fl_Widget *o, int &sx, int &sy) {
int tx, ty, px, py;
Fl_Widget *const *a;
tx = Fl::event_x() - sx;
ty = Fl::event_y() - sy;
px = o->x() + tx;
py = o->y() + ty;
/* check the bounds */
if(px < 0)
px = 0;
if(px + o->w() > self->panel_w())
px = self->panel_w() - o->w();
if(py < 0)
py = 0;
if(py + o->h() > self->y() + self->panel_h())
py = self->y() + self->panel_h() - o->h();
if(py + o->h() > self->panel_h())
py = self->panel_h() - o->h();
/* o->position(px, py); */
o->position(px, o->y());
/* find possible collision and move others */
a = self->array();
for(int i = self->children(); i--; ) {
if(o == a[i])
continue;
if(intersects(a[i], o)) {
px = a[i]->x() + tx;
py = a[i]->y() + ty;
/* check the bounds */
if(px < 0)
px = 0;
if(px + o->w() > self->panel_w())
px = self->panel_w() - o->w();
if(py < 0)
py = 0;
if(py + o->h() > self->y() + self->panel_h())
py = self->y() + self->panel_h() - o->h();
if(py + o->h() > self->panel_h())
py = self->panel_h() - o->h();
/* a[i]->position(px, py); */
a[i]->position(px, a[i]->y());
}
}
/* update current position */
sx = Fl::event_x();
sy = Fl::event_y();
o->parent()->redraw();
}
void Panel::do_layout(void) {
E_RETURN_IF_FAIL(mgr.napplets() > 0);
Fl_Widget *o;
unsigned long opts;
unsigned int lsz;
int X, W, free_w;
WidgetList left, right, center, unmanaged, resizable_h;
for(int i = 0; i < children(); i++) {
o = child(i);
/* first center it vertically */
center_widget_h(o, this);
/* could be slow, but I'm relaying how number of loaded applets will not be that large */
if(!mgr.get_applet_options(o, opts)) {
/* here are put widgets not loaded as applets */
unmanaged.push_back(o);
continue;
}
if(opts & EDE_PANEL_APPLET_OPTION_RESIZABLE_H)
resizable_h.push_back(o);
if(opts & EDE_PANEL_APPLET_OPTION_ALIGN_LEFT) {
/* first item will be most leftest */
left.push_back(o);
continue;
}
if(opts & EDE_PANEL_APPLET_OPTION_ALIGN_RIGHT) {
/* first item will be most rightest */
right.push_back(o);
continue;
}
/* rest of them */
center.push_back(o);
}
/* make sure we at the end have all widgets, so we can overwrite group array */
lsz = left.size() + center.size() + right.size() + unmanaged.size();
E_ASSERT(lsz == (unsigned int)children() && "Size of layout lists size not equal to group size");
X = INITIAL_SPACING;
/*
* Call add() on each element, processing lists in order. add() will remove element
* in group array and put it at the end of array. At the end, we should have array ordered by
* layout flags.
*/
add_from_list(left, this, X, true);
add_from_list(center, this, X, true);
add_from_list(unmanaged, this, X, true);
free_w = X;
/* elements right will be put from starting from the right panel border */
X = w() - INITIAL_SPACING;
add_from_list(right, this, X, false);
/*
* Code for horizontal streching.
*
* FIXME: This code pretty sucks and need better rewrite in future.
* To work properly, applets that will be streched must be successive or everything will be
* messed up. Also, applets that are placed right2left does not work with it; they will be resized to right.
*/
if(resizable_h.empty())
return;
/* calculate free space for horizontal alignement, per item in resizable_h list */
free_w = (X - free_w) / resizable_h.size();
if(!free_w) free_w = 0;
/*
* 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();
o = resizable_h.front();
X = o->x();
while(it != it_end) {
o = *it;
W = o->w() + free_w;
o->resize(X, o->y(), W, o->h());
X += W + DEFAULT_SPACING;
it = resizable_h.erase(it);
}
}
void Panel::show(void) {
if(shown()) {
Fl_Window::show();
return;
}
int X, Y, W, H;
fl_open_display();
/* position it */
if(!netwm_get_workarea(X, Y, W, H))
Fl::screen_xywh(X, Y, W, H);
resize(X, Y + H - DEFAULT_PANEL_H, W, DEFAULT_PANEL_H);
screen_x = X;
screen_y = Y;
screen_w = W;
screen_h = H;
screen_h_half = screen_h / 2;
do_layout();
window_xid_create(this, netwm_make_me_dock);
}
int Panel::handle(int e) {
switch(e) {
case FL_SHOW: {
int ret = PanelWindow::handle(e);
position(0, screen_h - h());
if(shown())
netwm_set_window_strut(this, 0, 0, 0, h());
return ret;
}
case FL_PUSH:
clicked = Fl::belowmouse();
if(clicked == this)
clicked = 0;
else if(clicked && clicked->takesevents())
clicked->handle(e);
/* record push position for possible child drag */
sx = Fl::event_x();
sy = Fl::event_y();
return 1;
case FL_DRAG: {
#if 0
if(clicked && clicked->takesevents()) {
cursor(FL_CURSOR_MOVE);
/* moving the child */
//move_widget(this, clicked, sx, sy);
clicked->handle(e);
} else {
#endif
cursor(FL_CURSOR_MOVE);
/* are moving the panel; only vertical moving is supported */
/* 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(screen_x, screen_y);
netwm_set_window_strut(this, 0, 0, h(), 0);
}
if(Fl::event_y_root() > screen_h_half && y() < screen_h_half) {
/* TODO: use area x and area y */
position(screen_x, screen_h - h());
netwm_set_window_strut(this, 0, 0, 0, h());
}
// }
return 1;
}
case FL_RELEASE:
cursor(FL_CURSOR_DEFAULT);
if(clicked && clicked->takesevents()) {
clicked->handle(e);
clicked = 0;
}
return 1;
}
return Fl_Window::handle(e);
}
void Panel::load_applets(void) {
/* FIXME: hardcoded order */
static const char *applets[] = {
"start_menu.so",
"quick_launch.so",
"pager.so",
"clock.so",
"taskbar.so",
0
};
String dir = Resource::find_data("panel-applets");
if(dir.empty())
return;
String tmp;
for(int i = 0; applets[i]; i++) {
tmp = build_filename(dir.c_str(), applets[i]);
mgr.load(tmp.c_str());
}
mgr.fill_group(this);
#if 0
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/clock/clock.so");
mgr.load("./applets/taskbar/taskbar.so");
mgr.fill_group(this);
#endif
}

36
ede-panel/Panel.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef __PANEL_H__
#define __PANEL_H__
#include <edelib/Window.h>
#include "AppletManager.h"
#define EDE_PANEL_CAST_TO_PANEL(obj) ((Panel*)(obj))
#define EDE_PANEL_GET_PANEL_OBJECT (EDE_PANEL_CAST_TO_PANEL(parent()))
EDELIB_NS_USING_AS(Window, PanelWindow)
class Panel : public PanelWindow {
private:
Fl_Widget *clicked;
int sx, sy;
int screen_x, screen_y, screen_w, screen_h, screen_h_half;
bool can_move_widgets;
AppletManager mgr;
void do_layout(void);
public:
Panel() : PanelWindow(300, 30), clicked(0), sx(0), sy(0),
screen_x(0), screen_y(0), screen_w(0), screen_h(0), screen_h_half(0), can_move_widgets(false)
{ box(FL_UP_BOX); }
int handle(int e);
void show(void);
void load_applets(void);
int panel_w(void) { return w(); }
int panel_h(void) { return h(); }
};
#endif

18
ede-panel/applets/Jamfile Normal file
View File

@ -0,0 +1,18 @@
#
# $Id$
#
# Part of Equinox Desktop Environment (EDE).
# Copyright (c) 2009 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-new applets ;
SubInclude TOP ede-panel-new applets demo ;
SubInclude TOP ede-panel-new applets clock ;
SubInclude TOP ede-panel-new applets pager ;
SubInclude TOP ede-panel-new applets quick-launch ;
SubInclude TOP ede-panel-new applets start-menu ;
SubInclude TOP ede-panel-new applets taskbar ;

View File

@ -0,0 +1,71 @@
#include "Applet.h"
#include <FL/Fl_Box.H>
#include <FL/Fl.H>
#include <time.h>
#include <edelib/Debug.h>
#include <edelib/Run.h>
EDELIB_NS_USING(run_async)
static void clock_refresh(void *o);
class Clock : public Fl_Box {
private:
char buf[64];
public:
Clock() : Fl_Box(450, 0, 80, 25, NULL) {
box(FL_THIN_DOWN_BOX);
}
~Clock() {
Fl::remove_timeout(clock_refresh);
}
int handle(int e);
void update_time(void);
};
static void clock_refresh(void *o) {
Clock *c = (Clock *)o;
c->update_time();
Fl::repeat_timeout(1.0, clock_refresh, o);
}
void Clock::update_time(void) {
time_t t;
struct tm *tmp;
t = time(NULL);
tmp = localtime(&t);
if(!tmp)
return;
strftime(buf, sizeof(buf), "%H:%M:%S", tmp);
label(buf);
}
int Clock::handle(int e) {
switch(e) {
case FL_SHOW:
Fl::add_timeout(0, clock_refresh, this);
break;
case FL_RELEASE:
run_async("ede-timedate");
break;
}
return Fl_Box::handle(e);
}
EDE_PANEL_APPLET_EXPORT (
Clock,
EDE_PANEL_APPLET_OPTION_ALIGN_RIGHT,
"Clock applet",
"0.1",
"empty",
"Sanel Zukan"
)

View File

@ -0,0 +1,13 @@
#
# $Id$
#
# Part of Equinox Desktop Environment (EDE).
# Copyright (c) 2009 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-new applets clock ;
PanelApplet clock : Clock.cpp ;

View File

@ -0,0 +1,26 @@
#include "Applet.h"
#include <FL/Fl_Button.H>
#include <FL/x.H>
#include <FL/Fl.H>
#include <stdio.h>
class MyButton : public Fl_Button {
public:
MyButton() : Fl_Button(0, 0, 90, 25, "xxx") {
color(FL_RED);
puts("MyButton::MyButton");
}
~MyButton() {
puts("MyButton::~MyButton");
}
};
EDE_PANEL_APPLET_EXPORT (
MyButton,
0,
"Panel button",
"0.1",
"empty",
"Sanel Zukan"
)

View File

@ -0,0 +1,13 @@
#
# $Id$
#
# Part of Equinox Desktop Environment (EDE).
# Copyright (c) 2009 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-new applets demo ;
PanelApplet demo : AppletDemo.cpp ;

View File

@ -0,0 +1,13 @@
#
# $Id$
#
# Part of Equinox Desktop Environment (EDE).
# Copyright (c) 2009 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-new applets pager ;
PanelApplet pager : Pager.cpp PagerButton.cpp ;

View File

@ -0,0 +1,125 @@
#include "Applet.h"
#include "Netwm.h"
#include <string.h>
#include <FL/Fl_Group.H>
#include <FL/Fl.H>
#include <edelib/Debug.h>
#include "PagerButton.h"
class Pager : public Fl_Group {
public:
Pager();
~Pager();
void init_workspace_boxes(void);
void workspace_changed(void);
};
static void box_cb(Fl_Widget*, void *b) {
PagerButton *pb = (PagerButton*)b;
/* because workspaces in button labels are increased */
int s = pb->get_workspace_label() - 1;
netwm_change_workspace(s);
}
static void net_event_cb(int action, Window xid, void *data) {
E_RETURN_IF_FAIL(data != NULL);
if(action == NETWM_CHANGED_CURRENT_WORKSPACE) {
Pager *p = (Pager*)data;
p->workspace_changed();
}
}
Pager::Pager() : Fl_Group(0, 0, 25, 25, NULL) {
box(FL_DOWN_BOX);
/* we will explicitly add elements */
end();
init_workspace_boxes();
netwm_callback_add(net_event_cb, this);
}
Pager::~Pager() {
netwm_callback_remove(net_event_cb);
}
void Pager::init_workspace_boxes(void) {
int X, Y, H;
/* prepare the sizes */
X = x() + Fl::box_dx(box());
Y = y() + Fl::box_dy(box());
H = h() - Fl::box_dh(box());
int nworkspaces, curr_workspace;
char **names = 0;
char nbuf[16];
nworkspaces = netwm_get_workspace_count();
curr_workspace = netwm_get_current_workspace();
netwm_get_workspace_names(names);
/*
* Resize group before childs, or they will be resized too, messing things up.
* Here, each child is 25px wide plus 1px for delimiter between the childs .
*/
int gw = nworkspaces * (25 + 1);
gw += Fl::box_dw(box());
/* last child do not ends with 1px wide delimiter */
gw -= 1;
size(gw, h());
for(int i = 0; i < nworkspaces; i++) {
/* let box width be fixed */
PagerButton *bx = new PagerButton(X, Y, 25, H);
bx->box(FL_FLAT_BOX);
if(i == curr_workspace)
bx->select_it(1);
else
bx->select_it(0);
/* workspaces are started from 0 */
bx->set_workspace_label(i + 1);
if(names)
bx->copy_tooltip(names[i]);
bx->callback(box_cb, bx);
add(bx);
/* position for the next box */
X = bx->x() + bx->w() + 1;
}
XFreeStringList(names);
}
void Pager::workspace_changed(void) {
int c = netwm_get_current_workspace();
PagerButton *pb;
E_RETURN_IF_FAIL(c < children());
for(int i = 0; i < children(); i++) {
pb = (PagerButton*)child(i);
pb->select_it(0);
}
pb = (PagerButton*)child(c);
pb->select_it(1);
}
EDE_PANEL_APPLET_EXPORT (
Pager,
EDE_PANEL_APPLET_OPTION_ALIGN_LEFT,
"Desktop switcher",
"0.1",
"empty",
"Sanel Zukan"
)

View File

@ -0,0 +1,40 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <edelib/Debug.h>
#include "PagerButton.h"
PagerButton::~PagerButton() {
if(ttip)
free(ttip);
}
void PagerButton::set_workspace_label(int l) {
wlabel = l;
char buf[16];
snprintf(buf, sizeof(buf), "%i", l);
copy_label(buf);
}
void PagerButton::copy_tooltip(const char *t) {
E_RETURN_IF_FAIL(t != NULL);
if(ttip)
free(ttip);
ttip = strdup(t);
tooltip(ttip);
}
void PagerButton::select_it(int i) {
if(i) {
color((Fl_Color)44);
labelcolor(FL_BLACK);
} else {
color((Fl_Color)33);
labelcolor(FL_GRAY);
}
redraw();
}

View File

@ -0,0 +1,22 @@
#ifndef __PAGERBUTTON_H__
#define __PAGERBUTTON_H__
#include <FL/Fl_Button.H>
class PagerButton : public Fl_Button {
private:
char *ttip;
int wlabel;
public:
PagerButton(int X, int Y, int W, int H, const char *l = 0) : Fl_Button(X, Y, W, H), ttip(NULL), wlabel(0)
{ }
~PagerButton();
void set_workspace_label(int l);
int get_workspace_label(void) { return wlabel; }
void copy_tooltip(const char *t);
void select_it(int i);
};
#endif

View File

@ -0,0 +1,13 @@
#
# $Id$
#
# Part of Equinox Desktop Environment (EDE).
# Copyright (c) 2009 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-new applets quick-launch ;
PanelApplet quick_launch : QuickLaunch.cpp ;

View File

@ -0,0 +1,117 @@
#include "Applet.h"
#include <ctype.h>
#include <FL/Fl.H>
#include <FL/Fl_Input.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Window.H>
#include <edelib/Debug.h>
#include <edelib/Nls.h>
#include <edelib/Run.h>
#include "edit-clear-icon.h"
EDELIB_NS_USING(run_async)
class QuickLaunch : public Fl_Input {
private:
Fl_Image *img;
int img_x, img_y;
public:
QuickLaunch();
void draw(void);
int handle(int e);
/* a stupid way to avoid draw_box() to draw the image */
void image2(Fl_Image *im) { img = im; }
Fl_Image *image2(void) { return img; }
};
static bool empty_string(const char *s) {
for(const char *ptr = s; ptr && *ptr; ptr++) {
if(!isspace(*ptr))
return false;
}
return true;
}
static void enter_cb(Fl_Widget*, void *o) {
QuickLaunch *ql = (QuickLaunch*)o;
if(ql->value() && !empty_string(ql->value()))
run_async("ede-launch %s", ql->value());
}
QuickLaunch::QuickLaunch() : Fl_Input(0, 0, 130, 25), img(NULL), img_x(0), img_y(0) {
when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED);
callback(enter_cb, this);
tooltip(_("Enter a command to be executed"));
image2((Fl_RGB_Image*)&image_edit);
}
void QuickLaunch::draw(void) {
Fl_Boxtype b = box(), oldb;
int X = x() + Fl::box_dx(b);
int Y = y() + Fl::box_dy(b);
int W = w() - Fl::box_dw(b);
int H = h() - Fl::box_dh(b);
if(img) {
W -= img->w() + 6;
img_x = X + W + 2;
img_y = (Y + H / 2) - (img->h() / 2);
}
if(damage() & FL_DAMAGE_ALL) {
draw_box(b, color());
if(img) img->draw(img_x, img_y);
}
/* use flat box when text is drawn or there would be visible border line */
oldb = box();
box(FL_FLAT_BOX);
Fl_Input_::drawtext(X, Y, W, H);
box(oldb);
}
int QuickLaunch::handle(int e) {
if(!img)
goto done;
switch(e) {
case FL_ENTER:
case FL_MOVE:
if(active_r() && window()) {
if(Fl::event_inside(img_x, img_y, img->w(), img->h()))
window()->cursor(FL_CURSOR_DEFAULT);
else
window()->cursor(FL_CURSOR_INSERT);
}
return 1;
case FL_RELEASE:
if(active_r() && Fl::event_inside(img_x, img_y, img->w(), img->h()))
value(0);
/* fallthrough */
}
done:
return Fl_Input::handle(e);
}
EDE_PANEL_APPLET_EXPORT (
QuickLaunch,
EDE_PANEL_APPLET_OPTION_ALIGN_LEFT,
"Quick Launch applet",
"0.1",
"empty",
"Sanel Zukan"
)

View File

@ -0,0 +1,55 @@
#ifndef __EDIT_CLEAR_ICON_H__
#define __EDIT_CLEAR_ICON_H__
#include <FL/Fl_Image.H>
static unsigned char idata_edit[] =
{255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
255,255,255,0,120,72,0,71,123,74,0,227,124,75,0,218,120,72,0,59,255,255,255,0,
255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,120,72,0,68,123,
74,0,245,171,109,11,255,166,105,10,255,123,74,0,229,255,255,255,0,255,255,255,
0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
255,255,0,156,139,0,19,156,139,0,130,138,105,0,2,123,74,0,218,169,107,10,255,
193,125,16,255,178,114,12,255,123,74,0,237,255,255,255,0,255,255,255,0,255,255,
255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,156,
139,0,41,156,139,0,255,154,133,0,206,132,82,1,242,193,125,16,255,188,122,15,255,
134,82,3,244,121,73,0,111,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,
0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,156,139,0,61,177,
160,29,242,190,174,50,254,161,136,1,255,178,118,11,255,128,78,1,244,123,74,0,
149,120,72,0,2,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
255,0,156,139,0,21,157,140,0,119,160,143,1,210,160,54,0,228,176,105,23,247,235,
222,119,255,205,189,65,255,156,136,0,254,135,100,0,129,255,255,255,0,255,255,
255,0,255,255,255,0,255,255,255,0,255,255,255,0,156,139,0,27,159,142,1,159,162,
144,9,246,204,189,67,247,234,220,114,255,215,177,98,255,171,27,13,255,200,109,
51,255,236,220,104,255,216,200,79,255,158,141,1,246,156,139,0,90,255,255,255,0,
156,139,0,2,156,139,0,64,159,142,0,163,159,143,5,247,205,190,69,250,248,234,136,
255,253,238,125,255,253,235,108,255,253,234,99,255,246,216,97,255,184,56,29,255,
187,74,40,255,187,165,41,246,158,141,0,235,156,139,0,95,255,255,255,0,157,140,0,
234,174,158,27,243,207,193,73,254,235,221,119,255,243,227,101,255,251,229,68,
255,253,233,82,255,253,236,109,255,253,239,132,255,253,236,107,255,251,234,132,
255,173,66,19,252,161,36,0,215,156,139,0,7,255,255,255,0,255,255,255,0,159,141,
1,233,226,212,103,255,228,210,73,255,220,198,16,255,231,208,24,255,243,219,42,
255,253,230,60,255,253,233,82,255,253,235,97,255,253,234,95,255,253,239,138,255,
192,176,47,245,156,127,0,95,255,255,255,0,255,255,255,0,255,255,255,0,159,142,0,
168,198,182,51,251,230,214,86,255,218,194,3,255,219,195,4,255,229,205,20,255,
238,215,35,255,246,222,47,255,251,228,55,255,252,229,60,255,251,237,139,255,165,
148,17,247,156,139,0,26,255,255,255,0,255,255,255,0,255,255,255,0,156,139,0,28,
159,142,4,244,220,205,88,255,228,211,76,255,218,194,3,255,218,194,3,255,220,196,
7,255,227,203,17,255,231,208,24,255,237,218,70,255,221,207,94,255,160,142,1,
212,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,156,
139,0,63,160,143,5,241,214,200,86,254,231,215,91,255,220,198,21,255,218,194,3,
255,218,194,3,255,220,197,16,255,232,218,108,255,171,155,26,246,156,139,0,67,
255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
255,0,156,139,0,38,158,141,0,230,197,180,50,251,231,217,109,255,229,212,78,255,
223,202,38,255,231,216,95,255,197,181,54,250,159,142,0,197,255,255,255,0,255,
255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
255,255,255,0,156,139,0,20,159,141,0,169,161,144,8,246,198,181,48,250,225,211,
91,255,210,195,79,253,158,141,0,226,156,139,0,19,255,255,255,0,255,255,255,0,
255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
255,0,255,255,255,0,255,255,255,0,156,139,0,33,158,141,0,158,158,141,0,236,157,
140,0,237,156,139,0,31,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,
255,255,255,0,255,255,255,0};
static Fl_RGB_Image image_edit(idata_edit, 16, 16, 4, 0);
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 B

View File

@ -0,0 +1,182 @@
#include <string.h>
#include <edelib/Util.h>
#include <edelib/StrUtil.h>
#include <edelib/Directory.h>
#include <edelib/DesktopFile.h>
#include "DesktopEntry.h"
EDELIB_NS_USING(DesktopFile)
EDELIB_NS_USING(build_filename)
EDELIB_NS_USING(stringtok)
EDELIB_NS_USING(DESK_FILE_TYPE_APPLICATION)
static int age_counter = 1;
DesktopEntry::~DesktopEntry() {
delete path;
delete id;
delete categories;
delete name;
delete generic_name;
delete comment;
delete icon;
delete exec;
}
void DesktopEntry::assign_path(const char *dir, const char *p, const char *basedir) {
E_ASSERT(dir != NULL);
E_ASSERT(p != NULL);
/* make sure we do not assign things twice */
E_RETURN_IF_FAIL(path == NULL);
E_RETURN_IF_FAIL(id == NULL);
const char *ptr;
String *spath, *sid;
/* full path */
spath = new String(build_filename(dir, p));
ptr = spath->c_str();
/* if we have basedir, skip directory path by jumping the size of basedir */
if(basedir) {
ptr += strlen(basedir);
/* skip ending delimiters */
while(*ptr == E_DIR_SEPARATOR)
ptr++;
}
sid = new String(ptr);
/* replace existing separators; this is in the spec */
sid->replace(E_DIR_SEPARATOR, '-');
path = spath;
id = sid;
age = age_counter++;
}
bool DesktopEntry::load(void) {
E_RETURN_VAL_IF_FAIL(path != NULL, false);
DesktopFile df;
if(!df.load(path->c_str())) {
E_WARNING(E_STRLOC ": Unable to load %s\n", path->c_str());
return false;
}
/* check if we are 'Hidden = true' or 'NoDisplay = true'; these must not be loaded */
if(df.hidden() || df.no_display())
return false;
/* it must be application type */
E_RETURN_VAL_IF_FAIL(df.type() == DESK_FILE_TYPE_APPLICATION, false);
char buf[128];
/* name must be present too */
E_RETURN_VAL_IF_FAIL(df.name(buf, sizeof(buf)) == true, false);
name = new String(buf);
/* optional */
if(df.get("Desktop Entry", "Categories", buf, sizeof(buf)))
categories = new String(buf);
if(df.generic_name(buf, sizeof(buf)))
generic_name = new String(buf);
if(df.comment(buf, sizeof(buf)))
comment = new String(buf);
if(df.icon(buf, sizeof(buf)))
icon = new String(buf);
if(df.exec(buf, sizeof(buf)))
exec = new String(buf);
return true;
}
bool DesktopEntry::in_category(const char *cat) {
E_RETURN_VAL_IF_FAIL(cat != NULL, false);
if(!categories)
return false;
StrListIt it, it_end;
if(category_list.empty()) {
stringtok(category_list, *categories, ";");
/* remove starting/ending spaces if exists */
it = category_list.begin();
it_end = category_list.end();
for(; it != it_end; ++it)
(*it).trim();
}
it = category_list.begin();
it_end = category_list.end();
for(; it != it_end; ++it) {
if((*it) == cat)
return true;
}
return false;
}
/* TODO: bug in edelib */
static bool id_age_sorter(DesktopEntry* const& u1, DesktopEntry* const& u2) {
return (strcmp(u1->get_id(), u2->get_id()) < 0) && (u1->get_age() < u2->get_age());
}
/* TODO: bug in edelib */
static bool name_sorter(DesktopEntry* const& u1, DesktopEntry* const& u2) {
return (strcmp(u1->get_name(), u2->get_name()) < 0);
}
void desktop_entry_list_remove_duplicates(DesktopEntryList &lst) {
if(lst.empty())
return;
/* sort them respecting name and age */
lst.sort(id_age_sorter);
DesktopEntryListIt it = lst.begin(), it_end = lst.end();
DesktopEntryListIt next = it;
/* do consecutive unique */
while(++next != it_end) {
if(strcmp((*it)->get_id(), (*next)->get_id()) == 0) {
delete *next;
lst.erase(next);
} else {
it = next;
}
next = it;
}
}
void desktop_entry_list_load_all(DesktopEntryList &lst) {
if(lst.empty())
return;
DesktopEntryListIt it = lst.begin(), it_end = lst.end();
while(it != it_end) {
if(!(*it)->load()) {
delete *it;
it = lst.erase(it);
} else {
++it;
}
}
}
void desktop_entry_list_sort(DesktopEntryList &lst) {
lst.sort(name_sorter);
}

View File

@ -0,0 +1,101 @@
#ifndef __DESKTOPENTRY_H__
#define __DESKTOPENTRY_H__
#include <edelib/String.h>
#include <edelib/Debug.h>
#include <edelib/List.h>
EDELIB_NS_USING(String)
EDELIB_NS_USING(list)
class DesktopEntry;
typedef list<DesktopEntry*> DesktopEntryList;
typedef list<DesktopEntry*>::iterator DesktopEntryListIt;
typedef list<String> StrList;
typedef list<String>::iterator StrListIt;
/* Represents entry for a menu. Do not confuse it with DesktopFile from edelib */
class DesktopEntry {
private:
/* used to load "later" found .desktop file, in case duplicate desktop file id's was found */
unsigned int age;
/* used for <OnlyUnallocated> and <NotOnlyUnallocated> */
bool allocated;
/* absolute path to .desktop file */
String *path;
/* Desktop File Id */
String *id;
/* Categories value from .desktop file; filled with load() */
String *categories;
/* Localized Name value from .desktop file; filled with load() */
String *name;
/* GenericName value from .desktop file; filled with load() */
String *generic_name;
/* Comment value from .desktop file; filled with load() */
String *comment;
/* Icon value from .desktop file; filled with load() */
String *icon;
/* Exec value from .desktop file; filled with load() */
String *exec;
/* tokenized 'categories' */
StrList category_list;
E_DISABLE_CLASS_COPY(DesktopEntry)
public:
DesktopEntry() : age(0), allocated(false), path(NULL), id(NULL),
categories(NULL), name(NULL), generic_name(NULL), comment(NULL), icon(NULL), exec(NULL) { }
~DesktopEntry();
/*
* Construct full path by using 'dir/p' and construct desktop file id according
* to the menu spec. If 'basedir' was given (can be NULL), 'dir' will be diffed against it
* so correct prefix for desktop file id can be calculated.
*
* The id is calculated like this:
* $XDG_DATA_DIRS/applications/foo.desktop => foo.desktop
* $XDG_DATA_DIRS/applications/ede/foo.desktop => ede-foo.desktop
* $XDG_DATA_DIRS/applications/ede/menu/foo.desktop => ede-menu-foo.desktop
*/
void assign_path(const char *dir, const char *p , const char *basedir);
/* loads actual .desktop file and reads it */
bool load(void);
/* check if Categories key contains given category */
bool in_category(const char *cat);
void mark_as_allocated(void) { allocated = true; }
bool is_allocated(void) { return allocated; }
const char *get_path(void) { return path ? path->c_str() : NULL; }
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 ? exec->c_str() : NULL; }
};
/* remove duplicate items in the list, by looking at DesktopEntry id */
void desktop_entry_list_remove_duplicates(DesktopEntryList &lst);
/* call 'load()' on each member; if 'load()' fails, that member will be removed */
void desktop_entry_list_load_all(DesktopEntryList &lst);
/* sort a list of entries */
void desktop_entry_list_sort(DesktopEntryList &lst);
#endif

View File

@ -0,0 +1,21 @@
#
# $Id$
#
# Part of Equinox Desktop Environment (EDE).
# Copyright (c) 2009 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-new applets start-menu ;
MENU_SRC = XdgMenuReader.cpp DesktopEntry.cpp MenuRules.cpp ;
# TODO: MENU_SRC files will be compiled twice, once for applet and once for test program.
# applet
PanelApplet start_menu : StartMenu.cpp $(MENU_SRC) ;
# test program
EdeProgram ede-menu-spec-test : ede-menu-spec-test.cpp $(MENU_SRC) ;

View File

@ -0,0 +1,156 @@
#include <edelib/Debug.h>
#include "MenuRules.h"
#include "DesktopEntry.h"
typedef list<bool> Stack;
typedef list<bool>::iterator StackIt;
#if 0
static char *rules_str[] = {
"None",
"Filename",
"Category",
"And",
"Or",
"Not",
"All"
};
#endif
MenuRules *menu_rules_new(void) {
MenuRules *r = new MenuRules;
r->rule_operator = MENU_RULES_OPERATOR_NONE;
return r;
}
MenuRules *menu_rules_append_rule(MenuRulesList &rules, short rule, const char *data) {
MenuRules *r = menu_rules_new();
r->rule_operator = rule;
if(data)
r->data = data;
/* NOTE: things are evaluated recursively, so we push deepest rule at the top */
rules.push_front(r);
return r;
}
void menu_rules_delete(MenuRules *r) {
if(!r->subrules.empty()) {
MenuRulesListIt it = r->subrules.begin(), it_end = r->subrules.end();
while(it != it_end) {
menu_rules_delete(*it);
it = r->subrules.erase(it);
}
}
delete r;
}
/*
* Rules are evaluated starting from the deepest one, and are much more like
* lisp expressions. Each rule behaves like function, returning false or true and top function
* gets applied on those results.
*
* TODO: this case will not work (KDE 3.5.x applications.menu):
* <And>
* <Or>
* <Category>c1</Category>
* <Category>c2</Category>
* <Category>c3</Category>
* </Or>
* <Not><Category>c4</Category></Not>
* </And>
*
* because due recrusion '<Not>...</Not>' result will be calculated inside '<Or>...</Or>' expression and
* '<And>' will receive the only one value.
*/
static void eval_with_stack(MenuRules *m, DesktopEntry *en, Stack &result_stack) {
if(!m->subrules.empty()) {
MenuRulesListIt it = m->subrules.begin(), it_end = m->subrules.end();
/* go to the deepest node */
for(; it != it_end; ++it)
eval_with_stack(*it, en, result_stack);
}
/* this will always evaluate to true so all items can be included */
if(m->rule_operator == MENU_RULES_OPERATOR_ALL) {
result_stack.push_front(true);
return;
}
if(m->rule_operator == MENU_RULES_OPERATOR_FILENAME) {
bool st = (m->data == en->get_id());
result_stack.push_front(st);
return;
}
if(m->rule_operator == MENU_RULES_OPERATOR_CATEGORY) {
bool st = en->in_category(m->data.c_str());
result_stack.push_front(st);
return;
}
if(m->rule_operator == MENU_RULES_OPERATOR_AND) {
StackIt it = result_stack.begin(), it_end = result_stack.end();
/* 'and' always evalutes to true */
bool st = true;
while(it != it_end) {
st &= *it;
it = result_stack.erase(it);
}
result_stack.push_front(st);
return;
}
/* operators 'not' and 'or' behaves much the same, except 'not' reverse the result additionally */
if(m->rule_operator == MENU_RULES_OPERATOR_OR || m->rule_operator == MENU_RULES_OPERATOR_NOT) {
StackIt it = result_stack.begin(), it_end = result_stack.end();
/* 'or' and 'not' always evalutes to false */
bool st = false;
while(it != it_end) {
st |= *it;
it = result_stack.erase(it);
}
if(m->rule_operator == MENU_RULES_OPERATOR_NOT)
st = !st;
result_stack.push_front(st);
return;
}
}
bool menu_rules_eval(MenuRules *m, DesktopEntry *en) {
Stack result_stack;
eval_with_stack(m, en, result_stack);
if(result_stack.size() == 1)
goto get_first;
else {
/*
* From the spec: "Each rule in a list of rules has a logical OR relationship, that is, desktop entries
* which match any rule are included in the menu."
*/
bool result = false;
StackIt it = result_stack.begin(), it_end = result_stack.end();
while(it != it_end) {
result |= *it;
result_stack.erase(it);
}
return result;
}
get_first:
return result_stack.front();
}

View File

@ -0,0 +1,40 @@
#ifndef __MENURULES_H__
#define __MENURULES_H__
#include <edelib/List.h>
#include <edelib/String.h>
EDELIB_NS_USING(list)
EDELIB_NS_USING(String)
struct MenuRules;
struct DesktopEntry;
typedef list<MenuRules*> MenuRulesList;
typedef list<MenuRules*>::iterator MenuRulesListIt;
enum {
MENU_RULES_OPERATOR_NONE,
MENU_RULES_OPERATOR_FILENAME,
MENU_RULES_OPERATOR_CATEGORY,
MENU_RULES_OPERATOR_AND,
MENU_RULES_OPERATOR_OR,
MENU_RULES_OPERATOR_NOT,
MENU_RULES_OPERATOR_ALL
};
struct MenuRules {
short rule_operator;
String data;
MenuRulesList subrules;
};
MenuRules *menu_rules_new(void);
MenuRules *menu_rules_append_rule(MenuRulesList &rules, short rule, const char *data);
void menu_rules_delete(MenuRules *m);
bool menu_rules_eval(MenuRules *m, DesktopEntry *en);
#endif

View File

@ -0,0 +1,168 @@
#include "Applet.h"
#include <FL/Fl.H>
#include <FL/fl_draw.H>
#include <edelib/MenuBase.h>
#include <edelib/Debug.h>
#include <edelib/Nls.h>
#include "XdgMenuReader.h"
#include "ede-icon.h"
EDELIB_NS_USING(MenuBase)
/* some of this code was ripped from Fl_Menu_Button.cxx */
class StartMenu : public MenuBase {
private:
MenuItem *mcontent;
public:
StartMenu();
~StartMenu();
void popup(void);
void draw(void);
int handle(int e);
};
StartMenu::StartMenu() : MenuBase(0, 0, 80, 25, "EDE"), mcontent(NULL) {
down_box(FL_NO_BOX);
labelfont(FL_HELVETICA_BOLD);
labelsize(14);
image(ede_icon_image);
tooltip(_("Click here to choose and start common programs"));
mcontent = xdg_menu_load();
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);
}
}
}
StartMenu::~StartMenu() {
xdg_menu_delete(mcontent);
}
static StartMenu *pressed_menu_button = 0;
void StartMenu::draw(void) {
if(!box() || type())
return;
draw_box(pressed_menu_button == this ? fl_down(box()) : box(), color());
if(image()) {
int X, Y, lw, lh;
X = x() + 5;
Y = (y() + h() / 2) - (image()->h() / 2);
image()->draw(X, Y);
X += image()->w() + 10;
fl_font(labelfont(), labelsize());
fl_color(labelcolor());
fl_measure(label(), lw, lh, align());
fl_draw(label(), X, Y, lw, lh, align(), 0, 0);
} else {
draw_label();
}
}
void StartMenu::popup(void) {
const MenuItem *m;
pressed_menu_button = this;
redraw();
Fl_Widget *mb = this;
Fl::watch_widget_pointer(mb);
if(!box() || type())
m = menu()->popup(Fl::event_x(), Fl::event_y(), label(), mvalue(), this);
else
m = menu()->pulldown(x(), y(), w(), h(), 0, this);
picked(m);
pressed_menu_button = 0;
Fl::release_widget_pointer(mb);
}
int StartMenu::handle(int e) {
if(!menu() || !menu()->text)
return 0;
switch(e) {
case FL_ENTER:
case FL_LEAVE:
return (box() && !type()) ? 1 : 0;
case FL_PUSH:
if(!box()) {
if(Fl::event_button() != 3)
return 0;
} else if(type()) {
if(!(type() & (1 << (Fl::event_button() - 1))))
return 0;
}
if(Fl::visible_focus())
Fl::focus(this);
popup();
return 1;
case FL_KEYBOARD:
if(!box()) return 0;
/*
* Win key will show the menu.
*
* In FLTK, Meta keys are equivalent to Alt keys. On other hand, eFLTK has them different, much
* the same as on M$ Windows. Here, I'm explicitly using hex codes, since Fl_Meta_L and Fl_Meta_R
* are unusable.
*/
if(Fl::event_key() == 0xffeb || Fl::event_key() == 0xffec) {
popup();
return 1;
}
return 0;
case FL_SHORTCUT:
if(Fl_Widget::test_shortcut()) {
popup();
return 1;
}
return test_shortcut() != 0;
case FL_FOCUS:
case FL_UNFOCUS:
if(box() && Fl::visible_focus()) {
redraw();
return 1;
}
default:
return 0;
}
/* not reached */
return 0;
}
EDE_PANEL_APPLET_EXPORT (
StartMenu,
EDE_PANEL_APPLET_OPTION_ALIGN_LEFT,
"Main menu",
"0.1",
"empty",
"Sanel Zukan"
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,13 @@
#ifndef __XDGMENUREADER_H__
#define __XDGMENUREADER_H__
#include <edelib/MenuItem.h>
EDELIB_NS_USING(MenuItem)
void xdg_menu_dump_for_test_suite(void);
MenuItem *xdg_menu_load(void);
void xdg_menu_delete(MenuItem *it);
#endif

View File

@ -0,0 +1,55 @@
<?xml version="1.0"?>
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" "http://www.freedesktop.org/standards/menu-spec/menu-1.0.dtd">
<Menu>
<Name>Applications</Name>
<Directory>Applications.directory</Directory>
<-- Search the default locations -->
<DefaultAppDirs/>
<DefaultDirectoryDirs/>
<-- Merge third-party submenus -->
<MergeDir>applications-merged</MergeDir>
<-- Merge legacy hierarchy -->
<LegacyDir>/usr/share/applnk</LegacyDir>
<-- Define default layout -->
<DefaultLayout>
<Merge type="menus"/>
<Merge type="files"/>
<Separator/>
<Menuname>More</Menuname>
</DefaultLayout>
<-- some random moves, maybe to clean up legacy dirs,
maybe from menu editing -->
<Move>
<Old>Foo</Old>
<New>Bar</New>
<Old>Foo2</Old>
<New>Bar2</New>
</Move>
<-- A preferences submenu, kept in a separate file
so it can also be used standalone -->
<Menu>
<Name>Preferences</Name>
<Directory>Preferences.directory</Directory>
<MergeFile>preferences.menu</MergeFile>
</Menu>
<-- An Office submenu, specified inline -->
<Menu>
<Name>Office</Name>
<Directory>Office.directory</Directory>
<Include>
<Category>Office</Category>
</Include>
<Exclude>
<Filename>foo.desktop</Filename>
</Exclude>
</Menu>
</Menu>
}

View File

@ -0,0 +1,50 @@
<?xml version="1.0"?>
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>Applications</Name>
<!-- Read .desktop file from only this location -->
<!-- Or remove and use the two items below -->
<AppDir>/home/ravenlock/.local/share/applications</AppDir>
<!-- Read standard .directory and .desktop file locations -->
<!-- by uncommenting these. -->
<!-- <DefaultAppDirs/> -->
<!-- <DefaultDirectoryDirs/> -->
<!-- Define a layout -->
<!-- The Layout is what gives your menu its sort order. -->
<!-- Without this section the menu is sorted alphabetically. -->
<Layout>
<Menuname>Testing</Menuname>
<Separator/>
<Menuname>Testing2</Menuname>
</Layout>
<!-- Testing submenu -->
<Menu>
<Name>Testing</Name>
<Include> <Category>TestingCat</Category> </Include>
<Menu>
<Name>Testing-sub</Name>
<Include> <Category>TestingCatSub</Category> </Include>
</Menu> <!-- End Testing submenu -->
</Menu> <!-- End Testing submenu -->
<!-- Testing2 submenu -->
<Menu>
<Name>Testing2</Name>
<Include> <Category>TestingCat2</Category> </Include>
<Menu>
<Name>Testing-sub2</Name>
<Include> <Category>TestingCatSub2</Category> </Include>
</Menu> <!-- End Testing submenu -->
</Menu> <!-- End Testing2 submenu -->
</Menu> <!-- End Applications -->

View File

@ -0,0 +1,55 @@
#ifndef __EDE_ICON_H__
#define __EDE_ICON_H__
#include <FL/Fl_Image.H>
static unsigned char idata_ede_icon[] =
{49,78,108,255,49,78,108,255,49,78,108,255,49,78,108,255,49,78,108,255,49,
78,108,255,49,78,108,255,49,78,108,255,49,78,108,255,49,78,108,255,49,78,108,
255,49,78,108,255,49,78,108,255,49,78,108,255,49,78,108,255,49,78,108,255,49,78,
108,255,49,78,108,236,49,78,108,192,49,78,108,192,49,78,108,192,49,78,108,192,
49,78,108,192,49,78,108,192,49,78,108,192,49,78,108,192,49,78,108,192,49,78,
108,192,49,78,108,192,49,78,108,192,49,78,108,232,49,78,108,255,49,78,108,255,
49,78,108,176,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
255,255,0,255,255,255,0,49,78,108,160,49,78,108,255,49,78,108,255,49,78,108,176,
255,255,255,0,255,255,255,0,255,255,255,0,45,75,105,17,49,78,109,98,49,78,108,
134,50,78,108,92,53,79,106,29,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
255,0,49,78,108,160,49,78,108,255,49,78,108,255,49,78,108,176,255,255,255,0,255,
255,255,0,49,79,109,42,49,78,108,229,49,78,108,255,49,78,108,255,49,78,108,255,
49,78,108,241,48,77,108,80,255,255,255,0,255,255,255,0,255,255,255,0,49,78,108,
160,49,78,108,255,49,78,108,255,49,78,108,176,255,255,255,0,255,255,255,0,49,78,
109,202,49,78,108,255,49,78,108,255,49,78,108,255,49,78,108,255,49,78,108,255,
48,78,108,179,51,77,102,10,255,255,255,0,49,78,108,29,49,78,108,214,49,78,108,
255,49,78,108,255,49,78,108,176,255,255,255,0,49,79,109,42,49,78,108,255,49,78,
108,255,49,78,108,255,49,78,108,255,49,78,108,210,48,78,107,69,255,255,255,0,52,
81,110,21,49,78,108,134,49,78,108,246,49,78,108,255,49,78,108,255,49,78,108,
255,49,78,108,176,255,255,255,0,47,77,109,70,49,78,108,255,49,78,108,255,49,78,
108,233,50,78,108,102,85,85,85,3,33,52,72,3,49,78,108,156,49,78,108,252,49,78,
108,255,49,78,108,210,49,78,108,186,49,78,108,255,49,78,108,255,49,78,108,176,
255,255,255,0,51,80,109,35,49,78,108,248,49,77,108,135,55,73,109,14,255,255,255,
0,49,79,108,115,49,78,108,246,49,78,108,255,49,78,108,255,49,78,108,130,49,78,
108,3,49,78,108,160,49,78,108,255,49,78,108,255,49,78,108,176,255,255,255,0,255,
255,255,0,51,77,111,30,255,255,255,0,48,78,109,74,49,78,108,232,49,78,108,255,
49,78,108,255,49,78,108,255,49,78,108,255,50,77,109,56,255,255,255,0,49,78,108,
160,49,78,108,255,49,78,108,255,49,78,108,176,255,255,255,0,255,255,255,0,0,0,0,
1,50,78,108,144,49,78,108,253,49,78,108,255,49,78,108,255,49,78,108,255,49,78,
108,255,49,79,108,224,51,102,102,5,255,255,255,0,49,78,108,160,49,78,108,255,49,
78,108,255,49,78,108,176,255,255,255,0,255,255,255,0,255,255,255,0,50,77,107,
76,49,78,108,244,49,78,108,255,49,78,108,255,49,78,108,255,49,78,108,239,49,76,
107,57,255,255,255,0,255,255,255,0,49,78,108,160,49,78,108,255,49,78,108,255,49,
78,108,176,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,48,80,112,
16,50,79,107,107,48,77,108,142,49,78,109,115,53,74,106,24,255,255,255,0,255,
255,255,0,255,255,255,0,49,78,108,160,49,78,108,255,49,78,108,255,49,78,108,176,
255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,
255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,255,255,0,255,
255,255,0,49,78,108,160,49,78,108,255,49,78,108,255,49,78,108,223,49,78,108,152,
49,78,108,152,49,78,108,152,49,78,108,152,49,78,108,152,49,78,108,152,49,78,
108,152,49,78,108,152,49,78,108,152,49,78,108,152,49,78,108,152,49,78,108,152,
49,78,108,217,49,78,108,255,49,78,108,255,49,78,108,255,49,78,108,255,49,78,
108,255,49,78,108,255,49,78,108,255,49,78,108,255,49,78,108,255,49,78,108,255,
49,78,108,255,49,78,108,255,49,78,108,255,49,78,108,255,49,78,108,255,49,78,
108,255,49,78,108,255};
static Fl_RGB_Image ede_icon_image(idata_ede_icon, 16, 16, 4, 0);
#endif

View File

@ -0,0 +1,6 @@
#include "XdgMenuReader.h"
int main(int argc, char **argv) {
xdg_menu_dump_for_test_suite();
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

View File

@ -0,0 +1,70 @@
2005-04-25 Mark McLoughlin <mark@skynet.ie>
* tests/u: add test for recursive inclusion of .menu files.
Also know as the "get really hosed and eat all the RAM
you can find" test.
2005-04-20 Waldo Bastian <bastian@kde.org>
* tests/s/result,
tests/s/test: Test that .desktop files under $HOME correctly
override .desktop files at system level
* tests/t/result,
tests/t/test: Test order in which <Move> elements are processed
2005-02-18 Mark McLoughlin <mark@skynet.ie>
Make it a bit more difficult in order to catch:
http://bugzilla.gnome.org/show_bug.cgi?id=167758
Thanks to Chris Lahey for the test case.
* tests/o/test: put freecell.desktop in a subdirectory.
2005-02-18 Mark McLoughlin <mark@skynet.ie>
* tests/o/result,
tests/o/test: test that
<And><Category>foo</Category><Not><Category>foo</Category></Not></And>
doesn't match anything.
* README: add bit about how to test the GNOME impl.
2005-02-18 Mark McLoughlin <mark@skynet.ie>
Problem pointed out by Waldo.
* menutest: don't try and run the "CVS" test :)
* tests/m/result,
tests/n/result: items in a hidden or deleted menu
should be considered allocated.
2004-12-08 Mark McLoughlin <mark@skynet.ie>
* tests/2/result,
tests/2/test: test the new <OnlyUnallocated> behaviour.
2004-08-29 Mark McLoughlin <mark@skynet.ie>
* tests/m: test for NoDisplay=true behavious in .desktop and
.directory files.
* data/hidden.desktop,
data/hidden.directory: add.
* data/apps.directory: add Type=Directory.
* menutest: actually generate a test result if one doesn't
exist - makes it easier to write new tests.
2003-10-23 Havoc Pennington <hp@redhat.com>
* tests/f/test: remove <OnlyUnallocated/> from inside <Include>
statement, not allowed.
2003-10-16 Havoc Pennington <hp@redhat.com>
* menutest: cat log file on failure; print list of failed tests
when we're done

View File

@ -0,0 +1,44 @@
This directory contains regression tests for the menu-spec.
To run these tests your menu-spec implementation should be
able to generate a menu in the following text format:
<Full Menu Name><tab><Desktop File Id><tab><Full Path to Desktop File>
Example:
Editors/ kde-kwrite.desktop /home/bastian/.local/share/applications/kde-kwrite.desktop
Editors/ kde-kate.desktop /home/bastian/.local/share/applications/kde-kate.desktop
Editors/ kde-KEdit.desktop /home/bastian/.local/share/applications/kde-KEdit.desktop
Development/ kde-gideon.desktop /opt/kde3/share/applnk/Development/gideon.desktop
Development/ kde-kbabel.desktop /opt/kde3/share/applnk/Development/kbabel.desktop
Development/ kde-quanta.desktop /opt/kde3/share/applnk/Development/quanta.desktop
/ kde-Kfind.desktop /opt/kde3/share/applnk/Kfind.desktop
/ kde-Home.desktop /opt/kde3/share/applnk/Home.desktop
/ kde-Help.desktop /opt/kde3/share/applnk/Help.desktop
The environment variable $MENUTEST should point to a command that is
able to generate the menu in the above format.
To test KDE one can use:
MENUTEST="kbuildsycoca --menutest"
With GNOME, you can use:
MENUTEST=gnome-menu-spec-test
The menutest script should be used to run the tests. The following commands can
be used:
MENUTEST="foo -bar" ./menutest
to run all tests
MENUTEST="foo -bar" TESTS="Deleted Directory" ./menutest
to run the tests named "Deleted" and "Directory" only
All tests contain of a test setup script named "test" and a file describing
the expected menu named "result".

View File

@ -0,0 +1,7 @@
This is an regression suite taken from http://freedesktop.org, to test
conformance against XDG menu specification.
Some test results (AppDir) were missing, so they are added. The rest
is unchanged.
Sanel Zukan

View File

@ -0,0 +1,5 @@
I hope you understand what i mean ;)
desktop-file-id stuff & overwrite stuff absolute path
onlyshowin - notshowin

View File

@ -0,0 +1,68 @@
[Desktop Entry]
Encoding=UTF-8
Exec=khelpcenter
Icon=khelpcenter
DocPath=khelpcenter/index.html
Type=Application
Terminal=0
Name=Help
Name[af]=Hulp
Name[az]=Yardım
Name[be]=Дапамога
Name[bg]=Помощ
Name[br]=Skoazell
Name[bs]=Pomoć
Name[ca]=Ajuda
Name[cs]=Nápověda
Name[cy]=Cymorth
Name[da]=Hjælp
Name[de]=Hilfe
Name[el]=Βοήθεια
Name[eo]=Helpo
Name[es]=Ayuda
Name[et]=Abiinfo
Name[eu]=Laguntza
Name[fa]=راهنما
Name[fi]=Ohje
Name[fr]=Aide
Name[gl]=Axuda
Name[he]=עזרה
Name[hr]=Pomoć
Name[hu]=Segítség
Name[id]=Keterangan bantu
Name[is]=Hjálp
Name[it]=Aiuto
Name[ja]=ヘルプ
Name[ko]=도움말
Name[lo]=ລະບົບຊ່ວຍເຫືລອ
Name[lt]=Pagalba
Name[lv]=Palīdzība
Name[mn]=Тусламж
Name[mt]=Għajnuna
Name[nb]=Hjelp
Name[nn]=Hjelp
Name[nso]=Thuso
Name[oc]=Ajuda
Name[pl]=Pomoc
Name[pt]=Ajuda
Name[pt_BR]=Ajuda
Name[ro]=Ajutor
Name[ru]=Справка
Name[sk]=Pomocník
Name[sl]=Pomoč
Name[sr]=Pomoć
Name[ss]=Sita
Name[sv]=Hjälp
Name[ta]=¯¾Å¢
Name[th]=ระบบช่วยเหลือ
Name[tr]=Yardım
Name[uk]=Довідка
Name[ven]=Thuso
Name[vi]=Trợ giúp
Name[wa]=Aidance
Name[xh]=Uncedo
Name[zh_CN]=帮助
Name[zh_TW]=求助
Name[zu]=Usizo

View File

@ -0,0 +1,127 @@
[Desktop Entry]
Encoding=UTF-8
Type=Application
Exec=kfmclient openProfile filemanagement
Icon=folder_home
Terminal=0
Name=Home
Name[af]=Huis
Name[az]=Başlanğıc
Name[be]=Хатні
Name[bg]=Домашна директория
Name[br]=Er-gêr
Name[bs]=Početak
Name[ca]=Inici
Name[cs]=Můj adresář
Name[cy]=Cartref
Name[da]=Hjem
Name[de]=Persönliches Verzeichnis
Name[el]=Σπίτι
Name[eo]=Hejmo
Name[es]=Personal
Name[et]=Kodukataloog
Name[eu]=Etxea
Name[fa]=خانه
Name[fi]=Koti
Name[fr]=Dossier personnel
Name[gl]=Persoal
Name[he]=בית
Name[hr]=Početak
Name[hu]=Saját könyvtár
Name[id]=Rumah
Name[is]=Heimasvæðið þitt
Name[ja]=ホーム
Name[ko]=홈
Name[lo]=ພື້ນທີ່ສ່ວນຕົວ
Name[lt]=Pradžia
Name[lv]=Mājas
Name[mn]=Хувийн лавлах
Name[mt]=Direttorju Personali
Name[nb]=Hjem
Name[nl]=Persoonlijke map
Name[nn]=Heim
Name[nso]=Gae
Name[oc]=Inici
Name[pl]=Katalog domowy
Name[pt]=Casa
Name[ro]=Acasă
Name[ru]=Домой
Name[sk]=Domov
Name[sl]=Domov
Name[sr]=Кориснички директоријум
Name[ss]=Ekhaya
Name[sv]=Hem
Name[ta]=¦¾¡¼ì¸õ
Name[th]=พื้นที่ส่วนตัว
Name[tr]=Başlangıç
Name[uk]=Домівка
Name[ven]=Haya
Name[wa]=Måjhon
Name[xh]=Ikhaya
Name[xx]=xxHomexx
Name[zh_CN]=起点
Name[zh_TW]=家目錄
Name[zu]=Ikhaya
GenericName=Personal Files
GenericName[af]=Persoonlike Lêers
GenericName[az]=Şəxsi Fayllar
GenericName[be]=Пэрсанальныя файлы
GenericName[bg]=Лични файлове
GenericName[br]=Restroù deoc'h
GenericName[bs]=Osobne datoteke
GenericName[ca]=Fitxers personals
GenericName[cs]=Osobní soubory
GenericName[cy]=Ffeiliau Personol
GenericName[da]=Personlige filer
GenericName[de]=Eigene Dateien
GenericName[el]=Προσωπικά Αρχεία
GenericName[eo]=Personaj dosieroj
GenericName[es]=Archivos personales
GenericName[et]=Isiklikud failid
GenericName[eu]=Fitxategi Pertsonalak
GenericName[fa]=پرونده‌های شخصی
GenericName[fi]=Omat tiedostot
GenericName[fr]=Fichiers personnels
GenericName[gl]=Ficheiros Persoais
GenericName[he]=קבצים אישיים
GenericName[hr]=Osobne datoteke
GenericName[hu]=személyes fájlok
GenericName[id]=File Pribadi
GenericName[is]=Skrárnar þínar
GenericName[it]=File personali
GenericName[ja]=個人のファイル
GenericName[ko]=혼자만 쓰는 파일
GenericName[lo]=ທີ່ເກັບແຟ້ມແລະເອກະສານສວ່ນຕົວຫລືອື່ນຯ
GenericName[lt]=Asmeninės Bylos
GenericName[lv]=Personālie Faili
GenericName[mn]=Өөрийн файлууд
GenericName[mt]=Fajls Personali
GenericName[nb]=Personlige filer
GenericName[nl]=persoonlijke bestanden
GenericName[nn]=Personlege filer
GenericName[nso]=Difaele tsa Botho
GenericName[oc]=FiquièRs personals
GenericName[pl]=Pliki osobiste
GenericName[pt]=Ficheiros Pessoais
GenericName[pt_BR]=Arquivos Pessoais
GenericName[ro]=Fişiere personale
GenericName[ru]=Личные файлы
GenericName[sk]=Osobné súbory
GenericName[sl]=Osebne datoteke
GenericName[sr]=Овај директоријум садржи ваше личне фајлове
GenericName[sv]=Personliga filer
GenericName[ta]=¦º¡ó¾ì §¸¡ôÒì¸û
GenericName[th]=ที่เก็บแฟ้มและเอกสารส่วนตัว หรืออื่น ๆ
GenericName[tr]=Kişisel Dosyalar
GenericName[uk]=Особисті файли
GenericName[ven]=Dzifaela dza vhune
GenericName[vi]=File cá nhân
GenericName[wa]=Fitchîs da vosse
GenericName[xh]=Iifayile Zobuqu
GenericName[xx]=xxPersonal Filesxx
GenericName[zh_CN]=个人文件
GenericName[zh_TW]=個人檔案
GenericName[zu]=Amafayela Omuntu siqu

View File

@ -0,0 +1,34 @@
[Desktop Entry]
Encoding=UTF-8
BinaryPattern=kedit;
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
GenericName=Simple Text Editor
GenericName[ca]=Editor de text
GenericName[cs]=Jednoduchý textový editor
GenericName[da]=Simpel teksteditor
GenericName[es]=Editor de texto sencillo
GenericName[fr]=Éditeur de texte élémentaire
GenericName[pt_BR]=Editor de Texto Simples
GenericName[sv]=Enkel texteditor
GenericName[wa]=Simpe aspougneu di tecse
Exec=kedit -caption "%c" %i %m %u
Icon=kedit
TerminalOptions=
Path=
DocPath=kedit/index.html
Type=Application
Terminal=0
Name=KEdit
Name[af]=Kredigeer
Name[eo]=Redaktilo
Name[hr]=Uređivač
Name[lv]=KRediģēt
Name[pl]=Edytor
Name[sv]=Kedit
Name[th]=แก้ไขข้อความ
Name[ven]=U sengulusa ha K
Name[xh]=Abahleli Be K
Name[zh_TW]=KDE 編輯器
X-KDE-StartupNotify=true
X-DCOP-ServiceType=Multi
Categories=Qt;KDE;TextEditor

View File

@ -0,0 +1,66 @@
[Desktop Entry]
Encoding=UTF-8
Exec=kfind %f
Icon=kfind
DocPath=kfind/index.html
TerminalOptions=
Path=
Type=Application
Terminal=0
Name=Find Files
Name[af]=Soek Lêers
Name[be]=Шукаць файлы
Name[bg]=Търсене на файлове
Name[br]=Klask restroù
Name[bs]=Pronađi datoteke
Name[ca]=Cerca fitxers
Name[cs]=Najít soubory
Name[cy]=Canfod Ffeiliau
Name[da]=Find filer
Name[de]=Dateien suchen
Name[el]=Εύρεση αρχείων
Name[eo]=Trovu dosierojn
Name[es]=KFind
Name[et]=Failide otsimine
Name[eu]=Fitxategiak Bilatu
Name[fa]=یافتن پرونده‌ها
Name[fi]=Etsi tiedostoja
Name[fr]=Recherche de fichiers
Name[gl]=Buscar Ficheiros
Name[he]=חפש קבצים
Name[hr]=Nađi datoteke
Name[hu]=Fájlkeresés
Name[id]=Cari Berkas
Name[it]=Trova file
Name[ja]=ファイルを検索
Name[ko]=파일 찾기
Name[lo]=ຄົ້ນຫາແຟ້ມ
Name[lt]=Rasti bylas
Name[lv]=Meklēt Failus
Name[mn]=Файл хайх
Name[mt]=Sib Fajls
Name[nb]=Finn filer
Name[nl]=Bestanden zoeken
Name[nn]=Finn filer
Name[nso]=Hwetsa Difaele
Name[oc]=Cerca fiquièrs
Name[pl]=Znajdź pliki
Name[pt]=Procurar Ficheiros
Name[pt_BR]=Encontrar arquivos
Name[ro]=Caută fişiere
Name[ru]=Поиск файлов
Name[sk]=Hľadať súbory
Name[sl]=Poišči datoteke
Name[sr]=Pretraga fajlova
Name[sv]=Hitta filer
Name[ta]=§¸¡ôÒì ¸ñÎÀ¢Ê
Name[th]=ค้นหาแฟ้ม
Name[tr]=Dosyalarda Bul
Name[uk]=Знайти файли
Name[ven]=Todani faela
Name[vi]=Tìm file
Name[xh]=Fumana Iifayile
Name[zh_CN]=查找文件
Name[zh_TW]=尋找檔案
Name[zu]=Thola Amafayela
X-KDE-StartupNotify=true

View File

@ -0,0 +1,66 @@
[Desktop Entry]
Encoding=UTF-8
Name=Apps
Name[af]=Programme
Name[ar]=تطبيقات
Name[az]=Proqram Tə'minatları
Name[be]=Дастасаваньні
Name[bg]=Приложения
Name[br]=Arloadoù
Name[bs]=Aplikacije
Name[ca]=Aplicacions
Name[cs]=Aplikace
Name[da]=Øvrige programmer
Name[de]=Programme
Name[el]=Εφαρμογές
Name[eo]=Aplikaĵoj
Name[es]=Aplicaciones
Name[et]=Rakendused
Name[eu]=Aplikazioak
Name[fa]=برنامه‌های کاربردی
Name[fi]=Sovellukset
Name[fo]=Nýtsluskipanir
Name[gl]=Aplicacións
Name[he]=יישומים
Name[hr]=Programi
Name[hu]=Alkalmazások
Name[id]=Aplikasi
Name[is]=Forrit
Name[it]=Applicazioni
Name[ja]=アプリケーション
Name[ko]=응용 프로그램
Name[lo]=ອັບພລິກເຄເຊິນ
Name[lt]=Programos
Name[lv]=Aplikācijas
Name[mk]=Апликации
Name[mt]=Applikazzjonijiet
Name[nb]=Programmer
Name[nl]=Programma's
Name[nn]=Program
Name[nso]=Ditshomiso
Name[oc]=Aplicacions
Name[pl]=Aplikacje
Name[pt]=Aplicações
Name[pt_BR]=Aplicativos
Name[ro]=Aplicaţii
Name[ru]=Приложения
Name[se]=Prográmmat
Name[sk]=Aplikácie
Name[sl]=Uporabniški programi
Name[sr]=Aplikacije
Name[ss]=Ticelo
Name[sv]=Program
Name[ta]=ÀÂýÀ¡Î¸û
Name[th]=แอพพลิเคชัน
Name[tr]=Uygulamalar
Name[uk]=Програми
Name[ven]=Apulikhesheni
Name[vi]=Chương trình
Name[wa]=Programes
Name[xh]=Izicelo
Name[zh_CN]=应用程序
Name[zh_TW]=應用程式
Name[zu]=Abayaleli
Type=Directory
Icon=package_applications

View File

@ -0,0 +1,83 @@
[Desktop Entry]
Encoding=UTF-8
Name=FreeCell
Name[be]=Вольная ячэя
Name[bg]=Свободна Клетка
Name[bn]=ফ্রীসেল
Name[ca]=FreeCell
Name[cs]=FreeCell
Name[da]=Napoleon
Name[de]=FreeCell
Name[el]=FreeCell
Name[es]=FreeCell
Name[et]=Freecell
Name[fi]=Vapaakenttä
Name[fr]=Freecell
Name[ga]=FreeCell
Name[gl]=FreeCell
Name[he]=פריסל
Name[hu]=FreeCell
Name[it]=FreeCell
Name[ja]=フリーセル
Name[ko]=프리셀
Name[lt]=FreeCell
Name[lv]=FreeCell
Name[mn]=Фриселл
Name[ms]=FreeCell
Name[nl]=FreeCell
Name[no]=Freecell
Name[pl]=FreeCell
Name[pt]=Freecell
Name[pt_BR]=FreeCell
Name[ru]=Фриселл
Name[sk]=FreeCell
Name[sl]=FreeCell
Name[sv]=Napoleon på S:t Helena
Name[tr]=İskambil falı
Name[uk]=Вільна комірка
Name[vi]=FreeCell
Name[wa]=Freecell
Name[zh_CN]=空当接龙
Name[zh_TW]=Freecell
Comment=FreeCell game
Comment[be]=Гульня ў Вольную ячэю
Comment[bg]=игра Свободна Клетка
Comment[bn]=ফ্রীসেল খেলা
Comment[ca]=Joc del FreeCell
Comment[cs]=Hra FreeCell
Comment[da]=Kortspillet Napoleon
Comment[de]=FreeCell-Spiel
Comment[el]=Το παιχνίδι FreeCell
Comment[es]=Juego FreeCell
Comment[et]=Kaardimäng FreeCell
Comment[fi]=Vapaakenttä-peli
Comment[fr]=Jeu de cartes Freecell
Comment[he]=משחק פריסל
Comment[hu]=FreeCell játék
Comment[it]=FreeCell
Comment[ja]=フリーセルの GNOME 版
Comment[lv]=FreeCell spēle
Comment[mn]=GNOME Фриселл тоглоом
Comment[ms]=Permainan FreeCell
Comment[nl]=FreeCell Spel
Comment[no]=Spillet FreeCell
Comment[pl]=Gra FreeCell
Comment[pt]=Jogo FreeCell
Comment[pt_BR]=Jogo de FreeCell
Comment[ru]=Пасьянс "Ячейка"
Comment[sk]=Hra FreeCell
Comment[sl]=Igra Freecell
Comment[sv]=Spelet Napoleon på S:t Helena
Comment[tr]=İskambil falı oyunu
Comment[uk]=Гра "Вільна комірка"
Comment[vi]=Trò chơi FreeCell
Comment[zh_TW]=Freecell 紙牌接龍遊戲
Exec=freecell
Icon=gnome-cardgame.png
Terminal=false
Type=Application
Categories=GNOME;Application;Game;CardGame;
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-games
X-GNOME-Bugzilla-Component=freecell
StartupNotify=true

View File

@ -0,0 +1,81 @@
[Desktop Entry]
Encoding=UTF-8
Icon=gataxx.png
Name=Gataxx
Name[am]=Gataxx
Name[be]=Gataxx
Name[bg]=Гатаксс
Name[bn]=জীঅ্যাটাক্স
Name[ca]=Gataxx
Name[cs]=Gataxx
Name[da]=Ataxx
Name[de]=Gataxx
Name[el]=Gataxx
Name[es]=Gataxx
Name[et]=Gataxx
Name[fi]=Gataxx
Name[fr]=Gataxx
Name[he]=Gataxx
Name[hu]=Gataxx
Name[it]=Gataxx
Name[ja]=Gataxx
Name[ko]=Gataxx
Name[lv]=Gataxx
Name[mn]=Gataxx
Name[ms]=Gataxx
Name[nl]=Gataxx
Name[no]=Gataxx
Name[pl]=Gataxx
Name[pt]=Gataxx
Name[pt_BR]=Gataxx
Name[ru]=Gataxx
Name[sk]=Gataxx
Name[sl]=Gataxx
Name[sv]=Gataxx
Name[tr]=Gataxx
Name[uk]=Атаки
Name[vi]=Gataxx
Name[wa]=Gataxx
Name[zh_CN]=Gataxx
Name[zh_TW]=Gataxx
Comment=Ataxx game
Comment[be]=Гульня Ataxx
Comment[bg]=Игра атаксс
Comment[bn]=অ্যাটাক্স খেলা
Comment[ca]=Joc del Ataxx
Comment[cs]=Hra Ataxx
Comment[da]=Spillet Ataxx
Comment[de]=Ataxx-Spiel
Comment[el]=Παιχνίδι Ataxx
Comment[es]=Un juego tipo Ataxx.
Comment[et]=Mäng nimega ataxx
Comment[fi]=Ataxx-peli
Comment[fr]=Jeu Ataxx
Comment[he]=משחק Ataxx
Comment[hu]=Ataxx játék
Comment[it]=Gioco Ataxx
Comment[ja]=Ataxx ゲーム
Comment[lv]=Ataxx spēle
Comment[mn]=Ataxx тоглоом.
Comment[ms]=Permainan Ataxx
Comment[nl]=Ataxx
Comment[no]=Ataxx-spill
Comment[pl]=Gra Ataxx
Comment[pt]=Jogo Ataxx
Comment[pt_BR]=Jogo Ataxx
Comment[ru]=Игра ataxx
Comment[sk]=Hra Ataxx
Comment[sl]=Igra Ataxx
Comment[sv]=Spelet Ataxx
Comment[tr]=Ataxx oyunu
Comment[uk]=Гра "Атаки"
Comment[vi]=Trò chơi Ataxx.
Comment[zh_TW]=Ataxx 遊戲
Exec=gataxx
Terminal=false
Type=Application
Categories=GNOME;Application;Game;BoardGame;
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-games
X-GNOME-Bugzilla-Component=gataxx
StartupNotify=true

View File

@ -0,0 +1,12 @@
[KDE Desktop Entry]
Encoding=UTF-8
BinaryPattern=kdevelop;
Type=Application
Exec=gideon %u
MimeType=application/x-kdevelop;
Icon=gideon
DocPath=kdevelop/index.html
Terminal=0
Name=KDevelop 3.0
Comment=IDE for C++/Qt/KDE
X-DCOP-ServiceType=Multi

View File

@ -0,0 +1,13 @@
[Desktop Entry]
Encoding=UTF-8
BinaryPattern=kdevelop;
Type=Application
Exec=gideon %u
MimeType=application/x-kdevelop;
Icon=gideon
DocPath=kdevelop/index.html
Terminal=0
Name=KDevelop 3.0
Comment=IDE for C++/Qt/KDE
X-DCOP-ServiceType=Multi
Categories=Qt;KDE;Development

View File

@ -0,0 +1,83 @@
[Desktop Entry]
Encoding=UTF-8
Name=Glines
Name[be]=Glines
Name[bg]=ГЛинии
Name[bn]=জীলাইন্‌স
Name[ca]=Glines
Name[cs]=Glines
Name[da]=Linjer
Name[de]=Glines
Name[el]=Glines
Name[es]=Glines
Name[et]=Glines
Name[eu]=Glines
Name[fi]=Glines
Name[fr]=Glines
Name[he]=Glines
Name[hu]=Glines
Name[it]=Glines
Name[ja]=Glines
Name[ko]=Glines
Name[lt]=Glines
Name[lv]=Glines
Name[mn]=Glines
Name[ms]=Glines
Name[nl]=GLines
Name[no]=Glines
Name[pl]=Glines
Name[pt]=GLinhas
Name[pt_BR]=Glines
Name[ro]=Glines
Name[ru]=Glines
Name[sk]=GČiary
Name[sl]=Glines
Name[sv]=Glinjer
Name[tr]=Sıradaki toplar
Name[uk]=Ряди
Name[vi]=Glines
Name[wa]=GRoyes
Name[zh_CN]=Glines
Name[zh_TW]=Glines
Comment=Color lines game
Comment[be]=Гульня "Каляровыя лініі"
Comment[bg]=Игра Цветни линии
Comment[bn]=কালার লাইন্‌স খেলা
Comment[ca]=Joc de línies de color
Comment[cs]=Hra Barevné linie
Comment[da]=Farvede linjer-spil
Comment[de]=Farblinienspiel
Comment[el]=Παιχνίδι γραμμών χρώματος
Comment[es]=Juego del tipo líneas de colores.
Comment[fi]=Väriviivapeli
Comment[fr]=Jeu de lignes colorées
Comment[he]=משחק שורות צבעוניות
Comment[hu]=Color lines játék
Comment[it]=Gioco Color Lines
Comment[ja]=カラーラインのゲーム
Comment[lv]=Krāsu līniju spēle
Comment[mn]=Өнгөт бөмбөлөг тоглоом
Comment[ms]=Permainan garisan warna
Comment[nl]=Kleurlijnen
Comment[no]=Spill med fargelinjer
Comment[pl]=Gra w kolorowe linie
Comment[pt]=Jogo das linhas coloridas
Comment[pt_BR]=Jogo de linhas coloridas
Comment[ru]=Игра "Цветные линии"
Comment[sk]=Hra Farebné čiary
Comment[sl]=Igra barvnih črt
Comment[sv]=Färglinjespel
Comment[tr]=Color lines oyunu
Comment[uk]=Гра "Кольорові ряди"
Comment[vi]=Trò chơi ColorLines
Comment[zh_TW]=Color lines 遊戲
Exec=glines
Icon=glines.png
Terminal=false
Type=Application
Categories=GNOME;Application;Game;PuzzleGame;
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-games
X-GNOME-Bugzilla-Component=glines
StartupNotify=true
NoDisplay=true

View File

@ -0,0 +1,82 @@
[Desktop Entry]
Encoding=UTF-8
Name=Glines
Name[be]=Glines
Name[bg]=ГЛинии
Name[bn]=জীলাইন্‌স
Name[ca]=Glines
Name[cs]=Glines
Name[da]=Linjer
Name[de]=Glines
Name[el]=Glines
Name[es]=Glines
Name[et]=Glines
Name[eu]=Glines
Name[fi]=Glines
Name[fr]=Glines
Name[he]=Glines
Name[hu]=Glines
Name[it]=Glines
Name[ja]=Glines
Name[ko]=Glines
Name[lt]=Glines
Name[lv]=Glines
Name[mn]=Glines
Name[ms]=Glines
Name[nl]=GLines
Name[no]=Glines
Name[pl]=Glines
Name[pt]=GLinhas
Name[pt_BR]=Glines
Name[ro]=Glines
Name[ru]=Glines
Name[sk]=GČiary
Name[sl]=Glines
Name[sv]=Glinjer
Name[tr]=Sıradaki toplar
Name[uk]=Ряди
Name[vi]=Glines
Name[wa]=GRoyes
Name[zh_CN]=Glines
Name[zh_TW]=Glines
Comment=Color lines game
Comment[be]=Гульня "Каляровыя лініі"
Comment[bg]=Игра Цветни линии
Comment[bn]=কালার লাইন্‌স খেলা
Comment[ca]=Joc de línies de color
Comment[cs]=Hra Barevné linie
Comment[da]=Farvede linjer-spil
Comment[de]=Farblinienspiel
Comment[el]=Παιχνίδι γραμμών χρώματος
Comment[es]=Juego del tipo líneas de colores.
Comment[fi]=Väriviivapeli
Comment[fr]=Jeu de lignes colorées
Comment[he]=משחק שורות צבעוניות
Comment[hu]=Color lines játék
Comment[it]=Gioco Color Lines
Comment[ja]=カラーラインのゲーム
Comment[lv]=Krāsu līniju spēle
Comment[mn]=Өнгөт бөмбөлөг тоглоом
Comment[ms]=Permainan garisan warna
Comment[nl]=Kleurlijnen
Comment[no]=Spill med fargelinjer
Comment[pl]=Gra w kolorowe linie
Comment[pt]=Jogo das linhas coloridas
Comment[pt_BR]=Jogo de linhas coloridas
Comment[ru]=Игра "Цветные линии"
Comment[sk]=Hra Farebné čiary
Comment[sl]=Igra barvnih črt
Comment[sv]=Färglinjespel
Comment[tr]=Color lines oyunu
Comment[uk]=Гра "Кольорові ряди"
Comment[vi]=Trò chơi ColorLines
Comment[zh_TW]=Color lines 遊戲
Exec=glines
Icon=glines.png
Terminal=false
Type=Application
Categories=GNOME;Application;Game;PuzzleGame;
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-games
X-GNOME-Bugzilla-Component=glines
StartupNotify=true

View File

@ -0,0 +1,8 @@
[Desktop Entry]
Encoding=UTF-8
Name=Hidden
Comment=You shouldn't see this
Exec=hidden
Type=Application
Categories=GNOME;Application;TextEditor;
NoDisplay=true

View File

@ -0,0 +1,5 @@
[Desktop Entry]
Encoding=UTF-8
Name=Hidden
Type=Directory
NoDisplay=true

View File

@ -0,0 +1,30 @@
[Desktop Entry]
Encoding=UTF-8
GenericName=Advanced Text Editor
GenericName[cy]=Golygydd Testun Uwch
GenericName[da]= Avanceret teksteditor
GenericName[el]=Προχωρημένος διορθωτής κειμένου
GenericName[es]=Editor de texto avanzado
GenericName[fa]=ویرایشگر متن پیشرفته
GenericName[hu]=szövegszerkesztő
GenericName[pt_BR]=Editor de Texto Avançado
GenericName[sr]=Napredni editor teksta
GenericName[sv]=Avancerad texteditor
BinaryPattern=
Name=Kate
Name[ar]=كيت
Name[bg]=Редактор Kate
Name[eo]=Kodredaktilo
Name[fa]=کِیت
Name[ko]=카테
Name[ru]=Редактор Kate
MimeType=text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;text/rdf;
Exec=kate %u
TerminalOptions=
Icon=kate
Path=
DocPath=kate/index.html
Type=Application
Terminal=0
X-DCOP-ServiceType=Multi
Categories=Qt;KDE;TextEditor

View File

@ -0,0 +1,69 @@
[Desktop Entry]
Encoding=UTF-8
Name=KBabel
Name[af]=Kbabel
Name[ar]=المترجم
Name[eo]=Babelo-tradukilo
Name[ko]=K바벨
Name[pt_BR]=Editor de POTFiles
Name[sv]=Kbabel
Name[xx]=xxKBabelxx
Exec=kbabel %i %m -caption "%c" %U
Icon=kbabel
MiniIcon=kbabel
Type=Application
DocPath=kbabel/index.html
MimeType=application/x-gettext;
GenericName=Translation Tool
GenericName[af]=Vertaling Program
GenericName[ar]=أداة الترجمة
GenericName[bg]=Инструменти за Превод
GenericName[bs]=Alat za prevođenje
GenericName[ca]=Eina de traducció
GenericName[cs]=Překladatelský nástroj
GenericName[cy]=Erfyn Cyfieithu
GenericName[da]=Oversættelsesværktøj
GenericName[de]=Übersetzungsprogramm
GenericName[el]=Εργαλείο μετάφρασης
GenericName[eo]=Tradukilo por Qt-programoj
GenericName[es]=Herramienta de traducción
GenericName[et]=Tõlkimise rakendus
GenericName[eu]=Itzulpenerako Tresnak
GenericName[fi]=Käännöstyökalu
GenericName[fo]=Umsetingaramboð
GenericName[fr]=Outil de traduction
GenericName[he]=כלי תרגום
GenericName[hr]=Uslužni program za prevođenje
GenericName[hu]=segédprogram fordítóknak
GenericName[it]=Strumento per le traduzioni
GenericName[ja]=翻訳ツール
GenericName[lt]=Vertimo įrankis
GenericName[lv]=Tulkošanas Rīks
GenericName[mt]=Għodda tat-traduzzjoni
GenericName[nb]=Oversettingsverktøy
GenericName[nl]=vertaalprogramma
GenericName[nn]=Omsetjingsverktøy
GenericName[nso]=Sebereka sa Thlathollo
GenericName[pl]=Narzędzie dla tłumaczy
GenericName[pt]=Ferramenta de Tradução
GenericName[pt_BR]=Ferramenta de Tradução
GenericName[ro]=Utilitar de traducere
GenericName[ru]=Утилита локализации приложений
GenericName[sk]=Prekladací nástroj
GenericName[sl]=Orodje za prevajanje
GenericName[sv]=Översättningsverktyg
GenericName[ta]=¦Á¡Æ¢¦ÀÂ÷ôÒì ¸ÕÅ¢
GenericName[th]=เครื่องมือแปลภาษา
GenericName[tr]=Çeviri Aracı
GenericName[uk]=Засіб для перекладів
GenericName[ven]=Zwishumiswa zwau Dologa
GenericName[vi]=Công cụ dịch
GenericName[xh]=Isixhobo Soguqulelo lomsebenzi kolunye ulwimi
GenericName[xx]=xxTranslation Toolxx
GenericName[zh_CN]=翻译工具
GenericName[zh_TW]=翻譯工具
GenericName[zu]=Ithuluzi Lokuguqulela
Terminal=0
X-KDE-StartupNotify=true
X-DCOP-ServiceType=Unique
Categories=Qt;KDE;Development

View File

@ -0,0 +1,33 @@
[Desktop Entry]
Encoding=UTF-8
BinaryPattern=kedit;
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
GenericName=Simple Text Editor
GenericName[ca]=Editor de text
GenericName[cs]=Jednoduchý textový editor
GenericName[da]=Simpel teksteditor
GenericName[es]=Editor de texto sencillo
GenericName[fr]=Éditeur de texte élémentaire
GenericName[pt_BR]=Editor de Texto Simples
GenericName[sv]=Enkel texteditor
GenericName[wa]=Simpe aspougneu di tecse
Exec=kedit -caption "%c" %i %m %u
Icon=kedit
TerminalOptions=
Path=
DocPath=kedit/index.html
Type=Application
Terminal=0
Name=KEdit
Name[af]=Kredigeer
Name[eo]=Redaktilo
Name[hr]=Uređivač
Name[lv]=KRediģēt
Name[pl]=Edytor
Name[sv]=Kedit
Name[th]=แก้ไขข้อความ
Name[ven]=U sengulusa ha K
Name[xh]=Abahleli Be K
Name[zh_TW]=KDE 編輯器
X-KDE-StartupNotify=true
X-DCOP-ServiceType=Multi

View File

@ -0,0 +1,84 @@
[Desktop Entry]
Encoding=UTF-8
GenericName=Text Editor
GenericName[af]=Teks Redigeerder
GenericName[ar]=محرر نصوص
GenericName[be]=Тэкставы рэдактар
GenericName[bg]=Текстов Редактор
GenericName[bs]=Tekst editor
GenericName[ca]=Editor de text
GenericName[cs]=Textový editor
GenericName[cy]=Golygydd Testun
GenericName[da]= Teksteditor
GenericName[de]=Texteditor
GenericName[el]=Διορθωτής Κειμένου
GenericName[eo]=Tekstredaktilo
GenericName[es]=Editor de texto
GenericName[et]=Tekstiredaktor
GenericName[eu]=Testu Editorea
GenericName[fa]=ویرایشگر متن
GenericName[fi]=Tekstieditori
GenericName[fo]=Tekstritil
GenericName[fr]=Éditeur de texte
GenericName[he]=עורך טקסט
GenericName[hr]=Uređivač teksta
GenericName[hu]=szövegszerkesztő
GenericName[is]=Textaritill
GenericName[it]=Editor di testi
GenericName[ja]=テキストエディタ
GenericName[ko]=글월 편집기
GenericName[lo]=ເຄື່ອງມືແກ້ໄຂຂໍ້ຄວາມ
GenericName[lt]=Teksto redaktorius
GenericName[lv]=Teksta Redaktors
GenericName[mn]=Текст боловсруулагч
GenericName[mt]=Editur tat-test
GenericName[nb]=Skriveprogram
GenericName[nl]=teksteditor
GenericName[nn]=Skriveprogram
GenericName[nso]=Mofetosi wa Sengwalwana
GenericName[pl]=Edytor tekstowy
GenericName[pt]=Editor de Texto
GenericName[pt_BR]=Editor de Texto
GenericName[ro]=Editor de text
GenericName[ru]=Текстовый редактор
GenericName[sk]=Textový editor
GenericName[sl]=Urejevalnik besedil
GenericName[sr]=Editor teksta
GenericName[ss]=Sihleli sembhalo
GenericName[sv]=Texteditor
GenericName[ta]=¯¨Ã ¦¾¡ÌôÀ¡Ç÷
GenericName[th]=เครื่องมือแก้ไขข้อความ
GenericName[tr]=Metin Düzenleyici
GenericName[uk]=Редактор текстів
GenericName[ven]=Musengulusi wa Manwalwa
GenericName[vi]=Trình soạn văn bản
GenericName[wa]=Aspougneu di tecse
GenericName[xh]=Umhleli Wombhalo
GenericName[zh_CN]=文本编辑器
GenericName[zh_TW]=文字編輯器
GenericName[zu]=Umlungisi wombhalo
BinaryPattern=
Name=KWrite
Name[af]=Kskryf
Name[ar]=كاتب كيدي
Name[eo]=Simpla kodredaktilo
Name[fa]=نوشتار K
Name[fo]=KSkriva
Name[lo]=Kwrite
Name[lv]=KRakstīt
Name[nso]=KNgwala
Name[ru]=Редактор KWrite
Name[sv]=Kwrite
Name[ven]=Nwala ha K
MimeType=text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;text/x-diff;text/rdf;
Exec=kwrite %u
X-KDE-StartupNotify=true
TerminalOptions=
Icon=kwrite
Path=
DocPath=kwrite/index.html
Type=Application
Terminal=0
InitialPreference=8
X-DCOP-ServiceType=Multi
Categories=Qt;KDE;TextEditor

View File

@ -0,0 +1,86 @@
[Desktop Entry]
Encoding=UTF-8
Name=Mahjongg
Name[am]=ማህጆንግ
Name[be]=Маджонг
Name[bg]=Махджонг
Name[bn]=মাহজং
Name[ca]=Mahjongg
Name[cs]=Mahjongg
Name[da]=Mahjongg
Name[de]=Mahjongg
Name[el]=Mahjongg
Name[es]=Mahjongg
Name[et]=Mahjongg
Name[fa]=ماهجونگ
Name[fi]=Mahjongg
Name[fr]=Mahjongg
Name[gl]=Mahjongg
Name[he]=Mahjongg
Name[hu]=Mahjongg
Name[it]=Mahjongg
Name[ja]=GNOME 上海
Name[ko]=그놈 마작
Name[lt]=Mahjongg
Name[lv]=Mahjongg
Name[mn]=Маджонг
Name[ms]=Mahjongg
Name[nl]=Mahjongg
Name[no]=Mahjongg
Name[pl]=Mahjongg
Name[pt]=Mahjongg
Name[pt_BR]=Mahjongg
Name[ru]=Маджонг
Name[sk]=Mahjongg
Name[sl]=Mahjongg
Name[sv]=Mah Jong
Name[tr]=Mahjongg
Name[uk]=Магджонґ
Name[vi]=Mahjongg
Name[wa]=Mahjongg
Name[zh_CN]=堆麻将
Name[zh_TW]=上海麻將
Comment=Mahjongg game
Comment[am]=የማህጆንግ ጨዋታ
Comment[be]=Гульня Маджонг
Comment[bg]=Игра на Махджонг
Comment[bn]=মাহজং খেলা
Comment[ca]=Joc del Mahjongg
Comment[cs]=Hra Mahjongg
Comment[da]=Mahjonggspil
Comment[de]=Mahjongg-Spiel
Comment[el]=Παιχνίδι Mahjongg
Comment[es]=Juego Mahjongg
Comment[et]=Mäng nimega mahjongg
Comment[fa]=بازی ماهجونگ
Comment[fi]=Mahjongg-peli
Comment[fr]=Jeu de Mahjongg
Comment[he]=משחק Mahjongg
Comment[hu]=Mahjongg játék
Comment[it]=Gioco Mahjongg
Comment[ja]=麻雀ゲーム
Comment[lv]=Mahjongg spēle
Comment[mn]=Mahjongg тоглоом
Comment[ms]=Permainan Mahjongg
Comment[nl]=Mahjongg
Comment[no]=Mahjongg-spill
Comment[pl]=Gra Mahjongg
Comment[pt]=Jogo Mahjongg
Comment[pt_BR]=Jogo Mahjongg
Comment[ru]=Игра Маджонг
Comment[sk]=Hra Mahjongg
Comment[sl]=Igra Mahjongg
Comment[sv]=Mah Jong-spel
Comment[tr]=Mahjongg oyunu
Comment[uk]=Гра "Магджонґ"
Comment[vi]=Trò chơi Mahjongg
Comment[zh_TW]=上海麻將遊戲
Exec=mahjongg
Icon=gnome-mahjongg.png
Terminal=false
Type=Application
Categories=GNOME;Application;Development;
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-games
X-GNOME-Bugzilla-Component=mahjongg
StartupNotify=true

View File

@ -0,0 +1,86 @@
[Desktop Entry]
Encoding=UTF-8
Name=Mahjongg
Name[am]=ማህጆንግ
Name[be]=Маджонг
Name[bg]=Махджонг
Name[bn]=মাহজং
Name[ca]=Mahjongg
Name[cs]=Mahjongg
Name[da]=Mahjongg
Name[de]=Mahjongg
Name[el]=Mahjongg
Name[es]=Mahjongg
Name[et]=Mahjongg
Name[fa]=ماهجونگ
Name[fi]=Mahjongg
Name[fr]=Mahjongg
Name[gl]=Mahjongg
Name[he]=Mahjongg
Name[hu]=Mahjongg
Name[it]=Mahjongg
Name[ja]=GNOME 上海
Name[ko]=그놈 마작
Name[lt]=Mahjongg
Name[lv]=Mahjongg
Name[mn]=Маджонг
Name[ms]=Mahjongg
Name[nl]=Mahjongg
Name[no]=Mahjongg
Name[pl]=Mahjongg
Name[pt]=Mahjongg
Name[pt_BR]=Mahjongg
Name[ru]=Маджонг
Name[sk]=Mahjongg
Name[sl]=Mahjongg
Name[sv]=Mah Jong
Name[tr]=Mahjongg
Name[uk]=Магджонґ
Name[vi]=Mahjongg
Name[wa]=Mahjongg
Name[zh_CN]=堆麻将
Name[zh_TW]=上海麻將
Comment=Mahjongg game
Comment[am]=የማህጆንግ ጨዋታ
Comment[be]=Гульня Маджонг
Comment[bg]=Игра на Махджонг
Comment[bn]=মাহজং খেলা
Comment[ca]=Joc del Mahjongg
Comment[cs]=Hra Mahjongg
Comment[da]=Mahjonggspil
Comment[de]=Mahjongg-Spiel
Comment[el]=Παιχνίδι Mahjongg
Comment[es]=Juego Mahjongg
Comment[et]=Mäng nimega mahjongg
Comment[fa]=بازی ماهجونگ
Comment[fi]=Mahjongg-peli
Comment[fr]=Jeu de Mahjongg
Comment[he]=משחק Mahjongg
Comment[hu]=Mahjongg játék
Comment[it]=Gioco Mahjongg
Comment[ja]=麻雀ゲーム
Comment[lv]=Mahjongg spēle
Comment[mn]=Mahjongg тоглоом
Comment[ms]=Permainan Mahjongg
Comment[nl]=Mahjongg
Comment[no]=Mahjongg-spill
Comment[pl]=Gra Mahjongg
Comment[pt]=Jogo Mahjongg
Comment[pt_BR]=Jogo Mahjongg
Comment[ru]=Игра Маджонг
Comment[sk]=Hra Mahjongg
Comment[sl]=Igra Mahjongg
Comment[sv]=Mah Jong-spel
Comment[tr]=Mahjongg oyunu
Comment[uk]=Гра "Магджонґ"
Comment[vi]=Trò chơi Mahjongg
Comment[zh_TW]=上海麻將遊戲
Exec=mahjongg
Icon=gnome-mahjongg.png
Terminal=false
Type=Application
Categories=GNOME;Application;Game;BoardGame;
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-games
X-GNOME-Bugzilla-Component=mahjongg
StartupNotify=true

View File

@ -0,0 +1,10 @@
[Desktop Entry]
Encoding=UTF-8
Name=Quanta Plus
Exec=quanta
Icon=quanta
Type=Application
MimeType=text/html
DocPath=quanta/index.html
Comment=Web Development Environment
Categories=Qt;KDE;Development

View File

@ -0,0 +1,12 @@
#!/usr/bin/perl
# This script performs expansion of environment variables of the form ${HOME}
while(<>)
{
while (($a) = ($_ =~ /[^\$]*\$\{([^\}]*)\}.*/))
{
s/([^\$]*)(\$\{$a\})(.*)/$1$ENV{$a}$3/;
}
printf $_;
}

View File

@ -0,0 +1,200 @@
#!/bin/bash
# these vars are usable *only* for debugging purposes; they're not allowed as part of the spec, thus don't use them.
# set MENU_FAKE_PREFIX to a non empty val to force testing for if things would succeed if XDG_MENU_PREFIX were
# implemented
# set MENU_FAKE_APPLICATIONS to force a work around for applications-merged postfixing.
#
function installData()
{
local DIR="$1"
shift
mkdir -p "${DIR}"
for file in $*; do
cp "data/${file}" "${DIR}"
WIPE[$WIPE_IDX]="${DIR}/${file}"
WIPE_IDX=$(( $WIPE_IDX + 1 ))
done
}
function installDataAs()
{
local DIR="$1"
mkdir -p "${DIR}"
cp "data/$2" "${DIR}/$3"
WIPE[${WIPE_IDX}]="${DIR}/${3}"
WIPE_IDX=$(( $WIPE_IDX + 1 ))
}
setup_local_xdg_vars() {
export XDG_CONFIG_HOME="${MENUTESTDIR}/xdg_config_home"
export XDG_DATA_HOME="${MENUTESTDIR}/xdg_data_home"
export XDG_CONFIG_DIR="${MENUTESTDIR}/xdg_config_dir"
export XDG_CONFIG_DIRS="$XDG_CONFIG_DIR:${XDG_CONFIG_DIRS}2"
export XDG_DATA_DIR="${MENUTESTDIR}/xdg_data_dir"
export XDG_DATA_DIRS="$XDG_DATA_DIR:${XDG_DATA_DIR}2"
export XDG_CACHE_HOME="${MENUTESTDIR}/xdg_cache_home"
}
setup_xdg_system_data_vars()
{
export XDG_CACHE_HOME="${XDG_DATA_HOME:-${HOME}/.cache}"
export XDG_DATA_HOME="${XDG_DATA_HOME:-${HOME}/.local/share}"
export XDG_CONFIG_DIR="${XDG_CONFIG_DIR:-/etc/xdg}"
if [ -z "${XDG_DATA_DIRS}" ]; then
export XDG_DATA_DIRS="/usr/local/share:/usr/share"
fi
export XDG_DATA_DIRS="${XDG_DATA_DIRS}:${MENUTESTDIR}/xdg_cache_dir"
export XDG_DATA_DIR="${XDG_DATA_DIRS//*:}"
if [ -z "${XDG_CONFIG_DIRS}" ]; then
export XDG_CONFIG_DIRS="/etc/xdg"
fi
export XDG_CONFIG_DIR="${XDG_CONFIG_DIRS/:*}"
}
run_test() {
if [ -z "$1" ]; then
echo "requires name of test directory to run"
exit 1
fi
local TEST="$1"
rm -rf "${MENUTESTDIR}" 2> /dev/null
mkdir "${MENUTESTDIR}"
RESULT="${TEST}/result"
(
unset WIPE WIPE_IDX
declare -a WIPE
declare -i WIPE_IDX=0
unset MODE
. ${TEST}/test
echo ">>> Running test ${TEST}, purpose $TEST_PURPOSE"
if [ "${MODE:-local}" == "local" ]; then
setup_local_xdg_vars
elif [ "${MODE}" == "system_data" ]; then
setup_xdg_system_data_vars
else
echo "!!! unknown MODE from $TEST, bailing"
exit -1
fi
test_code
declare -i IDX=0
while [ $WIPE_IDX -gt $IDX ]; do
echo "${WIPE[$IDX]}" >> "${MENUTESTDIR}/wipe"
IDX=$(( $IDX + 1 ))
done
DEBUG_OVERRIDES=''
[ -n "$MENU_FAKE_PREFIX" ] && DEBUG_OVERRIDES=.menu
[ -n "$MENU_FAKE_APPLICATIONS" ] && DEBUG_OVERIDES="${DEBUG_OVERRIDES} -merged"
for x in dir home; do
for y in ${DEBUG_OVERRIDES}; do
if [ -e "${MENUTESTDIR}/xdg_config_${x}/menus/applications${y}" ]; then
ln -s applications${y} "${MENUTESTDIR}/xdg_config_${x}/menus/kde-applications${y}"
ln -s applications${y} "${MENUTESTDIR}/xdg_config_${x}/menus/gnome-applications${y}"
fi
done
unset y
done
unset x DEBUG_OVERRIDES
$MENUTEST > ${MENUTESTDIR}/run-result 2> ${MENUTESTDIR}/log
if [ -e "${RESULT}" ]; then
./expand "${RESULT}" > "${MENUTESTDIR}/required-result"
fi
if [ "$(type -t interpret_results)" == "function" ]; then
interpret_results
else
default_interpret_results
fi
ret=$?
if [ -e "${MENUTESTDIR}/wipe" ]; then
cat "${MENUTESTDIR}/wipe" | while read l; do
[ -z "$l" ] && continue
rm "$l"
done
fi
return $ret
)
}
default_interpret_results() {
if [ ! -e "${RESULT}" ]; then
echo "!!! Result file (${RESULT}) for ${TEST} missing"
echo '>>> Failed'
return 1
elif diff -q "${MENUTESTDIR}/run-result" "${MENUTESTDIR}/required-result" > /dev/null; then
echo '>>> OK'
return 0
fi
sort "${MENUTESTDIR}/run-result" > "${MENUTESTDIR}/run-result.sorted"
sort "${MENUTESTDIR}/required-result" > "${MENUTESTDIR}/required-result.sorted"
if diff -u "${MENUTESTDIR}/run-result.sorted" "${MENUTESTDIR}/required-result.sorted" > "${MENUTESTDIR}/result.diff"; then
echo '>>> OK (different order)'
return 0
fi
grep "${MENUTESTDIR}" "${MENUTESTDIR}/run-result" > "${MENUTESTDIR}/run-result.filtered" 2> /dev/null
if diff -q "${MENUTESTDIR}/run-result.filtered" "${MENUTESTDIR}/required-result" > /dev/null; then
echo '>>> OK (additional system items)'
return 0
fi
grep "${MENUTESTDIR}" "${MENUTESTDIR}/run-result.sorted" > "${MENUTESTDIR}/required-result.filtered" 2> /dev/null
if diff -u "${MENUTESTDIR}/run-result.filtered" "${MENUTESTDIR}/required-result.sorted" > "${MENUTESTDIR}/result.diff"; then
echo '>>> OK (different order, additional system items)'
return 0
fi
echo '>>> Failed'
cat "${MENUTESTDIR}/result.diff"
cat "${MENUTESTDIR}/log"
return 1
}
if [ -z "${TESTS}" ]; then
export TESTS=`ls tests/*/test | sed -e 's:^\(\./\)\?tests/\+::' -e 's:/\+test$::'`
fi
if [ -z "$TET_RUN" ]; then
if [ "x${MENUTEST}" == "x" ]; then
echo 'To run the test set $MENUTEST to your menu-spec implementation.'
exit 1
fi
if [ "x${MENUTESTDIR}" == "x" ]; then
MENUTESTDIR=/tmp/menutestdir
echo Using ${MENUTESTDIR} as test directory, override with \$MENUTESTDIR.
else
echo Using ${MENUTESTDIR} as test directory.
fi
export MENUTESTDIR
export USER=${USER:-test}
FAILED=
SUCCEEDED=
for TESTCASE in ${TESTS}; do
if [ "${TESTCASE}" == "CVS" ]; then
continue
fi
echo
if ! run_test "tests/${TESTCASE}" ${MODE}; then
FAILED="${FAILED} ${TESTCASE}"
else
SUCCEEDED="${SUCCEEDED} ${TESTCASE}"
fi
done
echo "OK tests: ${SUCCEEDED}"
[ -n "${FAILED}" ] && echo "Failed tests: ${FAILED}"
echo "$(echo ${SUCCEEDED} | wc -w) tests passed, $(echo ${FAILED} | wc -w) tests failed"
[ -z "${FAILED}" ] && exit 0
exit 1
fi

View File

@ -0,0 +1,4 @@
Applications/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop
Applications/ gataxx.desktop ${XDG_DATA_DIR}/applications/gataxx.desktop
Applications/ glines.desktop ${XDG_DATA_DIR}/applications/glines.desktop
Applications/ mahjongg.desktop ${XDG_DATA_DIR}/applications/mahjongg.desktop

View File

@ -0,0 +1,26 @@
TEST_PURPOSE="<All> Keyword"
test_code() {
# Generate applications.menu
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<!-- Search the default locations -->
<DefaultAppDirs/>
<Menu>
<Name>Applications</Name>
<Include>
<All/>
</Include>
</Menu>
</Menu>
EOF
# Install .desktop files
installData ${XDG_DATA_DIR}/applications gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop
}

View File

@ -0,0 +1 @@
Applications/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop

View File

@ -0,0 +1,29 @@
TEST_PURPOSE="<And> Keyword"
test_code() {
# Generate applications.menu
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<!-- Search the default locations -->
<DefaultAppDirs/>
<Menu>
<Name>Applications</Name>
<Include>
<And>
<Filename>freecell.desktop</Filename>
<Category>Game</Category>
</And>
</Include>
</Menu>
</Menu>
EOF
# Install .desktop files
installData ${XDG_DATA_DIR}/applications gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop
}

View File

@ -0,0 +1,3 @@
Applications/ KEdit.desktop ${XDG_CONFIG_DIR}/menus/apps/KEdit.desktop
Applications/ kate.desktop ${XDG_CONFIG_DIR}/menus/apps/kate.desktop
Applications/ kwrite.desktop ${XDG_CONFIG_DIR}/menus/apps/kwrite.desktop

View File

@ -0,0 +1,27 @@
TEST_PURPOSE="<AppDir> relative path tag ..."
test_code() {
# Generate applications.menu
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<!-- Search the default locations -->
<AppDir>apps</AppDir>
<Menu>
<Name>Applications</Name>
<Include>
<Category>TextEditor</Category>
</Include>
</Menu>
</Menu>
EOF
# Install .desktop files
installData "${XDG_CONFIG_DIR}/menus/apps" kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop
installDataAs "${XDG_CONFIG_DIR}/menus/apps" kwrite.desktop should_be_ignored.notdesktop
}

View File

@ -0,0 +1,3 @@
Applications/ KEdit.desktop ${XDG_CONFIG_DIR}/menus/apps/KEdit.desktop
Applications/ kate.desktop ${XDG_CONFIG_DIR}/menus/apps/kate.desktop
Applications/ kwrite.desktop ${XDG_CONFIG_DIR}/menus/apps/kwrite.desktop

View File

@ -0,0 +1,4 @@
. tests/AppDir-relative/test
export PATH_EXPANSION='${XDG_CONFIG_DIR}/menus/'
TEST_PURPOSE="<AppDir> absolute path"

View File

@ -0,0 +1,3 @@
Editors/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop
Editors/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop
Editors/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop

View File

@ -0,0 +1,29 @@
TEST_PURPOSE="<Category> tag"
test_code() {
# Generate applications.menu
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<!-- Search the default locations -->
<DefaultAppDirs/>
<Menu>
<Name>Editors</Name>
<Include>
<Category>TextEditor</Category>
<!-- note it's lowercase, this is intentional to verify
it's a case sensitive implementation -->
<Category>application</Category>
</Include>
</Menu>
</Menu>
EOF
# Install .desktop files, freecell is daft but intentional to verify category support is case sensitive
installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop kate.desktop freecell.desktop
}

View File

@ -0,0 +1,5 @@
Applications/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop
Applications/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop
Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop
Development/ kbabel.desktop ${XDG_DATA_DIR}/applications/kbabel.desktop
Development/ quanta.desktop ${XDG_DATA_DIR}/applications/quanta.desktop

View File

@ -0,0 +1,43 @@
TEST_PURPOSE="<DefaultMergeDirs> tag ..."
test_code() {
# Generate applications.menu
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<DefaultAppDirs/>
<DefaultMergeDirs/>
<Menu>
<Name>Applications</Name>
<Include>
<Category>TextEditor</Category>
</Include>
</Menu>
</Menu>
EOF
mkdir ${XDG_CONFIG_DIR}/menus/applications-merged/
./expand > ${XDG_CONFIG_DIR}/menus/applications-merged/test.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<Menu>
<Name>Development</Name>
<Include>
<Category>Development</Category>
</Include>
</Menu>
</Menu>
EOF
# Install .desktop files
installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop
}

View File

@ -0,0 +1,2 @@
BoardGames/ gataxx.desktop ${XDG_DATA_DIR}/applications/gataxx.desktop
BoardGames/ mahjongg.desktop ${XDG_DATA_DIR}/applications/mahjongg.desktop

View File

@ -0,0 +1,35 @@
TEST_PURPOSE="<Deleted> tag"
test_code() {
# Generate applications.menu
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<!-- Search the default locations -->
<DefaultAppDirs/>
<Menu>
<Name>BoardGames</Name>
<Include>
<Category>BoardGame</Category>
</Include>
</Menu>
<Menu>
<Name>Games</Name>
<Include>
<Category>Game</Category>
</Include>
<Deleted/>
<NotDeleted/>
<Deleted/>
</Menu>
</Menu>
EOF
# Install .desktop files
installData ${XDG_DATA_DIR}/applications gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop
}

View File

@ -0,0 +1,4 @@
Applications/ company-games-freecell.desktop ${XDG_DATA_DIR}/applications/company/games/freecell.desktop
Applications/ company-games-gataxx.desktop ${XDG_DATA_DIR}/applications/company/games/gataxx.desktop
Applications/ company-games-glines.desktop ${XDG_DATA_DIR}/applications/company/games/glines.desktop
Applications/ company-games-mahjongg.desktop ${XDG_DATA_DIR}/applications/company/games/mahjongg.desktop

View File

@ -0,0 +1,26 @@
TEST_PURPOSE="DesktopFileIDs in submenus"
test_code() {
# Generate applications.menu
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<!-- Search the default locations -->
<DefaultAppDirs/>
<Menu>
<Name>Applications</Name>
<Include>
<Category>Game</Category>
</Include>
</Menu>
</Menu>
EOF
# Install .desktop files
installData ${XDG_DATA_DIR}/applications/company/games gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop
}

View File

@ -0,0 +1,3 @@
Apps/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop
Apps/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop
Apps/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop

View File

@ -0,0 +1,29 @@
TEST_PURPOSE="<Directory> tag ..."
test_code() {
# Generate applications.menu
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<!-- Search the default locations -->
<DefaultAppDirs/>
<DefaultDirectoryDirs/>
<Menu>
<Name>Applications</Name>
<Directory>apps.directory</Directory>
<Include>
<Category>TextEditor</Category>
</Include>
</Menu>
</Menu>
EOF
# Install .desktop files
installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop
installData ${XDG_DATA_DIR}/desktop-directories apps.directory
}

View File

@ -0,0 +1,3 @@
Apps/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop
Apps/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop
Apps/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop

View File

@ -0,0 +1,28 @@
TEST_PURPOSE="relative <DirectoryDir> tag ..."
test_code() {
# Generate applications.menu
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<!-- Search the default locations -->
<DefaultAppDirs/>
<DirectoryDir>${PATH_EXPANSION}desktop-directories</DirectoryDir>
<Menu>
<Name>Applications</Name>
<Directory>apps.directory</Directory>
<Include>
<Category>TextEditor</Category>
</Include>
</Menu>
</Menu>
EOF
# Install .desktop files
installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop
installData ${XDG_CONFIG_DIR}/menus/desktop-directories apps.directory
}

View File

@ -0,0 +1,4 @@
. tests/DirectoryDir-relative/test
export PATH_EXPANSION='${XDG_CONFIG_DIR}/menus/'
TEST_PURPOSE="<DirectoryDir> absolute path"

View File

@ -0,0 +1,3 @@
Applications/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop
Applications/ gataxx.desktop ${XDG_DATA_DIR}/applications/gataxx.desktop
Applications/ mahjongg.desktop ${XDG_DATA_DIR}/applications/mahjongg.desktop

View File

@ -0,0 +1,32 @@
TEST_PURPOSE="<Exclude> Keyword"
test_code() {
# Generate applications.menu
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<!-- Search the default locations -->
<DefaultAppDirs/>
<Menu>
<Name>Applications</Name>
<Include>
<Or>
<Filename>freecell.desktop</Filename>
<Category>Game</Category>
</Or>
</Include>
<Exclude>
<Filename>glines.desktop</Filename>
</Exclude>
</Menu>
</Menu>
EOF
# Install .desktop files
installData ${XDG_DATA_DIR}/applications gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop
}

View File

@ -0,0 +1 @@
Applications/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop

View File

@ -0,0 +1,26 @@
TEST_PURPOSE="<Filename> tag"
test_code() {
# Generate applications.menu
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<!-- Search the default locations -->
<DefaultAppDirs/>
<Menu>
<Name>Applications</Name>
<Include>
<Filename>freecell.desktop</Filename>
</Include>
</Menu>
</Menu>
EOF
# Install .desktop files
installData ${XDG_DATA_DIR}/applications gataxx.desktop mahjongg.desktop freecell.desktop glines.desktop
}

View File

@ -0,0 +1,2 @@
Editors/ gideon-legacy.desktop ${LEGACY_DIR}/Development/gideon-legacy.desktop
/ Home.desktop ${LEGACY_DIR}/Home.desktop

View File

@ -0,0 +1,39 @@
TEST_PURPOSE="move entries from <LegacyDir>"
test_code() {
LEGACY_DIR=${MENUTESTDIR}/legacy_applnk
export LEGACY_DIR
# Generate applications.menu
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<!-- Search the default locations -->
<LegacyDir>${LEGACY_DIR}</LegacyDir>
<DefaultAppDirs/>
<DefaultDirectoryDirs/>
<Menu>
<Name>Development</Name>
<Exclude>
<Filename>gideon-legacy.desktop</Filename>
</Exclude>
</Menu>
<Menu>
<Name>Editors</Name>
<Include>
<Filename>gideon-legacy.desktop</Filename>
</Include>
</Menu>
</Menu>
EOF
# Install .desktop files
installData ${LEGACY_DIR} Home.desktop
installData ${LEGACY_DIR}/Development gideon-legacy.desktop
}

View File

@ -0,0 +1,9 @@
Development/ gideon-legacy.desktop ${LEGACY_DIR}/Development/gideon-legacy.desktop
Development/ kbabel.desktop ${LEGACY_DIR}/Development/kbabel.desktop
Development/ quanta.desktop ${LEGACY_DIR}/Development/quanta.desktop
Editors/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop
Editors/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop
Editors/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop
/ Help.desktop ${LEGACY_DIR}/Help.desktop
/ Home.desktop ${LEGACY_DIR}/Home.desktop
/ Kfind.desktop ${LEGACY_DIR}/Kfind.desktop

View File

@ -0,0 +1,42 @@
TEST_PURPOSE="Simple <LegacyDir> test"
test_code() {
LEGACY_DIR=${MENUTESTDIR}/legacy_applnk
export LEGACY_DIR
# Generate applications.menu
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<!-- Search the default locations -->
<LegacyDir>${LEGACY_DIR}</LegacyDir>
<DefaultAppDirs/>
<DefaultDirectoryDirs/>
<Menu>
<Name>Editors</Name>
<Directory>kde-editors.directory</Directory>
<Include>
<Category>TextEditor</Category>
</Include>
</Menu>
<Menu>
<Name>Development</Name>
<Directory>kde-development.directory</Directory>
<Include>
<Category>Development</Category>
</Include>
</Menu>
</Menu>
EOF
# Install .desktop files
installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop kate.desktop
installData ${LEGACY_DIR}/Development gideon-legacy.desktop kbabel.desktop quanta.desktop
installData ${LEGACY_DIR} Kfind.desktop Home.desktop Help.desktop
}

View File

@ -0,0 +1 @@
Editors/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop

View File

@ -0,0 +1,46 @@
TEST_PURPOSE="Merge Two Menus and a Legacy Menu"
test_code() {
LEGACY_DIR=${MENUTESTDIR}/legacy_applnk
export LEGACY_DIR
# Generate applications.menu
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<!-- Search the default locations -->
<DefaultAppDirs/>
<DefaultDirectoryDirs/>
<LegacyDir>${LEGACY_DIR}</LegacyDir>
<Menu>
<Name>Development</Name>
<Include>
<Filename>kate.desktop</Filename>
</Include>
</Menu>
<Menu>
<Name>Development</Name>
<Include>
<Filename>KEdit.desktop</Filename>
</Include>
<Deleted/>
</Menu>
<Menu>
<Name>Editors</Name>
<Include>
<Filename>kwrite.desktop</Filename>
</Include>
</Menu>
</Menu>
EOF
# Install .desktop files
installData ${LEGACY_DIR}/Development gideon-legacy.desktop
installData ${XDG_DATA_DIR}/applications kate.desktop kwrite.desktop KEdit.desktop
}

View File

@ -0,0 +1,3 @@
. tests/MergeDir-relative/test
export PATH_EXPANSION='${XDG_CONFIG_DIR}/menus/'
export TEST_PURPOSE="<MergeDir> absolute path test"

View File

@ -0,0 +1,5 @@
Applications/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop
Applications/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop
Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop
Development/ kbabel.desktop ${XDG_DATA_DIR}/applications/kbabel.desktop
Development/ quanta.desktop ${XDG_DATA_DIR}/applications/quanta.desktop

View File

@ -0,0 +1,61 @@
TEST_PURPOSE="<MergeDir> relative path ..."
test_code() {
# Generate applications.menu
mkdir -p "${XDG_CONFIG_DIR}/menus"
./expand > "${XDG_CONFIG_DIR}/menus/applications.menu" <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<DefaultAppDirs/>
<MergeDir>${PATH_EXPANSION}applications-merged</MergeDir>
<Menu>
<Name>Applications</Name>
<Include>
<Category>TextEditor</Category>
</Include>
</Menu>
</Menu>
EOF
mkdir "${XDG_CONFIG_DIR}/menus/applications-merged/"
./expand > "${XDG_CONFIG_DIR}/menus/applications-merged/test.menu" <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<Menu>
<Name>Development</Name>
<Include>
<Category>Development</Category>
</Include>
</Menu>
</Menu>
EOF
# intentional crap entry to verify it does _not_ get picked up
./expand > "${XDG_CONFIG_DIR}/menus/applications-merged/dar.notmenu" <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<Menu>
<Name>testing</Name>
<Include>
<All/>
</Include>
</Menu>
</Menu>
EOF
# Install .desktop files
installData "${XDG_DATA_DIR}/applications" kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop
}

View File

@ -0,0 +1,3 @@
. tests/MergeFile-relative/test
export PATH_EXPANSION='${XDG_CONFIG_DIR}/menus/'
export TEST_PURPOSE="<MergeFile> absolute path"

View File

@ -0,0 +1,5 @@
Applications/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop
Applications/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop
Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop
Development/ kbabel.desktop ${XDG_DATA_DIR}/applications/kbabel.desktop
Development/ quanta.desktop ${XDG_DATA_DIR}/applications/quanta.desktop

View File

@ -0,0 +1,61 @@
TEST_PURPOSE="<MergeFile> tag ..."
test_code() {
# Tests the type attribute in <MergeFile>
# Generate applications.menu
mkdir -p ${XDG_CONFIG_HOME}/menus
./expand > ${XDG_CONFIG_HOME}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<DefaultAppDirs/>
<MergeFile type="parent">${XDG_CONFIG_DIR}/menus/test.menu</MergeFile>
<Menu>
<Name>Applications</Name>
<Include>
<Category>TextEditor</Category>
</Include>
</Menu>
</Menu>
EOF
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/test.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<Menu>
<Name>Games</Name>
<Include>
<Category>Game</Category>
</Include>
</Menu>
</Menu>
EOF
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<Menu>
<Name>Development</Name>
<Include>
<Category>Development</Category>
</Include>
</Menu>
</Menu>
EOF
# Install .desktop files
installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop freecell.desktop glines.desktop
}

View File

@ -0,0 +1,5 @@
Applications/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop
Applications/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop
Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop
Games/ freecell.desktop ${XDG_DATA_DIR}/applications/freecell.desktop
Games/ glines.desktop ${XDG_DATA_DIR}/applications/glines.desktop

View File

@ -0,0 +1,61 @@
TEST_PURPOSE="<MergeFile> tag ..."
test_code() {
# Tests the type attribute in <MergeFile>
# Generate applications.menu
mkdir -p ${XDG_CONFIG_HOME}/menus
./expand > ${XDG_CONFIG_HOME}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<DefaultAppDirs/>
<MergeFile type="path">${XDG_CONFIG_DIR}/menus/test.menu</MergeFile>
<Menu>
<Name>Applications</Name>
<Include>
<Category>TextEditor</Category>
</Include>
</Menu>
</Menu>
EOF
mkdir -p ${XDG_CONFIG_DIR}/menus
./expand > ${XDG_CONFIG_DIR}/menus/test.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<Menu>
<Name>Games</Name>
<Include>
<Category>Game</Category>
</Include>
</Menu>
</Menu>
EOF
./expand > ${XDG_CONFIG_DIR}/menus/applications.menu <<EOF
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
"http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
<Menu>
<Name>KDE</Name>
<Menu>
<Name>Development</Name>
<Include>
<Category>Development</Category>
</Include>
</Menu>
</Menu>
EOF
# Install .desktop files
installData ${XDG_DATA_DIR}/applications kwrite.desktop KEdit.desktop quanta.desktop kate.desktop kbabel.desktop freecell.desktop glines.desktop
}

View File

@ -0,0 +1,5 @@
Applications/ KEdit.desktop ${XDG_DATA_DIR}/applications/KEdit.desktop
Applications/ kate.desktop ${XDG_DATA_DIR}/applications/kate.desktop
Applications/ kwrite.desktop ${XDG_DATA_DIR}/applications/kwrite.desktop
Development/ kbabel.desktop ${XDG_DATA_DIR}/applications/kbabel.desktop
Development/ quanta.desktop ${XDG_DATA_DIR}/applications/quanta.desktop

Some files were not shown because too many files have changed in this diff Show More