Copying wm from old ede

This commit is contained in:
Sanel Zukan 2009-02-20 13:05:43 +00:00
parent f8c3e1ff7c
commit 7513426131
45 changed files with 7604 additions and 0 deletions

143
edewm/Cursor.cpp Normal file
View File

@ -0,0 +1,143 @@
#include "Frame.h"
#include <X11/Xlib.h>
#include <X11/cursorfont.h>
#include <efltk/Fl.h>
#include <efltk/Fl_Window.h>
#include <efltk/x.h>
// I like the MSWindows resize cursors, so I duplicate them here:
#define CURSORSIZE 16
#define HOTXY 8
static struct TableEntry {
uchar bits[CURSORSIZE*CURSORSIZE/8];
uchar mask[CURSORSIZE*CURSORSIZE/8];
Cursor cursor;
} table[] = {
{{ // FL_CURSOR_NS
0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0x80, 0x01, 0x80, 0x01,
0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00},
{
0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xc0, 0x03,
0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xf0, 0x0f,
0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01}},
{{ // FL_CURSOR_EW
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10,
0x0c, 0x30, 0xfe, 0x7f, 0xfe, 0x7f, 0x0c, 0x30, 0x08, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1c, 0x38,
0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x1c, 0x38, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
{{ // FL_CURSOR_NWSE
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x38, 0x00, 0x78, 0x00,
0xe8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x1c,
0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{
0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x7c, 0x00, 0xfc, 0x00,
0xfc, 0x01, 0xec, 0x03, 0xc0, 0x37, 0x80, 0x3f, 0x00, 0x3f, 0x00, 0x3e,
0x00, 0x3f, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00}},
{{ // FL_CURSOR_NESW
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1c, 0x00, 0x1e,
0x00, 0x17, 0x80, 0x03, 0xc0, 0x01, 0xe8, 0x00, 0x78, 0x00, 0x38, 0x00,
0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3f,
0x80, 0x3f, 0xc0, 0x37, 0xec, 0x03, 0xfc, 0x01, 0xfc, 0x00, 0x7c, 0x00,
0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00}},
{{0}, {0}} // FL_CURSOR_NONE & unknown
};
static int deleteit = 0;
static Cursor cursor;
void set_frame_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg, Window wid)
{
if(deleteit) XFreeCursor(fl_display, cursor);
deleteit=0;
if (!c) {
cursor = None;
} else {
if (c >= FL_CURSOR_NS) {
TableEntry *q = (c > FL_CURSOR_NESW) ? table+4 : table+(c-FL_CURSOR_NS);
if (!(q->cursor)) {
XColor dummy;
Pixmap p = XCreateBitmapFromData(fl_display,
RootWindow(fl_display, fl_screen), (const char*)(q->bits),
CURSORSIZE, CURSORSIZE);
Pixmap m = XCreateBitmapFromData(fl_display,
RootWindow(fl_display, fl_screen), (const char*)(q->mask),
CURSORSIZE, CURSORSIZE);
q->cursor = XCreatePixmapCursor(fl_display, p,m,&dummy, &dummy,
HOTXY, HOTXY);
XFreePixmap(fl_display, m);
XFreePixmap(fl_display, p);
}
cursor = q->cursor;
} else {
cursor = XCreateFontCursor(fl_display, (c-1)*2);
deleteit = 1;
}
XColor fgc;
fg = fl_get_color(fg);
fgc.red = (fg>>16)&0xFF00;
fgc.green = (fg>>8)&0xFF00;
fgc.blue = fg & 0xFF00;
XColor bgc;
bg = fl_get_color(bg);
bgc.red = (bg>>16)&0xFF00;
bgc.green = (bg>>8)&0xFF00;
bgc.blue = bg & 0xFF00;
XRecolorCursor(fl_display, cursor, &fgc, &bgc);
}
XDefineCursor(fl_display, wid, cursor);
}
static bool grab_ = false;
void grab_cursor(bool grab)
{
if (grab_) {
grab_ = false;
Fl::event_is_click(0); // avoid double click
XAllowEvents(fl_display, Fl::event()==FL_PUSH ? ReplayPointer : AsyncPointer, CurrentTime);
XUngrabPointer(fl_display, fl_event_time); // Qt did not do this...
XFlush(fl_display); // make sure we are out of danger before continuing...
// because we "pushed back" the FL_PUSH, make it think no buttons are down:
Fl::e_state &= 0xffffff;
Fl::e_keysym = 0;
}
// start the new grab:
// Both X and Win32 have the annoying requirement that a visible window
// be used as a target for the events, and it cannot disappear while the
// grab is running. I just grab efltk's first window:
if(grab && Frame::activeFrame()) {
Window window = fl_xid(Frame::activeFrame());
if(window &&
XGrabPointer(fl_display,
window,
true, // owner_events
ButtonPressMask|ButtonReleaseMask|
ButtonMotionMask|PointerMotionMask,
GrabModeSync, // pointer_mode
GrabModeAsync, // keyboard_mode
None, // confine_to
cursor, // cursor
fl_event_time) == GrabSuccess)
{
grab_ = true;
XAllowEvents(fl_display, AsyncPointer, CurrentTime);
} else {
//printf("XGrabPointer failed\n");
}
}
}
bool grab() {
return grab_;
}

296
edewm/Desktop.cpp Normal file
View File

@ -0,0 +1,296 @@
#include "config.h"
#include "debug.h"
#include "Winhints.h"
#include "Frame.h"
#include "Windowmanager.h"
#include "Desktop.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
Desktop_List desktops;
int Desktop::desktop_count_ = 0;
Desktop* Desktop::current_ = 0;
Desktop *Desktop::desktop(int num)
{
if(num>=(int)desktops.size()) return desktops.item(desktops.size()-1);
if(num<1) return desktops.item(0);
for(uint n=0; n<desktops.size(); n++) {
Desktop *d=desktops[n];
if(d->number()==num) return d;
}
return desktops.item(0);
}
Desktop *Desktop::next()
{
uint num = current()->number();
num++;
if(num > desktops.count())
current(0);
else
current(num);
return current();
}
Desktop *Desktop::prev()
{
int num = current()->number();
num--;
if(num < 1)
current(desktops.count());
else
current(num);
return current();
}
Desktop::Desktop(const char *name)
{
desktops.append(this);
number_ = desktops.count();
DBG("::Desktop %d", number_);
if(name)
name_ = strdup(name);
else
name_ = 0;
}
Desktop::~Desktop()
{
desktops.remove(this);
if(current_==this) {
current(desktop(number()+1));
}
// put any clients onto another desktop:
for(uint n=0; n<map_order.size(); n++)
if(map_order[n]->desktop()==this)
map_order[n]->desktop(current_);
if(name_) delete []name_;
}
void Desktop::name(const char *name)
{
if(name_) delete []name_;
if(name) name_ = strdup(name);
}
extern Frame *menu_frame; //Frame where titlebar menu is popped up. Set only when changing window desktop.
void Desktop::current(Desktop *cur)
{
if(cur == current_) return;
current_ = cur;
Frame *f = 0, *top = 0;
for(uint n=0; n<stack_order.size(); n++) {
f = stack_order[n];
if(!f->desktop() && f->state()!=UNMAPPED) {
if(f->state()==OTHER_DESKTOP) f->state(NORMAL);
if(!f->frame_flag(SKIP_FOCUS) && !f->frame_flag(SKIP_LIST)) top=f;
continue;
}
// Keep this window in 'NORMAL' state.
if(f==menu_frame && f->state()==NORMAL) {
top=f;
continue;
}
if(f->state()!=UNMAPPED) {
if(f->desktop()==cur) {
if(f->state()==OTHER_DESKTOP) {
f->state(NORMAL);
}
top=f;
} else {
if(f->state()==NORMAL) {
f->state(OTHER_DESKTOP);
}
}
}
}
if(cur!=0) {
setProperty(fl_xid(root), _XA_NET_CURRENT_DESKTOP, XA_CARDINAL, cur->number()-1);
if(top) {
top->activate();
top->raise();
}
DBG("Went to desktop: %d", cur->number());
}
}
Desktop* Desktop::add(const char *name)
{
Desktop *d = new Desktop(name);
if(!name) {
char buf[32]; sprintf(buf, _("Workspace %d"), d->number());
d->name(buf);
}
return d;
}
// Updates viewport info, since we dont support LARGE desktops
// According to NET-WM speac these MUST be set to (0,0)
void Desktop::update_desktop_viewport()
{
CARD32 val[2] = { 0, 0 };
XChangeProperty(fl_display, root_win, _XA_NET_DESKTOP_VIEWPORT, XA_CARDINAL,
32, PropModeReplace, (unsigned char *)&val, 2);
}
void Desktop::update_desktop_geometry()
{
CARD32 val[2] = { Fl::w(), Fl::h() };
XChangeProperty(fl_display, root_win, _XA_NET_DESKTOP_GEOMETRY, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *)&val, 2);
}
void Desktop::update_desktop_workarea()
{
CARD32 val[4];
val[0] = root->x();
val[1] = root->y();
val[2] = root->w();
val[3] = root->h();
XChangeProperty(fl_display, root_win, _XA_NET_WORKAREA, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *)&val, 4);
}
void Desktop::update_desktop_names(bool send)
{
char *workspaces[16] = { 0 };
int cnt=0;
for(uint n=0; n<desktops.size(); n++) {
Desktop *d=desktops[n];
if(!d->name()) {
char tmp[64]; snprintf(tmp, sizeof(tmp)-1, _("Workspace %d"), cnt+1);
workspaces[cnt] = strdup(tmp);
} else {
workspaces[cnt] = strdup(d->name());
}
cnt++;
}
if(send) {
XTextProperty names;
if(XStringListToTextProperty((char **)workspaces, cnt, &names)) {
XSetTextProperty(fl_display, fl_xid(root), &names, _XA_NET_DESKTOP_NAMES);
XFree(names.value);
}
}
}
// Updates both NET desktop count atoms
void Desktop::update_desktop_count(uint cnt, bool send)
{
if(cnt<0) cnt=0;
if(cnt>8) cnt=8;
Desktop::desktop_count_ = cnt;
if(send) {
setProperty(fl_xid(root), _XA_NET_NUM_DESKTOPS, XA_CARDINAL, Desktop::desktop_count_);
update_desktop_viewport();
update_desktop_workarea();
update_desktop_geometry();
}
if(desktops.count()<cnt) {
int add = cnt-desktops.count();
for(int a=0; a<add; a++)
Desktop::add();
DBG("Increased desktops to %d", desktops.count());
} else if(desktops.count()>cnt) {
int del = desktops.count()-cnt;
for(int a=0; a<del; a++) {
Desktop *d = desktops.item(desktops.size()-1);
delete d;
}
DBG("Decreased desktops to %d", desktops.count());
}
}
void Desktop::set_names()
{
int length=0;
char *buffer=0;
XTextProperty names;
// First try to get NET desktop names
XGetTextProperty(fl_display, RootWindow(fl_display, fl_screen), &names, _XA_NET_DESKTOP_NAMES);
buffer = (char *)names.value;
length = names.nitems;
if(buffer) {
char* c = buffer;
for (int i = 1; c < buffer+length; i++) {
char* d = c;
while(*d) d++;
Desktop::desktop(i)->name(c);
c = d+1;
}
XFree(names.value);
} else {
// No desktop names in XServer already, read from ede config file
Fl_Config cfg(fl_find_config_file("ede.conf", 0));
cfg.set_section("Workspaces");
char tmp[128], name[128];
for(uint n=1; n<=8; n++) {
snprintf(tmp, sizeof(tmp)-1, "Workspace%d", n);
if(!cfg.read(tmp, name, 0, sizeof(name))) {
if(n<=desktops.count()) {
Desktop::desktop(n)->name(name);
}
}
}
}
}
// called at startup, read the list of desktops from the root
// window properties, or on failure make some default desktops.
void init_desktops()
{
int current_num=0, p=0;
p = getIntProperty(fl_xid(root), _XA_NET_NUM_DESKTOPS, XA_CARDINAL, -1);
if(p<0) {
// No desktop count in XServer already, read from ede config file
Fl_Config cfg(fl_find_config_file("ede.conf", 0));
cfg.get("Workspaces", "Count", p, 4);
}
DBG("Total Desks: %d", p);
Desktop::update_desktop_count(p);
Desktop::set_names();
Desktop::update_desktop_names(true);
// Try to get current NET desktop
p = getIntProperty(fl_xid(root), _XA_NET_CURRENT_DESKTOP, XA_CARDINAL, -1);
// If not valid number, try GNOME
if(p >= 0 && p < Desktop::desktop_count()+1)
current_num = p+1; // Got valid
else
current_num = 1; // Not valid, use 1
DBG("Current desktop: %d", current_num);
Desktop::current(Desktop::desktop(current_num));
DBG("Desktops inited!");
}

69
edewm/Desktop.h Normal file
View File

@ -0,0 +1,69 @@
#ifndef _DESKTOP_H_
#define _DESKTOP_H_
#include <efltk/Fl_PtrList.h>
class Desktop {
public:
Desktop(const char *name);
~Desktop();
const char* name() const { return name_; }
void name(const char *name);
int number() const { return number_; }
static Desktop *desktop(int num);
static Desktop *next();
static Desktop *prev();
static Desktop *current() { return current_; }
static int current_num() { return current_ ? current_->number() : -1; }
static Desktop* add(const char *name=0);
static void current(Desktop *cur);
static void current(int cur) { current(desktop(cur)); }
static int desktop_count() { return desktop_count_; }
static void update_desktop_viewport();
static void update_desktop_workarea();
static void update_desktop_geometry();
static void update_desktop_count(uint cnt, bool send=true);
static void update_desktop_names(bool send=true);
static void set_names();
int junk; // for temporary storage by menu builder
private:
static Desktop* current_;
static int desktop_count_;
const char* name_;
int number_;
};
class Desktop_List : public Fl_Ptr_List {
public:
Desktop_List() : Fl_Ptr_List() { }
void append(Desktop *item) { Fl_Ptr_List::append((void *)item); }
void prepend(Desktop *item) { Fl_Ptr_List::prepend((void *)item); }
void insert(uint pos, Desktop *item) { Fl_Ptr_List::insert(pos, (void *)item); }
void replace(uint pos, Desktop *item) { Fl_Ptr_List::replace(pos, (void *)item); }
void remove(uint pos) { Fl_Ptr_List::remove(pos); }
bool remove(Desktop *item) { return Fl_Ptr_List::remove((void *)item); }
int index_of(const Desktop *w) const { return Fl_Ptr_List::index_of((void*)w); }
Desktop *item(uint index) const { return (Desktop*)Fl_Ptr_List::item(index); }
Desktop **data() { return (Desktop**)items; }
Desktop *operator [](uint ind) const { return (Desktop *)items[ind]; }
};
extern Desktop_List desktops;
#endif

375
edewm/Events.cpp Normal file
View File

@ -0,0 +1,375 @@
#include <stdio.h>
#include "Frame.h"
#include "Desktop.h"
#include "Netwm.h"
#include "Windowmanager.h"
#include "Icon.h"
#include "debug.h"
#include "Winhints.h"
bool Frame::configure_event(const XConfigureRequestEvent *e)
{
DBG("configure_event 0x%lx", e->window);
// Always update flags and border...
get_funcs_from_type();
updateBorder();
unsigned long mask = e->value_mask;
//if (mask & CWBorderWidth) app_border_width = e->border_width;
// Try to detect if the application is really trying to move the
// window, or is simply echoing it's postion, possibly with some
// variation (such as echoing the parent window position), and
// dont' move it in that case:
int X = (mask & CWX && e->x != x()) ? e->x-offset_x : x();
int Y = (mask & CWY && e->y != y()) ? e->y-offset_y : y();
int W = (mask & CWWidth) ? e->width+offset_w : w();
int H = (mask & CWHeight) ? e->height+offset_h : h();
// Fix Rick Sayre's program that resizes it's windows bigger than the maximum size:
// Just turn off sizehints
if(W > size_hints->max_width + offset_w) size_hints->max_width = 0;
if(H > size_hints->max_height + offset_h) size_hints->max_height = 0;
set_size(X, Y, W, H);
if (e->value_mask & CWStackMode && e->detail == Above && state()==NORMAL)
raise();
return true;
}
bool Frame::map_event(const XMapRequestEvent *e)
{
DBG("map_event 0x%lx", e->window);
if(state()!=NORMAL) state(NORMAL);
activate();
raise();
return true;
}
bool Frame::unmap_event(const XUnmapEvent *e)
{
DBG("unmap_event 0x%lx", e->window);
if(state()==OTHER_DESKTOP) return true;
if(state()==ICONIC) return true;
if(e->from_configure)
{
DBG("Unmap notify from configure\n");
state(UNMAPPED);
} else if(state_flags_&IGNORE_UNMAP)
clear_state_flag(IGNORE_UNMAP);
else
state(UNMAPPED);
WindowManager::update_client_list();
return true;
}
bool Frame::destroy_event(const XDestroyWindowEvent *e)
{
DBG("destroy_event 0x%lx", e->window);
destroy_frame();
return true;
}
bool Frame::reparent_event(const XReparentEvent *e)
{
DBG("reparent_event 0x%lx", e->window);
if(e->parent==fl_xid(this)) return true; // echo
if(e->parent==fl_xid(root)) return true; // app is trying to tear-off again?
DBG("Destroy in reparent_event");
destroy_frame(); // guess they are trying to paste tear-off thing back?
return true;
}
#include <efltk/fl_ask.h>
bool Frame::clientmsg_event(const XClientMessageEvent *e)
{
DBG("clientmsg_event 0x%lx", e->window);
if(e->message_type == _XA_WM_CHANGE_STATE && e->format == 32)
{
DBG("WIN change state");
if (e->data.l[0] == NormalState) raise();
else if (e->data.l[0] == IconicState) iconize();
return true;
}
else if(e->message_type == _XA_NET_WM_STATE)
{
/* int action = e->data.l[0]; */
Atom atom1 = e->data.l[1];
Atom atom2 = e->data.l[2];
// We accepts only HORZ - VERT combination (sent by taskbar).
// Horizontal or vertical maximization only, is not supported for now.
if((atom1 == _XA_NET_WM_STATE_MAXIMIZED_HORZ || atom1 == _XA_NET_WM_STATE_MAXIMIZED_VERT) &&
atom2 == _XA_NET_WM_STATE_MAXIMIZED_HORZ || atom2 == _XA_NET_WM_STATE_MAXIMIZED_VERT)
{
maximize();
return true;
}
DBG("NET state");
}
else if(e->message_type == _XA_NET_ACTIVE_WINDOW)
{
DBG("Net active window: %ld", e->window);
raise();
activate();
return true;
}
else if(e->message_type == _XA_NET_CLOSE_WINDOW)
{
DBG("Net close window: %ld", e->window);
close();
return true;
}
else if(e->message_type == _XA_NET_WM_DESKTOP)
{
DBG("Net wm desktop: %ld", e->window);
long d = e->data.l[0];
if(d<0) d=1;
else if(d>8) d=8;
else if((unsigned)d == 0xFFFFFFFE || (unsigned)d == 0xFFFFFFFF) d=-2;
else d++;
if(d>0) desktop(Desktop::desktop(d));
else desktop(0);
return true;
}
else if(e->message_type ==_XA_EDE_WM_ACTION)
{
Atom atom = e->data.l[0];
if(atom == _XA_EDE_WM_RESTORE_SIZE)
{
restore();
return true;
}
if(atom == _XA_EDE_WM_LOGOUT)
{
root->shutdown();
return true;
}
}
// Fl::warning("flwm: unexpected XClientMessageEvent, type 0x%lx, "
// "window 0x%lx\n", e->message_type, e->window);
return true;
}
bool Frame::colormap_event(const XColormapEvent *e)
{
DBG("colormap_event 0x%lx", e->window);
// this field is called "new" in the old C++-unaware Xlib
if(e->c_new)
{
colormap = e->colormap;
if(active())
installColormap();
}
return true;
}
bool Frame::property_event(const XPropertyEvent *e)
{
DBG("property_event 0x%lx", e->window);
Atom a = e->atom;
switch(a)
{
case XA_WM_NAME:
getLabel((e->state==PropertyDelete), XA_WM_NAME);
break;
case XA_WM_ICON_NAME:
break;
case XA_WM_HINTS:
{
get_wm_hints();
Icon *old_i = icon_;
icon_ = new Icon(wm_hints);
if(old_i) delete old_i;
old_i=0;
title->redraw();
redraw();
}
break;
case XA_WM_NORMAL_HINTS:
case XA_WM_SIZE_HINTS:
ICCCM::size_hints(this);
break;
case XA_WM_TRANSIENT_FOR:
XGetTransientForHint(fl_display, window_, &transient_for_xid);
fix_transient_for();
break;
default:
if(a==_XA_WM_COLORMAP_WINDOWS)
{
getColormaps();
if (active()) installColormap();
}
else if(a==_XA_WM_STATE)
{
// it's not clear if I really need to look at this. Need to make
// sure it is not seeing the state echoed by the application by
// checking for it being different...
switch (getIntProperty(_XA_WM_STATE, _XA_WM_STATE, state()))
{
case IconicState:
if (state() == NORMAL || state() == OTHER_DESKTOP)
{
iconize();
}
break;
case NormalState:
if (state() != NORMAL && state() != OTHER_DESKTOP)
{
raise();
}
break;
}
}
else if(a==_XATOM_MWM_HINTS)
{
// some SGI Motif programs change this after mapping the window!!!
MWM::get_hints(this);
if(MWM::update_hints(this)) // returns true if any flags changed
{
fix_transient_for();
updateBorder();
}
}
else if(a==_XA_WM_PROTOCOLS)
{
get_protocols();
//getMotifHints(); // get Motif hints since they may do something with QUIT
}
else if(a==_XA_NET_WM_WINDOW_TYPE)
{
DBG("New NET WM window type!");
if(NETWM::get_window_type(this))
{
// This call overwrites MWM hints!
get_funcs_from_type();
} // && wintype==TYPE_NORMAL && decor_flag(BORDER)) {
else if(transient_for_xid)
{
//title->h(15); title->label(0);
if(decor_flag(BORDER) || decor_flag(THIN_BORDER))
{
clear_decor_flag(BORDER);
set_decor_flag(THIN_BORDER);
wintype = TYPE_DIALOG;
get_funcs_from_type();
}
}
}
else if(a==_XA_NET_WM_STRUT)
{
DBG("New NET WM STRUT");
NETWM::get_strut(this);
root->update_workarea(true);
}
else if(a== _XA_NET_WM_NAME)
{
DBG("New NET WM NAME!");
getLabel((e->state==PropertyDelete), _XA_NET_WM_NAME);
}
else if(a== _XA_NET_WM_ICON)
{
DBG("New NET icon!");
}
else if(a== _XA_KWM_WIN_ICON)
{
DBG("New KWM icon!");
}
else
{
DBG("Unhandled atom %lx\n", a);
return false;
}
break;
}
return true;
}
bool Frame::visibility_event(const XVisibilityEvent *e)
{
DBG("visibility_event 0x%lx", e->window);
// POSSIBLE SPEED UP!
// if e->state==FullyObscured we dont need to
// map/draw window, when we change desktop!
/*if(e->state == VisibilityUnobscured)
DBG("Fully visible");
else
DBG("Partial visible");
*/
return true;
}
#ifdef SHAPE
bool Frame::shape_event(const XShapeEvent *e)
{
DBG("shape event 0x%lx", e->window);
XShapeSelectInput(fl_display, window_, ShapeNotifyMask);
if(get_shape())
{
clear_decor_flag(BORDER|THIN_BORDER);
XShapeCombineShape(fl_display, fl_xid(this), ShapeBounding,
0, 0, window_,
ShapeBounding, ShapeSet);
}
return true;
}
#endif

