From: John Levon Date: Sun, 26 May 2002 18:30:34 +0000 (+0000) Subject: move workarea to xforms/ for a better diff. X-Git-Tag: 1.6.10~19206 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=cc7901c5b88c14c88cd71f8df77c53d1feb1e826;p=features.git move workarea to xforms/ for a better diff. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@4211 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/src/frontends/ChangeLog b/src/frontends/ChangeLog index 73abcb5239..96ea9e1668 100644 --- a/src/frontends/ChangeLog +++ b/src/frontends/ChangeLog @@ -1,3 +1,9 @@ +2002-05-26 John Levon + + * Makefile.am: + * WorkArea.h: + * WorkArea.C: move to xforms/ for better diff + 2002-05-26 John Levon * key_state.h: diff --git a/src/frontends/Makefile.am b/src/frontends/Makefile.am index bf3402a592..3ae10cdd9d 100644 --- a/src/frontends/Makefile.am +++ b/src/frontends/Makefile.am @@ -34,7 +34,6 @@ libfrontends_la_SOURCES = \ Toolbar.h \ LyXView.C \ LyXView.h \ - WorkArea.C \ WorkArea.h \ font_loader.h \ font_metrics.h \ diff --git a/src/frontends/WorkArea.C b/src/frontends/WorkArea.C deleted file mode 100644 index dc5479d69f..0000000000 --- a/src/frontends/WorkArea.C +++ /dev/null @@ -1,682 +0,0 @@ -/* This file is part of - * ====================================================== - * - * LyX, The Document Processor - * - * Copyright 1995 Matthias Ettrich - * Copyright 1995-2001 The LyX Team. - * - * ====================================================== */ - -#include - -#ifdef __GNUG__ -#pragma implementation -#endif - -#include "WorkArea.h" -#include "debug.h" -#include "frontends/LyXView.h" -#include "lyxrc.h" // lyxrc.show_banner -#include "version.h" // lyx_version - -#if FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5) -#include "frontends/xforms/lyxlookup.h" -#endif - -#include "support/filetools.h" // LibFileSearch -#include "support/lstrings.h" -#include "support/LAssert.h" - -#include -#include - -// xforms doesn't define this (but it should be in ). -extern "C" -FL_APPEVENT_CB fl_set_preemptive_callback(Window, FL_APPEVENT_CB, void *); - -using std::endl; -using std::abs; -using std::hex; - -namespace { - -inline -void waitForX() -{ - XSync(fl_get_display(), 0); -} - -// FIXME ! -mouse_button::state x_button_state(unsigned int button) -{ - mouse_button::state b = mouse_button::none; - switch (button) { - case Button1: - b = mouse_button::button1; - break; - case Button2: - b = mouse_button::button2; - break; - case Button3: - b = mouse_button::button3; - break; - case Button4: - b = mouse_button::button4; - break; - case Button5: - b = mouse_button::button5; - break; - default: // FIXME - break; - } - return b; -} - - -// FIXME -mouse_button::state x_motion_state(unsigned int state) -{ - mouse_button::state b = mouse_button::none; - if (state & Button1MotionMask) - b |= mouse_button::button1; - if (state & Button2MotionMask) - b |= mouse_button::button2; - if (state & Button3MotionMask) - b |= mouse_button::button3; - if (state & Button4MotionMask) - b |= mouse_button::button4; - if (state & Button5MotionMask) - b |= mouse_button::button5; - return b; -} - - -key_modifier::state x_key_state(unsigned int state) -{ - key_modifier::state k = key_modifier::none; - if (state & ControlMask) - k |= key_modifier::ctrl; - if (state & ShiftMask) - k |= key_modifier::shift; - if (state & Mod1Mask) - k |= key_modifier::alt; - return k; -} - - -} // anon namespace - - -extern "C" { - // Just a bunch of C wrappers around static members of WorkArea - static - void C_WorkArea_scroll_cb(FL_OBJECT * ob, long buf) - { - WorkArea::scroll_cb(ob, buf); - } - - - static - int C_WorkArea_work_area_handler(FL_OBJECT * ob, int event, - FL_Coord, FL_Coord, - int key, void * xev) - { - return WorkArea::work_area_handler(ob, event, - 0, 0, key, xev); - } - - static - int C_WorkAreaEventCB(FL_FORM * form, void * xev) { - WorkArea * wa = static_cast(form->u_vdata); - return wa->event_cb(static_cast(xev)); - } -} - - -WorkArea::WorkArea(int xpos, int ypos, int width, int height) - : splash_(0), splash_text_(0), workareapixmap(0), painter_(*this) -{ - fl_freeze_all_forms(); - - if (lyxerr.debugging(Debug::WORKAREA)) - lyxerr << "Creating work area: +" - << xpos << '+' << ypos << ' ' - << width << 'x' << height << endl; - // - FL_OBJECT * obj; - int const bw = int(abs(fl_get_border_width())); - - // a box - if (lyxerr.debugging(Debug::WORKAREA)) - lyxerr << "\tbackground box: +" - << xpos << '+' << ypos << ' ' - << width - 15 << 'x' << height << endl; - backgroundbox = obj = fl_add_box(FL_BORDER_BOX, - xpos, ypos, - width - 15, - height,""); - fl_set_object_resize(obj, FL_RESIZE_ALL); - fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity); - - // Add a splash screen to the centre of the work area - string const splash_file = (lyxrc.show_banner) ? - LibFileSearch("images", "banner", "xpm") : string(); - - if (!splash_file.empty()) { - int const splash_w = 425; - int const splash_h = 290; - int const splash_x = xpos + (width - 15 - splash_w) / 2; - int const splash_y = ypos + (height - splash_h) / 2; - splash_ = obj = - fl_add_pixmapbutton(FL_NORMAL_BUTTON, - splash_x, splash_y, - splash_w, splash_h, ""); - fl_set_pixmapbutton_file(obj, splash_file.c_str()); - fl_set_pixmapbutton_focus_outline(obj, 3); - fl_set_object_boxtype(obj, FL_NO_BOX); - - int const text_x = splash_x + 260; - int const text_y = splash_y + 255; - splash_text_ = obj = - fl_add_text(FL_NORMAL_TEXT, text_x, text_y, 160, 16, - lyx_version); - fl_set_object_lsize(obj, FL_NORMAL_SIZE); - fl_mapcolor(FL_FREE_COL2, 0x2b, 0x47, 0x82); - fl_mapcolor(FL_FREE_COL3, 0xe1, 0xd2, 0x9b); - fl_set_object_color(obj, FL_FREE_COL2, FL_FREE_COL2); - fl_set_object_lcol(obj, FL_FREE_COL3); - fl_set_object_lalign(obj, FL_ALIGN_LEFT|FL_ALIGN_INSIDE); - fl_set_object_lstyle(obj, FL_BOLD_STYLE); - } - - // - // THE SCROLLBAR - // - - scrollbar = obj = fl_add_scrollbar(FL_VERT_SCROLLBAR, - xpos + width - 15, - ypos, 17, height, ""); - fl_set_object_boxtype(obj, FL_UP_BOX); - fl_set_object_resize(obj, FL_RESIZE_ALL); - fl_set_object_gravity(obj, NorthEastGravity, SouthEastGravity); - obj->u_vdata = this; - fl_set_object_callback(obj, C_WorkArea_scroll_cb, 0); - setScrollbarBounds(0.0, 0.0); - - /// - /// The free object - - // Create the workarea pixmap - createPixmap(width - 15 - 2 * bw, height - 2 * bw); - - // We add this object as late as possible to avoit problems - // with drawing. - if (lyxerr.debugging(Debug::WORKAREA)) - lyxerr << "\tfree object: +" - << xpos + bw << '+' << ypos + bw << ' ' - << width - 15 - 2 * bw << 'x' - << height - 2 * bw << endl; - - work_area = obj = fl_add_free(FL_ALL_FREE, - xpos + bw, ypos + bw, - width - 15 - 2 * bw, // scrollbarwidth - height - 2 * bw, "", - C_WorkArea_work_area_handler); - obj->wantkey = FL_KEY_ALL; - obj->u_vdata = this; /* This is how we pass the WorkArea - to the work_area_handler. */ - fl_set_object_boxtype(obj,FL_DOWN_BOX); - fl_set_object_resize(obj, FL_RESIZE_ALL); - fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity); - - /// X selection hook - xforms gets it wrong - fl_current_form->u_vdata = this; - fl_register_raw_callback(fl_current_form, FL_ALL_EVENT, C_WorkAreaEventCB); - - fl_unfreeze_all_forms(); -} - - -WorkArea::~WorkArea() -{ - if (workareapixmap) - XFreePixmap(fl_get_display(), workareapixmap); -} - - -bool WorkArea::belowMouse() const -{ - FL_Coord x, y; - unsigned int button; - fl_get_mouse(&x, &y, &button); - FL_Coord ulx = work_area->form->x + work_area->x; - FL_Coord uly = work_area->form->y + work_area->y; - FL_Coord w = work_area->w; - FL_Coord h = work_area->h; - if (x > ulx && y > uly && x < ulx + h && y < uly + w) - return true; - return false; -} - - -void WorkArea::resize(int xpos, int ypos, int width, int height) -{ - fl_freeze_all_forms(); - - int const bw = int(abs(fl_get_border_width())); - - // a box - fl_set_object_geometry(backgroundbox, xpos, ypos, width - 15, height); - - // - // THE SCROLLBAR - // - fl_set_object_geometry(scrollbar, xpos + width - 15, - ypos, 17, height); - - // Create the workarea pixmap - createPixmap(width - 15 - 2 * bw, height - 2 * bw); - - // the free object - fl_set_object_geometry(work_area, xpos + bw, ypos + bw, - width - 15 - 2 * bw, - height - 2 * bw); - - fl_unfreeze_all_forms(); -} - - -namespace { -void destroy_object(FL_OBJECT * obj) -{ - if (!obj) - return; - - if (obj->visible) { - fl_hide_object(obj); - } - fl_delete_object(obj); - fl_free_object(obj); -} -} // namespace anon - - -void WorkArea::createPixmap(int width, int height) -{ - // Three calls to createPixmap are needed to draw the initial view - // of LyX. Any more and the splash is destroyed. - static int counter = 0; - if (++counter == 4) { - destroy_object(splash_); - splash_ = 0; - destroy_object(splash_text_); - splash_text_ = 0; - } - - static int cur_width = -1; - static int cur_height = -1; - - if (cur_width == width && cur_height == height && workareapixmap) - return; - - cur_width = width; - cur_height = height; - - if (workareapixmap) - XFreePixmap(fl_get_display(), workareapixmap); - - if (lyxerr.debugging(Debug::WORKAREA)) - lyxerr << "Creating pixmap (" - << width << 'x' << height << ")" << endl; - - workareapixmap = XCreatePixmap(fl_get_display(), - RootWindow(fl_get_display(), 0), - width, - height, - fl_get_visual_depth()); - if (lyxerr.debugging(Debug::WORKAREA)) - lyxerr << "\tpixmap=" << workareapixmap << endl; -} - - -void WorkArea::greyOut() const -{ - if (!splash_) { - fl_winset(FL_ObjWin(work_area)); - fl_rectangle(1, work_area->x, work_area->y, - work_area->w, work_area->h, FL_GRAY63); - } -} - - -void WorkArea::setFocus() const -{ - fl_set_focus_object(work_area->form, work_area); -} - - -void WorkArea::setScrollbar(double pos, double length_fraction) const -{ - fl_set_scrollbar_value(scrollbar, pos); - fl_set_scrollbar_size(scrollbar, scrollbar->h * length_fraction); -} - - -void WorkArea::setScrollbarBounds(double l1, double l2) const -{ - fl_set_scrollbar_bounds(scrollbar, l1, l2); -} - - -void WorkArea::setScrollbarIncrements(double inc) const -{ - fl_set_scrollbar_increment(scrollbar, work_area->h - inc, inc); -} - - -// Callback for scrollbar slider -void WorkArea::scroll_cb(FL_OBJECT * ob, long) -{ - WorkArea * area = static_cast(ob->u_vdata); - // If we really want the accellerating scroll we can do that - // from here. IMHO that is a waste of effort since we already - // have other ways to move fast around in the document. (Lgb) - area->scrollCB(fl_get_scrollbar_value(ob)); - waitForX(); -} - - -int WorkArea::work_area_handler(FL_OBJECT * ob, int event, - FL_Coord, FL_Coord , - int key, void * xev) -{ - static int x_old = -1; - static int y_old = -1; - static long scrollbar_value_old = -1; - - XEvent * ev = static_cast(xev); - WorkArea * area = static_cast(ob->u_vdata); - - if (!area) return 1; - - switch (event) { - case FL_DRAW: - if (!area->work_area || - !area->work_area->form->visible) - return 1; - lyxerr[Debug::WORKAREA] << "Workarea event: DRAW" << endl; - area->createPixmap(area->workWidth(), area->height()); - area->workAreaExpose(); - break; - case FL_PUSH: - if (!ev || ev->xbutton.button == 0) break; - // Should really have used xbutton.state - lyxerr[Debug::WORKAREA] << "Workarea event: PUSH" << endl; - area->workAreaButtonPress(ev->xbutton.x - ob->x, - ev->xbutton.y - ob->y, - x_button_state(ev->xbutton.button)); - break; - case FL_RELEASE: - if (!ev || ev->xbutton.button == 0) break; - // Should really have used xbutton.state - lyxerr[Debug::WORKAREA] << "Workarea event: RELEASE" << endl; - area->workAreaButtonRelease(ev->xbutton.x - ob->x, - ev->xbutton.y - ob->y, - x_button_state(ev->xbutton.button)); - break; -#if FL_REVISION < 89 - case FL_MOUSE: -#else - case FL_DRAG: -#endif - if (!ev || ! area->scrollbar) break; - if (ev->xmotion.x != x_old || - ev->xmotion.y != y_old || - fl_get_scrollbar_value(area->scrollbar) != scrollbar_value_old - ) { - lyxerr[Debug::WORKAREA] << "Workarea event: MOUSE" << endl; - area->workAreaMotionNotify(ev->xmotion.x - ob->x, - ev->xmotion.y - ob->y, - x_motion_state(ev->xbutton.state)); - } - break; -#if FL_REVISION < 89 - case FL_KEYBOARD: -#else - case FL_KEYPRESS: -#endif - { - lyxerr[Debug::WORKAREA] << "Workarea event: KEYBOARD" << endl; - - KeySym keysym = 0; - char dummy[1]; - XKeyEvent * xke = reinterpret_cast(ev); -#if FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5) - // XForms < 0.89.5 does not have compose support - // so we are using our own compose support - LyXLookupString(ev, dummy, 1, &keysym); -#else - XLookupString(xke, dummy, 1, &keysym, 0); -// int num_keys = XLookupString(xke, dummy, 10, &keysym, &xcs); -// lyxerr << "We have " << num_keys << " keys in the returned buffer" << endl; -// lyxerr << "Our dummy string is " << dummy << endl; -#endif - if (lyxerr.debugging(Debug::KEY)) { - char const * tmp = XKeysymToString(key); - char const * tmp2 = XKeysymToString(keysym); - string const stm = (tmp ? tmp : ""); - string const stm2 = (tmp2 ? tmp2 : ""); - - lyxerr[Debug::KEY] << "WorkArea: Key is `" << stm << "' [" - << key << "]" << endl; - lyxerr[Debug::KEY] << "WorkArea: Keysym is `" << stm2 << "' [" - << keysym << "]" << endl; - } - -#if FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5) - if (keysym == NoSymbol) { - lyxerr[Debug::KEY] - << "Empty kdb action (probably composing)" - << endl; - break; - } - KeySym ret_key = keysym; -#else - // Note that we need this handling because of a bug - // in XForms 0.89, if this bug is resolved in the way I hope - // we can just use the keysym directly with out looking - // at key at all. (Lgb) - KeySym ret_key = 0; - if (!key) { - // We migth have to add more keysyms here also, - // we will do that as the issues arise. (Lgb) - if (keysym == XK_space) { - ret_key = keysym; - lyxerr[Debug::KEY] << "Using keysym [A]" - << endl; - } else - break; - } else { - // It seems that this was a bit optimistic... - // With this hacking things seems to be better (Lgb) - //if (!iscntrl(key)) { - // ret_key = key; - // lyxerr[Debug::KEY] - // << "Using key [B]\n" - // << "Uchar[" - // << static_cast(key) - // << endl; - //} else { - ret_key = (keysym ? keysym : key); - lyxerr[Debug::KEY] << "Using keysym [B]" - << endl; - //} - } - -#endif - unsigned int const ret_state = xke->state; - - // If you have a better way to handle "wild-output" of - // characters after the key has been released than the one - // below, please contact me. (Lgb) - static Time last_time_pressed; - static unsigned int last_key_pressed; - static unsigned int last_state_pressed; - lyxerr[Debug::KEY] << "Workarea Diff: " - << xke->time - last_time_pressed - << endl; - if (xke->time - last_time_pressed < 25 // should perhaps be tunable - && ret_state == last_state_pressed - && xke->keycode == last_key_pressed) { - lyxerr[Debug::KEY] - << "Workarea: Purging X events." << endl; - //lyxerr << "Workarea Events: " - // << XEventsQueued(fl_get_display(), QueuedAlready) - // << endl; - if (XEventsQueued(fl_get_display(), QueuedAlready) > 0) - XSync(fl_get_display(), 1); - // This purge make f.ex. scrolling stop immidiatly when - // releasing the PageDown button. The question is if - // this purging of XEvents can cause any harm... - // after some testing I can see no problems, but - // I'd like other reports too. - break; - } - last_time_pressed = xke->time; - last_key_pressed = xke->keycode; - last_state_pressed = ret_state; - - area->workAreaKeyPress(ret_key, x_key_state(ret_state)); - } - break; - -#if FL_REVISION >= 89 - case FL_KEYRELEASE: - lyxerr[Debug::WORKAREA] << "Workarea event: KEYRELEASE" << endl; - break; -#endif - - case FL_FOCUS: - lyxerr[Debug::WORKAREA] << "Workarea event: FOCUS" << endl; - area->workAreaFocus(); - break; - case FL_UNFOCUS: - lyxerr[Debug::WORKAREA] << "Workarea event: UNFOCUS" << endl; - area->workAreaUnfocus(); - break; - case FL_ENTER: - lyxerr[Debug::WORKAREA] << "Workarea event: ENTER" << endl; - area->workAreaEnter(); - break; - case FL_LEAVE: - lyxerr[Debug::WORKAREA] << "Workarea event: LEAVE" << endl; - area->workAreaLeave(); - break; - case FL_DBLCLICK: - if (!ev) break; - lyxerr[Debug::WORKAREA] << "Workarea event: DBLCLICK" << endl; - area->workAreaDoubleClick(ev->xbutton.x - ob->x, - ev->xbutton.y - ob->y, - x_button_state(ev->xbutton.button)); - break; - case FL_TRPLCLICK: - if (!ev) break; - lyxerr[Debug::WORKAREA] << "Workarea event: TRPLCLICK" << endl; - area->workAreaTripleClick(ev->xbutton.x - ob->x, - ev->xbutton.y - ob->y, - x_button_state(ev->xbutton.button)); - break; - case FL_OTHER: - if (!ev) break; - lyxerr[Debug::WORKAREA] << "Workarea event: OTHER" << endl; - break; - } - - return 1; -} - - -namespace { - -string clipboard_selection; -bool clipboard_read = false; - -extern "C" { - - static - int request_clipboard_cb(FL_OBJECT * /*ob*/, long /*type*/, - void const * data, long size) - { - clipboard_selection.erase(); - - if (size > 0) - clipboard_selection.reserve(size); - for (int i = 0; i < size; ++i) - clipboard_selection += - static_cast(data)[i]; - clipboard_read = true; - return 0; - } - -} - -} // namespace anon - - -int WorkArea::event_cb(XEvent * xev) -{ - int ret = 0; - switch (xev->type) { - case SelectionRequest: - lyxerr[Debug::GUI] << "X requested selection." << endl; - selectionRequested.emit(); - break; - case SelectionClear: - lyxerr[Debug::GUI] << "Lost selection." << endl; - selectionLost.emit(); - break; - } - return ret; -} - - -void WorkArea::haveSelection(bool yes) const -{ - if (!yes) { - XSetSelectionOwner(fl_get_display(), XA_PRIMARY, None, CurrentTime); - return; - } - - XSetSelectionOwner(fl_get_display(), XA_PRIMARY, FL_ObjWin(work_area), CurrentTime); -} - - -string const WorkArea::getClipboard() const -{ - clipboard_read = false; - - if (fl_request_clipboard(work_area, 0, request_clipboard_cb) == -1) - return string(); - - XEvent ev; - - while (!clipboard_read) { - if (fl_check_forms() == FL_EVENT) { - fl_XNextEvent(&ev); - lyxerr << "Received unhandled X11 event" << endl; - lyxerr << "Type: 0x" << hex << ev.xany.type << - " Target: 0x" << hex << ev.xany.window << endl; - } - } - return clipboard_selection; -} - - -void WorkArea::putClipboard(string const & s) const -{ - static string hold; - hold = s; - - fl_stuff_clipboard(work_area, 0, hold.data(), hold.size(), 0); -} diff --git a/src/frontends/WorkArea.h b/src/frontends/WorkArea.h index cef93f34ad..64f34d72ce 100644 --- a/src/frontends/WorkArea.h +++ b/src/frontends/WorkArea.h @@ -1,159 +1,2 @@ -// -*- C++ -*- -/* This file is part of - * ====================================================== - * - * LyX, The Document Processor - * - * Copyright 1995 Matthias Ettrich - * Copyright 1995-2001 The LyX Team. - * - * ======================================================*/ - -#ifndef WORKAREA_H -#define WORKAREA_H - -#ifdef __GNUG__ -#pragma interface -#endif - -#include - -#include - -#include FORMS_H_LOCATION -#include "frontends/Painter.h" -#include "frontends/mouse_state.h" -#include "frontends/key_state.h" - -/// -class WorkArea { -public: - /// - WorkArea(int xpos, int ypos, int width, int height); - /// - ~WorkArea(); - /// - Painter & getPainter() { return painter_; } - /// - int workWidth() const { return work_area->w; } - /// - unsigned int width() const { return work_area->w + scrollbar->w; } - //unsigned int width() const { return backgroundbox->w + 15; } - /// - unsigned int height() const { return work_area->h; } - //unsigned int height() const { return backgroundbox->h; } - /// - int xpos() const { return work_area->x; } - //int xpos() const { return backgroundbox->x; } - /// - int ypos() const { return work_area->y; } - //int ypos() const { return backgroundbox->y; } - /// - void resize(int xpos, int ypos, int width, int height); - /// - void redraw() const { - fl_redraw_object(work_area); - fl_redraw_object(scrollbar); - } - /// - void setFocus() const; - /// - Window getWin() const { return work_area->form->window; } - /// - bool hasFocus() const { return work_area->focus; } - /// - bool active() const { return work_area->active; } - /// - bool belowMouse() const; - /// - bool visible() const { return work_area->form->visible; } - /// - void greyOut() const; - /// - void setScrollbar(double pos, double length_fraction) const; - /// - void setScrollbarValue(double y) const { - fl_set_scrollbar_value(scrollbar, y); - } - /// - void setScrollbarBounds(double, double) const; - /// - void setScrollbarIncrements(double inc) const; - /// - double getScrollbarValue() const { - return fl_get_scrollbar_value(scrollbar); - } - /// - std::pair const getScrollbarBounds() const { - std::pair p; - fl_get_scrollbar_bounds(scrollbar, &p.first, &p.second); - return p; - } - /// - Pixmap getPixmap() const { return workareapixmap; } - /// xforms callback - static int work_area_handler(FL_OBJECT *, int event, - FL_Coord, FL_Coord, - int /*key*/, void * xev); - /// xforms callback - static void scroll_cb(FL_OBJECT *, long); - /// a selection exists - void haveSelection(bool) const; - /// - string const getClipboard() const; - /// - void putClipboard(string const &) const; - // Signals - /// - SigC::Signal0 workAreaExpose; - /// - SigC::Signal1 scrollCB; - /// - SigC::Signal2 workAreaKeyPress; - /// - SigC::Signal3 workAreaButtonPress; - /// - SigC::Signal3 workAreaButtonRelease; - /// - SigC::Signal3 workAreaMotionNotify; - /// - SigC::Signal0 workAreaFocus; - /// - SigC::Signal0 workAreaUnfocus; - /// - SigC::Signal0 workAreaEnter; - /// - SigC::Signal0 workAreaLeave; - /// - SigC::Signal3 workAreaDoubleClick; - /// - SigC::Signal3 workAreaTripleClick; - /// emitted when an X client has requested our selection - SigC::Signal0 selectionRequested; - /// emitted when another X client has stolen our selection - SigC::Signal0 selectionLost; - - /// handles SelectionRequest X Event, to fill the clipboard - int event_cb(XEvent * xev); -private: - /// - void createPixmap(int, int); - - /// - FL_OBJECT * backgroundbox; - /// - FL_OBJECT * work_area; - /// - FL_OBJECT * scrollbar; - /// - mutable FL_OBJECT * splash_; - /// - mutable FL_OBJECT * splash_text_; - /// The pixmap overlay on the workarea - Pixmap workareapixmap; - /// - Painter painter_; - /// if we call redraw with true needed for locking-insets - bool screen_cleared; -}; -#endif +// very temporary +#include "xforms/XWorkArea.h" diff --git a/src/frontends/xforms/ChangeLog b/src/frontends/xforms/ChangeLog index 6bad5ea2ba..7b434627d4 100644 --- a/src/frontends/xforms/ChangeLog +++ b/src/frontends/xforms/ChangeLog @@ -1,3 +1,9 @@ +2002-05-26 John Levon + + * Makefile.am: + * XWorkArea.h: + * XWorkArea.C: moved here + 2002-05-24 John Levon * ColorHandler.h: diff --git a/src/frontends/xforms/Makefile.am b/src/frontends/xforms/Makefile.am index 54e1b57c9b..c47effd118 100644 --- a/src/frontends/xforms/Makefile.am +++ b/src/frontends/xforms/Makefile.am @@ -218,6 +218,8 @@ libxforms_la_SOURCES = \ XFormsView.h \ XPainter.C \ XPainter.h \ + XWorkArea.h \ + XWorkArea.C \ xfont_loader.C \ xfont_loader.h \ xfont_metrics.C \ diff --git a/src/frontends/xforms/XWorkArea.C b/src/frontends/xforms/XWorkArea.C new file mode 100644 index 0000000000..dc5479d69f --- /dev/null +++ b/src/frontends/xforms/XWorkArea.C @@ -0,0 +1,682 @@ +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2001 The LyX Team. + * + * ====================================================== */ + +#include + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include "WorkArea.h" +#include "debug.h" +#include "frontends/LyXView.h" +#include "lyxrc.h" // lyxrc.show_banner +#include "version.h" // lyx_version + +#if FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5) +#include "frontends/xforms/lyxlookup.h" +#endif + +#include "support/filetools.h" // LibFileSearch +#include "support/lstrings.h" +#include "support/LAssert.h" + +#include +#include + +// xforms doesn't define this (but it should be in ). +extern "C" +FL_APPEVENT_CB fl_set_preemptive_callback(Window, FL_APPEVENT_CB, void *); + +using std::endl; +using std::abs; +using std::hex; + +namespace { + +inline +void waitForX() +{ + XSync(fl_get_display(), 0); +} + +// FIXME ! +mouse_button::state x_button_state(unsigned int button) +{ + mouse_button::state b = mouse_button::none; + switch (button) { + case Button1: + b = mouse_button::button1; + break; + case Button2: + b = mouse_button::button2; + break; + case Button3: + b = mouse_button::button3; + break; + case Button4: + b = mouse_button::button4; + break; + case Button5: + b = mouse_button::button5; + break; + default: // FIXME + break; + } + return b; +} + + +// FIXME +mouse_button::state x_motion_state(unsigned int state) +{ + mouse_button::state b = mouse_button::none; + if (state & Button1MotionMask) + b |= mouse_button::button1; + if (state & Button2MotionMask) + b |= mouse_button::button2; + if (state & Button3MotionMask) + b |= mouse_button::button3; + if (state & Button4MotionMask) + b |= mouse_button::button4; + if (state & Button5MotionMask) + b |= mouse_button::button5; + return b; +} + + +key_modifier::state x_key_state(unsigned int state) +{ + key_modifier::state k = key_modifier::none; + if (state & ControlMask) + k |= key_modifier::ctrl; + if (state & ShiftMask) + k |= key_modifier::shift; + if (state & Mod1Mask) + k |= key_modifier::alt; + return k; +} + + +} // anon namespace + + +extern "C" { + // Just a bunch of C wrappers around static members of WorkArea + static + void C_WorkArea_scroll_cb(FL_OBJECT * ob, long buf) + { + WorkArea::scroll_cb(ob, buf); + } + + + static + int C_WorkArea_work_area_handler(FL_OBJECT * ob, int event, + FL_Coord, FL_Coord, + int key, void * xev) + { + return WorkArea::work_area_handler(ob, event, + 0, 0, key, xev); + } + + static + int C_WorkAreaEventCB(FL_FORM * form, void * xev) { + WorkArea * wa = static_cast(form->u_vdata); + return wa->event_cb(static_cast(xev)); + } +} + + +WorkArea::WorkArea(int xpos, int ypos, int width, int height) + : splash_(0), splash_text_(0), workareapixmap(0), painter_(*this) +{ + fl_freeze_all_forms(); + + if (lyxerr.debugging(Debug::WORKAREA)) + lyxerr << "Creating work area: +" + << xpos << '+' << ypos << ' ' + << width << 'x' << height << endl; + // + FL_OBJECT * obj; + int const bw = int(abs(fl_get_border_width())); + + // a box + if (lyxerr.debugging(Debug::WORKAREA)) + lyxerr << "\tbackground box: +" + << xpos << '+' << ypos << ' ' + << width - 15 << 'x' << height << endl; + backgroundbox = obj = fl_add_box(FL_BORDER_BOX, + xpos, ypos, + width - 15, + height,""); + fl_set_object_resize(obj, FL_RESIZE_ALL); + fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity); + + // Add a splash screen to the centre of the work area + string const splash_file = (lyxrc.show_banner) ? + LibFileSearch("images", "banner", "xpm") : string(); + + if (!splash_file.empty()) { + int const splash_w = 425; + int const splash_h = 290; + int const splash_x = xpos + (width - 15 - splash_w) / 2; + int const splash_y = ypos + (height - splash_h) / 2; + splash_ = obj = + fl_add_pixmapbutton(FL_NORMAL_BUTTON, + splash_x, splash_y, + splash_w, splash_h, ""); + fl_set_pixmapbutton_file(obj, splash_file.c_str()); + fl_set_pixmapbutton_focus_outline(obj, 3); + fl_set_object_boxtype(obj, FL_NO_BOX); + + int const text_x = splash_x + 260; + int const text_y = splash_y + 255; + splash_text_ = obj = + fl_add_text(FL_NORMAL_TEXT, text_x, text_y, 160, 16, + lyx_version); + fl_set_object_lsize(obj, FL_NORMAL_SIZE); + fl_mapcolor(FL_FREE_COL2, 0x2b, 0x47, 0x82); + fl_mapcolor(FL_FREE_COL3, 0xe1, 0xd2, 0x9b); + fl_set_object_color(obj, FL_FREE_COL2, FL_FREE_COL2); + fl_set_object_lcol(obj, FL_FREE_COL3); + fl_set_object_lalign(obj, FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + fl_set_object_lstyle(obj, FL_BOLD_STYLE); + } + + // + // THE SCROLLBAR + // + + scrollbar = obj = fl_add_scrollbar(FL_VERT_SCROLLBAR, + xpos + width - 15, + ypos, 17, height, ""); + fl_set_object_boxtype(obj, FL_UP_BOX); + fl_set_object_resize(obj, FL_RESIZE_ALL); + fl_set_object_gravity(obj, NorthEastGravity, SouthEastGravity); + obj->u_vdata = this; + fl_set_object_callback(obj, C_WorkArea_scroll_cb, 0); + setScrollbarBounds(0.0, 0.0); + + /// + /// The free object + + // Create the workarea pixmap + createPixmap(width - 15 - 2 * bw, height - 2 * bw); + + // We add this object as late as possible to avoit problems + // with drawing. + if (lyxerr.debugging(Debug::WORKAREA)) + lyxerr << "\tfree object: +" + << xpos + bw << '+' << ypos + bw << ' ' + << width - 15 - 2 * bw << 'x' + << height - 2 * bw << endl; + + work_area = obj = fl_add_free(FL_ALL_FREE, + xpos + bw, ypos + bw, + width - 15 - 2 * bw, // scrollbarwidth + height - 2 * bw, "", + C_WorkArea_work_area_handler); + obj->wantkey = FL_KEY_ALL; + obj->u_vdata = this; /* This is how we pass the WorkArea + to the work_area_handler. */ + fl_set_object_boxtype(obj,FL_DOWN_BOX); + fl_set_object_resize(obj, FL_RESIZE_ALL); + fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity); + + /// X selection hook - xforms gets it wrong + fl_current_form->u_vdata = this; + fl_register_raw_callback(fl_current_form, FL_ALL_EVENT, C_WorkAreaEventCB); + + fl_unfreeze_all_forms(); +} + + +WorkArea::~WorkArea() +{ + if (workareapixmap) + XFreePixmap(fl_get_display(), workareapixmap); +} + + +bool WorkArea::belowMouse() const +{ + FL_Coord x, y; + unsigned int button; + fl_get_mouse(&x, &y, &button); + FL_Coord ulx = work_area->form->x + work_area->x; + FL_Coord uly = work_area->form->y + work_area->y; + FL_Coord w = work_area->w; + FL_Coord h = work_area->h; + if (x > ulx && y > uly && x < ulx + h && y < uly + w) + return true; + return false; +} + + +void WorkArea::resize(int xpos, int ypos, int width, int height) +{ + fl_freeze_all_forms(); + + int const bw = int(abs(fl_get_border_width())); + + // a box + fl_set_object_geometry(backgroundbox, xpos, ypos, width - 15, height); + + // + // THE SCROLLBAR + // + fl_set_object_geometry(scrollbar, xpos + width - 15, + ypos, 17, height); + + // Create the workarea pixmap + createPixmap(width - 15 - 2 * bw, height - 2 * bw); + + // the free object + fl_set_object_geometry(work_area, xpos + bw, ypos + bw, + width - 15 - 2 * bw, + height - 2 * bw); + + fl_unfreeze_all_forms(); +} + + +namespace { +void destroy_object(FL_OBJECT * obj) +{ + if (!obj) + return; + + if (obj->visible) { + fl_hide_object(obj); + } + fl_delete_object(obj); + fl_free_object(obj); +} +} // namespace anon + + +void WorkArea::createPixmap(int width, int height) +{ + // Three calls to createPixmap are needed to draw the initial view + // of LyX. Any more and the splash is destroyed. + static int counter = 0; + if (++counter == 4) { + destroy_object(splash_); + splash_ = 0; + destroy_object(splash_text_); + splash_text_ = 0; + } + + static int cur_width = -1; + static int cur_height = -1; + + if (cur_width == width && cur_height == height && workareapixmap) + return; + + cur_width = width; + cur_height = height; + + if (workareapixmap) + XFreePixmap(fl_get_display(), workareapixmap); + + if (lyxerr.debugging(Debug::WORKAREA)) + lyxerr << "Creating pixmap (" + << width << 'x' << height << ")" << endl; + + workareapixmap = XCreatePixmap(fl_get_display(), + RootWindow(fl_get_display(), 0), + width, + height, + fl_get_visual_depth()); + if (lyxerr.debugging(Debug::WORKAREA)) + lyxerr << "\tpixmap=" << workareapixmap << endl; +} + + +void WorkArea::greyOut() const +{ + if (!splash_) { + fl_winset(FL_ObjWin(work_area)); + fl_rectangle(1, work_area->x, work_area->y, + work_area->w, work_area->h, FL_GRAY63); + } +} + + +void WorkArea::setFocus() const +{ + fl_set_focus_object(work_area->form, work_area); +} + + +void WorkArea::setScrollbar(double pos, double length_fraction) const +{ + fl_set_scrollbar_value(scrollbar, pos); + fl_set_scrollbar_size(scrollbar, scrollbar->h * length_fraction); +} + + +void WorkArea::setScrollbarBounds(double l1, double l2) const +{ + fl_set_scrollbar_bounds(scrollbar, l1, l2); +} + + +void WorkArea::setScrollbarIncrements(double inc) const +{ + fl_set_scrollbar_increment(scrollbar, work_area->h - inc, inc); +} + + +// Callback for scrollbar slider +void WorkArea::scroll_cb(FL_OBJECT * ob, long) +{ + WorkArea * area = static_cast(ob->u_vdata); + // If we really want the accellerating scroll we can do that + // from here. IMHO that is a waste of effort since we already + // have other ways to move fast around in the document. (Lgb) + area->scrollCB(fl_get_scrollbar_value(ob)); + waitForX(); +} + + +int WorkArea::work_area_handler(FL_OBJECT * ob, int event, + FL_Coord, FL_Coord , + int key, void * xev) +{ + static int x_old = -1; + static int y_old = -1; + static long scrollbar_value_old = -1; + + XEvent * ev = static_cast(xev); + WorkArea * area = static_cast(ob->u_vdata); + + if (!area) return 1; + + switch (event) { + case FL_DRAW: + if (!area->work_area || + !area->work_area->form->visible) + return 1; + lyxerr[Debug::WORKAREA] << "Workarea event: DRAW" << endl; + area->createPixmap(area->workWidth(), area->height()); + area->workAreaExpose(); + break; + case FL_PUSH: + if (!ev || ev->xbutton.button == 0) break; + // Should really have used xbutton.state + lyxerr[Debug::WORKAREA] << "Workarea event: PUSH" << endl; + area->workAreaButtonPress(ev->xbutton.x - ob->x, + ev->xbutton.y - ob->y, + x_button_state(ev->xbutton.button)); + break; + case FL_RELEASE: + if (!ev || ev->xbutton.button == 0) break; + // Should really have used xbutton.state + lyxerr[Debug::WORKAREA] << "Workarea event: RELEASE" << endl; + area->workAreaButtonRelease(ev->xbutton.x - ob->x, + ev->xbutton.y - ob->y, + x_button_state(ev->xbutton.button)); + break; +#if FL_REVISION < 89 + case FL_MOUSE: +#else + case FL_DRAG: +#endif + if (!ev || ! area->scrollbar) break; + if (ev->xmotion.x != x_old || + ev->xmotion.y != y_old || + fl_get_scrollbar_value(area->scrollbar) != scrollbar_value_old + ) { + lyxerr[Debug::WORKAREA] << "Workarea event: MOUSE" << endl; + area->workAreaMotionNotify(ev->xmotion.x - ob->x, + ev->xmotion.y - ob->y, + x_motion_state(ev->xbutton.state)); + } + break; +#if FL_REVISION < 89 + case FL_KEYBOARD: +#else + case FL_KEYPRESS: +#endif + { + lyxerr[Debug::WORKAREA] << "Workarea event: KEYBOARD" << endl; + + KeySym keysym = 0; + char dummy[1]; + XKeyEvent * xke = reinterpret_cast(ev); +#if FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5) + // XForms < 0.89.5 does not have compose support + // so we are using our own compose support + LyXLookupString(ev, dummy, 1, &keysym); +#else + XLookupString(xke, dummy, 1, &keysym, 0); +// int num_keys = XLookupString(xke, dummy, 10, &keysym, &xcs); +// lyxerr << "We have " << num_keys << " keys in the returned buffer" << endl; +// lyxerr << "Our dummy string is " << dummy << endl; +#endif + if (lyxerr.debugging(Debug::KEY)) { + char const * tmp = XKeysymToString(key); + char const * tmp2 = XKeysymToString(keysym); + string const stm = (tmp ? tmp : ""); + string const stm2 = (tmp2 ? tmp2 : ""); + + lyxerr[Debug::KEY] << "WorkArea: Key is `" << stm << "' [" + << key << "]" << endl; + lyxerr[Debug::KEY] << "WorkArea: Keysym is `" << stm2 << "' [" + << keysym << "]" << endl; + } + +#if FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5) + if (keysym == NoSymbol) { + lyxerr[Debug::KEY] + << "Empty kdb action (probably composing)" + << endl; + break; + } + KeySym ret_key = keysym; +#else + // Note that we need this handling because of a bug + // in XForms 0.89, if this bug is resolved in the way I hope + // we can just use the keysym directly with out looking + // at key at all. (Lgb) + KeySym ret_key = 0; + if (!key) { + // We migth have to add more keysyms here also, + // we will do that as the issues arise. (Lgb) + if (keysym == XK_space) { + ret_key = keysym; + lyxerr[Debug::KEY] << "Using keysym [A]" + << endl; + } else + break; + } else { + // It seems that this was a bit optimistic... + // With this hacking things seems to be better (Lgb) + //if (!iscntrl(key)) { + // ret_key = key; + // lyxerr[Debug::KEY] + // << "Using key [B]\n" + // << "Uchar[" + // << static_cast(key) + // << endl; + //} else { + ret_key = (keysym ? keysym : key); + lyxerr[Debug::KEY] << "Using keysym [B]" + << endl; + //} + } + +#endif + unsigned int const ret_state = xke->state; + + // If you have a better way to handle "wild-output" of + // characters after the key has been released than the one + // below, please contact me. (Lgb) + static Time last_time_pressed; + static unsigned int last_key_pressed; + static unsigned int last_state_pressed; + lyxerr[Debug::KEY] << "Workarea Diff: " + << xke->time - last_time_pressed + << endl; + if (xke->time - last_time_pressed < 25 // should perhaps be tunable + && ret_state == last_state_pressed + && xke->keycode == last_key_pressed) { + lyxerr[Debug::KEY] + << "Workarea: Purging X events." << endl; + //lyxerr << "Workarea Events: " + // << XEventsQueued(fl_get_display(), QueuedAlready) + // << endl; + if (XEventsQueued(fl_get_display(), QueuedAlready) > 0) + XSync(fl_get_display(), 1); + // This purge make f.ex. scrolling stop immidiatly when + // releasing the PageDown button. The question is if + // this purging of XEvents can cause any harm... + // after some testing I can see no problems, but + // I'd like other reports too. + break; + } + last_time_pressed = xke->time; + last_key_pressed = xke->keycode; + last_state_pressed = ret_state; + + area->workAreaKeyPress(ret_key, x_key_state(ret_state)); + } + break; + +#if FL_REVISION >= 89 + case FL_KEYRELEASE: + lyxerr[Debug::WORKAREA] << "Workarea event: KEYRELEASE" << endl; + break; +#endif + + case FL_FOCUS: + lyxerr[Debug::WORKAREA] << "Workarea event: FOCUS" << endl; + area->workAreaFocus(); + break; + case FL_UNFOCUS: + lyxerr[Debug::WORKAREA] << "Workarea event: UNFOCUS" << endl; + area->workAreaUnfocus(); + break; + case FL_ENTER: + lyxerr[Debug::WORKAREA] << "Workarea event: ENTER" << endl; + area->workAreaEnter(); + break; + case FL_LEAVE: + lyxerr[Debug::WORKAREA] << "Workarea event: LEAVE" << endl; + area->workAreaLeave(); + break; + case FL_DBLCLICK: + if (!ev) break; + lyxerr[Debug::WORKAREA] << "Workarea event: DBLCLICK" << endl; + area->workAreaDoubleClick(ev->xbutton.x - ob->x, + ev->xbutton.y - ob->y, + x_button_state(ev->xbutton.button)); + break; + case FL_TRPLCLICK: + if (!ev) break; + lyxerr[Debug::WORKAREA] << "Workarea event: TRPLCLICK" << endl; + area->workAreaTripleClick(ev->xbutton.x - ob->x, + ev->xbutton.y - ob->y, + x_button_state(ev->xbutton.button)); + break; + case FL_OTHER: + if (!ev) break; + lyxerr[Debug::WORKAREA] << "Workarea event: OTHER" << endl; + break; + } + + return 1; +} + + +namespace { + +string clipboard_selection; +bool clipboard_read = false; + +extern "C" { + + static + int request_clipboard_cb(FL_OBJECT * /*ob*/, long /*type*/, + void const * data, long size) + { + clipboard_selection.erase(); + + if (size > 0) + clipboard_selection.reserve(size); + for (int i = 0; i < size; ++i) + clipboard_selection += + static_cast(data)[i]; + clipboard_read = true; + return 0; + } + +} + +} // namespace anon + + +int WorkArea::event_cb(XEvent * xev) +{ + int ret = 0; + switch (xev->type) { + case SelectionRequest: + lyxerr[Debug::GUI] << "X requested selection." << endl; + selectionRequested.emit(); + break; + case SelectionClear: + lyxerr[Debug::GUI] << "Lost selection." << endl; + selectionLost.emit(); + break; + } + return ret; +} + + +void WorkArea::haveSelection(bool yes) const +{ + if (!yes) { + XSetSelectionOwner(fl_get_display(), XA_PRIMARY, None, CurrentTime); + return; + } + + XSetSelectionOwner(fl_get_display(), XA_PRIMARY, FL_ObjWin(work_area), CurrentTime); +} + + +string const WorkArea::getClipboard() const +{ + clipboard_read = false; + + if (fl_request_clipboard(work_area, 0, request_clipboard_cb) == -1) + return string(); + + XEvent ev; + + while (!clipboard_read) { + if (fl_check_forms() == FL_EVENT) { + fl_XNextEvent(&ev); + lyxerr << "Received unhandled X11 event" << endl; + lyxerr << "Type: 0x" << hex << ev.xany.type << + " Target: 0x" << hex << ev.xany.window << endl; + } + } + return clipboard_selection; +} + + +void WorkArea::putClipboard(string const & s) const +{ + static string hold; + hold = s; + + fl_stuff_clipboard(work_area, 0, hold.data(), hold.size(), 0); +} diff --git a/src/frontends/xforms/XWorkArea.h b/src/frontends/xforms/XWorkArea.h new file mode 100644 index 0000000000..cef93f34ad --- /dev/null +++ b/src/frontends/xforms/XWorkArea.h @@ -0,0 +1,159 @@ +// -*- C++ -*- +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2001 The LyX Team. + * + * ======================================================*/ + +#ifndef WORKAREA_H +#define WORKAREA_H + +#ifdef __GNUG__ +#pragma interface +#endif + +#include + +#include + +#include FORMS_H_LOCATION +#include "frontends/Painter.h" +#include "frontends/mouse_state.h" +#include "frontends/key_state.h" + +/// +class WorkArea { +public: + /// + WorkArea(int xpos, int ypos, int width, int height); + /// + ~WorkArea(); + /// + Painter & getPainter() { return painter_; } + /// + int workWidth() const { return work_area->w; } + /// + unsigned int width() const { return work_area->w + scrollbar->w; } + //unsigned int width() const { return backgroundbox->w + 15; } + /// + unsigned int height() const { return work_area->h; } + //unsigned int height() const { return backgroundbox->h; } + /// + int xpos() const { return work_area->x; } + //int xpos() const { return backgroundbox->x; } + /// + int ypos() const { return work_area->y; } + //int ypos() const { return backgroundbox->y; } + /// + void resize(int xpos, int ypos, int width, int height); + /// + void redraw() const { + fl_redraw_object(work_area); + fl_redraw_object(scrollbar); + } + /// + void setFocus() const; + /// + Window getWin() const { return work_area->form->window; } + /// + bool hasFocus() const { return work_area->focus; } + /// + bool active() const { return work_area->active; } + /// + bool belowMouse() const; + /// + bool visible() const { return work_area->form->visible; } + /// + void greyOut() const; + /// + void setScrollbar(double pos, double length_fraction) const; + /// + void setScrollbarValue(double y) const { + fl_set_scrollbar_value(scrollbar, y); + } + /// + void setScrollbarBounds(double, double) const; + /// + void setScrollbarIncrements(double inc) const; + /// + double getScrollbarValue() const { + return fl_get_scrollbar_value(scrollbar); + } + /// + std::pair const getScrollbarBounds() const { + std::pair p; + fl_get_scrollbar_bounds(scrollbar, &p.first, &p.second); + return p; + } + /// + Pixmap getPixmap() const { return workareapixmap; } + /// xforms callback + static int work_area_handler(FL_OBJECT *, int event, + FL_Coord, FL_Coord, + int /*key*/, void * xev); + /// xforms callback + static void scroll_cb(FL_OBJECT *, long); + /// a selection exists + void haveSelection(bool) const; + /// + string const getClipboard() const; + /// + void putClipboard(string const &) const; + // Signals + /// + SigC::Signal0 workAreaExpose; + /// + SigC::Signal1 scrollCB; + /// + SigC::Signal2 workAreaKeyPress; + /// + SigC::Signal3 workAreaButtonPress; + /// + SigC::Signal3 workAreaButtonRelease; + /// + SigC::Signal3 workAreaMotionNotify; + /// + SigC::Signal0 workAreaFocus; + /// + SigC::Signal0 workAreaUnfocus; + /// + SigC::Signal0 workAreaEnter; + /// + SigC::Signal0 workAreaLeave; + /// + SigC::Signal3 workAreaDoubleClick; + /// + SigC::Signal3 workAreaTripleClick; + /// emitted when an X client has requested our selection + SigC::Signal0 selectionRequested; + /// emitted when another X client has stolen our selection + SigC::Signal0 selectionLost; + + /// handles SelectionRequest X Event, to fill the clipboard + int event_cb(XEvent * xev); +private: + /// + void createPixmap(int, int); + + /// + FL_OBJECT * backgroundbox; + /// + FL_OBJECT * work_area; + /// + FL_OBJECT * scrollbar; + /// + mutable FL_OBJECT * splash_; + /// + mutable FL_OBJECT * splash_text_; + /// The pixmap overlay on the workarea + Pixmap workareapixmap; + /// + Painter painter_; + /// if we call redraw with true needed for locking-insets + bool screen_cleared; +}; +#endif