X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fxforms%2FXWorkArea.C;h=51f9a4e405b439b75818cbdeacb50ee1f926a4f8;hb=37e82a546392d43f787826b85481a11f2a27af15;hp=6348e476e14f26518de8c81bec6a62ec24b58b37;hpb=f1c24d100985c6df2eb5ec390017b69c78fe49c7;p=lyx.git diff --git a/src/frontends/xforms/XWorkArea.C b/src/frontends/xforms/XWorkArea.C index 6348e476e1..51f9a4e405 100644 --- a/src/frontends/xforms/XWorkArea.C +++ b/src/frontends/xforms/XWorkArea.C @@ -1,112 +1,72 @@ /** * \file XWorkArea.C - * Copyright 1995-2002 the LyX Team - * Read the file COPYING + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. * * \author unknown - * \author John Levon + * \author John Levon + * + * Full author contact details are available in file CREDITS. */ #include -#ifdef __GNUG__ -#pragma implementation -#endif - #include "XWorkArea.h" -#include "debug.h" -#include "LyXView.h" -#include "lyxrc.h" // lyxrc.show_banner -#include "version.h" // lyx_version + +#include "Color.h" +#include "XFormsView.h" #include "XLyXKeySym.h" -#if FL_VERSION < 1 && (FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5)) -#include "lyxlookup.h" -#endif +#include "debug.h" +#include "funcrequest.h" +#include "LColor.h" +#include "Timeout.h" -#include "support/filetools.h" // LibFileSearch -#include "support/lstrings.h" -#include "support/LAssert.h" +#include -#include -#include +using boost::shared_ptr; -// 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::dec; +using std::endl; using std::hex; +using std::string; + +namespace lyx { +namespace frontend { namespace { -inline -void waitForX() +inline void waitForX(bool discard) { - XSync(fl_get_display(), 0); + XSync(fl_get_display(), discard); } -void setXtermCursor(Window win) -{ - static Cursor cursor; - static bool cursor_undefined = true; - if (cursor_undefined) { - cursor = XCreateFontCursor(fl_get_display(), XC_xterm); - XFlush(fl_get_display()); - cursor_undefined = false; - } - XDefineCursor(fl_get_display(), win, cursor); - XFlush(fl_get_display()); -} - - -// 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; + case FL_MBUTTON1: + b = mouse_button::button1; + break; + case FL_MBUTTON2: + b = mouse_button::button2; + break; + case FL_MBUTTON3: + b = mouse_button::button3; + break; + case FL_MBUTTON4: + b = mouse_button::button4; + break; + case FL_MBUTTON5: + b = mouse_button::button5; + 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; @@ -120,196 +80,117 @@ key_modifier::state x_key_state(unsigned int state) } -} // anon namespace +extern "C" { +void C_scroll_cb(FL_OBJECT * ob, long) +{ + XWorkArea * area = static_cast(ob->u_vdata); + area->scroll_cb(); +} -extern "C" { - // Just a bunch of C wrappers around static members of XWorkArea - static - void C_XWorkArea_scroll_cb(FL_OBJECT * ob, long) - { - XWorkArea * area = static_cast(ob->u_vdata); - area->scroll_cb(); - } +int C_work_area_handler(FL_OBJECT * ob, int event, FL_Coord, FL_Coord, + int key, void * xev) +{ + return XWorkArea::work_area_handler(ob, event, 0, 0, key, xev); +} - static - int C_XWorkArea_work_area_handler(FL_OBJECT * ob, int event, - FL_Coord, FL_Coord, - int key, void * xev) - { - return XWorkArea::work_area_handler(ob, event, - 0, 0, key, xev); - } - static - int C_XWorkAreaEventCB(FL_FORM * form, void * xev) { - XWorkArea * wa = static_cast(form->u_vdata); - return wa->event_cb(static_cast(xev)); - } +int C_event_cb(FL_FORM * form, void * xev) +{ + XWorkArea * area = static_cast(form->u_vdata); + return area->event_cb(static_cast(xev)); } +} // extern "C" +} // namespace anon + -XWorkArea::XWorkArea(int x, int y, int w, int h) - : splash_(0), splash_text_(0), workareapixmap(0), painter_(*this) +XWorkArea::XWorkArea(LyXView & owner, int w, int h) + : workareapixmap(0), painter_(*this) { fl_freeze_all_forms(); - // FL_OBJECT * obj; + FL_OBJECT * frame; - // a box - if (lyxerr.debugging(Debug::WORKAREA)) - lyxerr << "\tbackground box: +" - << x << '+' << y << ' ' - << w - 15 << 'x' << h << endl; - backgroundbox = 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); - // 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 = x + (w - 15 - splash_w) / 2; - int const splash_y = y + (h - 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); + 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); } - scrollbar = obj = fl_add_scrollbar(FL_VERT_SCROLLBAR, - x + w - 15, - y, 17, h, ""); + // 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); obj->u_vdata = this; - fl_set_object_callback(obj, C_XWorkArea_scroll_cb, 0); + fl_set_object_callback(obj, C_scroll_cb, 0); fl_set_scrollbar_bounds(scrollbar, 0.0, 0.0); fl_set_scrollbar_value(scrollbar, 0.0); fl_set_scrollbar_size(scrollbar, scrollbar->h); - - /// - /// The free object - int const bw = int(abs(fl_get_border_width())); - - // Create the workarea pixmap - createPixmap(w - 15 - 2 * bw, h - 2 * bw); - - // We add this object as late as possible to avoit problems - // with drawing. - if (lyxerr.debugging(Debug::WORKAREA)) - lyxerr << "\tfree object: +" - << x + bw << '+' << y + bw << ' ' - << w - 15 - 2 * bw << 'x' - << h - 2 * bw << endl; - - work_area = obj = fl_add_free(FL_ALL_FREE, - x + bw, y + bw, - w - 15 - 2 * bw, // scrollbarwidth - h - 2 * bw, "", - C_XWorkArea_work_area_handler); + // 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; /* This is how we pass the XWorkArea - to the work_area_handler. */ + obj->u_vdata = this; + 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_XWorkAreaEventCB); - - fl_unfreeze_all_forms(); -} - - -XWorkArea::~XWorkArea() -{ - if (workareapixmap) - XFreePixmap(fl_get_display(), workareapixmap); -} + // 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); -void XWorkArea::resize(int xpos, int ypos, int width, int height) -{ - fl_freeze_all_forms(); + 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); - // 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); + widgets_.add(scrollbar, wa_box_->children(), 17, 0); - // Create the workarea pixmap - createPixmap(width - 15 - 2 * bw, height - 2 * bw); + xview.metricsUpdated.connect(boost::bind(&WidgetMap::updateMetrics, + &widgets_)); - // the free object - fl_set_object_geometry(work_area, xpos + bw, ypos + bw, - width - 15 - 2 * bw, - height - 2 * bw); + /// 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); fl_unfreeze_all_forms(); + + XGCValues val; + + val.function = GXcopy; + val.graphics_exposures = false; + copy_gc = XCreateGC(fl_get_display(), RootWindow(fl_get_display(), 0), + GCFunction | GCGraphicsExposures, &val); } -namespace { -void destroy_object(FL_OBJECT * obj) +XWorkArea::~XWorkArea() { - if (!obj) - return; - - if (obj->visible) { - fl_hide_object(obj); - } - fl_delete_object(obj); - fl_free_object(obj); + XFreeGC(fl_get_display(), copy_gc); + if (workareapixmap) + XFreePixmap(fl_get_display(), workareapixmap); } -} // namespace anon -void XWorkArea::createPixmap(int width, int height) +void XWorkArea::updateGeometry(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; @@ -319,36 +200,36 @@ void XWorkArea::createPixmap(int width, int height) cur_width = width; cur_height = height; - if (workareapixmap) - XFreePixmap(fl_get_display(), workareapixmap); + if (lyxerr.debugging(Debug::WORKAREA)) { + lyxerr << "(Re)creating pixmap (" + << width << 'x' << height << ')' << endl; + } - if (lyxerr.debugging(Debug::WORKAREA)) - lyxerr << "Creating pixmap (" - << width << 'x' << height << ")" << endl; + if (workareapixmap) { + XFreePixmap(fl_get_display(), workareapixmap); + } 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 XWorkArea::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); - } + workAreaResize(); } -void XWorkArea::setFocus() const +void XWorkArea::paint(int x, int y, int w, int h) { - fl_set_focus_object(work_area->form, work_area); + 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); } @@ -365,14 +246,17 @@ void XWorkArea::setScrollbarParams(int height, int pos, int line_height) long const work_height = workHeight(); - lyxerr[Debug::GUI] << "scroll: height now " << height << endl; - lyxerr[Debug::GUI] << "scroll: work_height " << work_height << endl; - + if (lyxerr.debugging(Debug::GUI)) { + lyxerr << "scroll: height now " << height << '\n' + << "scroll: work_height " << work_height << endl; + } + /* If the text is smaller than the working area, the scrollbar * maximum must be the working area height. No scrolling will * be possible */ if (height <= work_height) { - lyxerr[Debug::GUI] << "scroll: doc smaller than workarea !" << endl; + lyxerr[Debug::GUI] << "scroll: doc smaller than workarea !" + << endl; fl_set_scrollbar_bounds(scrollbar, 0.0, 0.0); fl_set_scrollbar_value(scrollbar, pos); fl_set_scrollbar_size(scrollbar, scrollbar->h); @@ -395,118 +279,210 @@ void XWorkArea::setScrollbarParams(int height, int pos, int line_height) void XWorkArea::scroll_cb() { double const val = fl_get_scrollbar_value(scrollbar); - lyxerr[Debug::GUI] << "scroll: val: " << val << endl; - lyxerr[Debug::GUI] << "scroll: height: " << scrollbar->h << endl; - lyxerr[Debug::GUI] << "scroll: docheight: " << doc_height_ << endl; + + if (lyxerr.debugging(Debug::GUI)) { + lyxerr << "scroll: val: " << val << '\n' + << "scroll: height: " << scrollbar->h << '\n' + << "scroll: docheight: " << doc_height_ << endl; + } + scrollDocView(int(val)); - waitForX(); + waitForX(false); } int XWorkArea::work_area_handler(FL_OBJECT * ob, int event, - FL_Coord, FL_Coord , - int key, void * xev) + FL_Coord, FL_Coord, + int key, void * xev) { - static int x_old = -1; - static int y_old = -1; - static long scrollbar_value_old = -1; + 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: - if (!area->work_area || - !area->work_area->form->visible) + + 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->workHeight()); - area->workAreaExpose(); + + 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->workAreaButtonPress(ev->xbutton.x - ob->x, - ev->xbutton.y - ob->y, - x_button_state(ev->xbutton.button)); + area->dispatch( + FuncRequest(LFUN_MOUSE_PRESS, + ev->xbutton.x - ob->x, + 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->workAreaButtonRelease(ev->xbutton.x - ob->x, - ev->xbutton.y - ob->y, - x_button_state(ev->xbutton.button)); + + 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 - 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)); + + case FL_DRAG: { + lyxerr[Debug::WORKAREA] << "Workarea event: DRAG 0" << endl; + + if (!ev || !area->scrollbar) + break; + + int const drag_x = ev->xmotion.x; + int const drag_y = ev->xmotion.y; + int const area_y = ob->y; + int const area_h = ob->h; + + // Check if the mouse is above or below the workarea + if (drag_y <= area_y || drag_y >= area_y + area_h) { + // The mouse button is depressed and we are outside the + // workarea. That means we are simultaneously selecting + // text and scrolling the view. + // Use a Timeout to react to a drag events only every + // 200ms. All intervening events are discarded, + // allowing the user to control position easily. + static int const discard_interval = 200; + static Timeout timeout(discard_interval); + + if (timeout.running()) + break; + // The timeout is not running, so process the + // event, first starting the timeout to discard future + // events. + timeout.start(); + } + + static int x_old = -1; + static int y_old = -1; + static double scrollbar_value_old = -1.0; + + double const scrollbar_value = + fl_get_scrollbar_value(area->scrollbar); + + if (drag_x != x_old || drag_y != y_old || + scrollbar_value != scrollbar_value_old) { + x_old = drag_x; + y_old = drag_y; + scrollbar_value_old = scrollbar_value; + + lyxerr[Debug::WORKAREA] << "Workarea event: DRAG" + << endl; + + // It transpires that ev->xbutton.button == 0 when + // the mouse is dragged, so it cannot be used to + // initialise x_button_state and hence FuncRequest. + + // The 'key' that is passed into the function does + // contain the necessary info, however. + + // It is for this reason that x_button_state has + // been modified to work with key + // rather than ev->xbutton.button. + + // Angus 15 Oct 2002. + FuncRequest cmd(LFUN_MOUSE_MOTION, + ev->xbutton.x - ob->x, + ev->xbutton.y - ob->y, + x_button_state(key)); + area->dispatch(cmd); } break; -#if FL_VERSION < 1 && FL_REVISION < 89 - case FL_KEYBOARD: -#else - case FL_KEYPRESS: -#endif - { - lyxerr[Debug::WORKAREA] << "Workarea event: KEYBOARD" << endl; + } + + 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); -// 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] << "XWorkArea: Key is `" << stm << "' [" - << key << "]" << endl; - lyxerr[Debug::KEY] << "XWorkArea: Keysym is `" << stm2 << "' [" - << keysym << "]" << endl; + char const * const tmp = XKeysymToString(key); + char const * const tmp2 = XKeysymToString(keysym); + string const stm = (tmp ? tmp : string()); + string const stm2 = (tmp2 ? tmp2 : string()); + + lyxerr << "XWorkArea: Key is `" << stm + << "' [" << key << "]\n" + << "XWorkArea: Keysym is `" << stm2 + << "' [" << 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 with out looking + // we can just use the keysym directly without looking // at key at all. (Lgb) KeySym ret_key = 0; if (!key) { - // We migth have to add more keysyms here also, + // We might have to add more keysyms here also, // we will do that as the issues arise. (Lgb) if (keysym == XK_space) { ret_key = keysym; @@ -525,13 +501,12 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event, // << static_cast(key) // << endl; //} else { - ret_key = (keysym ? keysym : key); - lyxerr[Debug::KEY] << "Using keysym [B]" - << endl; + 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 @@ -552,8 +527,8 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event, // << 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 + waitForX(true); + // This purge make f.ex. scrolling stop immediately 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 @@ -566,49 +541,63 @@ int XWorkArea::work_area_handler(FL_OBJECT * ob, int event, XLyXKeySym * xlk = new XLyXKeySym; xlk->initFromKeySym(ret_key); - + 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_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; + 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) 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)); + 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, + ev->xbutton.y - ob->y, + x_button_state(key)); + area->dispatch(cmd); + } 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)); + 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, + ev->xbutton.y - ob->y, + x_button_state(key)); + area->dispatch(cmd); + } break; + case FL_OTHER: - if (!ev) break; - lyxerr[Debug::WORKAREA] << "Workarea event: OTHER" << endl; + if (ev) + lyxerr[Debug::WORKAREA] << "Workarea event: OTHER" << endl; break; } @@ -623,51 +612,43 @@ 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; - } - +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; } +} // extern "C" } // namespace anon int XWorkArea::event_cb(XEvent * xev) { - int ret = 0; switch (xev->type) { - case SelectionRequest: - lyxerr[Debug::GUI] << "X requested selection." << endl; - selectionRequested(); - break; - case SelectionClear: - lyxerr[Debug::GUI] << "Lost selection." << endl; - selectionLost(); - break; + case SelectionRequest: + lyxerr[Debug::GUI] << "X requested selection." << endl; + selectionRequested(); + break; + case SelectionClear: + lyxerr[Debug::GUI] << "Lost selection." << endl; + selectionLost(); + break; } - return ret; + return 0; } void XWorkArea::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); + Window const owner = yes ? FL_ObjWin(work_area) : None; + XSetSelectionOwner(fl_get_display(), XA_PRIMARY, owner, CurrentTime); } @@ -683,9 +664,10 @@ string const XWorkArea::getClipboard() const 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; + lyxerr << "Received unhandled X11 event\n" + << "Type: 0x" << hex << ev.xany.type + << " Target: 0x" << hex << ev.xany.window + << dec << endl; } } return clipboard_selection; @@ -699,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