1674
edewm/Frame.cpp Normal file

File diff suppressed because it is too large Load Diff

313
edewm/Frame.h Normal file
View File

@ -0,0 +1,313 @@
// Frame.H
// Each X window being managed by fltk has one of these
#ifndef Frame_H
#define Frame_H
#include "config.h"
#include "Mwm.h"
#include "Icccm.h"
#include <efltk/Fl.h>
#include <efltk/Fl_Window.h>
#include <efltk/Fl_Button.h>
#include <efltk/Fl_Bitmap.h>
#include <efltk/x.h>
#ifdef SHAPE
#include <X11/extensions/shape.h>
#endif
#include <efltk/Fl_Image.h>
// The state is an enumeration of reasons why the window may be invisible.
// Only if it is NORMAL is the window visible.
enum {
UNMAPPED = 0, // unmap command from app (X calls this WithdrawnState)
NORMAL = 1, // window is visible
SHADED = 2, // acts like NORMAL
ICONIC = 3, // hidden/iconized
OTHER_DESKTOP = 4 // normal but on another desktop
};
// values for frame flags:
// The flags are constant and are turned on by information learned
// from the Gnome, NETWM, and/or Motif window manager hints. edewm will
// ignore attempts to change these hints after the window is mapped.
enum {
NO_FOCUS = 0x00000001, // does not take focus
CLICK_TO_FOCUS = 0x00000002, // must click on window to give it focus
KEEP_ASPECT = 0x00000004, // aspect ratio from sizeHints
MODAL = 0x00000008, // grabs focus from transient_for window
TAKE_FOCUS_PRT = 0x00000010, // send junk when giving window focus
DELETE_WIN_PRT = 0x00000020, // close box sends a message
MAX_VERT = 0x00000100,
MAX_HORZ = 0x00000200,
STICKY = 0x00000400, // Everyone knows sticky
OWNER_HIDDEN = 0x00000800, // Owner of transient is hidden
FIXED_POSITION = 0x00001000, // Window is fixed in position even
SKIP_LIST = 0x00002000, // Not in window list
SKIP_FOCUS = 0x00004000 // Skip "Alt+Tab"
};
// values for func and decor flags:
enum {
// DECOR only:
BORDER = 1, // Draw border
THIN_BORDER = 2, // Draw thin border
TITLEBAR = 4, // Show titlebar
SYSMENU = 8, // Show system menu (left on titlebar)
//FUNC only:
MOVE = 16, // Add move action to system menu
CLOSE = 32, // Add close action to system menu
//Common flags:
MINIMIZE = 64, // Minimize button and minimize action
MAXIMIZE = 128, // Maximize button and maximize action
RESIZE = 256 // Resize allowed and resize action
};
// NETWM types
enum {
TYPE_DESKTOP = 1,
TYPE_DOCK,
TYPE_TOOLBAR,
TYPE_MENU,
TYPE_UTIL,
TYPE_SPLASH,
TYPE_DIALOG,
TYPE_NORMAL
};
// values for state_flags:
// These change over time
enum {
IGNORE_UNMAP = 0x01, // we did something that echos an UnmapNotify
};
class Icon;
class Desktop;
#include "Titlebar.h"
class Frame : public Fl_Window {
friend class Titlebar;
friend class ICCCM;
friend class MWM;
friend class NETWM;
Titlebar *title;
Window window_;
int wintype; //Type of window (see NETWM types)
int frame_flags_; // above constant flags
short state_; // X server state: iconic, withdrawn, normal
short state_flags_; // above state flags
short decor_flags_; // Decoration flags from MWM
short func_flags_; // Functions flags from MWM
int restore_x, restore_w; // saved size when min/max width is set
int restore_y, restore_h; // saved size when max height is set
double aspect_min, aspect_max;
Fl_Rect *strut_;
MwmHints *mwm_hints;
XWMHints *wm_hints;
XSizeHints *size_hints;
long win_hints;
Window transient_for_xid; // value from X
Frame* transient_for_; // the frame for that xid, if found
Frame* revert_to; // probably the xterm this was run from
Colormap colormap; // this window's colormap
int colormapWinCount; // list of other windows to install colormaps for
Window *colormapWindows;
Colormap *window_Colormaps; // their colormaps
// These are filled if window has icon
Icon *icon_;
Desktop* desktop_;
int maximize_width();
int maximize_height();
int force_x_onscreen(int X, int W);
int force_y_onscreen(int Y, int H);
void sendMessage(Atom, Atom) const;
void send_desktop();
void send_configurenotify();
void send_state_property();
void* getProperty(Atom, Atom = AnyPropertyType, unsigned long *length = 0, int *ret=0) const;
int getIntProperty(Atom, Atom = AnyPropertyType, int deflt = 0, int *ret = 0) const;
void setProperty(Atom, Atom, int) const;
void getLabel(bool del = false, Atom from_atom=0);
void getColormaps();
int getDesktop();
void updateBorder();
void fix_transient_for(); // called when transient_for_xid changes
void get_protocols();
void get_wm_hints();
void update_wm_hints();
void get_funcs_from_type();
void installColormap() const;
void set_cursor(int);
int mouse_location();
void layout() { Fl_Widget::layout(); }
void draw();
static Frame* active_;
void _desktop(Desktop*);
bool configure_event(const XConfigureRequestEvent *e);
bool map_event(const XMapRequestEvent *e);
bool unmap_event(const XUnmapEvent *e);
bool destroy_event(const XDestroyWindowEvent *e);
bool reparent_event(const XReparentEvent *e);
bool clientmsg_event(const XClientMessageEvent *e);
bool colormap_event(const XColormapEvent *e);
bool property_event(const XPropertyEvent *e);
bool visibility_event(const XVisibilityEvent *e);
bool shape_event(const XShapeEvent *e);
public:
bool shaped;
bool get_shape();
int offset_x, offset_y, offset_w, offset_h;
void set_size(int x, int y, int w, int h);
int frame_flags() const { return frame_flags_; }
short decor_flags() const { return decor_flags_; }
short func_flags() const { return func_flags_; }
short state_flags() const { return state_flags_; }
bool frame_flag(int i) { return ((frame_flags_&i)==i) ? true : false; }
void set_frame_flag(int i) { frame_flags_ |= i; }
void clear_frame_flag(int i) { frame_flags_ &=~i; }
void clear_frame_flags() { frame_flags_ = 0; }
bool decor_flag(short i) { return ((decor_flags_&i)==i) ? true : false; }
void set_decor_flag(short i) { decor_flags_ |= i; }
void clear_decor_flag(short i) { decor_flags_ &=~i; }
void clear_decor_flags() { decor_flags_ = 0; }
bool func_flag(short i) { return ((func_flags_&i)==i) ? true : false; }
void set_func_flag(short i) { func_flags_ |= i; }
void clear_func_flag(short i) { func_flags_ &=~i; }
void clear_func_flags() { func_flags_ = 0; }
bool state_flag(short i) { return ((state_flags_&i)==i) ? true : false; }
void set_state_flag(short i) { state_flags_ |= i; }
void clear_state_flag(short i) { state_flags_ &=~i; }
void clear_state_flags() { state_flags_ = 0; }
void cb_button_close(Fl_Button*);
void cb_button_kill(Fl_Button*);
void cb_button_max(Fl_Button*);
void cb_button_min(Fl_Button*);
int handle(int e); // handle fltk events
int handle(const XEvent *e);
void handle_move(int &nx, int &ny);
void window_type(int t) { wintype=t; }
int window_type() { return wintype; }
Frame(Window, XWindowAttributes* = 0);
~Frame();
void destroy_frame();
void settings_changed();
static void settings_changed_all();
Fl_Rect *strut() { return strut_; }
Icon *icon() { return icon_; }
Window window() const {return window_;}
Frame* transient_for() const {return transient_for_;}
int is_transient_for(const Frame*) const;
Desktop* desktop() const {return desktop_;}
void desktop(Desktop*);
static void desktop(Window wid, int desktop);
// Wm calls this, when user clicks inside frames
void content_click();
// Raises and put window top of stack
void raise();
static void raise(Window wid);
// Lowers and put window back of stack
void lower();
void iconize();
void maximize();
void restore();
void throw_focus(int destructor = 0);
// Closes window with given protocol, if theres no protocol we just kill it
static void close(Window wid);
void close();
void kill();
// returns true if it actually sets active state(focus)
bool activate();
bool activate_if_transient();
void deactivate();
// Get or set new state, handles iconizing, mapping and unmapping!
short state() const {return state_;}
void state(short newstate); // don't call this unless you know what you are doing!
int active() const {return active_==this;}
static Frame* activeFrame() {return active_;}
static bool do_opaque;
static bool focus_follows_mouse;
static bool animate;
static int animate_speed;
bool maximized;
};
// handy wrappers for those ugly X routines:
extern void* getProperty(Window, Atom, Atom = AnyPropertyType, unsigned long* length = 0, int *ret=0);
extern int getIntProperty(Window, Atom, Atom = AnyPropertyType, int deflt = 0, int *ret=0);
extern void setProperty(Window, Atom, Atom, int);
extern void draw_overlay(int x, int y, int w, int h);
void clear_overlay();
static inline int max(int a, int b) {return a > b ? a : b;}
static inline int min(int a, int b) {return a < b ? a : b;}
#endif

280
edewm/Hotkeys.cpp Normal file
View File

@ -0,0 +1,280 @@
// Hotkeys.cpp
// If you want to change what the hotkeys are, see the table at the bottom!
#include "config.h"
#include "Frame.h"
#include "Windowmanager.h"
#include "Desktop.h"
#include <efltk/Fl_Util.h>
#include "debug.h"
extern void show_tabmenu(int dir);
// Minimize presently active window
static void MinimizeWindow(char*)
{
Frame *act = Frame::activeFrame();
int acttype = act->window_type();
if ((acttype != TYPE_DESKTOP) && (acttype != TYPE_DOCK) && (acttype != TYPE_SPLASH))
act->iconize();
}
// Maximize presently active window
static void MaximizeWindow(char*)
{
Frame *act = Frame::activeFrame();
int acttype = act->window_type();
if ((acttype != TYPE_DESKTOP) && (acttype != TYPE_DOCK) && (acttype != TYPE_SPLASH)) {
// act->iconize();
// FIXME: a function for maximize operation like Frame::iconize()
Fl_Button *tmp; // this will never be used
act->cb_button_max(tmp);
}
}
// Close presently active window
static void CloseWindow(char *name)
{
Frame *act = Frame::activeFrame();
int acttype = act->window_type();
if ((acttype != TYPE_DESKTOP) && (acttype != TYPE_DOCK) && (acttype != TYPE_SPLASH))
act->close();
}
// Alt+Tab
static void NextWindow(char *name)
{
show_tabmenu(1);
}
// Alt+Shift+Tab
static void PreviousWindow(char *name) {
show_tabmenu(-1);
}
// Ctrl+Alt+Right
static void NextDesk(char *name)
{
Desktop::next();
}
// Ctrl+Alt+Left
static void PreviousDesk(char *name)
{
Desktop::prev();
}
// warning: this assummes it is bound to Fn key:
static void FKey_DeskNumber(char *name)
{
int desktop = 1; //Fl::event_key()-0xffbd; // default (bad) way of finding the desktop number
// kept for backwards compatibility only
// new (good) way of finding out the desktop number.
// "name" is something like "Desktop1" and we
// want to find the "1" on the end
if (name) {
int val;
if (sscanf(name,"Desktop%d",&val) == 1) desktop = val;
}
Desktop::current(Desktop::desktop(desktop));
}
static void FastRun(char *name)
{
fl_start_child_process("elauncher",false);
}
static void FindUtil(char *name)
{
fl_start_child_process("efinder",false);
}
static void LaunchApp(char *name)
{
Fl_Config conf(fl_find_config_file("wmanager.conf", false));
Fl_String app;
conf.get("Applications", name, app, NULL);
if(! app.empty())
fl_start_child_process(app, false);
}
////////////////////////////////////////////////////////////////
// I have to take some time to check it out
static struct {
char *name;
int key;
void (*func)(char *arg);
} keybindings[100]; // hopefully this is enough ;)
// This function will parse the hotkeys string used in config file,
// and construct an integer used by Fl::test_shortcut(int)
int parse_hotkey(char *hotkey)
{
// We do not have *all* possible keys here
// (see efltk/efltk/Enumerations.h for more)
static struct {
char *name;
int value;
} hotkeys[] = {
{"alt", FL_ALT},
{"ctrl", FL_CTRL},
{"shift", FL_SHIFT},
{"win", FL_WIN},
{"space", FL_Space},
{"backspace", FL_BackSpace},
{"tab", FL_Tab},
{"enter", FL_Enter},
{"escape", FL_Escape},
{"home", FL_Home},
{"left", FL_Left},
{"up", FL_Up},
{"right", FL_Right},
{"down", FL_Down},
{"pageup", FL_Page_Up},
{"pagedown", FL_Page_Down},
{"end", FL_End},
{"insert", FL_Insert},
{"delete", FL_Delete},
{"f1", FL_F(1)},
{"f2", FL_F(2)},
{"f3", FL_F(3)},
{"f4", FL_F(4)},
{"f5", FL_F(5)},
{"f6", FL_F(6)},
{"f7", FL_F(7)},
{"f8", FL_F(8)},
{"f9", FL_F(9)},
{"f10", FL_F(10)},
{"f11", FL_F(11)},
{"f12", FL_F(12)},
{0, 0}
};
int parsed = 0;
char f[20];
// The parser - case insensitive and hopefully robust
Fl_String_List elements(hotkey, "+");
for (uint i=0; i<elements.count(); i++) {
bool found = false;
for (int j=0; hotkeys[j].value; j++) {
Fl_String buf = Fl_String(hotkeys[j].name);
if (!elements.item(i).casecmp(buf)) {
parsed += hotkeys[j].value;
found = true;
}
}
if (!found) {
// use first letter or number as shortcut key
strcpy(f, elements.item(i));
if ((f[0] >= 'a') && (f[0] <= 'z')) {
parsed += f[0];
} else if ((f[0] >= 'A') && (f[0] <= 'Z')) {
parsed += (f[0] - 'A' + 'a');
} else if ((f[0] >= '0') && (f[0] <= '9')) {
parsed += f[0];
}
}
}
return parsed;
}
// Read wmanager.conf and initialize an array that will be used later
void read_hotkeys_configuration()
{
// All configurable hotkeys below - edit to add new keys
static struct {
char *name; // as used in wmanager.conf file
void (*func)(char *name); // callback function for this key
char *def_key; // default hotkey
} configurables[] = {
{"PreviousWindow", PreviousWindow, "Alt+Tab"},
{"NextWindow", NextWindow, "Alt+Shift+Tab"},
{"Desktop1", FKey_DeskNumber, "Alt+F1"},
{"Desktop2", FKey_DeskNumber, "Alt+F2"},
{"Desktop3", FKey_DeskNumber, "Alt+F3"},
{"Desktop4", FKey_DeskNumber, "Alt+F4"},
{"Desktop5", FKey_DeskNumber, "Alt+F5"},
{"Desktop6", FKey_DeskNumber, "Alt+F6"},
{"Desktop7", FKey_DeskNumber, "Alt+F7"},
{"Desktop8", FKey_DeskNumber, "Alt+F8"},
{"PreviousDesktop", PreviousDesk, "Alt+Ctrl+Right"},
{"NextDesktop", NextDesk, "Alt+Ctrl+Left"},
{"FindUtil", FindUtil, "Ctrl+F3"},
{"FastRun", FastRun, "Ctrl+F12"},
{"CloseWindow", CloseWindow, "Ctrl+F4"},
{"MinimizeWindow", MinimizeWindow, "Ctrl+F7"},
{"MaximizeWindow", MaximizeWindow, "Ctrl+F8"},
// Slots for user-defined applications and hotkeys
// 12 ought to be enough :-)
{"App1",LaunchApp,""},
{"App2",LaunchApp,""},
{"App3",LaunchApp,""},
{"App4",LaunchApp,""},
{"App5",LaunchApp,""},
{"App6",LaunchApp,""},
{"App7",LaunchApp,""},
{"App8",LaunchApp,""},
{"App9",LaunchApp,""},
{"App10",LaunchApp,""},
{"App11",LaunchApp,""},
{"App12",LaunchApp,""},
{"",NULL,""}
};
char buf[256];
int j=0;
Fl_Config wmconf(fl_find_config_file ("wmanager.conf",0));
wmconf.set_section("Hotkeys");
for (int i=0; configurables[i].name[0]; i++) {
wmconf.read(configurables[i].name, buf, configurables[i].def_key, sizeof(buf));
if (buf && buf[0]) {
keybindings[j].key=parse_hotkey(buf);
keybindings[j].name = strdup(configurables[i].name);
keybindings[j++].func=configurables[i].func;
}
}
keybindings[j].key = 0;
}
int Handle_Hotkey() {
for (int i = 0; keybindings[i].key; i++) {
if (Fl::test_shortcut(keybindings[i].key) ||
(keybindings[i].key & 0xFFFF) == FL_Delete
&& Fl::event_key() == FL_BackSpace// fltk bug?
) {
keybindings[i].func(keybindings[i].name);
return 1;
}
}
return 0;
}
void Grab_Hotkeys()
{
Window root_w = fl_xid(root);
for (int i = 0; keybindings[i].key; i++) {
int k = keybindings[i].key;
int keycode = XKeysymToKeycode(fl_display, k & 0xFFFF);
if(!keycode) continue;
// Silly X! we need to ignore caps lock & numlock keys by grabbing
// all the combinations:
XGrabKey(fl_display, keycode, k>>16, root_w, 0, 1, 1);
XGrabKey(fl_display, keycode, (k>>16)|2, root_w, 0, 1, 1); // CapsLock
XGrabKey(fl_display, keycode, (k>>16)|16, root_w, 0, 1, 1); // NumLock
XGrabKey(fl_display, keycode, (k>>16)|18, root_w, 0, 1, 1); // both
}
}

207
edewm/Icccm.cpp Normal file
View File

