X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fxforms%2FXWorkArea.C;h=51f9a4e405b439b75818cbdeacb50ee1f926a4f8;hb=37e82a546392d43f787826b85481a11f2a27af15;hp=75653a547551b92e56585f15542382fc9092669c;hpb=b879148cdc1c820f2446215091ce3154a215d40b;p=lyx.git diff --git a/src/frontends/xforms/XWorkArea.C b/src/frontends/xforms/XWorkArea.C index 75653a5475..51f9a4e405 100644 --- a/src/frontends/xforms/XWorkArea.C +++ b/src/frontends/xforms/XWorkArea.C @@ -6,34 +6,38 @@ * \author unknown * \author John Levon * - * Full author contact details are available in file CREDITS + * Full author contact details are available in file CREDITS. */ #include -#ifdef __GNUG__ -#pragma implementation -#endif - #include "XWorkArea.h" -#include "debug.h" + +#include "Color.h" +#include "XFormsView.h" #include "XLyXKeySym.h" + +#include "debug.h" #include "funcrequest.h" +#include "LColor.h" #include "Timeout.h" -#if FL_VERSION < 1 && (FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5)) -#include "lyxlookup.h" -#endif +#include + +using boost::shared_ptr; -using std::endl; using std::abs; -using std::hex; using std::dec; +using std::endl; +using std::hex; +using std::string; + +namespace lyx { +namespace frontend { namespace { -inline -void waitForX(bool discard) +inline void waitForX(bool discard) { XSync(fl_get_display(), discard); } @@ -102,25 +106,27 @@ int C_event_cb(FL_FORM * form, void * xev) } // namespace anon -XWorkArea::XWorkArea(int x, int y, int w, int h) +XWorkArea::XWorkArea(LyXView & owner, int w, int h) : workareapixmap(0), painter_(*this) { - if (lyxerr.debugging(Debug::WORKAREA)) { - lyxerr << "\tbackground box: +" - << x << '+' << y << ' ' - << w - 15 << 'x' << h << endl; - } - fl_freeze_all_forms(); FL_OBJECT * obj; + FL_OBJECT * frame; - obj = fl_add_box(FL_BORDER_BOX, x, y, w - 15, h, ""); + // A frame around the work area. + frame = obj = fl_add_box(FL_BORDER_BOX, 0, 0, w, h, ""); fl_set_object_resize(obj, FL_RESIZE_ALL); fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity); - scrollbar = obj = fl_add_scrollbar(FL_VERT_SCROLLBAR, - x + w - 15, y, 17, h, ""); + unsigned int r, g, b; + if (getRGBColor(LColor::background, r, g, b)) { + fl_mapcolor(FL_FREE_COL12, r, g, b); + fl_set_object_color(obj, FL_FREE_COL12, FL_MCOL); + } + + // The scrollbar. + scrollbar = obj = fl_add_scrollbar(FL_VERT_SCROLLBAR, 0, 0, w, h, ""); fl_set_object_boxtype(obj, FL_UP_BOX); fl_set_object_resize(obj, FL_RESIZE_ALL); fl_set_object_gravity(obj, NorthEastGravity, SouthEastGravity); @@ -130,24 +136,8 @@ XWorkArea::XWorkArea(int x, int y, int w, int h) fl_set_scrollbar_value(scrollbar, 0.0); fl_set_scrollbar_size(scrollbar, scrollbar->h); - int const bw = int(abs(fl_get_border_width())); - - // Create the workarea pixmap - // FIXME remove redraw(w - 15 - 2 * bw, h - 2 * bw); - - if (lyxerr.debugging(Debug::WORKAREA)) - lyxerr << "\tfree object: +" - << x + bw << '+' << y + bw << ' ' - << w - 15 - 2 * bw << 'x' - << h - 2 * bw << endl; - - // We add this object as late as possible to avoid problems - // with drawing. - // FIXME: like ?? - work_area = obj = fl_add_free(FL_ALL_FREE, - x + bw, y + bw, - w - 15 - 2 * bw, - h - 2 * bw, "", + // The work area itself + work_area = obj = fl_add_free(FL_ALL_FREE, 0, 0, w, h, "", C_work_area_handler); obj->wantkey = FL_KEY_ALL; obj->u_vdata = this; @@ -156,6 +146,26 @@ XWorkArea::XWorkArea(int x, int y, int w, int h) fl_set_object_resize(obj, FL_RESIZE_ALL); fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity); + // Hand control of the layout of these widgets to the + // Layout Engine. + XFormsView & xview = dynamic_cast(owner); + BoxList & boxlist = xview.getBox(XFormsView::Center)->children(); + + wa_box_ = boxlist.push_back(Box(0,0)); + wa_box_->set(Box::Horizontal); + + shared_ptr frame_box = widgets_.add(frame, wa_box_->children(), 0, 0); + frame_box->set(Box::Expand); + + int const bw = int(abs(fl_get_border_width())); + shared_ptr wa_box = embed(work_area, frame_box->children(), widgets_, bw); + wa_box->set(Box::Expand); + + widgets_.add(scrollbar, wa_box_->children(), 17, 0); + + xview.metricsUpdated.connect(boost::bind(&WidgetMap::updateMetrics, + &widgets_)); + /// X selection hook - xforms gets it wrong fl_current_form->u_vdata = this; fl_register_raw_callback(fl_current_form, FL_ALL_EVENT, C_event_cb); @@ -165,8 +175,9 @@ XWorkArea::XWorkArea(int x, int y, int w, int h) XGCValues val; val.function = GXcopy; + val.graphics_exposures = false; copy_gc = XCreateGC(fl_get_display(), RootWindow(fl_get_display(), 0), - GCFunction, &val); + GCFunction | GCGraphicsExposures, &val); } @@ -178,17 +189,13 @@ XWorkArea::~XWorkArea() } -void XWorkArea::redraw(int width, int height) +void XWorkArea::updateGeometry(int width, int height) { static int cur_width = -1; static int cur_height = -1; - if (cur_width == width && cur_height == height && workareapixmap) { - XCopyArea(fl_get_display(), - getPixmap(), getWin(), copy_gc, - 0, 0, width, height, xpos(), ypos()); + if (cur_width == width && cur_height == height && workareapixmap) return; - } cur_width = width; cur_height = height; @@ -212,6 +219,20 @@ void XWorkArea::redraw(int width, int height) } +void XWorkArea::paint(int x, int y, int w, int h) +{ + lyxerr[Debug::WORKAREA] + << "XWorkarea::paint " << w << 'x' << h + << '+' << x << '+' << y << endl; + + updateGeometry(workWidth(), workHeight()); + XCopyArea(fl_get_display(), + getPixmap(), getWin(), + copy_gc, x, y, w, h, + work_area->x + x, work_area->y + y); +} + + void XWorkArea::setScrollbarParams(int height, int pos, int line_height) { // we need to cache this for scroll_cb @@ -269,25 +290,78 @@ void XWorkArea::scroll_cb() waitForX(false); } - + int XWorkArea::work_area_handler(FL_OBJECT * ob, int event, FL_Coord, FL_Coord, int key, void * xev) { + if (event != 11) + lyxerr[Debug::WORKAREA] << "Workarea event: EVENT: " << event << endl; + XEvent * ev = static_cast(xev); XWorkArea * area = static_cast(ob->u_vdata); - if (!area) return 1; + if (!area) + return 1; switch (event) { - case FL_DRAW: + + case FL_DRAW: { if (!area->work_area || !area->work_area->form->visible) return 1; - lyxerr[Debug::WORKAREA] << "Workarea event: DRAW" << endl; - area->redraw(area->workWidth(), area->workHeight()); + + if (ev) { + lyxerr[Debug::WORKAREA] + << "work_area_handler, handling X11 " + "expose event " + << ev->xexpose.width << 'x' + << ev->xexpose.height << '+' + << ev->xexpose.x << '+' + << ev->xexpose.y << endl; + + // X11 generates XEvents with x, y relative to the + // top left corner of the window. + // XScreen::expose emulates this behaviour. + // We therefore need to remove this offset before + // generating the pixmap. + int const x = ev->xexpose.x - ob->x; + int const y = ev->xexpose.y - ob->y; + + area->paint(x, y, + ev->xexpose.width, ev->xexpose.height); + } else + area->paint(0, 0, + area->workWidth(), area->workHeight()); + break; + } + case FL_PUSH: if (!ev || ev->xbutton.button == 0) break; + + if (ev->xbutton.button == 4 || ev->xbutton.button == 5) { + static long last_wheel; + + long cur_wheel = ev->xbutton.time; + if (last_wheel == cur_wheel) + break; + + last_wheel = cur_wheel; + + float l, r; + fl_get_scrollbar_increment(area->scrollbar, &l, &r); + + if (ev->xbutton.button == 4) + l *= -1.0; + + fl_set_scrollbar_value( + area->scrollbar, + fl_get_scrollbar_value(area->scrollbar) + l); + + area->scroll_cb(); + break; + } + // Should really have used xbutton.state lyxerr[Debug::WORKAREA] << "Workarea event: PUSH" << endl; area->dispatch( @@ -296,22 +370,28 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event, ev->xbutton.y - ob->y, x_button_state(key))); break; + case FL_RELEASE: if (!ev || ev->xbutton.button == 0) break; // Should really have used xbutton.state + + if (ev->xbutton.button == 4 || ev->xbutton.button == 5) { + // We ingnore wheel event here + break; + } + lyxerr[Debug::WORKAREA] << "Workarea event: RELEASE" << endl; + area->dispatch( FuncRequest(LFUN_MOUSE_RELEASE, ev->xbutton.x - ob->x, ev->xbutton.y - ob->y, x_button_state(key))); break; -#if FL_VERSION < 1 && FL_REVISION < 89 - case FL_MOUSE: -#else - case FL_DRAG: -#endif - { + + case FL_DRAG: { + lyxerr[Debug::WORKAREA] << "Workarea event: DRAG 0" << endl; + if (!ev || !area->scrollbar) break; @@ -376,24 +456,13 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event, break; } -#if FL_VERSION < 1 && FL_REVISION < 89 - case FL_KEYBOARD: -#else - case FL_KEYPRESS: -#endif - { + case FL_KEYPRESS: { lyxerr[Debug::WORKAREA] << "Workarea event: KEYPRESS" << endl; KeySym keysym = 0; char dummy[1]; XKeyEvent * xke = reinterpret_cast(ev); -#if FL_VERSION < 1 && (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); -#endif if (lyxerr.debugging(Debug::KEY)) { char const * const tmp = XKeysymToString(key); @@ -407,15 +476,6 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event, << "' [" << keysym << ']' << endl; } -#if FL_VERSION < 1 && (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 without looking @@ -447,7 +507,6 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event, //} } -#endif unsigned int const ret_state = xke->state; // If you have a better way to handle "wild-output" of @@ -485,26 +544,32 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event, area->workAreaKeyPress(LyXKeySymPtr(xlk), x_key_state(ret_state)); + break; } - break; -#if FL_VERSION > 0 || FL_REVISION >= 89 case FL_KEYRELEASE: lyxerr[Debug::WORKAREA] << "Workarea event: KEYRELEASE" << endl; break; -#endif case FL_ENTER: lyxerr[Debug::WORKAREA] << "Workarea event: ENTER" << endl; fl_set_cursor(FL_ObjWin(area->work_area), XC_xterm); break; + case FL_LEAVE: lyxerr[Debug::WORKAREA] << "Workarea event: LEAVE" << endl; // There should be no need for this. But there is. fl_set_cursor(FL_ObjWin(area->work_area), FL_DEFAULT_CURSOR); break; + case FL_DBLCLICK: if (ev) { + if (ev->xbutton.button == 4 || ev->xbutton.button == 5) { + // Ignore wheel events + break; + } + + lyxerr[Debug::WORKAREA] << "Workarea event: DBLCLICK" << endl; FuncRequest cmd(LFUN_MOUSE_DOUBLE, ev->xbutton.x - ob->x, @@ -513,8 +578,14 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event, area->dispatch(cmd); } break; + case FL_TRPLCLICK: if (ev) { + if (ev->xbutton.button == 4 || ev->xbutton.button == 5) { + // Ignore wheel events + break; + } + lyxerr[Debug::WORKAREA] << "Workarea event: TRPLCLICK" << endl; FuncRequest cmd(LFUN_MOUSE_TRIPLE, ev->xbutton.x - ob->x, @@ -523,6 +594,7 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event, area->dispatch(cmd); } break; + case FL_OTHER: if (ev) lyxerr[Debug::WORKAREA] << "Workarea event: OTHER" << endl; @@ -609,3 +681,6 @@ void XWorkArea::putClipboard(string const & s) const fl_stuff_clipboard(work_area, 0, hold.data(), hold.size(), 0); } + +} // namespace frontend +} // namespace lyx