mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
Use wm specific code from edelib.
This commit is contained in:
parent
31fbe5bc06
commit
bbbb00fdca
|
@ -10,13 +10,7 @@
|
|||
|
||||
SubDir TOP ede-panel ;
|
||||
|
||||
# make it as library, so applets can use it too
|
||||
ObjectC++Flags Netwm.cpp : $(GLOBALFLAGS) -fPIC $(FLTKINCLUDE) $(EDELIBINCLUDE) ;
|
||||
StaticLibrary libnetwm : Netwm.cpp ;
|
||||
NETWMLIB = -L$(SUBDIR) -lnetwm ;
|
||||
|
||||
EdeProgram ede-panel : Panel.cpp AppletManager.cpp ede-panel.cpp ;
|
||||
LinkAgainst ede-panel : $(NETWMLIB) ;
|
||||
|
||||
if $(OS) != "SOLARIS" {
|
||||
# also must use this flag (on anything but Solaris) or program will crash
|
||||
|
@ -40,7 +34,7 @@ rule PanelApplet
|
|||
Main $(target) : $(>) ;
|
||||
ObjectC++Flags $(>) : $(GLOBALFLAGS) -fPIC $(FLTKINCLUDE) -I [ FDirName $(TOP) ede-panel ] $(EDELIBINCLUDE) ;
|
||||
|
||||
LinkAgainst $(target) : $(NETWMLIB) $(3) $(EDELIBLIB) $(EDELIB_GUI_LIB) $(FLTKLIB) $(STDLIB) ;
|
||||
LinkAgainst $(target) : $(3) $(EDELIBLIB) $(EDELIB_GUI_LIB) $(FLTKLIB) $(STDLIB) ;
|
||||
LINKFLAGS on $(target) = $(linker_stuff) [ on $(target) return $(LINKFLAGS) ] ;
|
||||
|
||||
InstallProgram $(EDE_PANEL_APPLETS_DIR) : $(target) ;
|
||||
|
|
|
@ -1,564 +0,0 @@
|
|||
#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 */
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
#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
|
|
@ -9,9 +9,9 @@
|
|||
#include <edelib/WindowXid.h>
|
||||
#include <edelib/Resource.h>
|
||||
#include <edelib/Util.h>
|
||||
#include <edelib/Netwm.h>
|
||||
|
||||
#include "Panel.h"
|
||||
#include "Netwm.h"
|
||||
|
||||
/* empty space from left and right panel border */
|
||||
#define INITIAL_SPACING 5
|
||||
|
@ -32,10 +32,19 @@ EDELIB_NS_USING(Resource)
|
|||
EDELIB_NS_USING(String)
|
||||
EDELIB_NS_USING(window_xid_create)
|
||||
EDELIB_NS_USING(build_filename)
|
||||
EDELIB_NS_USING(netwm_window_set_strut)
|
||||
EDELIB_NS_USING(netwm_window_set_type)
|
||||
EDELIB_NS_USING(netwm_workarea_get_size)
|
||||
EDELIB_NS_USING(NETWM_WINDOW_TYPE_DOCK)
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
static int xerror_handler(Display *d, XErrorEvent *e) {
|
||||
if(e->request_code == X_GetImage)
|
||||
return 0;
|
||||
|
@ -63,9 +72,8 @@ static int xerror_handler(Display *d, XErrorEvent *e) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
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()));
|
||||
static void make_me_dock(Fl_Window *win) {
|
||||
netwm_window_set_type(fl_xid(win), NETWM_WINDOW_TYPE_DOCK);
|
||||
}
|
||||
|
||||
/* horizontaly centers widget in the panel */
|
||||
|
@ -310,7 +318,7 @@ void Panel::show(void) {
|
|||
XSetErrorHandler((XErrorHandler) xerror_handler);
|
||||
|
||||
/* position it */
|
||||
if(!netwm_get_workarea(X, Y, W, H))
|
||||
if(!netwm_workarea_get_size(X, Y, W, H))
|
||||
Fl::screen_xywh(X, Y, W, H);
|
||||
|
||||
screen_x = X;
|
||||
|
@ -323,16 +331,16 @@ void Panel::show(void) {
|
|||
size(W, DEFAULT_PANEL_H);
|
||||
|
||||
do_layout();
|
||||
window_xid_create(this, netwm_make_me_dock);
|
||||
window_xid_create(this, make_me_dock);
|
||||
|
||||
/* position it, this is done after XID was created */
|
||||
if(vpos == PANEL_POSITION_BOTTOM) {
|
||||
position(screen_x, screen_h - h());
|
||||
netwm_set_window_strut(this, 0, 0, 0, h());
|
||||
netwm_window_set_strut(fl_xid(this), 0, 0, 0, h());
|
||||
} else {
|
||||
/* FIXME: this does not work well with edewm (nor pekwm). kwin do it correctly. */
|
||||
position(screen_x, screen_y);
|
||||
netwm_set_window_strut(this, 0, 0, h(), 0);
|
||||
netwm_window_set_strut(fl_xid(this), 0, 0, h(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -362,13 +370,13 @@ int Panel::handle(int e) {
|
|||
/* 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);
|
||||
netwm_window_set_strut(fl_xid(this), 0, 0, h(), 0);
|
||||
vpos = PANEL_POSITION_TOP;
|
||||
}
|
||||
|
||||
if(Fl::event_y_root() > screen_h_half && y() < screen_h_half) {
|
||||
position(screen_x, screen_h - h());
|
||||
netwm_set_window_strut(this, 0, 0, 0, h());
|
||||
netwm_window_set_strut(fl_xid(this), 0, 0, 0, h());
|
||||
vpos = PANEL_POSITION_BOTTOM;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
#include "Applet.h"
|
||||
#include "Netwm.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <FL/Fl_Group.H>
|
||||
#include <FL/Fl.H>
|
||||
#include <edelib/Debug.h>
|
||||
#include <edelib/Netwm.h>
|
||||
|
||||
#include "PagerButton.h"
|
||||
|
||||
EDELIB_NS_USING(netwm_workspace_change)
|
||||
EDELIB_NS_USING(netwm_workspace_get_current)
|
||||
EDELIB_NS_USING(netwm_workspace_get_count)
|
||||
EDELIB_NS_USING(netwm_workspace_get_names)
|
||||
EDELIB_NS_USING(netwm_workspace_free_names)
|
||||
EDELIB_NS_USING(netwm_callback_add)
|
||||
EDELIB_NS_USING(netwm_callback_remove)
|
||||
EDELIB_NS_USING(NETWM_CHANGED_CURRENT_WORKSPACE)
|
||||
|
||||
class Pager : public Fl_Group {
|
||||
public:
|
||||
Pager();
|
||||
|
@ -22,7 +31,7 @@ static void box_cb(Fl_Widget*, void *b) {
|
|||
|
||||
/* because workspaces in button labels are increased */
|
||||
int s = pb->get_workspace_label() - 1;
|
||||
netwm_change_workspace(s);
|
||||
netwm_workspace_change(s);
|
||||
}
|
||||
|
||||
static void net_event_cb(int action, Window xid, void *data) {
|
||||
|
@ -58,9 +67,9 @@ void Pager::init_workspace_boxes(void) {
|
|||
int nworkspaces, curr_workspace;
|
||||
char **names = 0;
|
||||
|
||||
nworkspaces = netwm_get_workspace_count();
|
||||
curr_workspace = netwm_get_current_workspace();
|
||||
netwm_get_workspace_names(names);
|
||||
nworkspaces = netwm_workspace_get_count();
|
||||
curr_workspace = netwm_workspace_get_current();
|
||||
netwm_workspace_get_names(names);
|
||||
|
||||
/*
|
||||
* Resize group before childs, or they will be resized too, messing things up.
|
||||
|
@ -96,11 +105,11 @@ void Pager::init_workspace_boxes(void) {
|
|||
X = bx->x() + bx->w() + 1;
|
||||
}
|
||||
|
||||
XFreeStringList(names);
|
||||
netwm_workspace_free_names(names);
|
||||
}
|
||||
|
||||
void Pager::workspace_changed(void) {
|
||||
int c = netwm_get_current_workspace();
|
||||
int c = netwm_workspace_get_current();
|
||||
PagerButton *pb;
|
||||
|
||||
E_RETURN_IF_FAIL(c < children());
|
||||
|
|
|
@ -7,15 +7,23 @@
|
|||
#include <edelib/Nls.h>
|
||||
#include <edelib/MenuItem.h>
|
||||
#include <edelib/IconLoader.h>
|
||||
#include <edelib/Netwm.h>
|
||||
|
||||
#include "TaskButton.h"
|
||||
#include "Taskbar.h"
|
||||
#include "Netwm.h"
|
||||
#include "icons/window.xpm"
|
||||
|
||||
EDELIB_NS_USING(MenuItem)
|
||||
EDELIB_NS_USING(IconLoader)
|
||||
EDELIB_NS_USING(ICON_SIZE_TINY)
|
||||
EDELIB_NS_USING(netwm_window_close)
|
||||
EDELIB_NS_USING(netwm_window_set_active)
|
||||
EDELIB_NS_USING(netwm_window_maximize)
|
||||
EDELIB_NS_USING(netwm_window_get_title)
|
||||
EDELIB_NS_USING(wm_window_ede_restore)
|
||||
EDELIB_NS_USING(wm_window_get_state)
|
||||
EDELIB_NS_USING(wm_window_set_state)
|
||||
EDELIB_NS_USING(WM_WINDOW_STATE_ICONIC)
|
||||
|
||||
static Fl_Pixmap image_window(window_xpm);
|
||||
|
||||
|
@ -40,23 +48,23 @@ static void redraw_whole_panel(TaskButton *b) {
|
|||
|
||||
static void close_cb(Fl_Widget*, void *b) {
|
||||
TaskButton *bb = (TaskButton*)b;
|
||||
netwm_close_window(bb->get_window_xid());
|
||||
netwm_window_close(bb->get_window_xid());
|
||||
/* no need to redraw whole panel since taskbar elements are recreated again */
|
||||
}
|
||||
|
||||
static void restore_cb(Fl_Widget*, void *b) {
|
||||
TaskButton *bb = (TaskButton*)b;
|
||||
wm_ede_restore_window(bb->get_window_xid());
|
||||
wm_window_ede_restore(bb->get_window_xid());
|
||||
|
||||
netwm_set_active_window(bb->get_window_xid());
|
||||
netwm_window_set_active(bb->get_window_xid());
|
||||
redraw_whole_panel(bb);
|
||||
}
|
||||
|
||||
static void minimize_cb(Fl_Widget*, void *b) {
|
||||
TaskButton *bb = (TaskButton*)b;
|
||||
|
||||
if(wm_get_window_state(bb->get_window_xid()) != WM_STATE_ICONIC)
|
||||
wm_set_window_state(bb->get_window_xid(), WM_STATE_ICONIC);
|
||||
if(wm_window_get_state(bb->get_window_xid()) != WM_WINDOW_STATE_ICONIC)
|
||||
wm_window_set_state(bb->get_window_xid(), WM_WINDOW_STATE_ICONIC);
|
||||
|
||||
redraw_whole_panel(bb);
|
||||
}
|
||||
|
@ -64,8 +72,8 @@ static void minimize_cb(Fl_Widget*, void *b) {
|
|||
static void maximize_cb(Fl_Widget*, void *b) {
|
||||
TaskButton *bb = (TaskButton*)b;
|
||||
|
||||
netwm_set_active_window(bb->get_window_xid());
|
||||
netwm_maximize_window(bb->get_window_xid());
|
||||
netwm_window_set_active(bb->get_window_xid());
|
||||
netwm_window_maximize(bb->get_window_xid());
|
||||
|
||||
redraw_whole_panel(bb);
|
||||
}
|
||||
|
@ -143,7 +151,7 @@ void TaskButton::display_menu(void) {
|
|||
void TaskButton::update_title_from_xid(void) {
|
||||
E_RETURN_IF_FAIL(xid >= 0);
|
||||
|
||||
char *title = netwm_get_window_title(xid);
|
||||
char *title = netwm_window_get_title(xid);
|
||||
if(!title) {
|
||||
label("...");
|
||||
tooltip("...");
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <edelib/Debug.h>
|
||||
#include <edelib/Netwm.h>
|
||||
|
||||
#include "Netwm.h"
|
||||
#include "TaskButton.h"
|
||||
#include "Taskbar.h"
|
||||
#include "Panel.h"
|
||||
|
@ -12,6 +12,22 @@
|
|||
#define DEFAULT_CHILD_W 175
|
||||
#define DEFAULT_SPACING 5
|
||||
|
||||
EDELIB_NS_USING(netwm_callback_add)
|
||||
EDELIB_NS_USING(netwm_callback_remove)
|
||||
EDELIB_NS_USING(netwm_window_get_all_mapped)
|
||||
EDELIB_NS_USING(netwm_window_is_manageable)
|
||||
EDELIB_NS_USING(netwm_window_get_workspace)
|
||||
EDELIB_NS_USING(netwm_window_get_active)
|
||||
EDELIB_NS_USING(netwm_window_set_active)
|
||||
EDELIB_NS_USING(netwm_workspace_get_current)
|
||||
EDELIB_NS_USING(wm_window_set_state)
|
||||
EDELIB_NS_USING(wm_window_get_state)
|
||||
EDELIB_NS_USING(NETWM_CHANGED_ACTIVE_WINDOW)
|
||||
EDELIB_NS_USING(NETWM_CHANGED_CURRENT_WORKSPACE)
|
||||
EDELIB_NS_USING(NETWM_CHANGED_WINDOW_LIST)
|
||||
EDELIB_NS_USING(NETWM_CHANGED_WINDOW_NAME)
|
||||
EDELIB_NS_USING(WM_WINDOW_STATE_ICONIC)
|
||||
|
||||
static void button_cb(TaskButton *b, void *t) {
|
||||
Taskbar *tt = (Taskbar*)t;
|
||||
|
||||
|
@ -36,7 +52,7 @@ static void net_event_cb(int action, Window xid, void *data) {
|
|||
return;
|
||||
}
|
||||
|
||||
/* this is a message, so property is not changed and netwm_get_active_window() must be called */
|
||||
/* this is a message, so property is not changed and netwm_window_get_active() must be called */
|
||||
if(action == NETWM_CHANGED_ACTIVE_WINDOW) {
|
||||
Taskbar *tt = (Taskbar*)data;
|
||||
tt->update_active_button();
|
||||
|
@ -72,20 +88,20 @@ void Taskbar::create_task_buttons(void) {
|
|||
panel_redraw();
|
||||
|
||||
Window *wins;
|
||||
int nwins = netwm_get_mapped_windows(&wins);
|
||||
int nwins = netwm_window_get_all_mapped(&wins);
|
||||
|
||||
if(nwins > 0) {
|
||||
TaskButton *b;
|
||||
int curr_workspace = netwm_get_current_workspace();
|
||||
int curr_workspace = netwm_workspace_get_current();
|
||||
|
||||
for(int i = 0; i < nwins; i++) {
|
||||
if(!netwm_manageable_window(wins[i]))
|
||||
if(!netwm_window_is_manageable(wins[i]))
|
||||
continue;
|
||||
/*
|
||||
* show window per workspace
|
||||
* TODO: allow showing all windows in each workspace
|
||||
*/
|
||||
if(curr_workspace == netwm_get_window_workspace(wins[i])) {
|
||||
if(curr_workspace == netwm_window_get_workspace(wins[i])) {
|
||||
b = new TaskButton(0, 0, DEFAULT_CHILD_W, 25);
|
||||
b->set_window_xid(wins[i]);
|
||||
b->update_title_from_xid();
|
||||
|
@ -149,7 +165,7 @@ void Taskbar::update_active_button(int xid) {
|
|||
return;
|
||||
|
||||
if(xid == -1) {
|
||||
xid = netwm_get_active_window();
|
||||
xid = netwm_window_get_active();
|
||||
/* TODO: make sure panel does not get 'active', or all buttons will be FL_UP_BOX */
|
||||
}
|
||||
|
||||
|
@ -173,13 +189,13 @@ void Taskbar::activate_window(TaskButton *b) {
|
|||
|
||||
/* if clicked on activated button, it will be minimized, then next one will be activated */
|
||||
if(b == curr_active) {
|
||||
if(wm_get_window_state(xid) != WM_STATE_ICONIC) {
|
||||
if(wm_window_get_state(xid) != WM_WINDOW_STATE_ICONIC) {
|
||||
/* minimize if not so */
|
||||
wm_set_window_state(xid, WM_STATE_ICONIC);
|
||||
wm_window_set_state(xid, WM_WINDOW_STATE_ICONIC);
|
||||
|
||||
if(prev_active &&
|
||||
prev_active != b &&
|
||||
wm_get_window_state(prev_active->get_window_xid()) != WM_STATE_ICONIC)
|
||||
wm_window_get_state(prev_active->get_window_xid()) != WM_WINDOW_STATE_ICONIC)
|
||||
{
|
||||
xid = prev_active->get_window_xid();
|
||||
b = prev_active;
|
||||
|
@ -190,7 +206,7 @@ void Taskbar::activate_window(TaskButton *b) {
|
|||
}
|
||||
|
||||
/* active or restore minimized */
|
||||
netwm_set_active_window(xid);
|
||||
netwm_window_set_active(xid);
|
||||
update_active_button(xid);
|
||||
|
||||
/* TODO: use stack for this (case when this can't handle: minimize three window, out of four on the workspace) */
|
||||
|
|
Loading…
Reference in New Issue
Block a user