@ -0,0 +1,207 @@
#include "Icccm.h"
#include "Frame.h"
#include "Winhints.h"
#include "Windowmanager.h"
#include <edeconf.h>
static void icccm_send_state(Window wid, long state)
{
long data[2];
data[0] = state;
data[1] = None;
XChangeProperty(fl_display, wid, _XA_WM_STATE, _XA_WM_STATE,
32, PropModeReplace, (unsigned char *)data, 2);
}
void ICCCM::state_iconic(Frame *f)
{
icccm_send_state(f->window(), IconicState);
}
void ICCCM::state_normal(Frame *f)
{
icccm_send_state(f->window(), NormalState);
}
void ICCCM::state_withdrawn(Frame *f)
{
icccm_send_state(f->window(), WithdrawnState);
}
bool ICCCM::get_size(Frame *f, int &w, int &h)
{
bool ret=false;
int i, j;
double aspect;
XSizeHints *sh = f->size_hints;
int real_minw = (f->decor_flag(BORDER) || f->decor_flag(THIN_BORDER)) ? 100 : 0;
int minw = max(sh->min_width + f->offset_w, real_minw);
int minh = sh->min_height+ f->offset_h;
if(w > sh->max_width) { w = sh->max_width; ret = true; }
if(h > sh->max_height) { h = sh->max_height; ret = true; }
if(w < minw) { w = minw; ret = true; }
if(h < minh) { h = minh; ret = true; }
if( w>0 && h>0 )
{
w -= sh->base_width;
h -= sh->base_height;
if( w>0 && h>0 )
{
if(f->frame_flag(KEEP_ASPECT)) {
aspect = ((double)w) / ((double)h);
if (aspect < f->aspect_min)
w = (int)((double)h * f->aspect_min);
if (aspect > f->aspect_max)
h = (int)((double)w / f->aspect_max);
}
i = w / sh->width_inc;
j = h / sh->height_inc;
w = i * sh->width_inc;
h = j * sh->height_inc;
}
w += sh->base_width;
h += sh->base_height;
}
return ret;
}
void ICCCM::configure(Frame *f)
{
XConfigureEvent ce;
ce.send_event = True;
ce.display = fl_display;
ce.type = ConfigureNotify;
ce.event = f->window();
ce.window = f->window();
ce.x = f->x()+f->offset_x;
ce.y = f->y()+f->offset_y;
ce.width = f->w()-f->offset_w;
ce.height = f->h()-f->offset_h;
ce.border_width = f->box()->dx();
ce.above = None;
ce.override_redirect = False;
XSendEvent(fl_display, f->window(), False, StructureNotifyMask, (XEvent*)&ce);
}
void ICCCM::set_iconsizes()
{
XIconSize *is = XAllocIconSize();
is->min_width = 8;
is->min_height = 8;
is->max_width = 48;
is->max_height = 48;
is->width_inc = 1;
is->height_inc = 1;
XSetIconSizes(fl_display, root_win, is, 1);
XFree(is);
}
char *ICCCM::get_title(Frame *f)
{
XTextProperty xtp;
char *title = 0;
if(XGetWMName(fl_display, f->window(), &xtp))
{
if(xtp.encoding == XA_STRING) {
title = strdup((const char*)xtp.value);
} else {
#if HAVE_X11_UTF_TEXT_PROP
int items;
char **list=0;
Status s;
s = Xutf8TextPropertyToTextList(fl_display, &xtp, &list, &items);
if((s == Success) && (items > 0)) {
title = strdup((const char *)*list);
} else
title = strdup((const char *)xtp.value);
if(list) XFreeStringList(list);
#else
title = strdup((const char*)xtp.value);
#endif
}
XFree(xtp.value);
}
return title;
}
// Read the sizeHints to size_hints object
// Returns true if autoplace should be done.
bool ICCCM::size_hints(Frame *f)
{
long supplied;
XSizeHints *size_hints = f->size_hints;
if(!XGetWMNormalHints(fl_display, f->window(), size_hints, &supplied))
size_hints->flags = 0;
if(size_hints->flags & PResizeInc) {
if(size_hints->width_inc < 1) size_hints->width_inc = 1;
if(size_hints->height_inc < 1) size_hints->height_inc = 1;
} else
size_hints->width_inc = size_hints->height_inc = 1;
if(!(size_hints->flags & PBaseSize)) {
if (size_hints->flags & PMinSize) {
size_hints->base_width = size_hints->min_width;
size_hints->base_height = size_hints->min_height;
} else
size_hints->base_width = size_hints->base_height = 0;
}
if(!(size_hints->flags & PMinSize)) {
size_hints->min_width = size_hints->base_width;
size_hints->min_height = size_hints->base_height;
}
if(!(size_hints->flags & PMaxSize)) {
size_hints->max_width = 32767;
size_hints->max_height = 32767;
}
if (size_hints->min_height <= 0)
size_hints->min_height = 1;
if (size_hints->min_width <= 0)
size_hints->min_width = 1;
if(size_hints->max_width<size_hints->min_width || size_hints->max_width<=0)
size_hints->max_width = 32767;
if(size_hints->max_height<size_hints->min_height || size_hints->max_height<=0)
size_hints->max_height = 32767;
if(!(size_hints->flags & PWinGravity)) {
size_hints->win_gravity = NorthWestGravity;
size_hints->flags |= PWinGravity;
}
if(size_hints->flags & PAspect) {
f->set_frame_flag(KEEP_ASPECT);
if((size_hints->min_aspect.y > 0.0) && (size_hints->min_aspect.x > 0.0)) {
f->aspect_min = ((double)size_hints->min_aspect.x) / ((double)size_hints->min_aspect.y);
} else {
f->aspect_min = 0.0;
}
if((size_hints->max_aspect.y > 0.0) && (size_hints->max_aspect.x > 0.0)) {
f->aspect_max = ((double)size_hints->max_aspect.x) / ((double)size_hints->max_aspect.y);
} else {
f->aspect_max = 32767.0;
}
} else {
f->aspect_min = 0.0;
f->aspect_max = 32767.0;
}
// fix for old gimp, which sets PPosition to 0,0:
// if(f->x() <= 0 && f->y() <= 0) size_hints->flags &= ~PPosition;
return !(size_hints->flags & (USPosition|PPosition));
}

23
edewm/Icccm.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef _ICCCM_H_
#define _ICCCM_H_
class Frame;
class ICCCM
{
public:
static void state_iconic(Frame *f);
static void state_normal(Frame *f);
static void state_withdrawn(Frame *f);
static void configure(Frame *f);
static void set_iconsizes();
static bool get_size(Frame *f, int &w, int &h);
static char *get_title(Frame *f);
static bool size_hints(Frame *f);
};
#endif

165
edewm/Icon.cpp Normal file
View File

@ -0,0 +1,165 @@
#include "Icon.h"
#include "debug.h"
// Default icon
#include "tux.xpm"
#define I(i) ((Fl_Image*)i)
static Fl_Image default_icon(tux_xpm);
uint8 *cvt1to32(XImage *xim, int ow, int oh)
{
int pixel;
int pitch = Fl_Renderer::calc_pitch(4, ow);
uint8 *data = new uint8[oh*pitch];
uint32 *ptr;
int x,y;
for(y = 0; y < oh; y++)
{
ptr = (uint32*) (data + (pitch*y));
for(x = 0; x < ow; x++) {
pixel = XGetPixel(xim, x, y);
if(pixel) *ptr++ = 0x00000000;
else *ptr++ = 0xFFFFFFFF;
}
}
return data;
}
extern uint8 *ximage_to_data(XImage *im, Fl_PixelFormat *desired);
Icon::Icon(XWMHints *wm_hints)
{
// Max size 128x128
Fl_Rect r(0, 0, 128, 128);
XImage *xim;
image=0;
mask=0;
// ICON
if(wm_hints && wm_hints->flags & IconPixmapHint && wm_hints->icon_pixmap)
{
xim = Fl_Renderer::ximage_from_pixmap(wm_hints->icon_pixmap, r);
if(xim)
{
Fl_PixelFormat fmt;
DBG("Icon format: %dx%d %d\n",xim->width, xim->height, xim->depth);
DBG("depth/padding: %d/%d; r/g/b mask: %lx/%lx/%lx\n",
xim->depth, xim->bitmap_pad,
xim->red_mask, xim->green_mask, xim->blue_mask);
uint8 *data=0;
if(xim->depth==1) {
data = cvt1to32(xim, xim->width, xim->height);
fmt.realloc(32,0xFF0000,0x00FF00,0x0000FF,0);
} else {
data = ximage_to_data(xim, Fl_Renderer::system_format());
fmt.copy(Fl_Renderer::system_format());
}
// Create Fl_Image, masks are calculated automaticly
image = new Fl_Image(xim->width, xim->height, &fmt, data);
image->mask_type(FL_MASK_NONE);
XDestroyImage(xim);
}
}
// MASK
if(wm_hints && image && wm_hints->flags & IconMaskHint && wm_hints->icon_mask)
{
xim = Fl_Renderer::ximage_from_pixmap(wm_hints->icon_mask, r);
if(xim) {
uint8 *data = cvt1to32(xim, xim->width, xim->height);
mask = new Fl_Image(xim->width, xim->height, 32, data, 0,0,0,0);
mask->no_screen(true);
XDestroyImage(xim);
}
}
// If no icon, set default
if(!image) {
image = &default_icon;
mask = 0;
}
}
Icon::~Icon()
{
if(image && image!=&default_icon) { delete image; image=0; }
if(mask) { delete mask; mask=0; }
for(ImageMap::Iterator it(images); it.current(); it++) {
Fl_Image *i = I(it.value());
if(i && i!=&default_icon) {
delete i;
}
}
}
Fl_Image *Icon::get_icon(int W, int H)
{
if (!image) return 0;
Fl_Image *scaled=0, *cached=0;
Fl_String key;
key += Fl_String(W);
key += 'x';
key += Fl_String(H);
if(image==&default_icon)
{
if(W!=image->width() || H!=image->height())
{
cached = I(images.get_value(key));
if(cached) {
//printf("1. Cached\n");
return cached;
}
scaled = image->scale(W, H);
scaled->set_mask(default_icon.create_scaled_bitmap_mask(W, H), true);
images.insert(key, scaled);
return scaled;
} else
return image;
}
cached = I(images.get_value(key));
if(cached) {
//printf("2. Cached\n");
return cached;
}
// Check for default size image
if(W==image->width() && H==image->height()) {
if(mask && mask->get_mask()==0) {
// Init mask
mask->mask_type(MASK_COLORKEY);
mask->colorkey(0xFFFFFFFF);
Pixmap m = mask->create_mask(W, H);
mask->set_mask(m, true);
image->set_mask(mask->get_mask());
}
return image;
}
// Create NEW
scaled = image->scale(W,H);
if(mask) {
Fl_Image *smask = mask->scale(W, H);
smask->mask_type(MASK_COLORKEY);
smask->colorkey(0xFFFFFFFF);
Pixmap m = smask->create_mask(W, H);
delete smask;
scaled->set_mask(m, true);
}
images.insert(key, scaled);
return scaled;
}

26
edewm/Icon.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef _ICON_H_
#define _ICON_H_
#include "Frame.h"
#include <efltk/Fl_Image.h>
#include <efltk/Fl_Renderer.h>
#include <efltk/Fl_Map.h>
typedef Fl_String_Ptr_Map ImageMap;
class Icon
{
public:
Icon(XWMHints *wm_hints);
~Icon();
Fl_Image *get_icon(int W, int H);
private:
ImageMap images;
Fl_Image *image, *mask;
};
#endif

49
edewm/Makefile Normal file
View File

@ -0,0 +1,49 @@
#
# $Id: Makefile 1957 2007-06-25 19:42:47Z vljubovic $
#
# Part of Equinox Desktop Environment (EDE).
# Copyright (c) 2000-2006 EDE Authors.
#
# This program is licenced under terms of the
# GNU General Public Licence version 2 or newer.
# See COPYING for details.
CPPFILES = WMWindow.cpp\
Theme.cpp\
Netwm.cpp\
Mwm.cpp\
Icccm.cpp\
Icon.cpp\
Cursor.cpp\
Desktop.cpp\
Events.cpp\
Frame.cpp\
Hotkeys.cpp\
Tabmenu.cpp\
Titlebar.cpp\
Windowmanager.cpp\
Winhints.cpp\
main.cpp
TARGET = edewm
POFILES = locale/ru.po\
locale/sr.po\
locale/sk.po\
locale/hu.po\
locale/de.po\
locale/fr.po
include ../makeinclude
install:
$(INSTALL_PROGRAM) $(TARGET) $(bindir)
$(INSTALL_LOCALE)
uninstall:
$(RM) $(bindir)/$(TARGET)
clean:
$(RM) $(TARGET)
$(RM) *.o

191
edewm/Mwm.cpp Normal file
View File

@ -0,0 +1,191 @@
#include "Mwm.h"
#include "Frame.h"
#include "Winhints.h"
#include "Windowmanager.h"
void MWM::get_hints(Frame *f)
{
if(f->mwm_hints) {
XFree((char *)f->mwm_hints);
f->mwm_hints = 0;
}
unsigned long n=0;
f->mwm_hints = (MwmHints *)getProperty(f->window(), _XATOM_MWM_HINTS, _XATOM_MWM_HINTS, &n);
if(n >= PROP_MWM_HINTS_ELEMENTS) {
// Fill in the default value for missing fields:
if(!(f->mwm_hints->flags & MWM_HINTS_FUNCTIONS))
f->mwm_hints->functions = MWM_FUNC_ALL;
if(!(f->mwm_hints->flags & MWM_HINTS_DECORATIONS))
f->mwm_hints->decorations = MWM_DECOR_ALL;
} else {
XFree((char *)f->mwm_hints);
f->mwm_hints = 0;
}
}
static long mwm_functions(MwmHints *hints, XSizeHints *sh)
{
long functions = ~0U;
if(hints && (hints->flags & MWM_HINTS_FUNCTIONS))
{
if(hints->functions & MWM_FUNC_ALL)
functions = ~hints->functions;
else
functions = hints->functions;
} else {
if(sh) {
bool minmax = false;
if(sh->min_width == sh->max_width && sh->min_height == sh->max_height) {
functions &= ~MWM_FUNC_RESIZE;
minmax = true;
}
if((minmax && !(sh->flags & PResizeInc)) ||
(sh->width_inc == 0 && sh->height_inc == 0))
functions &= ~MWM_FUNC_MAXIMIZE;
}
}
functions &= (MWM_FUNC_RESIZE | MWM_FUNC_MOVE |
MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE |
MWM_FUNC_CLOSE);
return functions;
}
static long mwm_decors(MwmHints *hints, XSizeHints *sh)
{
long decors = ~0U;
long func = mwm_functions(hints, sh);
if(hints && (hints->flags & MWM_HINTS_DECORATIONS)) {
if(hints->decorations & MWM_DECOR_ALL)
decors = ~hints->decorations;
else
decors = hints->decorations;
} else {
if(sh) {
bool minmax = false;
if(sh->min_width == sh->max_width && sh->min_height == sh->max_height) {
decors &= ~MWM_DECOR_RESIZEH;
minmax = true;
}
if((minmax && !(sh->flags & PResizeInc)) ||
(sh->width_inc == 0 && sh->height_inc == 0))
decors &= ~MWM_DECOR_MAXIMIZE;
}
}
decors &= (MWM_DECOR_BORDER | MWM_DECOR_RESIZEH |
MWM_DECOR_TITLE | MWM_DECOR_MENU |
MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE);
// Add disabled buttons !!!
decors &=
~(/*((func & MWM_FUNC_RESIZE) ? 0 : MWM_DECOR_RESIZEH) |*/
((func & MWM_FUNC_MINIMIZE) ? 0 : MWM_DECOR_MINIMIZE) |
((func & MWM_FUNC_MAXIMIZE) ? 0 : MWM_DECOR_MAXIMIZE));
return decors;
}
bool MWM::update_hints(Frame *f)
{
MwmHints *mwm_hints = f->mwm_hints;
XSizeHints *size_hints = f->size_hints;
long decors = mwm_decors(mwm_hints, size_hints);
long functions = mwm_functions(mwm_hints, size_hints);
bool funcs_only = (mwm_hints &&
(mwm_hints->flags & (MWM_HINTS_FUNCTIONS) == MWM_HINTS_FUNCTIONS) &&
(mwm_hints->flags & (MWM_HINTS_DECORATIONS) != MWM_HINTS_DECORATIONS)
);
// The low bit means "turn the marked items off", invert this.
// Transient windows already have size & iconize buttons turned off:
if(functions & MWM_FUNC_ALL)
functions = ~functions & (f->transient_for_xid ? ~0x58 : -1);
if(decors & MWM_DECOR_ALL)
decors = ~decors & (f->transient_for_xid ? ~0x60 : -1);
int old_decor_flags = f->decor_flags();
int old_func_flags = f->func_flags();
int old_frame_flags = f->frame_flags();
// Get decorations
f->clear_decor_flags();
if(decors & MWM_DECOR_BORDER)
f->set_decor_flag(BORDER);
if(decors & MWM_DECOR_TITLE)
f->set_decor_flag(TITLEBAR);
if(decors & MWM_DECOR_MENU)
f->set_decor_flag(SYSMENU);
if(decors & MWM_DECOR_MINIMIZE)
f->set_decor_flag(MINIMIZE);
if(decors & MWM_DECOR_MAXIMIZE)
f->set_decor_flag(MAXIMIZE);
if(decors & MWM_DECOR_RESIZEH)
f->set_decor_flag(RESIZE);
// Get functions
f->clear_func_flags();
if(functions & MWM_FUNC_RESIZE) {
f->set_func_flag(RESIZE);
if(funcs_only) f->set_decor_flag(RESIZE|BORDER);
}
if(functions & MWM_FUNC_MOVE) {
f->set_func_flag(MOVE);
if(funcs_only) f->set_decor_flag(BORDER);
}
if(functions & MWM_FUNC_MINIMIZE) {
f->set_func_flag(MINIMIZE);
if(funcs_only) f->set_decor_flag(MINIMIZE);
}
if(functions & MWM_FUNC_MAXIMIZE) {
f->set_func_flag(MAXIMIZE);
if(funcs_only) f->set_decor_flag(MAXIMIZE);
}
if(functions & MWM_FUNC_CLOSE) {
f->set_func_flag(CLOSE);
f->set_decor_flag(CLOSE);
}
// some Motif programs use this to disable resize :-(
// and some programs change this after the window is shown (*&%$#%)
if(!(functions & MWM_FUNC_RESIZE) || !(decors & MWM_DECOR_RESIZEH))
f->clear_decor_flag(RESIZE);
else
f->set_decor_flag(RESIZE);
// and some use this to disable the Close function. The commented
// out test is it trying to turn off the mwm menu button: it appears
// programs that do that still expect Alt+F4 to close them, so I
// leave the close on then:
if (!(functions & 0x20) /*|| !(prop[2]&0x10)*/) {
f->clear_func_flag(CLOSE);
f->clear_decor_flag(CLOSE);
} else {
f->set_func_flag(CLOSE);
f->set_decor_flag(CLOSE);
}
// Set modal
if(!f->shown() && mwm_hints && (mwm_hints->flags & MWM_HINTS_INPUT_MODE) && (mwm_hints->input_mode != MWM_INPUT_MODELESS))
f->set_frame_flag(MODAL);
return ((f->frame_flags() ^ old_frame_flags) || (f->decor_flags() ^ old_decor_flags) || (f->func_flags() ^ old_func_flags));
}
void MWM::set_motif_info()
{
MotifWmInfo mwminfo;
mwminfo.flags = MWM_INFO_STARTUP_CUSTOM;
mwminfo.wm_window = root_win;
XChangeProperty(fl_display, root_win, _XATOM_MOTIF_WM_INFO, _XATOM_MOTIF_WM_INFO,
32, PropModeReplace,
(unsigned char *)&mwminfo, 2);
}

83
edewm/Mwm.h Normal file
View File

@ -0,0 +1,83 @@
#ifndef _MWM_H_
#define _MWM_H_
#include <X11/Xmd.h>
#include <X11/Xlib.h>
/* This file is part of the GNU LessTif Library. */
typedef struct {
long flags;
Window wm_window;
} MotifWmInfo;
#define MWM_INFO_STARTUP_STANDARD (1L<<0)
#define MWM_INFO_STARTUP_CUSTOM (1L<<1)
typedef struct {
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long input_mode;
unsigned long status;
} MwmHints;
#define MWM_HINTS_FUNCTIONS (1L << 0)
#define MWM_HINTS_DECORATIONS (1L << 1)
#define MWM_HINTS_INPUT_MODE (1L << 2)
#define MWM_HINTS_STATUS (1L << 3)
#define MWM_FUNC_ALL (1L << 0)
#define MWM_FUNC_RESIZE (1L << 1)
#define MWM_FUNC_MOVE (1L << 2)
#define MWM_FUNC_MINIMIZE (1L << 3)
#define MWM_FUNC_MAXIMIZE (1L << 4)
#define MWM_FUNC_CLOSE (1L << 5)
#define MWM_DECOR_ALL (1L << 0)
#define MWM_DECOR_BORDER (1L << 1)
#define MWM_DECOR_RESIZEH (1L << 2)
#define MWM_DECOR_TITLE (1L << 3)
#define MWM_DECOR_MENU (1L << 4)
#define MWM_DECOR_MINIMIZE (1L << 5)
#define MWM_DECOR_MAXIMIZE (1L << 6)
#define MWM_INPUT_MODELESS 0
#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1
#define MWM_INPUT_SYSTEM_MODAL 2
#define MWM_INPUT_FULL_APPLICATION_MODAL 3
#define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL
#define MWM_TEAROFF_WINDOW (1L<<0)
/*
* atoms
*/
#define _XA_MOTIF_BINDINGS "_MOTIF_BINDINGS"
#define _XA_MOTIF_WM_HINTS "_MOTIF_WM_HINTS"
#define _XA_MOTIF_WM_MESSAGES "_MOTIF_WM_MESSAGES"
#define _XA_MOTIF_WM_OFFSET "_MOTIF_WM_OFFSET"
#define _XA_MOTIF_WM_MENU "_MOTIF_WM_MENU"
#define _XA_MOTIF_WM_INFO "_MOTIF_WM_INFO"
#define _XA_MWM_HINTS _XA_MOTIF_WM_HINTS
#define _XA_MWM_MESSAGES _XA_MOTIF_WM_MESSAGES
#define _XA_MWM_MENU _XA_MOTIF_WM_MENU
#define _XA_MWM_INFO _XA_MOTIF_WM_INFO
#define PROP_MOTIF_WM_HINTS_ELEMENTS 5
#define PROP_MWM_HINTS_ELEMENTS PROP_MOTIF_WM_HINTS_ELEMENTS
////////////////////////////////////
class Frame;
class MWM
{
public:
static void get_hints(Frame *f);
static bool update_hints(Frame *f);
static void set_motif_info();
};
#endif

116
edewm/Netwm.cpp Normal file
View File

@ -0,0 +1,116 @@
#include "Netwm.h"
#include "Frame.h"
#include "Winhints.h"
#include "Windowmanager.h"
#include "debug.h"
void NETWM::get_strut(Frame *f)
{
unsigned long size = 0;
CARD32 *val=0;
val = (CARD32 *)getProperty(f->window(), _XA_NET_WM_STRUT, XA_CARDINAL, &size);
if(!val) return;
if ((size / (sizeof(CARD32))) != 4) {
DBG("Window 0x%lx has wrong STRUT value (%d)\n", f->window(), size / (sizeof(CARD32)));
XFree((char*)val);
return;
}
if(!f->strut_) f->strut_ = new Fl_Rect();
int l=val[0];
int r=val[1];
int t=val[2];
int b=val[3];
f->strut_->set(l, t, l+r, t+b);
XFree((char*)val);
}
bool NETWM::get_window_type(Frame *f)
{
unsigned long size = 0;
Atom *val=0;
int ret=0;
int wintype = TYPE_NORMAL;
val = (Atom *)getProperty(f->window(), _XA_NET_WM_WINDOW_TYPE, XA_ATOM, &size, &ret);
if(!val || ret!=Success) {
f->window_type(TYPE_NORMAL);
return false;
}
for(uint i = 0; i < (size / (sizeof(Atom))); i++)
{
if (val[i] == _XA_NET_WM_WINDOW_TYPE_DOCK)
{
DBG("_XA_NET_WM_WINDOW_TYPE_DOCK\n");
wintype = TYPE_DOCK;
break;
}
else if (val[i] == _XA_NET_WM_WINDOW_TYPE_TOOLBAR)
{
DBG("_XA_NET_WM_WINDOW_TYPE_TOOLBAR\n");
wintype = TYPE_TOOLBAR;
break;
}
else if (val[i] == _XA_NET_WM_WINDOW_TYPE_MENU)
{
DBG("_XA_NET_WM_WINDOW_TYPE_MENU\n");
wintype = TYPE_MENU;
break;
}
else if (val[i] == _XA_NET_WM_WINDOW_TYPE_UTIL)
{
DBG("_XA_NET_WM_WINDOW_TYPE_UTIL\n");
wintype = TYPE_UTIL;
break;
}
else if (val[i] == _XA_NET_WM_WINDOW_TYPE_DIALOG)
{
DBG("_XA_NET_WM_WINDOW_TYPE_DIALOG\n");
wintype = TYPE_DIALOG;
break;
}
else if (val[i] == _XA_NET_WM_WINDOW_TYPE_NORMAL)
{
DBG("_XA_NET_WM_WINDOW_TYPE_NORMAL\n");
wintype = TYPE_NORMAL;
break;
}
else if (val[i] == _XA_NET_WM_WINDOW_TYPE_DESKTOP)
{
DBG("_XA_NET_WM_WINDOW_TYPE_DESKTOP\n");
wintype = TYPE_DESKTOP;
break;
} else {
DBG("Unknown NETWM window type 0x%08lx\n", val[i]);
}
} /* for */
XFree((char*)val);
f->window_type(wintype);
return true;
}
void NETWM::set_active_window(Window win)
{
//Set NET-WM active window
XChangeProperty(fl_display, root_win, _XA_NET_ACTIVE_WINDOW, XA_WINDOW, 32,
PropModeReplace, (unsigned char *)&win, 1);
}
char *NETWM::get_title(Frame *f)
{
int ret=0;
char *title = (char*)getProperty(f->window(), _XA_NET_WM_NAME, _XA_UTF8_STRING, 0, &ret);
if(!title || ret!=Success) {
return 0;
}
return title;
}

