Many changes so it compiles and works with fltk2. Menus are

still a bit screwed up.
This commit is contained in:
Bill Spitzak
2004-10-11 06:35:02 +00:00
parent 9cbc566a07
commit 5c20a23b4c
7 changed files with 306 additions and 89 deletions

240
Frame.C
View File

@ -8,6 +8,7 @@
#include <FL/fl_draw.H>
#include "Rotated.H"
static Atom wm_state = 0;
static Atom wm_change_state;
static Atom wm_protocols;
@ -63,7 +64,7 @@ int dont_set_event_mask = 0; // used by FrameWindow
// passed for an already-existing window when the window manager is
// starting up. If so we don't want to alter the state, size, or
// position. If null than this is a MapRequest of a new window.
Frame::Frame(Window window, XWindowAttributes* existing) :
Frame::Frame(XWindow window, XWindowAttributes* existing) :
Fl_Window(0,0),
window_(window),
state_flags_(0),
@ -223,20 +224,9 @@ Frame::Frame(Window window, XWindowAttributes* existing) :
show_hide_buttons();
if (autoplace && !existing && !(transient_for() && (x() || y()))) {
// autoplacement (stupid version for now)
x(Root->x()+(Root->w()-w())/2);
y(Root->y()+(Root->h()-h())/2);
// move it until it does not hide any existing windows:
const int delta = TITLE_WIDTH+LEFT;
for (Frame* f = next; f; f = f->next) {
if (f->x()+delta > x() && f->y()+delta > y() &&
f->x()+f->w()-delta < x()+w() && f->y()+f->h()-delta < y()+h()) {
x(max(x(),f->x()+delta));
y(max(y(),f->y()+delta));
f = this;
}
}
place_window();
}
// move window so contents and border are visible:
x(force_x_onscreen(x(), w()));
y(force_y_onscreen(y(), h()));
@ -260,7 +250,8 @@ Frame::Frame(Window window, XWindowAttributes* existing) :
sattr.bit_gravity = NorthWestGravity;
sattr.override_redirect = 1;
sattr.background_pixel = fl_xpixel(FL_GRAY);
Fl_X::set_xid(this, XCreateWindow(fl_display, fl_xid(Root),
Fl_X::set_xid(this, XCreateWindow(fl_display,
RootWindow(fl_display,fl_screen),
x(), y(), w(), h(), 0,
fl_visual->depth,
InputOutput,
@ -277,16 +268,141 @@ Frame::Frame(Window window, XWindowAttributes* existing) :
sendConfigureNotify(); // many apps expect this even if window size unchanged
#if CLICK_RAISES || CLICK_TO_TYPE
XGrabButton(fl_display, AnyButton, AnyModifier, window, False,
ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
if (!dont_set_event_mask)
XGrabButton(fl_display, AnyButton, AnyModifier, window, False,
ButtonPressMask, GrabModeSync, GrabModeAsync, None, None);
#endif
if (state_ == NORMAL) {
XMapWindow(fl_display, fl_xid(this));
if (!existing) activate_if_transient();
}
set_visible();
}
#if SMART_PLACEMENT
// Helper functions for "smart" window placement.
int overlap1(int p1, int l1, int p2, int l2) {
int ret = 0;
if(p1 <= p2 && p2 <= p1 + l1) {
ret = min(p1 + l1 - p2, l2);
} else if (p2 <= p1 && p1 <= p2 + l2) {
ret = min(p2 + l2 - p1, l1);
}
return ret;
}
int overlap(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) {
return (overlap1(x1, w1, x2, w2) * overlap1(y1, h1, y2, h2));
}
// Compute the overlap with existing windows.
// For normal windows the overlapping area is taken into account plus a
// constant value for every overlapping window.
// The active window counts twice.
// For iconic windows half the overlapping area is taken into account.
int getOverlap(int x, int y, int w, int h, Frame *first, Frame *self) {
int ret = 0;
short state;
for (Frame* f = first; f; f = f->next) {
if (f != self) {
state = f->state();
if (state == NORMAL || state == ICONIC) {
int o = overlap(x, y, w, h, f->x(), f->y(), f->w(), f->h());
if (state == NORMAL) {
ret = ret + o + (o>0?40000:0) + (o * f->active());
} else if (state == ICONIC) {
ret = ret + o/2;
}
}
}
}
return ret;
}
// autoplacement (brute force version for now)
void Frame::place_window() {
int min_overlap = -1;
int tmp_x, tmp_y, tmp_o;
int best_x = 0;
int best_y = 0;
int _w = w();
int _h = h();
int max_x = Root->x() + Root->w();
int max_y = Root->y() + Root->h();
Frame *f1 = Frame::first;
for(int i=0;; i++) {
if (i==0) {
tmp_x = 0;
} else if (i==1) {
tmp_x = max_x - _w;
} else {
if (f1 == this) {
f1 = f1->next;
}
if (!f1) {
break;
}
tmp_x = f1->x() + f1->w();
f1 = f1->next;
}
Frame *f2 = Frame::first;
for(int j=0;; j++) {
if (j==0) {
tmp_y = 0;
} else if (j==1) {
tmp_y = max_y - _h;
} else {
if (f2 == this) {
f2 = f2->next;
}
if (!f2) {
break;
}
tmp_y = f2->y() + f2->h();
f2 = f2->next;
}
if ((tmp_x + _w <= max_x) && (tmp_y + _h <= max_y)) {
tmp_o = getOverlap(tmp_x, tmp_y, _w, _h, Frame::first, this);
if(tmp_o < min_overlap || min_overlap < 0) {
best_x = tmp_x;
best_y = tmp_y;
min_overlap = tmp_o;
if (min_overlap == 0) {
break;
}
}
}
}
if (min_overlap == 0) {
break;
}
}
x(best_x);
y(best_y);
}
#else
// autoplacement (stupid version for now)
void Frame::place_window() {
x(Root->x()+(Root->w()-w())/2);
y(Root->y()+(Root->h()-h())/2);
// move it until it does not hide any existing windows:
const int delta = TITLE_WIDTH+LEFT;
for (Frame* f = next; f; f = f->next) {
if (f->x()+delta > x() && f->y()+delta > y() &&
f->x()+f->w()-delta < x()+w() && f->y()+f->h()-delta < y()+h()) {
x(max(x(),f->x()+delta));
y(max(y(),f->y()+delta));
f = this;
}
}
}
#endif
// modify the passed X & W to a legal horizontal window position
int Frame::force_x_onscreen(int X, int W) {
// force all except the black border on-screen:
@ -333,10 +449,12 @@ Frame::~Frame() {
// a legal state value to this location:
state_ = UNMAPPED;
#if FL_MAJOR_VERSION < 2
// fix fltk bug:
fl_xfocus = 0;
fl_xmousewin = 0;
Fl::focus_ = 0;
#endif
// remove any pointers to this:
Frame** cp; for (cp = &first; *cp; cp = &((*cp)->next))
@ -554,7 +672,7 @@ int Frame::getMotifHints() {
// see if they set "input hint" to non-zero:
// prop[3] should be nonzero but the only example of this I have
// found is Netscape 3.0 and it sets it to zero...
if (!shown() && (prop[0]&4) /*&& prop[3]*/) set_flag(MODAL);
if (!shown() && (prop[0]&4) /*&& prop[3]*/) set_flag(::MODAL);
// see if it is forcing the iconize button back on. This makes
// transient_for act like group instead...
@ -578,7 +696,7 @@ void Frame::getColormaps(void) {
delete[] window_Colormaps;
}
int n;
Window* cw = (Window*)getProperty(wm_colormap_windows, XA_WINDOW, &n);
XWindow* cw = (XWindow*)getProperty(wm_colormap_windows, XA_WINDOW, &n);
if (cw) {
colormapWinCount = n;
colormapWindows = cw;
@ -644,7 +762,7 @@ int Frame::activate_if_transient() {
int Frame::activate(int warp) {
// see if a modal & newer window is up:
for (Frame* c = first; c && c != this; c = c->next)
if (c->flag(MODAL) && c->transient_for() == this)
if (c->flag(::MODAL) && c->transient_for() == this)
if (c->activate(warp)) return 1;
// ignore invisible windows:
if (state() != NORMAL || w() <= dwidth) return 0;
@ -670,14 +788,14 @@ int Frame::activate(int warp) {
if (active_ != this) {
if (active_) active_->deactivate();
active_ = this;
#if defined(ACTIVE_COLOR)
#ifdef ACTIVE_COLOR
XSetWindowAttributes a;
a.background_pixel = fl_xpixel(FL_SELECTION_COLOR);
XChangeWindowAttributes(fl_display, fl_xid(this), CWBackPixel, &a);
labelcolor(contrast(FL_BLACK, FL_SELECTION_COLOR));
XClearArea(fl_display, fl_xid(this), 2, 2, w()-4, h()-4, 1);
#else
#if defined(SHOW_CLOCK)
#ifdef SHOW_CLOCK
redraw();
#endif
#endif
@ -690,14 +808,14 @@ int Frame::activate(int warp) {
// this private function should only be called by constructor and if
// the window is active():
void Frame::deactivate() {
#if defined(ACTIVE_COLOR)
#ifdef ACTIVE_COLOR
XSetWindowAttributes a;
a.background_pixel = fl_xpixel(FL_GRAY);
XChangeWindowAttributes(fl_display, fl_xid(this), CWBackPixel, &a);
labelcolor(FL_BLACK);
XClearArea(fl_display, fl_xid(this), 2, 2, w()-4, h()-4, 1);
#else
#if defined(SHOW_CLOCK)
#ifdef SHOW_CLOCK
redraw();
#endif
#endif
@ -737,9 +855,9 @@ void Frame::state(short newstate) {
switch (newstate) {
case UNMAPPED:
throw_focus();
set_state_flag(IGNORE_UNMAP);
XUnmapWindow(fl_display, fl_xid(this));
XUnmapWindow(fl_display, window_);
//set_state_flag(IGNORE_UNMAP);
//XUnmapWindow(fl_display, window_);
XRemoveFromSaveSet(fl_display, window_);
break;
case NORMAL:
@ -753,9 +871,9 @@ void Frame::state(short newstate) {
XAddToSaveSet(fl_display, window_);
} else if (oldstate == NORMAL) {
throw_focus();
set_state_flag(IGNORE_UNMAP);
XUnmapWindow(fl_display, fl_xid(this));
XUnmapWindow(fl_display, window_);
//set_state_flag(IGNORE_UNMAP);
//XUnmapWindow(fl_display, window_);
} else {
return; // don't setStateProperty IconicState multiple times
}
@ -908,7 +1026,7 @@ void Frame::set_size(int nx, int ny, int nw, int nh, int warp) {
int old_label_y = label_y;
int old_label_h = label_h;
h(nh); show_hide_buttons();
#ifdef SHOW_CLOCK
#if 1 //def SHOW_CLOCK
int t = label_y + 3; // we have to clear the entire label area
#else
int t = nh;
@ -1075,6 +1193,8 @@ void Frame::show_hide_buttons() {
// make sure fltk does not try to set the window size:
void Frame::resize(int, int, int, int) {}
// For fltk2.0:
void Frame::layout() {layout_damage(0);}
////////////////////////////////////////////////////////////////
@ -1110,19 +1230,27 @@ void Frame::save_protocol() {
////////////////////////////////////////////////////////////////
// Drawing code:
#if FL_MAJOR_VERSION>1
# include <fltk/Box.h>
#endif
void Frame::draw() {
if (flag(NO_BORDER)) return;
if (!flag(THIN_BORDER)) Fl_Window::draw();
if (damage() != FL_DAMAGE_CHILD) {
#if ACTIVE_COLOR
#ifdef ACTIVE_COLOR
fl_frame2(active() ? "AAAAJJWW" : "AAAAJJWWNNTT",0,0,w(),h());
if (active()) {
fl_color(FL_GRAY_RAMP+('N'-'A'));
fl_xyline(2, h()-3, w()-3, 2);
}
#else
# if FL_MAJOR_VERSION>1
static fltk::FrameBox framebox(0,"AAAAJJWWNNTT");
framebox.draw(0,0,w(),h(),style(),fltk::INVISIBLE); // INVISIBLE = draw edge only
# else
fl_frame("AAAAWWJJTTNN",0,0,w(),h());
# endif
#endif
if (!flag(THIN_BORDER) && label_h > 3) {
#ifdef SHOW_CLOCK
@ -1168,39 +1296,48 @@ void Frame::redraw_clock() {
#endif
void FrameButton::draw() {
#if FL_MAJOR_VERSION>1
const int x = 0;
const int y = 0;
FL_UP_BOX->draw(0,0,w(),h(),style(),
value() ? (fltk::INVISIBLE|fltk::VALUE) : fltk::INVISIBLE);
#else
const int x = this->x();
const int y = this->y();
Fl_Widget::draw_box(value() ? FL_DOWN_FRAME : FL_UP_FRAME, FL_GRAY);
#endif
fl_color(parent()->labelcolor());
switch (label()[0]) {
case 'W':
#if MINIMIZE_ARROW
fl_line (x()+2,y()+(h())/2,x()+w()-4,y()+h()/2);
fl_line (x()+2,y()+(h())/2,x()+2+4,y()+h()/2+4);
fl_line (x()+2,y()+(h())/2,x()+2+4,y()+h()/2-4);
fl_line (x+2,y+(h())/2,x+w()-4,y+h()/2);
fl_line (x+2,y+(h())/2,x+2+4,y+h()/2+4);
fl_line (x+2,y+(h())/2,x+2+4,y+h()/2-4);
#else
fl_rect(x()+(h()-7)/2,y()+3,2,h()-6);
fl_rect(x+(h()-7)/2,y+3,2,h()-6);
#endif
return;
case 'w':
fl_rect(x()+2,y()+(h()-7)/2,w()-4,7);
fl_rect(x+2,y+(h()-7)/2,w()-4,7);
return;
case 'h':
fl_rect(x()+(h()-7)/2,y()+2,7,h()-4);
fl_rect(x+(h()-7)/2,y+2,7,h()-4);
return;
case 'X':
#if CLOSE_X
fl_line(x()+2,y()+3,x()+w()-5,y()+h()-4);
fl_line(x()+3,y()+3,x()+w()-4,y()+h()-4);
fl_line(x()+2,y()+h()-4,x()+w()-5,y()+3);
fl_line(x()+3,y()+h()-4,x()+w()-4,y()+3);
fl_line(x+2,y+3,x+w()-5,y+h()-4);
fl_line(x+3,y+3,x+w()-4,y+h()-4);
fl_line(x+2,y+h()-4,x+w()-5,y+3);
fl_line(x+3,y+h()-4,x+w()-4,y+3);
#endif
#if CLOSE_HITTITE_LIGHTNING
fl_arc(x()+3,y()+3,w()-6,h()-6,0,360);
fl_line(x()+7,y()+3, x()+7,y()+11);
fl_arc(x+3,y+3,w()-6,h()-6,0,360);
fl_line(x+7,y+3, x+7,y+11);
#endif
return;
case 'i':
#if ICONIZE_BOX
fl_rect(x()+w()/2-1,y()+h()/2-1,3,3);
fl_rect(x+w()/2-1,y+h()/2-1,3,3);
#endif
return;
}
@ -1324,7 +1461,11 @@ void Frame::set_cursor(int r) {
if (this != previous_frame || c != previous_cursor) {
previous_frame = this;
previous_cursor = c;
#if FL_MAJOR_VERSION>1
cursor(c);
#else
cursor(c, CURSOR_FG_SLOT, CURSOR_BG_SLOT);
#endif
}
}
@ -1577,9 +1718,10 @@ int Frame::handle(const XEvent* ei) {
case UnmapNotify: {
const XUnmapEvent* e = &(ei->xunmap);
if (e->from_configure);
else if (state_flags_&IGNORE_UNMAP) clear_state_flag(IGNORE_UNMAP);
else state(UNMAPPED);
if (e->window == window_ && !e->from_configure) {
if (state_flags_&IGNORE_UNMAP) clear_state_flag(IGNORE_UNMAP);
else state(UNMAPPED);
}
return 1;}
case DestroyNotify: {
@ -1676,7 +1818,7 @@ void* Frame::getProperty(Atom a, Atom type, int* np) const {
return ::getProperty(window_, a, type, np);
}
void* getProperty(Window w, Atom a, Atom type, int* np) {
void* getProperty(XWindow w, Atom a, Atom type, int* np) {
Atom realType;
int format;
unsigned long n, extra;
@ -1696,7 +1838,7 @@ int Frame::getIntProperty(Atom a, Atom type, int deflt) const {
return ::getIntProperty(window_, a, type, deflt);
}
int getIntProperty(Window w, Atom a, Atom type, int deflt) {
int getIntProperty(XWindow w, Atom a, Atom type, int deflt) {
void* prop = getProperty(w, a, type);
if (!prop) return deflt;
int r = int(*(long*)prop);
@ -1704,7 +1846,7 @@ int getIntProperty(Window w, Atom a, Atom type, int deflt) {
return r;
}
void setProperty(Window w, Atom a, Atom type, int v) {
void setProperty(XWindow w, Atom a, Atom type, int v) {
long prop = v;
XChangeProperty(fl_display, w, a, type, 32, PropModeReplace, (uchar*)&prop,1);
}

21
Frame.H
View File

@ -9,6 +9,9 @@
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <FL/x.H>
#if FL_MAJOR_VERSION<2
# define XWindow Window
#endif
// The state is an enumeration of reasons why the window may be invisible.
// Only if it is NORMAL is the window visible.
@ -58,7 +61,7 @@ class Desktop;
class Frame : public Fl_Window {
Window window_;
XWindow window_;
short state_; // X server state: iconic, withdrawn, normal
short state_flags_; // above state flags
@ -79,14 +82,14 @@ class Frame : public Fl_Window {
int label_y, label_h; // location of label
int label_w; // measured width of printed label
Window transient_for_xid; // value from X
XWindow 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;
XWindow *colormapWindows;
Colormap *window_Colormaps; // their colormaps
Desktop* desktop_;
@ -101,6 +104,7 @@ class Frame : public Fl_Window {
int maximize_height();
int force_x_onscreen(int X, int W);
int force_y_onscreen(int Y, int H);
void place_window();
void sendMessage(Atom, Atom) const;
void sendConfigureNotify() const;
@ -122,6 +126,7 @@ class Frame : public Fl_Window {
void set_size(int,int,int,int, int warp=0);
void resize(int,int,int,int);
void layout();
void show_hide_buttons();
int handle(int); // handle fltk events
@ -151,10 +156,10 @@ public:
static Frame* first;
Frame* next; // stacking order, top to bottom
Frame(Window, XWindowAttributes* = 0);
Frame(XWindow, XWindowAttributes* = 0);
~Frame();
Window window() const {return window_;}
XWindow window() const {return window_;}
Frame* transient_for() const {return transient_for_;}
int is_transient_for(const Frame*) const;
@ -185,8 +190,8 @@ public:
};
// handy wrappers for those ugly X routines:
void* getProperty(Window, Atom, Atom = AnyPropertyType, int* length = 0);
int getIntProperty(Window, Atom, Atom = AnyPropertyType, int deflt = 0);
void setProperty(Window, Atom, Atom, int);
void* getProperty(XWindow, Atom, Atom = AnyPropertyType, int* length = 0);
int getIntProperty(XWindow, Atom, Atom = AnyPropertyType, int deflt = 0);
void setProperty(XWindow, Atom, Atom, int);
#endif

View File

@ -165,7 +165,7 @@ int Handle_Hotkey() {
extern Fl_Window* Root;
void Grab_Hotkeys() {
Window root = fl_xid(Root);
XWindow root = fl_xid(Root);
for (int i = 0; keybindings[i].key; i++) {
int k = keybindings[i].key;
int keycode = XKeysymToKeycode(fl_display, k & 0xFFFF);

26
Menu.C
View File

@ -61,6 +61,7 @@ move_frame_callback(Fl_Widget*, void*d)
extern Fl_Window* Root;
#if FL_MAJOR_VERSION < 2
static void
frame_label_draw(const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align)
{
@ -131,6 +132,8 @@ label_measure(const Fl_Label* o, int& W, int& H)
#define FRAME_LABEL FL_FREE_LABELTYPE
#define TEXT_LABEL Fl_Labeltype(FL_FREE_LABELTYPE+1)
#endif // FL_MAJOR_VERSION < 2
////////////////////////////////////////////////////////////////
static void
@ -155,7 +158,7 @@ delete_desktop_cb(Fl_Widget*, void* v)
#if ASK_FOR_NEW_DESKTOP_NAME
static Fl_Input* new_desktop_input;
static Fl_Input* new_desktop_input = 0;
static void
new_desktop_ok_cb(Fl_Widget* w, void*)
@ -205,6 +208,7 @@ new_desktop_cb(Fl_Widget*, void*)
static void
exit_cb(Fl_Widget*, void*)
{
printf("exit_cb\n");
Frame::save_protocol();
exit(0);
}
@ -212,7 +216,7 @@ exit_cb(Fl_Widget*, void*)
static void
logout_cb(Fl_Widget*, void*)
{
static FrameWindow* w;
static FrameWindow* w = 0;
if (!w) {
w = new FrameWindow(190,90);
Fl_Box* l = new Fl_Box(0, 0, 190, 60, "Really log out?");
@ -419,8 +423,10 @@ ShowTabMenu(int tab)
static char beenhere;
if (!beenhere) {
beenhere = 1;
#if FL_MAJOR_VERSION < 2
Fl::set_labeltype(FRAME_LABEL, frame_label_draw, frame_label_measure);
Fl::set_labeltype(TEXT_LABEL, label_draw, label_measure);
#endif
if (exit_flag) {
Fl_Menu_Item* m = other_menu_items+num_other_items-2;
m->label("Exit");
@ -507,8 +513,12 @@ ShowTabMenu(int tab)
#endif
for (c = Frame::first; c; c = c->next) {
if (c->state() == UNMAPPED || c->transient_for()) continue;
#if FL_MAJOR_VERSION < 2
init(menu[n],(char*)c);
menu[n].labeltype(FRAME_LABEL);
#else
init(menu[n],c->label());
#endif
menu[n].callback(frame_callback, c);
if (is_active_frame(c)) preset = menu+n;
n++;
@ -537,7 +547,12 @@ ShowTabMenu(int tab)
if (c->state() == UNMAPPED || c->transient_for()) continue;
if (c->desktop() == d || !c->desktop() && d == Desktop::current()) {
init(menu[n],(char*)c);
#if FL_MAJOR_VERSION < 2
init(menu[n],(char*)c);
menu[n].labeltype(FRAME_LABEL);
#else
init(menu[n],c->label());
#endif
menu[n].callback(d == Desktop::current() ?
frame_callback : move_frame_callback, c);
if (d == Desktop::current() && is_active_frame(c)) preset = menu+n;
@ -581,12 +596,13 @@ ShowTabMenu(int tab)
cmd = wmxlist[i];
cmd += strspn(cmd, "/")-1;
init(menu[n], cmd+pathlen[level]);
#if FL_MAJOR_VERSION < 2
#if DESKTOPS
if (one_desktop)
#endif
if (!level)
menu[n].labeltype(TEXT_LABEL);
#endif
int nextlev = (i==num_wmx-1)?0:strspn(wmxlist[i+1], "/")-1;
if (nextlev < level) {
menu[n].callback(spawn_cb, cmd);
@ -613,15 +629,19 @@ ShowTabMenu(int tab)
#endif
#endif
memcpy(menu+n, other_menu_items, sizeof(other_menu_items));
#if FL_MAJOR_VERSION < 2
#if DESKTOPS
if (one_desktop)
#endif
// fix the menus items so they are indented to align with window names:
while (menu[n].label()) menu[n++].labeltype(TEXT_LABEL);
#endif
const Fl_Menu_Item* picked =
menu->popup(Fl::event_x(), Fl::event_y(), 0, preset);
#if FL_MAJOR_VERSION < 2
if (picked && picked->callback()) picked->do_callback(0);
#endif
}
void ShowMenu() {ShowTabMenu(0);}

View File

@ -27,6 +27,9 @@
/* ********************************************************************** */
#include <FL/x.H>
#if FL_MAJOR_VERSION < 2
# define XWindow Window
#endif
#include <FL/fl_draw.H>
#include "Rotated.H"
#include <stdlib.h>
@ -67,7 +70,7 @@ XRotLoadFont(Display *dpy, XFontStruct* fontstruct, int dir)
char val;
XImage *I1, *I2;
Pixmap canvas;
Window root;
XWindow root;
int screen;
GC font_gc;
char text[3];/*, errstr[300];*/
@ -235,9 +238,9 @@ XRotLoadFont(Display *dpy, XFontStruct* fontstruct, int dir)
}
for (ichar = 0; ichar < min_char; ichar++)
rotfont->per_char[ichar] = rotfont->per_char['?'];
rotfont->per_char[ichar] = rotfont->per_char[int('?')];
for (ichar = max_char+1; ichar < 256; ichar++)
rotfont->per_char[ichar] = rotfont->per_char['?'];
rotfont->per_char[ichar] = rotfont->per_char[int('?')];
/* free pixmap and GC ... */
XFreePixmap(dpy, canvas);
@ -351,23 +354,25 @@ static int XRotTextWidth(XRotFontStruct *rotfont, const char *str, int len)
static XRotFontStruct* font;
void draw_rotated(const char* text, int n, int x, int y, int angle) {
if (!text || !*text) return;
static void setrotfont(int angle) {
/* make angle positive ... */
if (angle < 0) do angle += 360; while (angle < 0);
/* get nearest vertical or horizontal direction ... */
int dir = ((angle+45)/90)%4;
if (font && font->xfontstruct == fl_xfont && font->dir == dir) {
;
} else {
if (font) XRotUnloadFont(fl_display, font);
font = XRotLoadFont(fl_display, fl_xfont, dir);
if (font) {
if (font->xfontstruct == fl_xfont && font->dir == dir) return;
XRotUnloadFont(fl_display, font);
}
font = XRotLoadFont(fl_display, fl_xfont, dir);
}
void draw_rotated(const char* text, int n, int x, int y, int angle) {
if (!text || !*text) return;
setrotfont(angle);
XRotDrawString(fl_display, font, fl_window, fl_gc, x, y, text, n);
}
#ifndef FLWM
#if !defined(FLWM) || FL_MAJOR_VERSION>=2
void draw_rotated(const char* text, int x, int y, int angle) {
if (!text || !*text) return;
draw_rotated(text, strlen(text), x, y, angle);
@ -384,12 +389,20 @@ void draw_rotated90(
if (!str || !*str) return;
if (w && h && !fl_not_clipped(x, y, w, h)) return;
if (align & FL_ALIGN_CLIP) fl_clip(x, y, w, h);
#if FL_MAJOR_VERSION>1
setrotfont(90);
int a = font->xfontstruct->ascent;
int d = font->xfontstruct->descent;
XRotDrawString(fl_display, font, fl_window, fl_gc,
x+(w+a-d+1)/2, y+h, str, strlen(str));
#else
int a1 = align&(-16);
if (align & FL_ALIGN_LEFT) a1 |= FL_ALIGN_TOP;
if (align & FL_ALIGN_RIGHT) a1 |= FL_ALIGN_BOTTOM;
if (align & FL_ALIGN_TOP) a1 |= FL_ALIGN_RIGHT;
if (align & FL_ALIGN_BOTTOM) a1 |= FL_ALIGN_LEFT;
fl_draw(str, -(y+h), x, h, w, (Fl_Align)a1, draw_rot90);
#endif
if (align & FL_ALIGN_CLIP) fl_pop_clip();
}

View File

@ -25,6 +25,12 @@
// nothing is done if this is not defined:
//#define AUTO_RAISE 0.5
// Perform "smart" autoplacement.
// New windows are put at positions where they cover as few existing windows
// as possible. A brute force algorithm is used, so it consumes quite a bit
// of CPU time.
#define SMART_PLACEMENT 1
// set this to zero to remove the multiple-desktop code. This will
// make flwm about 20K smaller
#define DESKTOPS 1

63
main.C
View File

@ -69,7 +69,7 @@ extern void click_raise(Frame*);
// fltk calls this for any events it does not understand:
static int flwm_event_handler(int e) {
if (!e) { // XEvent that fltk did not understand.
Window window = fl_xevent->xany.window;
XWindow window = fl_xevent->xany.window;
// unfortunately most of the redirect events put the interesting
// window id in a different place:
switch (fl_xevent->type) {
@ -114,7 +114,11 @@ static int flwm_event_handler(int e) {
XKeycodeToKeysym(fl_display, fl_xevent->xkey.keycode, 0);
if (keysym == FL_Alt_L || keysym == FL_Alt_R) {
Fl::e_keysym = FL_Enter;
#if FL_MAJOR_VERSION>1
return Fl::modal()->handle(FL_KEYBOARD);
#else
return Fl::grab()->handle(FL_KEYBOARD);
#endif
}
return 0;}
}
@ -189,28 +193,26 @@ void flwm_clock_alarm_off(int) {
#endif
static const char* cfg, *cbg;
#if FL_MAJOR_VERSION>1
static fltk::Cursor* cursor = FL_CURSOR_ARROW;
extern FL_API fltk::Color fl_cursor_fg;
extern FL_API fltk::Color fl_cursor_bg;
#else
static int cursor = FL_CURSOR_ARROW;
static void color_setup(Fl_Color slot, const char* arg, ulong value) {
if (arg) {
XColor x;
if (XParseColor(fl_display, fl_colormap, arg, &x))
value = ((x.red>>8)<<24)|((x.green>>8)<<16)|((x.blue));
}
Fl::set_color(slot, value);
}
#endif
static void initialize() {
Display* d = fl_display;
#ifdef TEST
Window w = XCreateSimpleWindow(d, root,
XWindow w = XCreateSimpleWindow(d, RootWindow(d, fl_screen),
100, 100, 200, 300, 10,
BlackPixel(fl_display, 0),
// WhitePixel(fl_display, 0));
0x1234);
Frame* frame = new Frame(w);
frame->label("flwm test window");
XSelectInput(d, w,
ExposureMask | StructureNotifyMask |
KeyPressMask | KeyReleaseMask | FocusChangeMask |
@ -230,9 +232,11 @@ static void initialize() {
ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask |
KeyPressMask | KeyReleaseMask | KeymapStateMask);
color_setup(CURSOR_FG_SLOT, cfg, CURSOR_FG_COLOR<<8);
color_setup(CURSOR_BG_SLOT, cbg, CURSOR_BG_COLOR<<8);
#if FL_MAJOR_VERSION>1
Root->cursor(cursor);
#else
Root->cursor((Fl_Cursor)cursor, CURSOR_FG_SLOT, CURSOR_BG_SLOT);
#endif
#ifdef TITLE_FONT
Fl::set_font(TITLE_FONT_SLOT, TITLE_FONT);
@ -247,7 +251,7 @@ static void initialize() {
// Gnome crap:
// First create a window that can be watched to see if wm dies:
Atom a = XInternAtom(d, "_WIN_SUPPORTING_WM_CHECK", False);
Window win = XCreateSimpleWindow(d, fl_xid(Root), -200, -200, 5, 5, 0, 0, 0);
XWindow win = XCreateSimpleWindow(d, fl_xid(Root), -200, -200, 5, 5, 0, 0, 0);
CARD32 val = win;
XChangeProperty(d, fl_xid(Root), a, XA_CARDINAL, 32, PropModeReplace, (uchar*)&val, 1);
XChangeProperty(d, win, a, XA_CARDINAL, 32, PropModeReplace, (uchar*)&val, 1);
@ -287,7 +291,7 @@ static void initialize() {
// find all the windows and create a Frame for each:
unsigned int n;
Window w1, w2, *wins;
XWindow w1, w2, *wins;
XWindowAttributes attr;
XQueryTree(d, fl_xid(Root), &w1, &w2, &wins, &n);
for (i = 0; i < n; ++i) {
@ -328,8 +332,10 @@ int arg(int argc, char **argv, int &i) {
cfg = v;
} else if (!strcmp(s, "cbg")) {
cbg = v;
#if FL_MAJOR_VERSION < 2
} else if (*s == 'c') {
cursor = atoi(v);
#endif
} else if (*s == 'v') {
int visid = atoi(v);
fl_open_display();
@ -350,6 +356,17 @@ int arg(int argc, char **argv, int &i) {
return 2;
}
#if FL_MAJOR_VERSION<2
static void color_setup(Fl_Color slot, const char* arg, ulong value) {
if (arg) {
XColor x;
if (XParseColor(fl_display, fl_colormap, arg, &x))
value = ((x.red>>8)<<24)|((x.green>>8)<<16)|((x.blue));
}
Fl::set_color(slot, value);
}
#endif
int main(int argc, char** argv) {
program_name = filename_name(argv[0]);
int i; if (Fl::args(argc, argv, i, arg) < argc) Fl::error(
@ -369,8 +386,22 @@ int main(int argc, char** argv) {
#ifndef FL_NORMAL_SIZE // detect new versions of fltk where this is a variable
FL_NORMAL_SIZE = 12;
#endif
#if FL_MAJOR_VERSION>1
if (cfg) fl_cursor_fg = fltk::color(cfg);
if (cbg) fl_cursor_bg = fltk::color(cbg);
#else
fl_open_display();
color_setup(CURSOR_FG_SLOT, cfg, CURSOR_FG_COLOR<<8);
color_setup(CURSOR_BG_SLOT, cbg, CURSOR_BG_COLOR<<8);
Fl::set_color(FL_SELECTION_COLOR,0,0,128);
Root = new Fl_Root();
#endif
Fl_Root root;
Root = &root;
#if FL_MAJOR_VERSION>1
// show() is not a virtual function in fltk2.0, this fools it:
fltk::load_theme();
root.show();
#endif
Root->show(argc,argv); // fools fltk into using -geometry to set the size
XSetErrorHandler(xerror_handler);
initialize();