From 5c20a23b4c1f943730cfc9b525aae473272cca17 Mon Sep 17 00:00:00 2001 From: Bill Spitzak Date: Mon, 11 Oct 2004 06:35:02 +0000 Subject: [PATCH] Many changes so it compiles and works with fltk2. Menus are still a bit screwed up. --- Frame.C | 240 +++++++++++++++++++++++++++++++++++++++++++----------- Frame.H | 21 +++-- Hotkeys.C | 2 +- Menu.C | 26 +++++- Rotated.C | 37 ++++++--- config.h | 6 ++ main.C | 63 ++++++++++---- 7 files changed, 306 insertions(+), 89 deletions(-) diff --git a/Frame.C b/Frame.C index 5584df1..890d90f 100644 --- a/Frame.C +++ b/Frame.C @@ -8,6 +8,7 @@ #include #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 +#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); } diff --git a/Frame.H b/Frame.H index 6c680ab..df69e38 100644 --- a/Frame.H +++ b/Frame.H @@ -9,6 +9,9 @@ #include #include #include +#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 diff --git a/Hotkeys.C b/Hotkeys.C index 8b4197e..2ded959 100644 --- a/Hotkeys.C +++ b/Hotkeys.C @@ -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); diff --git a/Menu.C b/Menu.C index 1c31040..c863b00 100644 --- a/Menu.C +++ b/Menu.C @@ -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);} diff --git a/Rotated.C b/Rotated.C index daa4d43..fef4f74 100644 --- a/Rotated.C +++ b/Rotated.C @@ -27,6 +27,9 @@ /* ********************************************************************** */ #include +#if FL_MAJOR_VERSION < 2 +# define XWindow Window +#endif #include #include "Rotated.H" #include @@ -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(); } diff --git a/config.h b/config.h index 51bbcdd..ea191b5 100644 --- a/config.h +++ b/config.h @@ -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 diff --git a/main.C b/main.C index 9fbe2d7..a556bad 100644 --- a/main.C +++ b/main.C @@ -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();