17
edewm/Netwm.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef _NETWM_H_
#define _NETWM_H_
#include <X11/Xlib.h>
class Frame;
class NETWM
{
public:
static void get_strut(Frame *f);
static bool get_window_type(Frame *f);
static char *get_title(Frame *f);
static void set_active_window(Window win);
};
#endif

201
edewm/Tabmenu.cpp Normal file
View File

@ -0,0 +1,201 @@
//nothing yet!
#include <efltk/Fl_Box.h>
#include <efltk/Fl_Pack.h>
#include "Icon.h"
#include "Frame.h"
#include "Desktop.h"
#include "debug.h"
#include "Windowmanager.h"
class TabWin : public Fl_Window
{
public:
TabWin(Frame_List &list, int dir) : Fl_Window(Fl::w()/2-100, Fl::h()/2-40, 200, 96, "tabwin")
{
direction = dir;
selected=-1;
box(FL_UP_BOX);
label = new Fl_Box(10,50,180,20);
label->box(FL_THIN_DOWN_BOX);
label->align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE|FL_ALIGN_LEFT);
p = new Fl_Pack(0,0,200,50);
p->type(Fl_Pack::HORIZONTAL);
p->layout_spacing(3);
p->begin();
for(uint n=0; n<list.size(); n++) {
Frame *f = list[n];
Fl_Box *b = new Fl_Box(0,0,50,50,f->label());
b->color(FL_GRAY);
b->layout_align(FL_ALIGN_LEFT);
b->user_data(f);
b->label_type(FL_NO_LABEL);
b->box(FL_BORDER_BOX);
if(f->icon()) {
b->image(f->icon()->get_icon(48,48));
}
if(f->active())
{
selected = n;
b->set_selected();
b->color(FL_RED);
b->box(FL_THIN_DOWN_BOX);
label->label(f->label());
}
}
p->end();
layout();
create();
}
void next() {
if(selected==-1) selected=0;
if(p->child(selected)->selected())
p->child(selected)->clear_selected();
p->child(selected)->color(FL_GRAY);
p->child(selected)->box(FL_BORDER_BOX);
selected += direction;
if(direction==1 && selected>=p->children()) {
selected = 0;
}
else if(direction==-1 && selected<0) {
selected = p->children()-1;
}
p->child(selected)->set_selected();
p->child(selected)->color(p->selection_color());
p->child(selected)->box(FL_THIN_DOWN_BOX);
label->label(p->child(selected)->label());
redraw(FL_DAMAGE_ALL);
}
Frame *selected_frame() {
if(selected==-1) return 0;
return (Frame *)p->child(selected)->user_data();
}
int handle(int ev);
void layout();
void draw();
Fl_Pack *p;
Fl_Box *label;
int selected;
int direction;
};
TabWin *win=0;
int TabWin::handle(int ev)
{
return Fl_Window::handle(ev);
}
void TabWin::draw()
{
if(damage()&FL_DAMAGE_ALL || damage()&FL_DAMAGE_EXPOSE) {
Fl_Window::draw();
}
}
void TabWin::layout()
{
p->layout();
int w = p->w()+20;
if(w<300) w=300;
int h=100;
int x = Fl::w()/2-(w/2);
int y = Fl::h()/2-(h/2);
resize(x, y, w, h);
p->resize(10, 10, p->w(), 50);
label->resize(10, h-30, w-20, 20);
Fl_Window::layout();
}
static void timeout(void *data) {
if(!Fl::get_key_state(FL_Alt_L))
{
Frame *f = win->selected_frame();
if(f) {
f->activate();
f->raise();
}
win->destroy();
delete win;
win=0;
} else
Fl::repeat_timeout(0.1, timeout, 0);
}
void show_tabmenu(int direction)
{
if(!win)
{
Frame_List list;
for(uint n=stack_order.size(); n--;) {
Frame *f = stack_order[n];
if( (f->state()==NORMAL || f->state()==ICONIC) && (f->desktop()==Desktop::current() || !f->desktop()) && !f->frame_flag(SKIP_LIST) && !f->frame_flag(SKIP_FOCUS) && !f->frame_flag(CLICK_TO_FOCUS) ) {
list.append(f);
}
}
if(list.count()<1) return;
if(list.count()==1) {
list[0]->activate();
list[0]->raise();
return;
}
win = new TabWin(list, direction);
XSetWindowAttributes attr;
attr.border_pixel = 0;
attr.colormap = fl_colormap;
attr.bit_gravity = 0;
attr.event_mask = ExposureMask | StructureNotifyMask
| KeyPressMask | KeyReleaseMask | KeymapStateMask | FocusChangeMask
| ButtonPressMask | ButtonReleaseMask
| EnterWindowMask | LeaveWindowMask
| PointerMotionMask;
attr.override_redirect = 1;
attr.save_under = 0;
int mask = CWBorderPixel|CWColormap|CWEventMask|CWBitGravity|CWOverrideRedirect|CWSaveUnder;
Window xid = XCreateWindow(fl_display,
fl_xid(root),
win->x(), win->y(), win->w(), win->h(),
0, // borderwidth
fl_visual->depth,
InputOutput,
fl_visual->visual,
mask, &attr);
XDestroyWindow(fl_display, fl_xid(win));
Fl_X::i(win)->xid = xid;
win->show();
XMapWindow(fl_display, xid);
Fl::add_timeout(0.1, timeout, 0);
}
win->next();
}

117
edewm/Theme.cpp Normal file
View File

@ -0,0 +1,117 @@
#include "Theme.h"
#include <efltk/Fl.h>
namespace Theme {
Fl_Image *images[IMAGES_LAST];
Fl_Color _frame_color;
Fl_Image_List loaded;
bool use;
bool use_theme() { return use; }
void use_theme(bool val) { use = val; }
static Fl_Image *load_image(const char *name, const Fl_String &path, Fl_Config &cfg)
{
Fl_String filename;
cfg.read(name, filename, 0);
Fl_String img_path(path + filename);
return Fl_Image::read(img_path);
}
bool load_theme(const Fl_String &file)
{
if(!fl_file_exists(file))
return false;
int pos = file.rpos('/');
if(pos==-1) return false;
unload_theme();
Fl_String path(file.sub_str(0, pos+1));
Fl_String filename;
Fl_Config themeconf(file);
themeconf.set_section("Theme");
themeconf.read("Frame color", _frame_color, FL_NO_COLOR);
images[TITLEBAR_BG] = load_image("Title image", path, themeconf);
if(images[TITLEBAR_BG])
loaded.append(images[TITLEBAR_BG]);
Fl_Image *up = load_image("Close image up", path, themeconf);
Fl_Image *down = load_image("Close image down", path, themeconf);
if(up && down) {
images[TITLEBAR_CLOSE_UP] = up;
images[TITLEBAR_CLOSE_DOWN] = down;
up->state_effect(false);
down->state_effect(false);
loaded.append(up);
loaded.append(down);
} else {
if(up) delete up;
if(down) delete down;
}
up = load_image("Maximize image up", path, themeconf);
down = load_image("Maximize image down", path, themeconf);
if(up && down) {
images[TITLEBAR_MAX_UP] = up;
images[TITLEBAR_MAX_DOWN] = down;
up->state_effect(false);
down->state_effect(false);
loaded.append(up);
loaded.append(down);
} else {
if(up) delete up;
if(down) delete down;
}
up = load_image("Minimize image up", path, themeconf);
down = load_image("Minimize image down", path, themeconf);
if(up && down) {
images[TITLEBAR_MIN_UP] = up;
images[TITLEBAR_MIN_DOWN] = down;
up->state_effect(false);
down->state_effect(false);
loaded.append(up);
loaded.append(down);
} else {
if(up) delete up;
if(down) delete down;
}
return true;
}
void unload_theme()
{
for(unsigned n=0; n<loaded.size(); n++) {
delete loaded[n];
}
loaded.clear();
for(int n=0; n<IMAGES_LAST; n++)
images[n] = 0;
_frame_color = FL_NO_COLOR;
}
Fl_Image *image(int which)
{
if(which<0 || which>=IMAGES_LAST) {
Fl::warning("Invalid theme image index: %d", which);
return 0;
}
return images[which];
}
Fl_Color frame_color()
{
return _frame_color;
}
}; /* namespace Theme */

31
edewm/Theme.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef _THEME_H_
#define _THEME_H_
#include <efltk/Fl_Image.h>
#include <efltk/Fl_Image_List.h>
#include <efltk/Fl_Multi_Image.h>
#include <efltk/Fl_Config.h>
#include <efltk/Fl_String.h>
enum {
TITLEBAR_BG = 0,
TITLEBAR_CLOSE_UP, TITLEBAR_CLOSE_DOWN,
TITLEBAR_MAX_UP, TITLEBAR_MAX_DOWN,
TITLEBAR_MIN_UP, TITLEBAR_MIN_DOWN,
IMAGES_LAST
};
namespace Theme {
extern bool use_theme();
extern void use_theme(bool val);
extern bool load_theme(const Fl_String &file);
extern void unload_theme();
extern Fl_Image *image(int which);
extern Fl_Color frame_color();
};
#endif

657
edewm/Titlebar.cpp Normal file
View File

@ -0,0 +1,657 @@
#include "Titlebar.h"
#include "Windowmanager.h"
#include "Frame.h"
#include "Desktop.h"
#include "Icon.h"
#include "Theme.h"
#include <efltk/Fl_Item.h>
#include <efltk/Fl_Divider.h>
#include <efltk/fl_draw.h>
#include <efltk/Fl_Util.h>
#include <efltk/Fl_Menu_.h>
#include <efltk/Fl.h>
#include <efltk/fl_ask.h>
#include <sys/select.h>
#include <sys/time.h>
#include "config.h"
#include "debug.h"
extern bool grab();
extern void grab_cursor(bool grab);
int Titlebar::box_type = 0;
int Titlebar::label_align = FL_ALIGN_LEFT;
int Titlebar::default_height = 20;
//Fl_Config wm_config(fl_find_config_file("wmanager.conf", true));
static Fl_Menu_ *title_menu=0;
Frame *menu_frame=0; //This is set to frame,where menu were popped up
// this is called when user clicks the buttons:
void Frame::cb_button_close(Fl_Button* b)
{
close();
}
void Frame::cb_button_kill(Fl_Button* b)
{
kill();
}
/*
static void animate(int fx, int fy, int fw, int fh,
int tx, int ty, int tw, int th)
{
# undef max
# define max(a,b) (a) > (b) ? (a) : (b)
double max_steps = max( (tw-fw), (th-fh) );
double min_steps = max( (fw-tw), (fh-th) );
double steps = max(max_steps, min_steps);
steps/=Frame::animate_speed;
double sx = max( ((double)(fx-tx)/steps), ((double)(tx-fx)/steps) );
double sy = max( ((double)(fy-ty)/steps), ((double)(ty-fy)/steps) );
double sw = max( ((double)(fw-tw)/steps), ((double)(tw-fw)/steps) );
double sh = max( ((double)(fh-th)/steps), ((double)(th-fh)/steps) );
int xinc = fx < tx ? 1 : -1;
int yinc = fy < ty ? 1 : -1;
int winc = fw < tw ? 1 : -1;
int hinc = fh < th ? 1 : -1;
double rx=fx,ry=fy,rw=fw,rh=fh;
XGrabServer(fl_display);
while(steps-- > 0) {
rx+=(sx*xinc);
ry+=(sy*yinc);
rw+=(sw*winc);
rh+=(sh*hinc);
draw_overlay((int)rx, (int)ry, (int)rw, (int)rh);
Fl::sleep(10);
XFlush(fl_display);
}
clear_overlay();
XUngrabServer(fl_display);
}
void Frame::cb_button_max(Fl_Button* b)
{
if(maximized) {
if(Frame::animate) {
::animate(x(), y(), w(), h(),
restore_x, restore_y, restore_w, restore_h);
}
set_size(restore_x, restore_y, restore_w, restore_h);
maximized = false;
} else {
bool m = true;
restore_x = x();
restore_y = y();
restore_w = w();
restore_h = h();
int W=root->w(), H=root->h();
W-=offset_w;
H-=offset_h;
if(ICCCM::get_size(this, W, H)) {
m=false;
}
W+=offset_w;
H+=offset_h;
if(Frame::animate) {
::animate(x(), y(), w(), h(),
root->x(), root->y(), root->w(), root->h());
}
set_size(root->x(), root->y(), W, H);
maximized = m;
redraw();
}
}
*/
void Frame::cb_button_max(Fl_Button* b)
{
if(maximized)
restore();
else
maximize();
}
void Frame::cb_button_min(Fl_Button* b)
{
iconize();
}
// Min/Max/Close button symbols drawing stuff:
extern int fl_add_symbol(const char *name, void (*drawit)(Fl_Color), int scalable);
#define vv(x,y) fl_vertex(x,y)
void draw_cl(Fl_Color col)
{
fl_rotate(45);
fl_color(col);
vv(-0.9f,-0.12f); vv(-0.9f,0.12f); vv(0.9f,0.12f); vv(0.9f,-0.12f); fl_fill_stroke(FL_DARK3);
vv(-0.12f,-0.9f); vv(-0.12f,0.9f); vv(0.12f,0.9f); vv(0.12f,-0.9f); fl_fill_stroke(FL_DARK3);
}
#define MAX_OF .6f
void draw_max(Fl_Color col)
{
fl_color(col);
vv(-MAX_OF, -MAX_OF); vv(MAX_OF, -MAX_OF);
vv(MAX_OF,-MAX_OF+0.4); vv(-MAX_OF,-MAX_OF+0.4);
fl_fill();
vv(MAX_OF,-MAX_OF); vv(MAX_OF,MAX_OF);
vv(-MAX_OF,MAX_OF); vv(-MAX_OF,-MAX_OF);
fl_stroke();
}
#define MIN_OF .5f
void draw_min(Fl_Color col)
{
fl_color(col);
vv(-MIN_OF, MIN_OF); vv(MIN_OF, MIN_OF);
vv(MIN_OF, MIN_OF+.2f); vv(-MIN_OF, MIN_OF+.2f);
fl_fill();
}
// static callbacks for efltk:
void button_cb_close(Fl_Widget *w, void *d)
{
Frame *f = d ? (Frame *)d : menu_frame;
f->cb_button_close((Fl_Button*)w);
}
void button_cb_kill(Fl_Widget *w, void *d)
{
Frame *f = d ? (Frame *)d : menu_frame;
f->cb_button_kill((Fl_Button*)w);
}
void button_cb_max(Fl_Widget *w, void *d)
{
Frame *f = d ? (Frame *)d : menu_frame;
f->cb_button_max((Fl_Button*)w);
}
void button_cb_min(Fl_Widget *w, void *d)
{
Frame *f = d ? (Frame *)d : menu_frame;
f->cb_button_min((Fl_Button*)w);
}
void Titlebar::cb_change_desktop(Fl_Widget *w, void *data)
{
Desktop *d = (Desktop*)data;
menu_frame->desktop_ = d;
if(d && d!=Desktop::current()) {
Desktop::current(d);
menu_frame->raise();
}
menu_frame->send_desktop();
menu_frame=0;
}
void update_desktops(Fl_Group *g)
{
g->clear();
g->begin();
Fl_Item *i;
i = new Fl_Item(_("Sticky"));
i->type(Fl_Item::TOGGLE);
i->callback(Titlebar::cb_change_desktop);
if(menu_frame->desktop()) {
i->clear_value();
i->user_data(0);
} else {
i->set_value();
i->user_data(Desktop::current());
}
new Fl_Divider();
for(uint n=0; n<desktops.size(); n++) {
Desktop *d = desktops[n];
i = new Fl_Item(d->name());
i->type(Fl_Item::RADIO);
if(menu_frame->desktop()==d) i->set_value();
else i->clear_value();
i->callback(Titlebar::cb_change_desktop, d);
}
g->end();
}
#include "WMWindow.h"
#include <efltk/Fl_Box.h>
#include <efltk/Fl_Divider.h>
#include <efltk/Fl_Value_Input.h>
#include <efltk/fl_ask.h>
Fl_Button *ok_button;
Fl_Value_Input *w_width, *w_height;
//Fl_Input *size;
static WMWindow *win = 0;
static void real_set_size_cb(Fl_Widget *w, void *d)
{
Frame *f = (Frame*)d;
int W = (int)w_width->value();
int H = (int)w_height->value();
ICCCM::get_size(f, W, H);
f->set_size(f->x(), f->y(), W, H);
f->redraw();
win->destroy();
}
static void close_set_size_cb(Fl_Widget *w, void *d)
{
win->destroy();
}
static void set_size_cb(Fl_Widget *w, void *d)
{
win = new WMWindow(300, 110, _("Set size"));
Fl_Box *b = new Fl_Box(5, 5, 295, 15, _("Set size to window:"));
b->label_font(b->label_font()->bold());
Fl_String tmplabel = menu_frame->label();
if (tmplabel.length() > 50)
tmplabel = tmplabel.sub_str(0,20) + " ... " + tmplabel.sub_str(tmplabel.length()-20,20);
b = new Fl_Box(0, 20, 296, 15, tmplabel);
w_width = new Fl_Value_Input(45, 45, 90, 20, _("width:"));
w_width->step(1);
w_height = new Fl_Value_Input(195, 45, 90, 20, _("height:"));
w_height->step(1);
new Fl_Divider(5, 70, 290, 10);
Fl_Button *but = ok_button = new Fl_Button(60,80,85,25, _("&OK"));
but->callback(real_set_size_cb);
but = new Fl_Button(155, 80, 85, 25, _("&Cancel"));
but->callback(close_set_size_cb);
win->end();
w_width->value(menu_frame->w());
w_height->value(menu_frame->h());
ok_button->user_data(menu_frame);
win->callback(close_set_size_cb);
win->show();
}
void Titlebar::popup_menu(Frame *frame)
{
menu_frame = frame;
static Fl_Widget *max;
static Fl_Widget *set_size;
static Fl_Widget *min;
static Fl_Group *desktop;
if(!title_menu) {
title_menu = new Fl_Menu_();
max=title_menu->add(_("Maximize"), 0, button_cb_max);
min=title_menu->add(_("Minimize"), 0, button_cb_min);
set_size=title_menu->add(_("Set size"), 0, set_size_cb, 0, FL_MENU_DIVIDER);
desktop=(Fl_Group*)title_menu->add(_("To Desktop"), 0, 0, 0, FL_SUBMENU|FL_MENU_DIVIDER);
title_menu->add(_("Kill"), 0, button_cb_kill);
title_menu->add(_("Close"), 0, button_cb_close);
title_menu->end();
}
update_desktops(desktop);
if(menu_frame->maximized) max->label(_("Restore"));
else max->label(_("Maximize"));
// we don't want animation for dialogs and utils frames
// MWM hints can set MAXIMIZE and MINIMIZE options separately
// so we must check them each
if(menu_frame->window_type() == TYPE_NORMAL)
{
if(menu_frame->decor_flag(MAXIMIZE))
{
max->activate();
set_size->activate();
}
if(menu_frame->decor_flag(MINIMIZE))
min->activate();
}
else
{
max->deactivate();
set_size->deactivate();
min->deactivate();
}
title_menu->Fl_Group::focus(-1);
title_menu->popup(Fl::event_x_root(), Fl::event_y_root());
menu_frame = 0;
}
Titlebar_Button::Titlebar_Button(int type)
: Fl_Button(0,0,0,0), m_type(type)
{
focus_box(FL_NO_BOX);
label_type(FL_SYMBOL_LABEL);
switch(m_type) {
case TITLEBAR_MAX_UP: label("@mx"); break;
case TITLEBAR_MIN_UP: label("@ii"); break;
case TITLEBAR_CLOSE_UP: label("@xx"); break;
};
}
void Titlebar_Button::draw()
{
int idx = m_type;
if(flags() & FL_VALUE) idx++;
Fl_Image *i = Theme::image(idx);
if(i) {
Fl_Flags scale = 0;
if(i->height()!=h()) scale = FL_ALIGN_SCALE;
i->draw(0,0,w(),h(), scale);
} else {
Fl_Button::draw();
}
}
Titlebar::Titlebar(int x,int y,int w,int h,const char *l)
: Fl_Window(x,y,w,h,0),
_close(TITLEBAR_CLOSE_UP), _max(TITLEBAR_MAX_UP), _min(TITLEBAR_MIN_UP)
{
f = (Frame *)parent();
title_icon = 0;
text_w=0;
static bool init = false;
if(!init) {
fl_add_symbol("xx", draw_cl, 1);
fl_add_symbol("mx", draw_max, 1);
fl_add_symbol("ii", draw_min, 1);
init = true;
}
setting_changed();
end();
}
Titlebar::~Titlebar()
{
}
void Titlebar::setting_changed()
{
_close.callback(button_cb_close, f);
_max.callback(button_cb_max, f);
_min.callback(button_cb_min, f);
if(Titlebar::default_height != h()) {
h(Titlebar::default_height);
f->updateBorder();
}
layout();
redraw();
}
void Titlebar::show()
{
if(!shown()) create();
XMapWindow(fl_display, fl_xid(this));
XRaiseWindow(fl_display, fl_xid(this));
}
void Titlebar::hide()
{
if(shown())
XUnmapWindow(fl_display, fl_xid(this));
}
#define set_box(b) if(box()!=b) box(b); break
void Titlebar::layout()
{
if(Theme::use_theme()) {
if(box()!=FL_FLAT_BOX) box(FL_FLAT_BOX);
} else {
switch(box_type) {
default:
case 0: set_box(FL_FLAT_BOX);
case 1: set_box(FL_HOR_SHADE_FLAT_BOX);
case 2: set_box(FL_THIN_DOWN_BOX);
case 3: set_box(FL_UP_BOX);
case 4: set_box(FL_DOWN_BOX);
case 5: set_box(FL_PLASTIC_BOX);
}
}
int W = w()-box()->dx();
int lsize = h()/2+2;
label_size(lsize);
// Try to detect what buttons are showed
if(!f->func_flag(MINIMIZE)) _min.deactivate(); else _min.activate();
if(!f->func_flag(MAXIMIZE)) _max.deactivate(); else _max.activate();
if(!f->decor_flag(MINIMIZE) || f->frame_flag(KEEP_ASPECT)) _min.hide();
if(!f->decor_flag(MAXIMIZE) || f->frame_flag(KEEP_ASPECT)) _max.hide();
if(f->size_hints->min_width==f->size_hints->max_width || f->transient_for_xid) {
_min.hide();
_max.hide();
} else {
_min.show();
_max.show();
}
int offset=0;
int s = h();
int mid = 0;
if(!Theme::use_theme()) {
s -= 4;
mid = 2;
offset=2;
}
int bx = W-s-offset;
_close.resize(bx, mid, s, s);
if(_close.visible()) bx -= s+offset;
_max.resize(bx, mid, s, s);
if(_max.visible()) bx -= s+offset;
_min.resize(bx, mid, s, s);
text_w = bx - (f->decor_flag(SYSMENU)?h():0) - 10;
fl_font(label_font(), label_size());
if(!f->label().empty()) {
Fl_Widget::label(fl_cut_line(f->label(), text_w));
if(strcmp(label(), f->label())) {
tooltip(f->label());
} else {
tooltip("");
}
} else {
label("");
tooltip("");
}
// Reset layout flags
Fl_Widget::layout();
}
void Titlebar::draw()
{
DBG("Titlebar::draw(): %s", label().c_str());
if(Theme::use_theme() && Theme::image(TITLEBAR_BG)) {
int X=0, Y=0, W=w(), H=h();
Theme::image(TITLEBAR_BG)->draw(X,Y,W,H,FL_ALIGN_SCALE);
} else {
draw_box();
}
int s=h()-4;
// Resize and set image & mask
if(f->icon() && f->decor_flag(SYSMENU)) {
title_icon = f->icon()->get_icon(s, s);
} else
title_icon = 0;
int tx = box()->dx()+1;
if(title_icon) {
title_icon->draw(2,2, s, s);
tx += s + 5; // Separate text a few pixels from icon
}
draw_label(tx, 0, text_w, h(), Titlebar::label_align);
draw_child(_close);
draw_child(_max);
draw_child(_min);
}
int Titlebar::handle(int event)
{
static bool grabbed=false;
static int dx,dy,nx,ny;
switch(event)
{
case FL_PUSH: {
if(grabbed) return 1;
dx = Fl::event_x_root()-f->x();
dy = Fl::event_y_root()-f->y();
nx = Fl::event_x_root()-dx;
ny = Fl::event_y_root()-dy;
// Send event to buttons...
for(int i = children(); i--;) {
Fl_Widget& o = *child(i);
int mx = Fl::event_x() - o.x() - 2;
int my = Fl::event_y() - o.y() - 2;
if (mx >= 0 && mx < o.w() && my >= 0 && my < o.h()+4)
if(child(i)->send(event)) {
extern bool handle_title;
handle_title = false;
return 1;
}
}
if(Fl::event_clicks() && Fl::event_button()==1) {
// we don't want animation for dialogs and utils frames
if(f->window_type() == TYPE_NORMAL && f->decor_flag(MAXIMIZE))
f->cb_button_max(0);
Fl::event_clicks(0);
return 1;
} else if (Fl::event_button()==3) {
Titlebar::popup_menu(f);
return 1;
}
return 1;
}
case FL_RELEASE: {
if(Fl::event_state(FL_BUTTON1)) return 1;
if(grabbed) {
if(!Frame::do_opaque) {
clear_overlay();
f->set_size(nx, ny, f->w(), f->h());
XUngrabServer(fl_display);
}
grab_cursor(false);
grabbed = false;
}
if(root->get_cursor()==FL_CURSOR_MOVE)
root->set_default_cursor();
if (Fl::event_is_click()) {
f->activate();
f->raise();
}
return 1;
}
case FL_DRAG: {
if(Fl::event_is_click()) return 1; // don't drag yet
if(!Fl::event_state(FL_BUTTON1)) return 0;
// Change to MOVE cursor
if(root->get_cursor()!=FL_CURSOR_MOVE) {
root->set_cursor(FL_CURSOR_MOVE, FL_WHITE, FL_BLACK);
}
// We need to grab server while moving,
// since if underlying window redraws our overlay will fuck up...
if(!grabbed) {
if(!Frame::do_opaque) XGrabServer(fl_display);
grab_cursor(true);
grabbed=true;
}
nx = Fl::event_x_root()-dx;
ny = Fl::event_y_root()-dy;
f->handle_move(nx, ny);
return 1;
}
// default:
// return 1;
}
return 0;
}

59
edewm/Titlebar.h Normal file
View File

@ -0,0 +1,59 @@
#ifndef _TITLEBAR_H_
#define _TITLEBAR_H_
class Frame;
#include <efltk/Fl_Button.h>
#include <efltk/Fl_Window.h>
#include <efltk/Fl_Multi_Image.h>
#include <efltk/Fl_Double_Window.h>
#include <efltk/Fl_Group.h>
#include <efltk/x.h>
#include <efltk/Fl_Image.h>
class Titlebar_Button : public Fl_Button
{
int m_type;
public:
Titlebar_Button(int type);
void draw();
};
class Titlebar : public Fl_Window {
friend class Frame;
public:
Titlebar(int x,int y,int w,int h,const char *l=0);
virtual ~Titlebar();
void setting_changed();
void show();
void hide();
virtual void draw();
virtual int handle(int event);
virtual void layout();
void draw_opaque(int, int, int, int);
Fl_Button *close() { return &_close; }
Fl_Button *min() { return &_min; }
Fl_Button *max() { return &_max; }
static void popup_menu(Frame *frame);
static void cb_change_desktop(Fl_Widget *w, void *data);
static int box_type;
static int label_align;
static int default_height;
Frame *f;
protected:
Fl_Image *title_icon;
Titlebar_Button _close, _max, _min;
int text_w;
};
#endif

43
edewm/WMWindow.cpp Normal file
View File

@ -0,0 +1,43 @@
// X does not echo back the window-map events (it probably should when
// override_redirect is off). Unfortunately this means you have to use
// this subclass if you want a "normal" fltk window, it will force a
// Frame to be created and destroy it upon hide.
// Warning: modal() does not work! Don't turn it on as it screws up the
// interface with the window borders. You can use set_non_modal() to
// disable the iconize box but the window manager must be written to
// not be modal.
#include <efltk/Fl.h>
#include "WMWindow.h"
#include "Frame.h"
#include "Windowmanager.h"
extern int dont_set_event_mask;
void WMWindow::create()
{
Fl_Window::create();
if(!frame) {
dont_set_event_mask = 1;
frame = new Frame(fl_xid(this));
dont_set_event_mask = 0;
}
}
void WMWindow::destroy()
{
if(frame) {
frame->destroy_frame();
frame=0;
}
Fl_Window::destroy();
}
int WMWindow::handle(int e)
{
if(e==FL_PUSH || e==FL_MOUSEWHEEL) {
frame->content_click();
}
return Fl_Window::handle(e);
}

30
edewm/WMWindow.h Normal file
View File

@ -0,0 +1,30 @@
// X does not echo back the window-map events (it probably should when
// override_redirect is off). Unfortunately this means you have to use
// this subclass if you want a "normal" fltk window, it will force a
// Frame to be created and destroy it upon hide.
// Warning: modal() does not work! Don't turn it on as it screws up the
// interface with the window borders. You can use set_non_modal() to
// disable the iconize box but the window manager must be written to
// not be modal.
#ifndef _WMWINDOW_H_
#define _WMWINDOW_H_
#include <efltk/Fl_Window.h>
class Frame;
class WMWindow : public Fl_Window {
Frame* frame;
static void cb(Fl_Widget *w, void *) { ((Fl_Window*)w)->destroy(); }
public:
WMWindow(int W, int H, const char* L = 0) : Fl_Window(W,H,L) { frame=0; callback(cb); }
virtual void create();
virtual void destroy();
virtual int handle(int e);
};
#endif

618
edewm/Windowmanager.cpp Normal file
View File

@ -0,0 +1,618 @@
#include "Windowmanager.h"
#include "Icccm.h"
#include "Frame.h"
#include "Desktop.h"
#include "Winhints.h"
#include "Theme.h"
#include <X11/Xproto.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../exset/exset.h"
#include "config.h"
#include "debug.h"
WindowManager *root;
Window root_win;
Frame_List remove_list;
Frame_List stack_order;
Frame_List map_order;
////////////////////////////////////////////////////////////////
static int initializing;
Exset xset;
static const char* program_name;
// in Hotkeys.cpp
extern int Handle_Hotkey();
extern void Grab_Hotkeys();
extern void read_hotkeys_configuration();
void read_disp_configuration();
#if DESKTOPS
extern void init_desktops();
#endif
static const char* cfg, *cbg;
Fl_Color title_active_color, title_active_color_text;
Fl_Color title_normal_color, title_normal_color_text;
////////////////////////////////////////////////////////////////
// fltk calls this for any events it does not understand:
static int wm_event_handler(int e)
{
if(fl_xevent.type == KeyPress) e=FL_KEY;
// XEvent that fltk did not understand.
if(!e) {
Window window = fl_xevent.xany.window;
// unfortunately most of the redirect events put the interesting
// window id in a different place:
switch (fl_xevent.type) {
case CirculateNotify:
case CirculateRequest:
case ConfigureNotify:
case ConfigureRequest:
case CreateNotify:
case GravityNotify:
case MapNotify:
case MapRequest:
case ReparentNotify:
case UnmapNotify:
window = fl_xevent.xmaprequest.window;
break;
}
for(uint n=stack_order.size(); n--;) {
Frame *c = stack_order[n];
if (c->window() == window || fl_xid(c) == window) {
return c->handle(&fl_xevent);
}
}
return root->handle(&fl_xevent);
} else
return root->handle(e);
return 0;
}
static int xerror_handler(Display* d, XErrorEvent* e) {
if(initializing && (e->request_code == X_ChangeWindowAttributes) && e->error_code == BadAccess)
Fl::fatal(_("Another window manager is running. You must exit it before running %s."), program_name);
#ifndef DEBUG
if (e->error_code == BadWindow) return 0;
if (e->error_code == BadColor) return 0;
#endif
char buf1[128], buf2[128];
sprintf(buf1, "XRequest.%d", e->request_code);
XGetErrorDatabaseText(d,"",buf1,buf1,buf2,128);
XGetErrorText(d, e->error_code, buf1, 128);
Fl::warning("%s: %s: %s 0x%lx", program_name, buf2, buf1, e->resourceid);
return 0;
}
WindowManager::WindowManager(int argc, char *argv[])
: Fl_Window(0, 0, Fl::w(), Fl::h())
{
root = this;
xset = new Exset();
init_wm(argc, argv);
box(FL_NO_BOX);
}
// consume a switch from argv. Returns number of words eaten, 0 on error:
int arg(int argc, char **argv, int &i) {
const char *s = argv[i];
if (s[0] != '-') return 0;
s++;
// do single-word switches:
if (!strcmp(s,"x")) {
//exit_flag = 1;
i++;
return 1;
}
// do switches with a value:
const char *v = argv[i+1];
if (i >= argc-1 || !v)
return 0; // all the rest need an argument, so if missing it is an error
if (!strcmp(s, "cfg")) {
cfg = v;
} else if (!strcmp(s, "cbg")) {
cbg = v;
} else if (*s == 'v') {
int visid = atoi(v);
fl_open_display();
XVisualInfo templt; int num;
templt.visualid = visid;
fl_visual = XGetVisualInfo(fl_display, VisualIDMask, &templt, &num);
if (!fl_visual) Fl::fatal("No visual with id %d",visid);
fl_colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen),
fl_visual->visual, AllocNone);
} else
return 0; // unrecognized
// return the fact that we consumed 2 switches:
i += 2;
return 2;
}
int real_align(int i) {
switch(i) {
default:
case 0: break;
case 1: return FL_ALIGN_RIGHT;
case 2: return FL_ALIGN_CENTER;
}
return FL_ALIGN_LEFT;
}
void read_configuration()
{
Fl_String buf;
Fl_Config wmconf(fl_find_config_file("wmanager.conf", 0));
wmconf.set_section("TitleBar");
wmconf.read("Active color", title_active_color, fl_rgb(0,0,128));
wmconf.read("Normal color", title_normal_color, fl_rgb(192,192,192));
wmconf.read("Active color text", title_active_color_text, fl_rgb(255,255,255));
wmconf.read("Normal color text", title_normal_color_text, fl_rgb(0,0,128));
wmconf.read("Box type", Titlebar::box_type, 0);
wmconf.read("Height", Titlebar::default_height, 20);
wmconf.read("Text align", Titlebar::label_align, 0);
Titlebar::label_align = real_align(Titlebar::label_align);
wmconf.set_section("Resize");
wmconf.read("Opaque resize", Frame::do_opaque, false);
wmconf.read("Animate", Frame::animate, true);
wmconf.read("Animate Speed", Frame::animate_speed, 15);
wmconf.set_section("Misc");
wmconf.read("FocusFollowsMouse", Frame::focus_follows_mouse, false);
bool theme = false;
wmconf.read("Use theme", theme, false);
if(theme) {
wmconf.read("Theme path", buf, 0);
Theme::load_theme(buf);
Theme::use_theme(true);
} else {
Theme::unload_theme();
Theme::use_theme(false);
}
Frame::settings_changed_all();
read_hotkeys_configuration();
}
void do_xset_from_conf()
{
Fl_Config config(fl_find_config_file("ede.conf",1));
int val1, val2, val3;
config.set_section("Mouse");
config.read("Accel", val1, 4);
config.read("Thress",val2, 4);
xset.set_mouse(val1, val2);
config.set_section("Bell");
config.read("Volume", val1, 50);
config.read("Pitch", val2, 440);
config.read("Duration", val3, 200);
xset.set_bell(val1, val2, val3);
config.set_section("Keyboard");
config.read("Repeat", val1, 1);
config.read("ClickVolume", val2, 50);
xset.set_keybd(val1, val2);
config.set_section("Screen");
config.read("Delay", val1, 15);
config.read("Pattern",val2, 2);
xset.set_pattern(val1, val2);
config.read("CheckBlank", val1, 1);
xset.set_check_blank(val1);
config.read("Pattern", val1, 2);
xset.set_blank(val1);
}
void WindowManager::init_wm(int argc, char *argv[])
{
static bool wm_inited = false;
if(wm_inited) return;
DBG("init windowmanager");
fl_open_display();
XShapeQueryExtension(fl_display, &XShapeEventBase, &XShapeErrorBase);
wm_area.set(0, 0/*22*/, Fl::w(), Fl::h()/*-22*/);
program_name = fl_file_filename(argv[0]);
int i;
if(Fl::args(argc, argv, i, arg) < argc)
Fl::error("options are:\n"
" -d[isplay] host:#.#\tX display & screen to use\n"
" -v[isual] #\t\tvisual to use\n"
" -g[eometry] WxH+X+Y\tlimits windows to this area\n"
" -x\t\t\tmenu says Exit instead of logout\n"
" -bg color\t\tFrame color\n"
" -fg color\t\tLabel color\n"
" -bg2 color\t\tText field color\n"
" -cfg color\t\tCursor color\n"
" -cbg color\t\tCursor outline color" );
// Init started
initializing = 1;
XSetErrorHandler(xerror_handler);
Fl::add_handler(wm_event_handler);
init_atoms(); // intern atoms
read_configuration();
do_xset_from_conf();
show(); // Set XID now
set_default_cursor();
ICCCM::set_iconsizes();
MWM::set_motif_info();
register_protocols(fl_xid(this));
Grab_Hotkeys();
XSync(fl_display, 0);
init_desktops();
//Init done
initializing = 0;
wm_inited = true;
// find all the windows and create a Frame for each:
Frame *f=0;
unsigned int n;
Window w1, w2, *wins;
XWindowAttributes attr;
XQueryTree(fl_display, fl_xid(this), &w1, &w2, &wins, &n);
for (i = 0; i < (int)n; ++i) {
XGetWindowAttributes(fl_display, wins[i], &attr);
if(attr.override_redirect) continue;
if(!attr.map_state) {
if(getIntProperty(wins[i], _XA_WM_STATE, _XA_WM_STATE, 0) != IconicState)
continue;
}
f = new Frame(wins[i], &attr);
}
XFree((void *)wins);
// Activate last one
for(uint n=0; n<map_order.size(); n++) {
Frame *f = map_order[n];
if(f->desktop()==Desktop::current()) {
f->activate();
f->raise();
break;
}
}
update_workarea(true);
}
void WindowManager::show()
{
if(!shown()) {
create();
// Destroy FLTK window
XDestroyWindow(fl_display, Fl_X::i(this)->xid);
// Set RootWindow to our xid
Fl_X::i(this)->xid = RootWindow(fl_display, fl_screen);
root_win = RootWindow(fl_display, fl_screen);
// setting attributes on root window makes it the window manager:
XSelectInput(fl_display, fl_xid(this),
SubstructureRedirectMask | SubstructureNotifyMask |
ColormapChangeMask | PropertyChangeMask |
ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask |
KeyPressMask | KeyReleaseMask | KeymapStateMask);
DBG("RootWindow ID set to xid");
draw();
}
}
void WindowManager::draw()
{
DBG("ROOT DRAW");
//Redraw root window
XClearWindow(fl_display, fl_xid(this));
}
extern void set_frame_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg, Window wid);
void WindowManager::set_default_cursor()
{
cursor = FL_CURSOR_ARROW;
set_frame_cursor(FL_CURSOR_ARROW, FL_WHITE, FL_BLACK, root_win);
}
void WindowManager::set_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg)
{
cursor = c;
set_frame_cursor(c, bg, fg, root_win);
}
Frame *WindowManager::find_by_wid(Window wid)
{
for(uint n=0; n<map_order.size(); n++) {
Frame *f = map_order[n];
if(f->window()==wid) return f;
}
return 0;
}
void WindowManager::restack_windows()
{
Window *windows = new Window[1];
int total=0;
DBG("Restack: DOCK, SPLASH");
for(uint n=0; n<stack_order.size(); n++) {
Frame *f = stack_order[n];
if(f->window_type()==TYPE_DOCK || f->window_type()==TYPE_SPLASH) {
windows = (Window*)realloc(windows, (total+1)*sizeof(Window));
windows[total++] = fl_xid(f);
}
}
DBG("Restack: TOOLBAR, MENU");
for(uint n=0; n<stack_order.size(); n++) {
Frame *f = stack_order[n];
if(f->window_type()==TYPE_TOOLBAR || f->window_type()==TYPE_MENU) {
windows = (Window*)realloc(windows, (total+1)*sizeof(Window));
windows[total++] = fl_xid(f);
}
}
DBG("Restack: NORMAL, UTIL, DIALOG");
for(uint n=stack_order.size(); n--;) {
Frame *f = stack_order[n];
if( (f->window_type()==TYPE_NORMAL ||
f->window_type()==TYPE_UTIL ||
f->window_type()==TYPE_DIALOG) &&
f->state()==NORMAL ) {
windows = (Window*)realloc(windows, (total+1)*sizeof(Window));
windows[total++] = fl_xid(f);
}
}
DBG("Restack: DESKTOP");
for(uint n=0; n<stack_order.size(); n++) {
Frame *f = stack_order[n];
if(f->window_type()==TYPE_DESKTOP) {
windows = (Window*)realloc(windows, (total+1)*sizeof(Window));
windows[total++] = fl_xid(f);
}
}
DBG("Restack: Call XRestackWindows!");
if(total) XRestackWindows(fl_display, windows, total);
delete []windows;
}
void WindowManager::update_workarea(bool send)
{
int left = 0;
int right = 0;
int top = 0;
int bottom = 0;
for(uint n=0; n<map_order.size(); n++) {
Frame *f = map_order[n];
if( f->strut() && (f->desktop()==Desktop::current() || f->frame_flag(STICKY)) ) {
left = max(left, f->strut()->left());
right= max(right, f->strut()->right());
top = max(top, f->strut()->top());
bottom = max(bottom,f->strut()->bottom());
}
}
wm_area.set(left, top, Fl::w()-(left+right), Fl::h()-(top+bottom));
for(uint n=stack_order.size(); n--;) {
Frame *f = stack_order[n];
if(f->maximized && f->state()==NORMAL) {
int W=wm_area.w(), H=wm_area.h();
W-=f->offset_w;
H-=f->offset_h;
ICCCM::get_size(f, W, H);
W+=f->offset_w;
H+=f->offset_h;
f->set_size(wm_area.x(), wm_area.y(), W, H);
f->maximized = true;
}
}
if(send) {
Desktop::update_desktop_workarea();
Desktop::update_desktop_geometry();
}
}
//Updates NET client list atoms
void WindowManager::update_client_list()
{
int i=0, client_count=0;
Frame *f;
Window *net_map_order = 0;
Window *net_stack_order = 0;
for(uint n=0; n<map_order.size(); n++) {
f = map_order[n];
if(!f->frame_flag(SKIP_LIST))
client_count++;
}
if(!client_count) return;
net_map_order = new Window[client_count];
net_stack_order = new Window[client_count];
i=0;
for(uint n=0; n<stack_order.size(); n++) {
f = stack_order[n];
// We don't want to include transients in our client list
if(!f->frame_flag(SKIP_LIST)) {
net_stack_order[i++] = f->window();
}
}
i=0;
for(uint n=0; n<map_order.size(); n++) {
f = map_order[n];
// We don't want to include transients in our client list
if(!f->frame_flag(SKIP_LIST)) {
net_map_order[i++] = f->window();
}
}
XChangeProperty(fl_display, fl_xid(root), _XA_NET_CLIENT_LIST, XA_WINDOW, 32, PropModeReplace, (unsigned char*)net_map_order, client_count);
XChangeProperty(fl_display, fl_xid(root), _XA_NET_CLIENT_LIST_STACKING, XA_WINDOW, 32, PropModeReplace, (unsigned char*)net_stack_order, client_count);
delete []net_stack_order;
delete []net_map_order;
}
void WindowManager::idle()
{
for(uint n=remove_list.size(); n--;) {
Frame *c = remove_list[n];
delete c;
}
remove_list.clear();
}
// Really really really quick fix, since this
// solution sucks. Btw wm_shutdown is in main.cpp.
extern bool wm_shutdown;
void WindowManager::shutdown()
{
for(uint n = 0; n < map_order.size(); n++)
{
Frame* f = map_order[n];
f->kill();
}
wm_shutdown = true;
}
int WindowManager::handle(int e)
{
Window window = fl_xevent.xany.window;
switch(e) {
case FL_PUSH:
{
for(uint n=stack_order.size(); n--;) {
Frame *c = map_order[n];
if (c->window() == window || fl_xid(c) == window) {
c->content_click();
return 1;
}
}
DBG("Button press in root?!?!");
return 0;
}
case FL_SHORTCUT:
case FL_KEY:
//case FL_KEYUP:
return Handle_Hotkey();
case FL_MOUSEWHEEL:
{
XAllowEvents(fl_display, ReplayPointer, CurrentTime);
}
}
return 0;
}
int WindowManager::handle(XEvent *e)
{
switch(e->type)
{
case ClientMessage: {
DBG("WindowManager ClientMessage 0x%lx", e->xclient.window);
if(handle_desktop_msgs(&(e->xclient))) return 1;
return 0;
}
case ConfigureRequest: {
DBG("WindowManager ConfigureRequest: 0x%lx", e->xconfigurerequest.window);
const XConfigureRequestEvent *e = &(fl_xevent.xconfigurerequest);
XConfigureWindow(fl_display, e->window,
e->value_mask&~(CWSibling|CWStackMode),
(XWindowChanges*)&(e->x));
return 1;
}
case MapRequest: {
DBG("WindowManager MapRequest: 0x%lx", e->xmaprequest.window);
const XMapRequestEvent* e = &(fl_xevent.xmaprequest);
new Frame(e->window);
return 1;
}
}
return 0;
}
bool WindowManager::handle_desktop_msgs(const XClientMessageEvent *e)
{
if(e->format!=32) return false;
if(e->message_type==_XA_NET_CURRENT_DESKTOP) {
Desktop::current((int)e->data.l[0]+1);
return true;
} else
if(e->message_type==_XA_NET_NUM_DESKTOPS) {
DBG("New desk count: %ld", e->data.l[0]);
Desktop::update_desktop_count(e->data.l[0]);
// Set also new names...
Desktop::set_names();
return true;
} else
if(e->message_type==FLTKChangeSettings) {
DBG("FLTK change settings");
read_configuration();
return true;
}
return false;
}

93
edewm/Windowmanager.h Normal file
View File

@ -0,0 +1,93 @@
#ifndef _WINDOWMANAGER_H_
#define _WINDOWMANAGER_H_
#include <efltk/Fl.h>
#include <efltk/Fl_Window.h>
#include <efltk/x.h>
#include <efltk/fl_draw.h>
#include <efltk/filename.h>
#include <efltk/Fl_Ptr_List.h>
#include <efltk/Fl_Config.h>
#include <efltk/Fl_Locale.h>
#include "../exset/exset.h"
class Frame;
class Frame_List : public Fl_Ptr_List {
public:
Frame_List() : Fl_Ptr_List() { }
void append(Frame *item) { Fl_Ptr_List::append((void *)item); }
void prepend(Frame *item) { Fl_Ptr_List::prepend((void *)item); }
void insert(uint pos, Frame *item) { Fl_Ptr_List::insert(pos, (void *)item); }
void replace(uint pos, Frame *item) { Fl_Ptr_List::replace(pos, (void *)item); }
void remove(uint pos) { Fl_Ptr_List::remove(pos); }
bool remove(Frame *item) { return Fl_Ptr_List::remove((void *)item); }
int index_of(const Frame *w) const { return Fl_Ptr_List::index_of((void*)w); }
Frame *item(uint index) const { return (Frame*)Fl_Ptr_List::item(index); }
Frame **data() { return (Frame**)items; }
Frame *operator [](uint ind) const { return (Frame *)items[ind]; }
};
////////////////////////////////////////////////////////////////
// The WindowManager class looks like a window to efltk but is actually the
// screen's root window. This is done by setting xid to "show" it
// rather than have efltk create the window. Class handles all root
// windows X events
class WindowManager : public Fl_Window
{
void init_wm(int argc, char *argv[]);
Fl_Rect wm_area;
Fl_Cursor cursor;
Exset *xset;
public:
WindowManager(int argc, char *argv[]);
~WindowManager() { }
void set_default_cursor();
void set_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg);
void read_dispconf();
Fl_Cursor get_cursor() { return cursor; }
void idle();
int handle(int e);
int handle(XEvent *e);
void show();
void hide() { } //Prevent efltk to hide root window
void draw();
void update_workarea(bool send=true);
void shutdown();
Frame *find_by_wid(Window wid);
void restack_windows();
//Updates GNOME and NET client list atoms
static void update_client_list();
static bool handle_desktop_msgs(const XClientMessageEvent *e);
int x() { return wm_area.x(); }
int y() { return wm_area.y(); }
int w() { return wm_area.w(); }
int h() { return wm_area.h(); }
int XShapeEventBase, XShapeErrorBase;
};
extern WindowManager *root;
extern Window root_win;
extern Frame_List stack_order;
extern Frame_List map_order;
extern Frame_List remove_list;
#endif

333
edewm/Winhints.cpp Normal file
View File

@ -0,0 +1,333 @@
#include "Frame.h"
#include "Winhints.h"
#include "Desktop.h"
#include "debug.h"
Atom _XA_UTF8_STRING;
Atom _XA_SM_CLIENT_ID;
//ICCCM
Atom _XA_WM_CLIENT_LEADER;
Atom _XA_WM_PROTOCOLS;
Atom _XA_WM_TAKE_FOCUS;
Atom _XA_WM_DELETE_WINDOW;
Atom _XA_WM_STATE;
Atom _XA_WM_CHANGE_STATE;
Atom _XA_WM_COLORMAP_WINDOWS;
//MWM
Atom _XATOM_MWM_HINTS;
Atom _XATOM_MOTIF_WM_INFO;
// Extended WM (NetWM)
Atom _XA_NET_SUPPORTED;
Atom _XA_NET_CLIENT_LIST;
Atom _XA_NET_CLIENT_LIST_STACKING;
Atom _XA_NET_NUM_DESKTOPS;
Atom _XA_NET_DESKTOP_GEOMETRY;
Atom _XA_NET_DESKTOP_VIEWPORT;
Atom _XA_NET_CURRENT_DESKTOP;
Atom _XA_NET_DESKTOP_NAMES;
Atom _XA_NET_ACTIVE_WINDOW;
Atom _XA_NET_WORKAREA;
Atom _XA_NET_SUPPORTING_WM_CHECK;
Atom _XA_NET_VIRTUAL_ROOTS;
Atom _XA_NET_DESKTOP_LAYOUT;
Atom _XA_NET_SHOWING_DESKTOP;
Atom _XA_NET_CLOSE_WINDOW;
Atom _XA_NET_WM_MOVERESIZE;
Atom _XA_NET_RESTACK_WINDOW;
Atom _XA_NET_REQUEST_FRAME_EXTENTS;
Atom _XA_NET_WM_NAME;
Atom _XA_NET_WM_VISIBLE_NAME;
Atom _XA_NET_WM_ICON_NAME;
Atom _XA_NET_WM_ICON_VISIBLE_NAME;
Atom _XA_NET_WM_DESKTOP;
Atom _XA_NET_WM_WINDOW_TYPE;
Atom _XA_NET_WM_WINDOW_TYPE_DESKTOP;
Atom _XA_NET_WM_WINDOW_TYPE_DOCK;
Atom _XA_NET_WM_WINDOW_TYPE_TOOLBAR;
Atom _XA_NET_WM_WINDOW_TYPE_MENU;
Atom _XA_NET_WM_WINDOW_TYPE_UTIL;
Atom _XA_NET_WM_WINDOW_TYPE_SPLASH;
Atom _XA_NET_WM_WINDOW_TYPE_DIALOG;
Atom _XA_NET_WM_WINDOW_TYPE_NORMAL;
Atom _XA_NET_WM_STATE;
Atom _XA_NET_WM_STATE_MODAL;
Atom _XA_NET_WM_STATE_STICKY;
Atom _XA_NET_WM_STATE_MAXIMIZED_VERT;
Atom _XA_NET_WM_STATE_MAXIMIZED_HORZ;
Atom _XA_NET_WM_STATE_SHADED;
Atom _XA_NET_WM_STATE_SKIP_TASKBAR;
Atom _XA_NET_WM_STATE_SKIP_PAGER;
Atom _XA_NET_WM_STATE_HIDDEN; // new in spec. 1.3
Atom _XA_NET_WM_STATE_FULLSCREEN; // new in spec. 1.3
Atom _XA_NET_WM_STATE_ABOVE; // new in spec. 1.3
Atom _XA_NET_WM_STATE_BELOW; // new in spec. 1.3
Atom _XA_NET_WM_STATE_DEMANDS_ATTENTION; // new in spec. 1.3
Atom _XA_NET_WM_ALLOWED_ACTIONS;
Atom _XA_NET_WM_ACTION_MOVE;
Atom _XA_NET_WM_ACTION_RESIZE;
Atom _XA_NET_WM_ACTION_MINIMIZE;
Atom _XA_NET_WM_ACTION_SHADE;
Atom _XA_NET_WM_ACTION_STICK;
Atom _XA_NET_WM_ACTION_MAXIMIZE_HORZ;
Atom _XA_NET_WM_ACTION_MAXIMIZE_VERT;
Atom _XA_NET_WM_ACTION_FULLSCREEN;
Atom _XA_NET_WM_ACTION_CHANGE_DESKTOP;
Atom _XA_NET_WM_ACTION_CLOSE;
Atom _XA_NET_WM_STRUT;
Atom _XA_NET_WM_STRUT_PARTIAL;
Atom _XA_NET_WM_ICON_GEOMETRY;
Atom _XA_NET_WM_ICON;
Atom _XA_NET_WM_PID;
Atom _XA_NET_WM_HANDLED_ICONS;
Atom _XA_NET_WM_USER_TIME;
Atom _XA_NET_FRAME_EXTENTS;
Atom _XA_NET_WM_PING;
Atom _XA_NET_WM_SYNC_REQUEST;
Atom _XA_NET_WM_STATE_STAYS_ON_TOP;
//KDE1
Atom _XA_KWM_WIN_ICON;
//EDE
Atom _XA_EDE_WM_ACTION;
Atom _XA_EDE_WM_LOGOUT;
Atom _XA_EDE_WM_RESTORE_SIZE;
#define CNT(x) (sizeof(x)/sizeof(x[0]))
static bool atoms_inited = false;
void init_atoms()
{
if(atoms_inited) return;
struct {
Atom *atom;
const char *name;
} atom_info[] = {
{ &_XA_UTF8_STRING, "UTF8_STRING" },
{ &_XA_SM_CLIENT_ID, "SM_CLIENT_ID" },
//ICCCM
{ &_XA_WM_PROTOCOLS, "WM_PROTOCOLS" },
{ &_XA_WM_TAKE_FOCUS, "WM_TAKE_FOCUS" },
{ &_XA_WM_DELETE_WINDOW, "WM_DELETE_WINDOW" },
{ &_XA_WM_STATE, "WM_STATE" },
{ &_XA_WM_CHANGE_STATE, "WM_CHANGE_STATE" },
{ &_XA_WM_COLORMAP_WINDOWS, "WM_COLORMAP_WINDOWS" },
{ &_XA_WM_CLIENT_LEADER, "WM_CLIENT_LEADER" },
//MWM
{ &_XATOM_MWM_HINTS, _XA_MOTIF_WM_HINTS },
{ &_XATOM_MOTIF_WM_INFO, _XA_MOTIF_WM_INFO },
//KDE1
{ &_XA_KWM_WIN_ICON, "KWM_WIN_ICON" },
//Extended WM
{ &_XA_NET_SUPPORTED, "_NET_SUPPORTED" },
{ &_XA_NET_CLIENT_LIST, "_NET_CLIENT_LIST" },
{ &_XA_NET_CLIENT_LIST_STACKING, "_NET_CLIENT_LIST_STACKING" },
{ &_XA_NET_NUM_DESKTOPS, "_NET_NUMBER_OF_DESKTOPS" },
{ &_XA_NET_DESKTOP_GEOMETRY,"_NET_DESKTOP_GEOMETRY" },
{ &_XA_NET_DESKTOP_VIEWPORT,"_NET_DESKTOP_VIEWPORT" },
{ &_XA_NET_CURRENT_DESKTOP, "_NET_CURRENT_DESKTOP" },
{ &_XA_NET_DESKTOP_NAMES, "_NET_DESKTOP_NAMES" },
{ &_XA_NET_ACTIVE_WINDOW, "_NET_ACTIVE_WINDOW" },
{ &_XA_NET_WORKAREA, "_NET_WORKAREA" },
{ &_XA_NET_SUPPORTING_WM_CHECK, "_NET_SUPPORTING_WM_CHECK" },
{ &_XA_NET_VIRTUAL_ROOTS, "_NET_VIRTUAL_ROOTS" },
{ &_XA_NET_DESKTOP_LAYOUT, "_NET_DESKTOP_LAYOUT" },
{ &_XA_NET_SHOWING_DESKTOP, "_NET_SHOWING_DESKTOP" },
{ &_XA_NET_CLOSE_WINDOW, "_NET_CLOSE_WINDOW" },
{ &_XA_NET_WM_MOVERESIZE, "_NET_WM_MOVERESIZE" },
{ &_XA_NET_RESTACK_WINDOW, "_NET_RESTACK_WINDOW" },
{ &_XA_NET_REQUEST_FRAME_EXTENTS, "_NET_REQUEST_FRAME_EXTENTS" },
{ &_XA_NET_WM_NAME, "_NET_WM_NAME" },
{ &_XA_NET_WM_VISIBLE_NAME, "_NET_WM_VISIBLE_NAME" },
{ &_XA_NET_WM_ICON_NAME, "_NET_WM_ICON_NAME" },
{ &_XA_NET_WM_ICON_VISIBLE_NAME, "_NET_WM_ICON_VISIBLE_NAME" },
{ &_XA_NET_WM_DESKTOP, "_NET_WM_DESKTOP" },
{ &_XA_NET_WM_WINDOW_TYPE, "_NET_WM_WINDOW_TYPE" },
{ &_XA_NET_WM_WINDOW_TYPE_DESKTOP, "_NET_WM_WINDOW_TYPE_DESKTOP" },
{ &_XA_NET_WM_WINDOW_TYPE_DOCK, "_NET_WM_WINDOW_TYPE_DOCK" },
{ &_XA_NET_WM_WINDOW_TYPE_TOOLBAR, "_NET_WM_WINDOW_TYPE_TOOLBAR" },
{ &_XA_NET_WM_WINDOW_TYPE_MENU, "_NET_WM_WINDOW_TYPE_MENU" },
{ &_XA_NET_WM_WINDOW_TYPE_UTIL, "_NET_WM_WINDOW_TYPE_UTILITY" },
{ &_XA_NET_WM_WINDOW_TYPE_SPLASH, "_NET_WM_WINDOW_TYPE_SPLASH" },
{ &_XA_NET_WM_WINDOW_TYPE_DIALOG, "_NET_WM_WINDOW_TYPE_DIALOG" },
{ &_XA_NET_WM_WINDOW_TYPE_NORMAL, "_NET_WM_WINDOW_TYPE_NORMAL" },
{ &_XA_NET_WM_STATE, "_NET_WM_STATE" },
{ &_XA_NET_WM_STATE_MODAL, "_NET_WM_STATE_MODAL" },
{ &_XA_NET_WM_STATE_STICKY, "_NET_WM_STATE_STICKY" },
{ &_XA_NET_WM_STATE_MAXIMIZED_VERT, "_NET_WM_STATE_MAXIMIZED_VERT" },
{ &_XA_NET_WM_STATE_MAXIMIZED_HORZ, "_NET_WM_STATE_MAXIMIZED_HORZ" },
{ &_XA_NET_WM_STATE_SHADED, "_NET_WM_STATE_SHADED" },
{ &_XA_NET_WM_STATE_SKIP_TASKBAR, "_NET_WM_STATE_SKIP_TASKBAR" },
{ &_XA_NET_WM_STATE_SKIP_PAGER, "_NET_WM_STATE_SKIP_PAGER" },
{ &_XA_NET_WM_STATE_HIDDEN, "_NET_WM_STATE_HIDDEN" },
{ &_XA_NET_WM_STATE_FULLSCREEN, "_NET_WM_STATE_FULLSCREEN" },
{ &_XA_NET_WM_STATE_ABOVE, "_NET_WM_STATE_ABOVE" },
{ &_XA_NET_WM_STATE_BELOW, "_NET_WM_STATE_BELOW" },
{ &_XA_NET_WM_STATE_DEMANDS_ATTENTION, "_NET_WM_STATE_DEMANDS_ATTENTION" },
{ &_XA_NET_WM_ALLOWED_ACTIONS, "_NET_WM_ALLOWED_ACTIONS" },
{ &_XA_NET_WM_ACTION_MOVE, "_NET_WM_ACTION_MOVE" },
{ &_XA_NET_WM_ACTION_RESIZE, "_NET_WM_ACTION_RESIZE" },
{ &_XA_NET_WM_ACTION_MINIMIZE, "_NET_WM_ACTION_MINIMIZE" },
{ &_XA_NET_WM_ACTION_SHADE, "_NET_WM_ACTION_SHADE" },
{ &_XA_NET_WM_ACTION_STICK, "_NET_WM_ACTION_STICK" },
{ &_XA_NET_WM_ACTION_MAXIMIZE_HORZ, "_NET_WM_ACTION_MAXIMIZE_HORZ" },
{ &_XA_NET_WM_ACTION_MAXIMIZE_VERT, "_NET_WM_ACTION_MAXIMIZE_VERT" },
{ &_XA_NET_WM_ACTION_FULLSCREEN, "_NET_WM_ACTION_FULLSCREEN" },
{ &_XA_NET_WM_ACTION_CHANGE_DESKTOP, "_NET_WM_ACTION_CHANGE_DESKTOP" },
{ &_XA_NET_WM_ACTION_CLOSE, "_NET_WM_ACTION_CLOSE" },
{ &_XA_NET_WM_STRUT, "_NET_WM_STRUT" },
{ &_XA_NET_WM_STRUT_PARTIAL, "_NET_WM_STRUT_PARTIAL" },
{ &_XA_NET_WM_ICON_GEOMETRY, "_NET_WM_ICON_GEOMETRY" },
{ &_XA_NET_WM_ICON, "_NET_WM_ICON" },
{ &_XA_NET_WM_PID, "_NET_WM_PID" },
{ &_XA_NET_WM_HANDLED_ICONS, "_NET_WM_HANDLED_ICONS" },
{ &_XA_NET_WM_USER_TIME, "_NET_WM_USER_TIME" },
{ &_XA_NET_FRAME_EXTENTS, "_NET_FRAME_EXTENTS" },
{ &_XA_NET_WM_PING, "_NET_WM_PING" },
{ &_XA_NET_WM_SYNC_REQUEST, "_NET_WM_SYNC_REQUEST" },
/* the next one is not in the spec but KDE use it */
{ &_XA_NET_WM_STATE_STAYS_ON_TOP, "_NET_WM_STATE_STAYS_ON_TOP" },
/* KDE 1 */
{ &_XA_KWM_WIN_ICON, "_NET_KWM_WIN_ICON" },
/* EDE specific message */
{ &_XA_EDE_WM_ACTION, "_EDE_WM_ACTION" },
{ &_XA_EDE_WM_LOGOUT, "_EDE_WM_LOGOUT" },
{ &_XA_EDE_WM_RESTORE_SIZE, "_EDE_WM_RESTORE_SIZE" }
/*
{ &_XA_CLIPBOARD, "CLIPBOARD" },
{ &_XA_TARGETS, "TARGETS" },
{ &XA_XdndAware, "XdndAware" },
{ &XA_XdndEnter, "XdndEnter" },
{ &XA_XdndLeave, "XdndLeave" },
{ &XA_XdndPosition, "XdndPosition" },
{ &XA_XdndStatus, "XdndStatus" },
{ &XA_XdndDrop, "XdndDrop" },
{ &XA_XdndFinished, "XdndFinished" }
*/
};
unsigned int i;
for(i = 0; i < CNT(atom_info); i++) {
*(atom_info[i].atom) = XInternAtom(fl_display, atom_info[i].name, False);
}
atoms_inited = true;
}
void register_protocols(Window root)
{
static bool protos_registered = false;
if(protos_registered) return;
Atom net_proto[] = {
_XA_NET_SUPPORTED,
_XA_NET_CLIENT_LIST,
_XA_NET_CLIENT_LIST_STACKING,
_XA_NET_NUM_DESKTOPS,
_XA_NET_DESKTOP_GEOMETRY,
_XA_NET_DESKTOP_VIEWPORT,
_XA_NET_SHOWING_DESKTOP,
_XA_NET_CURRENT_DESKTOP,
_XA_NET_DESKTOP_NAMES,
_XA_NET_ACTIVE_WINDOW,
_XA_NET_WORKAREA,
_XA_NET_SUPPORTING_WM_CHECK,
//_XA_NET_VIRTUAL_ROOTS, //hmmm.... I didnt understand this one...
_XA_NET_CLOSE_WINDOW,
//_XA_NET_WM_MOVERESIZE,
_XA_NET_WM_NAME,
//_XA_NET_WM_VISIBLE_NAME,
_XA_NET_WM_ICON_NAME,
//_XA_NET_WM_ICON_VISIBLE_NAME,
_XA_NET_WM_DESKTOP,
_XA_NET_WM_WINDOW_TYPE,
_XA_NET_WM_WINDOW_TYPE_DESKTOP,
_XA_NET_WM_WINDOW_TYPE_DOCK,
_XA_NET_WM_WINDOW_TYPE_TOOLBAR,
_XA_NET_WM_WINDOW_TYPE_MENU,
_XA_NET_WM_WINDOW_TYPE_UTIL,
_XA_NET_WM_WINDOW_TYPE_SPLASH,
_XA_NET_WM_WINDOW_TYPE_DIALOG,
_XA_NET_WM_WINDOW_TYPE_NORMAL,
//_XA_NET_WM_STATE,
//_XA_NET_WM_STATE_MODAL,
//_XA_NET_WM_STATE_STICKY,
//_XA_NET_WM_STATE_MAXIMIZED_VERT,
//_XA_NET_WM_STATE_MAXIMIZED_HORZ,
//_XA_NET_WM_STATE_SHADED,
//_XA_NET_WM_STATE_SKIP_TASKBAR,
//_XA_NET_WM_STATE_SKIP_PAGER,
// the next one is not in the spec but KDE use it
//_XA_NET_WM_STATE_STAYS_ON_TOP,
_XA_NET_WM_STRUT
//_XA_NET_WM_ICON_GEOMETRY,
//_XA_NET_WM_ICON,
//_XA_NET_WM_PID,
//_XA_NET_WM_HANDLED_ICONS,
//_XA_NET_WM_PING
};
//Set supported NET protos
XChangeProperty(fl_display, root,
_XA_NET_SUPPORTED, XA_ATOM, 32, PropModeReplace,
(unsigned char *)net_proto, CNT(net_proto));
Window support_xid = XCreateSimpleWindow(fl_display, root, -200, -200, 5, 5, 0, 0, 0);
//NET:
XChangeProperty(fl_display, support_xid,
_XA_NET_SUPPORTING_WM_CHECK, XA_WINDOW, 32,
PropModeReplace, (unsigned char *)&support_xid, 1);
XChangeProperty(fl_display, root,
_XA_NET_SUPPORTING_WM_CHECK, XA_WINDOW, 32,
PropModeReplace, (unsigned char *)&support_xid, 1);
protos_registered = true;
}
void Frame::get_protocols()
{
unsigned long n;
Atom* p = (Atom*)getProperty(_XA_WM_PROTOCOLS, XA_ATOM, &n);
if(p) {
DBG("get_protocols()");
clear_flag(DELETE_WIN_PRT|TAKE_FOCUS_PRT);
for(unsigned int i = 0; i < n; ++i) {
if(p[i]==_XA_WM_DELETE_WINDOW) {
set_frame_flag(DELETE_WIN_PRT);
} else if(p[i]==_XA_WM_TAKE_FOCUS) {
set_frame_flag(TAKE_FOCUS_PRT);
}
}
}
XFree((char*)p);
}
void Frame::get_wm_hints()
{
if(wm_hints) {
XFree((char *)wm_hints);
wm_hints = 0;
}
wm_hints = XGetWMHints(fl_display, window_);
}
void Frame::update_wm_hints()
{
if(!wm_hints) return;
if((wm_hints->flags & InputHint) && !wm_hints->input)
set_frame_flag(NO_FOCUS);
}

164
edewm/Winhints.h Normal file
View File

@ -0,0 +1,164 @@
#ifndef _WINHINTS_H_
#define _WINHINTS_H_
#include <X11/Xlib.h>
#include "Mwm.h"
//extern Atom _XA_SM_CLIENT_ID;
extern Atom _XA_UTF8_STRING;
// ICCCM
extern Atom _XA_WM_CLIENT_LEADER;
extern Atom _XA_WM_PROTOCOLS;
extern Atom _XA_WM_TAKE_FOCUS;
extern Atom _XA_WM_DELETE_WINDOW;
extern Atom _XA_WM_STATE;
extern Atom _XA_WM_CHANGE_STATE;
extern Atom _XA_WM_COLORMAP_WINDOWS;
//MWM
extern Atom _XATOM_MWM_HINTS;
extern Atom _XATOM_MOTIF_WM_INFO;
// Extended WM Hints:
// NetWM support
// http://standards.freedesktop.org/wm-spec/
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
#define _NET_WM_MOVERESIZE_SIZE_TOP 1
#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
#define _NET_WM_MOVERESIZE_MOVE 8 /* Movement only */
//_NET_SUPPORTED, ATOM[]/32
extern Atom _XA_NET_SUPPORTED;
//_NET_CLIENT_LIST, XA_WINDOW[]/32
extern Atom _XA_NET_CLIENT_LIST;
//_NET_CLIENT_LIST_STACKING, XA_WINDOW[]/32
extern Atom _XA_NET_CLIENT_LIST_STACKING;
//_NET_NUMBER_OF_DESKTOPS, CARDINAL/32
extern Atom _XA_NET_NUM_DESKTOPS;
//_NET_DESKTOP_GEOMETRY width,height, CARDINAL[2]/32 | C
extern Atom _XA_NET_DESKTOP_GEOMETRY;
//_NET_DESKTOP_VIEWPORT x,y, CARDINAL[][2]/32 | C
extern Atom _XA_NET_DESKTOP_VIEWPORT;
//_NET_CURRENT_DESKTOP <desktop>, CARDINAL[1]/32 | C
extern Atom _XA_NET_CURRENT_DESKTOP;
//_NET_DESKTOP_NAMES, UTF8
extern Atom _XA_NET_DESKTOP_NAMES;
//_NET_ACTIVE_WINDOW, WINDOW/32
extern Atom _XA_NET_ACTIVE_WINDOW;
//_NET_WORKAREA, CARDINAL[][4]/32
extern Atom _XA_NET_WORKAREA;
//_NET_SUPPORTING_WM_CHECK, XA_WINDOW/32
extern Atom _XA_NET_SUPPORTING_WM_CHECK;
//_NET_VIRTUAL_ROOTS, XA_WINDOW[]/32
extern Atom _XA_NET_VIRTUAL_ROOTS;
//_NET_DESKTOP_LAYOUT, orientation, columns, rows, starting_corner CARDINAL[4]/32
// (not implemented, used by pagers)
extern Atom _XA_NET_DESKTOP_LAYOUT;
//_NET_SHOWING_DESKTOP desktop, CARDINAL/32
// (not implemented)
extern Atom _XA_NET_SHOWING_DESKTOP;
//_NET_CLOSE_WINDOW - closes active window
extern Atom _XA_NET_CLOSE_WINDOW;
//_NET_WM_MOVERESIZE | C
extern Atom _XA_NET_WM_MOVERESIZE;
//_NET_RESTACK_WINDOW
// (not implemented, used by pagers)
extern Atom _XA_NET_RESTACK_WINDOW;
// _NET_REQUEST_FRAME_EXTENTS
// (not implemented, used to detect frame size)
extern Atom _XA_NET_REQUEST_FRAME_EXTENTS;
//_NET_WM_NAME - UTF8
extern Atom _XA_NET_WM_NAME;
//_NET_WM_VISIBLE_NAME, UTF8
extern Atom _XA_NET_WM_VISIBLE_NAME;
//_NET_WM_ICON_NAME, UTF8
extern Atom _XA_NET_WM_ICON_NAME;
//_NET_WM_VISIBLE_ICON_NAME, UTF8
extern Atom _XA_NET_WM_ICON_VISIBLE_NAME;
//_NET_WM_DESKTOP <desktop>, CARDINAL/32 | C
extern Atom _XA_NET_WM_DESKTOP;
//_NET_WM_WINDOW_TYPE, ATOM[]/32
extern Atom _XA_NET_WM_WINDOW_TYPE;
extern Atom _XA_NET_WM_WINDOW_TYPE_DESKTOP;
extern Atom _XA_NET_WM_WINDOW_TYPE_DOCK;
extern Atom _XA_NET_WM_WINDOW_TYPE_TOOLBAR;
extern Atom _XA_NET_WM_WINDOW_TYPE_MENU;
extern Atom _XA_NET_WM_WINDOW_TYPE_UTIL;
extern Atom _XA_NET_WM_WINDOW_TYPE_SPLASH;
extern Atom _XA_NET_WM_WINDOW_TYPE_DIALOG; //Transient type
extern Atom _XA_NET_WM_WINDOW_TYPE_NORMAL; //Normal
//_NET_WM_STATE, ATOM[] | C
extern Atom _XA_NET_WM_STATE;
extern Atom _XA_NET_WM_STATE_MODAL; //Needs transient for (root for whole group)
extern Atom _XA_NET_WM_STATE_STICKY; //Pos fixed, even if virt. desk. scrolls
extern Atom _XA_NET_WM_STATE_MAXIMIZED_VERT;
extern Atom _XA_NET_WM_STATE_MAXIMIZED_HORZ;
extern Atom _XA_NET_WM_STATE_SHADED;
extern Atom _XA_NET_WM_STATE_SKIP_TASKBAR;
extern Atom _XA_NET_WM_STATE_SKIP_PAGER;
extern Atom _XA_NET_WM_STATE_HIDDEN; // new in spec. 1.3
extern Atom _XA_NET_WM_STATE_FULLSCREEN; // new in spec. 1.3
extern Atom _XA_NET_WM_STATE_ABOVE; // new in spec. 1.3
extern Atom _XA_NET_WM_STATE_BELOW; // new in spec. 1.3
extern Atom _XA_NET_WM_STATE_DEMANDS_ATTENTION; // new in spec. 1.3
//_NET_WM_ALLOWED_ACTIONS, ATOM[]
// (not implemented, used to manipulate stuff from taskbar)
extern Atom _XA_NET_WM_ALLOWED_ACTIONS;
extern Atom _XA_NET_WM_ACTION_MOVE;
extern Atom _XA_NET_WM_ACTION_RESIZE;
extern Atom _XA_NET_WM_ACTION_MINIMIZE;
extern Atom _XA_NET_WM_ACTION_SHADE;
extern Atom _XA_NET_WM_ACTION_STICK;
extern Atom _XA_NET_WM_ACTION_MAXIMIZE_HORZ;
extern Atom _XA_NET_WM_ACTION_MAXIMIZE_VERT;
extern Atom _XA_NET_WM_ACTION_FULLSCREEN;
extern Atom _XA_NET_WM_ACTION_CHANGE_DESKTOP;
extern Atom _XA_NET_WM_ACTION_CLOSE;
//_NET_WM_STRUT, CARDINAL[4]/32
extern Atom _XA_NET_WM_STRUT;
//_NET_WM_STRUT_PARTIAL, left, right, top, bottom, left_start_y, left_end_y,
//right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x,
//bottom_end_x,CARDINAL[12]/32
// (not implemented)
extern Atom _XA_NET_WM_STRUT_PARTIAL;
//_NET_WM_ICON_GEOMETRY, CARDINAL[4] - array of x,y,w,h of type CARDINAL, format 32
extern Atom _XA_NET_WM_ICON_GEOMETRY;
//_NET_WM_ICON CARDINAL[][2+n]/32 - 32bit packed CARDINAL ARGB with high byte being A, low byte being B
extern Atom _XA_NET_WM_ICON;
//_NET_WM_PID CARDINAL/32
extern Atom _XA_NET_WM_PID;
//_NET_WM_HANDLED_ICONS
extern Atom _XA_NET_WM_HANDLED_ICONS;
//_NET_WM_USER_TIME CARDINAL/32
// (not implemented, used by e.g. autoaway in chat programs)
extern Atom _XA_NET_WM_USER_TIME;
//_NET_FRAME_EXTENTS, left, right, top, bottom, CARDINAL[4]/32
// (not implemented, used to detect frame size)
extern Atom _XA_NET_FRAME_EXTENTS;
//_NET_WM_PING
extern Atom _XA_NET_WM_PING;
//_NET_WM_SYNC_REQUEST
// (not implemented, used for XSync extension)
extern Atom _XA_NET_WM_SYNC_REQUEST;
// the next one is not in the spec but KDE use it
// obsoleted by _NET_WM_STATE_ABOVE
extern Atom _XA_NET_WM_STATE_STAYS_ON_TOP;
// KDE1 icon support, thats all of it :)
extern Atom _XA_KWM_WIN_ICON;
// EDE specific message
extern Atom _XA_EDE_WM_ACTION;
extern Atom _XA_EDE_WM_LOGOUT;
extern Atom _XA_EDE_WM_RESTORE_SIZE;
extern void init_atoms();
extern void register_protocols(Window root);
#endif

40
edewm/config.h Normal file
View File

@ -0,0 +1,40 @@
// config.h
// You can edit these symbols to change the behavior & appearance of flwm.
// Turning off features will make flwm smaller too!
////////////////////////////////////////////////////////////////
// BEHAVIOR:
// Turn this on for click-to-type (rather than point-to-type).
// On: clicking on the window gives it focus
// Off: pointing at the window gives it the focus.
#define CLICK_TO_TYPE 1
// For point-to-type, sticky focus means you don't lose the focus
// until you move the cursor to another window that wants focus.
// If this is off you lose focus as soon as the cursor goes outside
// the window (such as to the desktop):
#define STICKY_FOCUS 0
// For point-to-type, after this many seconds the window is raised,
// nothing is done if this is not defined:
//#define AUTO_RAISE 0.5
// set this to zero to remove the multiple-desktop code. This will
// make flwm about 20K smaller
#define DESKTOPS 1
////////////////////////////////////////////////////////////////
// APPEARANCE:
// how many pixels from edge for resize handle:
#define RESIZE_EDGE 6
// must drag window this far off screen to snap the border off the screen:
#define EDGE_SNAP 20
// must drag window this far off screen to actually move it off screen:
#define SCREEN_SNAP 40
#define SHAPE 1

9
edewm/debug.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _DEBUG_H_
#define _DEBUG_H_
#include <stdio.h>
#include <stdarg.h>
extern void DBG(const char *str, ...);
#endif

88
edewm/locale/de.po Normal file
View File

@ -0,0 +1,88 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2006 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the EDE package.
# Ralf Eichinger <ralf.eichinger@pixotec.de>, 2006.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: edewm 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-12-12 21:03+0100\n"
"PO-Revision-Date: 2006-12-14 07:50+0100\n"
"Last-Translator: Ralf Eichinger <ralf.eichinger@pixotec.de>\n"
"Language-Team: German <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: edewm/Desktop.cpp:138 edewm/Desktop.cpp:180
#, c-format
msgid "Workspace %d"
msgstr "Arbeitsplatz %d"
#: edewm/Frame.cpp:146
msgid "Untitled"
msgstr "Ohne Titel"
#: edewm/Frame.cpp:977
#, c-format
msgid "EDEWM: Internal bug, when restacking (%d != %d)! Exiting... "
msgstr ""
#: edewm/Titlebar.cpp:225
msgid "Sticky"
msgstr "jeden Arbeitsplatz"
#: edewm/Titlebar.cpp:285 edewm/Titlebar.cpp:330
msgid "Set size"
msgstr "Größe ändern"
#: edewm/Titlebar.cpp:286
msgid "Set size to window:"
msgstr "Fenstergröße ändern auf:"
#: edewm/Titlebar.cpp:295
msgid "width:"
msgstr "Breite:"
#: edewm/Titlebar.cpp:297
msgid "height:"
msgstr "Höhe:"
#: edewm/Titlebar.cpp:301
msgid "&OK"
msgstr "&OK"
#: edewm/Titlebar.cpp:304
msgid "&Cancel"
msgstr "&Abbrechen"
#: edewm/Titlebar.cpp:328 edewm/Titlebar.cpp:341
msgid "Maximize"
msgstr "Maximieren"
#: edewm/Titlebar.cpp:329
msgid "Minimize"
msgstr "Minimieren"
#: edewm/Titlebar.cpp:331
msgid "To Desktop"
msgstr "Verschieben auf"
#: edewm/Titlebar.cpp:332
msgid "Kill"
msgstr "Abbrechen"
#: edewm/Titlebar.cpp:333
msgid "Close"
msgstr "Schließen"
#: edewm/Titlebar.cpp:340
msgid "Restore"
msgstr "Wiederherstellen"
#: edewm/Windowmanager.cpp:90
#, c-format
msgid "Another window manager is running. You must exit it before running %s."
msgstr "Ein anderer Fenstermanager läuft bereits. Beenden Sie diesen bevor Sie %s ausführen."

89
edewm/locale/fi.po Normal file
View File

@ -0,0 +1,89 @@
# Finnish translation of edewm.
# Copyright (C) 2002 THE edewm'S COPYRIGHT HOLDER
# This file is distributed under the same license as the edewm package.
# Mikko L. <Laza@Flashmail.com>, 2002.
#
msgid ""
msgstr ""
"Project-Id-Version: edewm 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-02-04 12:33+0100\n"
"PO-Revision-Date: 2002-09-16 11:07+0300\n"
"Last-Translator: Mikko L. <Laza@Flashmail.com>\n"
"Language-Team: Finnish <fi@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-15\n"
"Content-Transfer-Encoding: 8bit\n"
#: Desktop.cpp:138 Desktop.cpp:180
#, c-format
msgid "Workspace %d"
msgstr "Työpöytä %d"
#: Frame.cpp:106
msgid "Untitled"
msgstr "Nimetön"
#: Frame.cpp:938
#, c-format
msgid "EDEWM: Internal bug, when restacking (%d != %d)! Exiting... "
msgstr ""
#: Titlebar.cpp:215
msgid "Sticky"
msgstr "Kiinteä"
#: Titlebar.cpp:275 Titlebar.cpp:320
msgid "Set size"
msgstr ""
#: Titlebar.cpp:276
msgid "Set size to window:"
msgstr ""
#: Titlebar.cpp:285
msgid "width:"
msgstr ""
#: Titlebar.cpp:287
msgid "height:"
msgstr ""
#: Titlebar.cpp:291
msgid "&OK"
msgstr ""
#: Titlebar.cpp:294
msgid "&Cancel"
msgstr ""
#: Titlebar.cpp:318 Titlebar.cpp:331
msgid "Maximize"
msgstr "Suurenna"
#: Titlebar.cpp:319
msgid "Minimize"
msgstr "Pienennä"
#: Titlebar.cpp:321
msgid "To Desktop"
msgstr "Työpöydälle:"
#: Titlebar.cpp:322
msgid "Kill"
msgstr "Tapa"
#: Titlebar.cpp:323
msgid "Close"
msgstr "Sulje"
#: Titlebar.cpp:330
msgid "Restore"
msgstr "Palauta"
#: Windowmanager.cpp:90
#, c-format
msgid "Another window manager is running. You must exit it before running %s."
msgstr ""
"Toinen ikkunointi järjestelmä käynnissä. Sinun täytyy lopettaa se ennen kuin "
"voit ajaa: %s"

90
edewm/locale/fr.po Normal file
View File

@ -0,0 +1,90 @@
# French translation of ede.
# Copyright (C) 2007 THE ede'S COPYRIGHT HOLDER
# This file is distributed under the same license as the ede package.
# emmanuel coutant <ecoutan@cegetel.net>, 2007.
# , fuzzy
#
#
msgid ""
msgstr ""
"Project-Id-Version: ede 1.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-01-07 14:49+0100\n"
"PO-Revision-Date: 2007-01-07 16:41+0100\n"
"Last-Translator: emmanuel coutant <ecoutan@cegetel.net>\n"
"Language-Team: French\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit"
#: edewm/Desktop.cpp:138 edewm/Desktop.cpp:180
#, c-format
msgid "Workspace %d"
msgstr "Bureau %d"
#: edewm/Frame.cpp:146
msgid "Untitled"
msgstr "Sans titre"
#: edewm/Frame.cpp:977
#, c-format
msgid "EDEWM: Internal bug, when restacking (%d != %d)! Exiting... "
msgstr ""
#: edewm/Titlebar.cpp:225
msgid "Sticky"
msgstr "Punaiser"
#: edewm/Titlebar.cpp:285 edewm/Titlebar.cpp:330
msgid "Set size"
msgstr "Redimensionner"
#: edewm/Titlebar.cpp:286
msgid "Set size to window:"
msgstr ""
#: edewm/Titlebar.cpp:295
msgid "width:"
msgstr "Largeur:"
#: edewm/Titlebar.cpp:297
msgid "height:"
msgstr "Hauteur:"
#: edewm/Titlebar.cpp:301
msgid "&OK"
msgstr "&OK"
#: edewm/Titlebar.cpp:304
msgid "&Cancel"
msgstr "&Annuler"
#: edewm/Titlebar.cpp:328 edewm/Titlebar.cpp:341
msgid "Maximize"
msgstr "Maximiser"
#: edewm/Titlebar.cpp:329
msgid "Minimize"
msgstr "Minimiser"
#: edewm/Titlebar.cpp:331
msgid "To Desktop"
msgstr "Vers le bureau"
#: edewm/Titlebar.cpp:332
msgid "Kill"
msgstr "Tuer"
#: edewm/Titlebar.cpp:333
msgid "Close"
msgstr "Fermer"
#: edewm/Titlebar.cpp:340
msgid "Restore"
msgstr "Restaurer"
#: edewm/Windowmanager.cpp:90
#, c-format
msgid "Another window manager is running. You must exit it before running %s."
msgstr "Un autre gestionnaire de fenêtre est actif. Vous devez le quitter avant de démarrer %s."

BIN
edewm/locale/hu.mo Normal file

Binary file not shown.

85
edewm/locale/hu.po Normal file
View File

@ -0,0 +1,85 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2005-02-09 11:21+0100\n"
"Last-Translator: Nemeth Otto <otto_nemeth@freemail.hu>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: Desktop.cpp:138
#: Desktop.cpp:180
#, c-format
msgid "Workspace %d"
msgstr "Munkaterület %d"
#: Frame.cpp:106
msgid "Untitled"
msgstr "Névtelen"
#: Frame.cpp:938
#, c-format
msgid "EDEWM: Internal bug, when restacking (%d != %d)! Exiting... "
msgstr "EDEWM: Belső hiba, restacking (%d != %d)! Kilépés... "
#: Titlebar.cpp:215
msgid "Sticky"
msgstr "Ragadós"
#: Titlebar.cpp:275
#: Titlebar.cpp:320
msgid "Set size"
msgstr "Méret beállítása"
#: Titlebar.cpp:276
msgid "Set size to window:"
msgstr "Ablakméret beállítása:"
#: Titlebar.cpp:285
msgid "width:"
msgstr "szél.:"
#: Titlebar.cpp:287
msgid "height:"
msgstr "mag.:"
#: Titlebar.cpp:291
msgid "&OK"
msgstr "&OK"
#: Titlebar.cpp:294
msgid "&Cancel"
msgstr "Mégs&em"
#: Titlebar.cpp:318
#: Titlebar.cpp:331
msgid "Maximize"
msgstr "Maximalizálás"
#: Titlebar.cpp:319
msgid "Minimize"
msgstr "Minimalizálás"
#: Titlebar.cpp:321
msgid "To Desktop"
msgstr "Munkaterületre"
#: Titlebar.cpp:322
msgid "Kill"
msgstr "Kilövés"
#: Titlebar.cpp:323
msgid "Close"
msgstr "Bezárás"
#: Titlebar.cpp:330
msgid "Restore"
msgstr "Visszaállítás"
#: Windowmanager.cpp:90
#, c-format
msgid "Another window manager is running. You must exit it before running %s."
msgstr "Egy másik ablakkezelő fut. Ki kell lépni belőle mielőtt ezt futtatod: %s."

89
edewm/locale/id.po Normal file
View File

@ -0,0 +1,89 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: edewm 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-02-04 12:33+0100\n"
"PO-Revision-Date: 202-11-29 14:20+0700\n"
"Last-Translator: Bambang Purnomosidi D. P. <i-am-the-boss@bpdp.org>\n"
"Language-Team: id <i-am-the-boss@bpdp.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-2\n"
"Content-Transfer-Encoding: 8bit\n"
#: Desktop.cpp:138 Desktop.cpp:180
#, c-format
msgid "Workspace %d"
msgstr "Ruangkerja %d"
#: Frame.cpp:106
msgid "Untitled"
msgstr "Tanpa judul"
#: Frame.cpp:938
#, c-format
msgid "EDEWM: Internal bug, when restacking (%d != %d)! Exiting... "
msgstr ""
#: Titlebar.cpp:215
msgid "Sticky"
msgstr "Sticky"
#: Titlebar.cpp:275 Titlebar.cpp:320
msgid "Set size"
msgstr ""
#: Titlebar.cpp:276
msgid "Set size to window:"
msgstr ""
#: Titlebar.cpp:285
msgid "width:"
msgstr ""
#: Titlebar.cpp:287
msgid "height:"
msgstr ""
#: Titlebar.cpp:291
msgid "&OK"
msgstr ""
#: Titlebar.cpp:294
msgid "&Cancel"
msgstr ""
#: Titlebar.cpp:318 Titlebar.cpp:331
msgid "Maximize"
msgstr "Maksimalkan"
#: Titlebar.cpp:319
msgid "Minimize"
msgstr "Minimalkan"
#: Titlebar.cpp:321
msgid "To Desktop"
msgstr "Ke Desktop"
#: Titlebar.cpp:322
msgid "Kill"
msgstr ""
#: Titlebar.cpp:323
msgid "Close"
msgstr "Tutup"
#: Titlebar.cpp:330
msgid "Restore"
msgstr "Kembalikan"
#: Windowmanager.cpp:90
#, c-format
msgid "Another window manager is running. You must exit it before running %s."
msgstr ""
"Window manager lain sedang berjalan. Anda harus menghentikannya sebelum "
"menjalankan %s."

View File

@ -0,0 +1,63 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#: Desktop.cpp:233 Windowmanager.cpp:97
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2002-09-16 10:58+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: Desktop.cpp:247
#, c-format
msgid "Workspace %d"
msgstr ""
#: Frame.cpp:134 main.cpp:51
msgid "Untitled"
msgstr ""
#: Titlebar.cpp:211
msgid "Sticky"
msgstr ""
#: Titlebar.cpp:247 Titlebar.cpp:257
msgid "Maximize"
msgstr ""
#: Titlebar.cpp:248
msgid "Minimize"
msgstr ""
#: Titlebar.cpp:249
msgid "To Desktop"
msgstr ""
#: Titlebar.cpp:250
msgid "Close"
msgstr ""
#: Titlebar.cpp:272
msgid "Kill"
msgstr ""
#: Titlebar.cpp:256
msgid "Restore"
msgstr ""
#: Windowmanager.cpp:88
#, c-format
msgid "Another window manager is running. You must exit it before running %s."
msgstr ""

88
edewm/locale/messages.pot Normal file
View File

@ -0,0 +1,88 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-02-04 12:33+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: Desktop.cpp:138 Desktop.cpp:180
#, c-format
msgid "Workspace %d"
msgstr ""
#: Frame.cpp:106
msgid "Untitled"
msgstr ""
#: Frame.cpp:938
#, c-format
msgid "EDEWM: Internal bug, when restacking (%d != %d)! Exiting... "
msgstr ""
#: Titlebar.cpp:215
msgid "Sticky"
msgstr ""
#: Titlebar.cpp:275 Titlebar.cpp:320
msgid "Set size"
msgstr ""
#: Titlebar.cpp:276
msgid "Set size to window:"
msgstr ""
#: Titlebar.cpp:285
msgid "width:"
msgstr ""
#: Titlebar.cpp:287
msgid "height:"
msgstr ""
#: Titlebar.cpp:291
msgid "&OK"
msgstr ""
#: Titlebar.cpp:294
msgid "&Cancel"
msgstr ""
#: Titlebar.cpp:318 Titlebar.cpp:331
msgid "Maximize"
msgstr ""
#: Titlebar.cpp:319
msgid "Minimize"
msgstr ""
#: Titlebar.cpp:321
msgid "To Desktop"
msgstr ""
#: Titlebar.cpp:322
msgid "Kill"
msgstr ""
#: Titlebar.cpp:323
msgid "Close"
msgstr ""
#: Titlebar.cpp:330
msgid "Restore"
msgstr ""
#: Windowmanager.cpp:90
#, c-format
msgid "Another window manager is running. You must exit it before running %s."
msgstr ""

BIN
edewm/locale/ru.mo Normal file

Binary file not shown.

90
edewm/locale/ru.po Normal file
View File

@ -0,0 +1,90 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-02-04 12:33+0100\n"
"PO-Revision-Date: 2002-11-28 HO:MI+ZONE\n"
"Last-Translator: aabbvv <null@list.ru>\n"
"Language-Team: RUSSIAN <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=koi8-r\n"
"Content-Transfer-Encoding: 8bit\n"
#: Desktop.cpp:138 Desktop.cpp:180
#, c-format
msgid "Workspace %d"
msgstr "òÁÂÏÞÉÊ ÓÔÏÌ %d"
#: Frame.cpp:106
msgid "Untitled"
msgstr "îÅÐÏÉÍÅÎÏ×ÁÎÎÙÊ"
#: Frame.cpp:938
#, c-format
msgid "EDEWM: Internal bug, when restacking (%d != %d)! Exiting... "
msgstr ""
#: Titlebar.cpp:215
msgid "Sticky"
msgstr "÷ÓÅ ÓÒÁÚÕ"
#: Titlebar.cpp:275 Titlebar.cpp:320
msgid "Set size"
msgstr ""
#: Titlebar.cpp:276
msgid "Set size to window:"
msgstr ""
#: Titlebar.cpp:285
msgid "width:"
msgstr ""
#: Titlebar.cpp:287
msgid "height:"
msgstr ""
#: Titlebar.cpp:291
msgid "&OK"
msgstr ""
#: Titlebar.cpp:294
msgid "&Cancel"
msgstr ""
#: Titlebar.cpp:318 Titlebar.cpp:331
msgid "Maximize"
msgstr "òÁÚ×ÅÒÎÕÔØ"
#: Titlebar.cpp:319
msgid "Minimize"
msgstr "ó×ÅÒÎÕÔØ"
#: Titlebar.cpp:321
msgid "To Desktop"
msgstr "îÁ ÒÁÂÏÞÉÊ ÓÔÏÌ"
#: Titlebar.cpp:322
msgid "Kill"
msgstr ""
#: Titlebar.cpp:323
msgid "Close"
msgstr "úÁËÒÙÔØ"
#: Titlebar.cpp:330
msgid "Restore"
msgstr "÷ÏÓÓÔÁÎÏ×ÉÔØ"
#: Windowmanager.cpp:90
#, c-format
msgid "Another window manager is running. You must exit it before running %s."
msgstr ""
"úÁÐÕÝÅÎ ÄÒÕÇÏÊ ÏËÏÎÎÙÊ ÍÅÎÅÄÖÅÒ. îÅÏÂÈÏÄÉÍÏ ×ÙÊÔÉ ÉÈ ÎÅÇÏ ÐÅÒÅ ÔÅÍ ËÁË "
"ÚÁÐÕÓÔÉÔØ %s."

BIN
edewm/locale/sk.mo Normal file

Binary file not shown.

87
edewm/locale/sk.po Normal file
View File

@ -0,0 +1,87 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Free Software Foundation, Inc.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: edewm 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-02-04 12:33+0100\n"
"PO-Revision-Date: 2002-04-21 14:50+0200\n"
"Last-Translator: Martin Pekar <cortex@nextra.sk>\n"
"Language-Team: Slovak <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: Desktop.cpp:138 Desktop.cpp:180
#, c-format
msgid "Workspace %d"
msgstr "Plocha %d"
#: Frame.cpp:106
msgid "Untitled"
msgstr "Bez názvu"
#: Frame.cpp:938
#, c-format
msgid "EDEWM: Internal bug, when restacking (%d != %d)! Exiting... "
msgstr ""
#: Titlebar.cpp:215
msgid "Sticky"
msgstr "Lepkavý"
#: Titlebar.cpp:275 Titlebar.cpp:320
msgid "Set size"
msgstr ""
#: Titlebar.cpp:276
msgid "Set size to window:"
msgstr ""
#: Titlebar.cpp:285
msgid "width:"
msgstr ""
#: Titlebar.cpp:287
msgid "height:"
msgstr ""
#: Titlebar.cpp:291
msgid "&OK"
msgstr ""
#: Titlebar.cpp:294
msgid "&Cancel"
msgstr ""
#: Titlebar.cpp:318 Titlebar.cpp:331
msgid "Maximize"
msgstr "Maximalizovať"
#: Titlebar.cpp:319
msgid "Minimize"
msgstr "Minimalizovať"
#: Titlebar.cpp:321
msgid "To Desktop"
msgstr "Na plochu"
#: Titlebar.cpp:322
msgid "Kill"
msgstr "Ukončiť"
#: Titlebar.cpp:323
msgid "Close"
msgstr "Zavrieť"
#: Titlebar.cpp:330
msgid "Restore"
msgstr "Obnoviť"
#: Windowmanager.cpp:90
#, c-format
msgid "Another window manager is running. You must exit it before running %s."
msgstr ""
"Práve beží už iný manažér okien. Musíte ho ukončiť a chcete spustiť %s."

BIN
edewm/locale/sr.mo Normal file

Binary file not shown.

87
edewm/locale/sr.po Normal file
View File

@ -0,0 +1,87 @@
# EDEWM - Prevod na srpski jezik
# Copyright (C) 2002 EDE Team
# Dejan Lekic Dejan Lekic <dejan@nu6.org>, 2002.
#
msgid ""
msgstr ""
"Project-Id-Version: EDEWM 0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-02-04 12:33+0100\n"
"PO-Revision-Date: 2002-11-21 08:26+0100\n"
"Last-Translator: Dejan Lekic <dejan@nu6.org>\n"
"Language-Team: LINUKS.org T.T. <i18n@linuks.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: Desktop.cpp:138 Desktop.cpp:180
#, c-format
msgid "Workspace %d"
msgstr "Радни простор %d"
#: Frame.cpp:106
msgid "Untitled"
msgstr "Неименован"
#: Frame.cpp:938
#, c-format
msgid "EDEWM: Internal bug, when restacking (%d != %d)! Exiting... "
msgstr ""
#: Titlebar.cpp:215
msgid "Sticky"
msgstr "Стики"
#: Titlebar.cpp:275 Titlebar.cpp:320
msgid "Set size"
msgstr ""
#: Titlebar.cpp:276
msgid "Set size to window:"
msgstr ""
#: Titlebar.cpp:285
msgid "width:"
msgstr ""
#: Titlebar.cpp:287
msgid "height:"
msgstr ""
#: Titlebar.cpp:291
msgid "&OK"
msgstr ""
#: Titlebar.cpp:294
msgid "&Cancel"
msgstr ""
#: Titlebar.cpp:318 Titlebar.cpp:331
msgid "Maximize"
msgstr "Максимизуј"
#: Titlebar.cpp:319
msgid "Minimize"
msgstr "Минимизуј"
#: Titlebar.cpp:321
msgid "To Desktop"
msgstr "На десктоп"
#: Titlebar.cpp:322
msgid "Kill"
msgstr ""
#: Titlebar.cpp:323
msgid "Close"
msgstr "Затвори"
#: Titlebar.cpp:330
msgid "Restore"
msgstr "Врати"
#: Windowmanager.cpp:90
#, c-format
msgid "Another window manager is running. You must exit it before running %s."
msgstr ""
"Други менаџер прозора је активан. Мораћете га угасити пре покретања %s."

68
edewm/main.cpp Normal file
View File

@ -0,0 +1,68 @@
#include "Frame.h"
#include "Desktop.h"
#include "Windowmanager.h"
#include <efltk/filename.h>
#include <efltk/fl_draw.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "debug.h"
#include <edeconf.h>
#include <signal.h>
bool wm_shutdown = false;
void exit_signal(int signum)
{
printf("EDEWM: Exiting (got signal %d)\n", signum);
wm_shutdown = true;
}
int main(int argc, char ** argv)
{
signal(SIGTERM, exit_signal);
signal(SIGKILL, exit_signal);
signal(SIGINT, exit_signal);
Fl::args(argc, argv);
fl_init_locale_support("edewm", PREFIX"/share/locale");
WindowManager wm(argc, argv);
root = &wm;
Fl_Style::load_theme();
while(!wm_shutdown) {
Fl::wait();
wm.idle();
}
Frame_List l(map_order);
for(uint n=0; n<l.size(); n++) {
Frame *f = l[n];
delete f;
}
DBG("Going down");
return 0;
}
void DBG(const char *str, ...)
{
#ifdef _DEBUG
fprintf(stderr, "EDEWM DEBUG: ");
va_list args;
va_start(args, str);
vfprintf(stderr, str, args);
va_end(args);
fprintf(stderr, "\n");
fflush(stderr);
#endif
}

258
edewm/tux.xpm Normal file
View File

@ -0,0 +1,258 @@
/* XPM */
static const char * tux_xpm[] = {
"48 48 207 2",
" c None",
". c #000000",
"+ c #858585",
"@ c #333333",
"# c #7F7F7F",
"$ c #BABABA",
"% c #B8B8B8",
"& c #C1C1C1",
"* c #2D2D2D",
"= c #C6C6C6",
"- c #D9D9D9",
"; c #8A8A8A",
"> c #BBBBBB",
", c #C9C9C9",
"' c #9C9C9C",
") c #EDEDED",
"! c #D7D7D7",
"~ c #888888",
"{ c #DEDEDE",
"] c #E9E9E9",
"^ c #EAEAEA",
"/ c #C2C2C2",
"( c #EBEBEB",
"_ c #BEBEBE",
": c #262626",
"< c #929292",
"[ c #999999",
"} c #828282",
"| c #F3F3F3",
"1 c #DDDDDD",
"2 c #ABABAB",
"3 c #DCAF00",
"4 c #FFDC00",
"5 c #939393",
"6 c #878787",
"7 c #F2F2F2",
"8 c #FFF793",
"9 c #FFF148",
"0 c #FFE957",
"a c #EFE3A3",
"b c #482D00",
"c c #424242",
"d c #AF6800",
"e c #FFF461",
"f c #FFF1C1",
"g c #FFF1B5",
"h c #FFE600",
"i c #E1B500",
"j c #815200",
"k c #484848",
"l c #EBC200",
"m c #FFEB84",
"n c #FFE71C",
"o c #C99300",
"p c #610000",
"q c #343434",
"r c #DBC975",
"s c #D8AA00",
"t c #D9AB00",
"u c #B57300",
"v c #C08500",
"w c #E3B800",
"x c #2D0000",
"y c #636363",
"z c #A1A1A1",
"A c #EEEEEE",
"B c #E9D677",
"C c #CC9A00",
"D c #DFB300",
"E c #E7BE00",
"F c #EDD700",
"G c #EEE3AD",
"H c #666666",
"I c #8D8D8D",
"J c #B2B2B2",
"K c #3F3F3F",
"L c #D1D1D1",
"M c #F1F1F1",
"N c #E8E8E8",
"O c #DADADA",
"P c #ECECEC",
"Q c #DFDFDF",
"R c #818181",
"S c #393939",
"T c #676767",
"U c #D3D3D3",
"V c #F0F0F0",
"W c #D2D2D2",
"X c #CACACA",
"Y c #C4C4C4",
"Z c #646464",
"` c #D8D8D8",
" . c #F5F5F5",
".. c #F7F7F7",
"+. c #F8F8F8",
"@. c #CDCDCD",
"#. c #EFEFEF",
"$. c #E4E4E4",
"%. c #FAFAFA",
"&. c #E7E7E7",
"*. c #E1E1E1",
"=. c #DCDCDC",
"-. c #C7C7C7",
";. c #898989",
">. c #FBFBFB",
",. c #F9F9F9",
"'. c #8E8E8E",
"). c #D5D5D5",
"!. c #E3E3E3",
"~. c #AFAFAF",
"{. c #E6E6E6",
"]. c #D0D0D0",
"^. c #E5E5E5",
"/. c #E0E0E0",
"(. c #767676",
"_. c #414141",
":. c #E1E0DF",
"<. c #575757",
"[. c #959595",
"}. c #FCF8E8",
"|. c #F9F3DB",
"1. c #E2E2E2",
"2. c #1C0000",
"3. c #F7EFC6",
"4. c #A49F8F",
"5. c #5F5D51",
"6. c #D9D2BB",
"7. c #FFEA66",
"8. c #D8B400",
"9. c #B4B4B4",
"0. c #D9D9D7",
"a. c #614800",
"b. c #FCF7E3",
"c. c #CBA900",
"d. c #9B7300",
"e. c #8A7C00",
"f. c #521C00",
"g. c #1C1A00",
"h. c #CCC9C2",
"i. c #FAF3D8",
"j. c #FFED92",
"k. c #FBD700",
"l. c #F7D300",
"m. c #D7B300",
"n. c #616161",
"o. c #D6D6D5",
"p. c #684C00",
"q. c #FBF3C9",
"r. c #FAD700",
"s. c #E0BD00",
"t. c #BB9600",
"u. c #E3C000",
"v. c #9A9382",
"w. c #E7DFBC",
"x. c #D4CDA8",
"y. c #FFE400",
"z. c #F2CF00",
"A. c #EECB00",
"B. c #D7B400",
"C. c #CCCCCC",
"D. c #5F5F5F",
"E. c #FBF0C3",
"F. c #F9D700",
"G. c #FDDA00",
"H. c #C9B400",
"I. c #EEDA55",
"J. c #E9C700",
"K. c #938500",
"L. c #DED086",
"M. c #EAC700",
"N. c #C9A700",
"O. c #979797",
"P. c #BFBFBF",
"Q. c #A6A6A6",
"R. c #989898",
"S. c #595959",
"T. c #F8EFC3",
"U. c #F7D400",
"V. c #EDCB00",
"W. c #D3B400",
"X. c #877000",
"Y. c #E7DDAA",
"Z. c #FBE100",
"`. c #DCB900",
" + c #947300",
".+ c #F5ECC3",
"++ c #EBC900",
"@+ c #F3CF00",
"#+ c #EFCC00",
"$+ c #E6C200",
"%+ c #B39600",
"&+ c #A99500",
"*+ c #DCB800",
"=+ c #D3B000",
"-+ c #CFAC00",
";+ c #AF8A00",
">+ c #836300",
",+ c #EDE09B",
"'+ c #EAD866",
")+ c #E1BE00",
"!+ c #B79A00",
"~+ c #9A8100",
"{+ c #605721",
"]+ c #9D8B21",
"^+ c #968319",
"/+ c #746100",
"(+ c #211E0D",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" . . ",
" . . . . . . . + ",
" . . . . @ # $ # . ",
" . . . . . . . % & . . ",
" . . . . . . . . * . . . ",
" . . . . . . . . . . . . . ",
" . . = - ; . . > , . . . . ",
" . ' ) ) ! ~ { ] ^ / . . . ",
" . ( _ : < [ = . } | . . . ",
" . 1 2 . 3 4 5 . 6 7 . . . ",
" . @ 3 8 9 0 4 4 a b . . . c ",
" . d e f g h 4 4 4 i j . . k ",
" . . 3 l m n 4 3 d o p . . q ",
" . . r s t d u v w x . [ . y ",
" . z A B C D E F G H . I J . ",
" . K L M M N O A P ] Q R . . . . ",
" S . T U V W N W N X - / Y . . . . . ",
" . Z ` ...+.@.( | #.$.U ! + . . . . . ",
" . . , $...%.+.&... .M A *.=.-.. . . . . ",
" . . ;.M .+.>.>.,.1 .M A ( &.$.'.. . . . ",
" . . ).M ...%.,.Q P .M A ( &.!.~.. . . . ",
" . . X V | .....- .| V ) ^ {.!.].. . . . ",
" . . + A M | . .- | M A ( N ^.*.& . . . . ",
" . . . % ! ^.M M =.V #.P ] {.!./.'.H (.. ",
" . . . . . . _.& A /.#.( ] &.$.:.. . . . . <. ",
" . [.}.|.. . . . . X !.$.N {.$.1.2.3.4.. . . . 5. ",
" . . 6.7.4 8.. . . . 9.&.` &.!.*.0.a.b.c.. . d.e.f.g. ",
" . h.i.j.4 k.l.m.. n./ !.!.{ *./.{ o.p.q.r.s.t.u.v.w.. ",
" . x.y.4 k.l.z.A.B.. L /./.Q { 1 C.D.. E.F.G.G.H.I.J.K.. ",
" . L.k.l.z.A.M.N.. O.P.@._ Q.R.S.. . T.l.r.r.U.V.W.X.. ",
" . Y.Z.l.z.A.M.`. +. . . . . . . . . . .+++@+#+$+%+. . ",
" . &+*+B.=+-+;+>+. . . . . . . . . . . ,+'+)+!+~+. ",
" . . . . . . . . . . . . {+]+^+/+. ",
" (+ ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};