X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FWorkArea.C;h=ea9324e037d1889905e6f870b78d77ec16bdf1cb;hb=32ef0d04c48a1751abbb5e3b17d1bec25f22c255;hp=900db135a4055fb382e46b4d85d42d09d65ca5f4;hpb=ba5e47f1a92c3688d16f76f654fd3768672ebb50;p=lyx.git diff --git a/src/WorkArea.C b/src/WorkArea.C index 900db135a4..ea9324e037 100644 --- a/src/WorkArea.C +++ b/src/WorkArea.C @@ -4,44 +4,47 @@ * LyX, The Document Processor * * Copyright 1995 Matthias Ettrich - * Copyright 1995-2000 The LyX Team. + * Copyright 1995-2001 The LyX Team. * * ====================================================== */ #include #include - +#include #ifdef __GNUG__ #pragma implementation #endif #include "WorkArea.h" -#include "up.xpm" -#include "down.xpm" #include "debug.h" #include "support/lstrings.h" -#include "BufferView.h" +#include "LyXView.h" + +#if FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5) +#include "lyxlookup.h" +#endif + +using std::endl; FL_OBJECT * figinset_canvas; -static inline +// needed to make the c++ compiler find the correct version of abs. +// This is at least true for g++. +//using std::abs; + +namespace { + +inline void waitForX() { XSync(fl_get_display(), 0); } -extern "C" { -// Just a bunch of C wrappers around static members of WorkArea - void C_WorkArea_up_cb(FL_OBJECT * ob, long buf) - { - WorkArea::up_cb(ob, buf); - } +} // anon namespace - void C_WorkArea_down_cb(FL_OBJECT * ob, long buf) - { - WorkArea::down_cb(ob, buf); - } +extern "C" { +// Just a bunch of C wrappers around static members of WorkArea void C_WorkArea_scroll_cb(FL_OBJECT * ob, long buf) { WorkArea::scroll_cb(ob, buf); @@ -57,20 +60,20 @@ extern "C" { } - -WorkArea::WorkArea(BufferView * o, int xpos, int ypos, int width, int height) - : owner(o), workareapixmap(0), painter_(*this) +WorkArea::WorkArea(int xpos, int ypos, int width, int height) + : workareapixmap(0), painter_(*this) { fl_freeze_all_forms(); figinset_canvas = 0; - - lyxerr << "Creating work area: +" - << xpos << '+' << ypos << ' ' - << width << 'x' << height << endl; + + if (lyxerr.debugging(Debug::GUI)) + lyxerr << "Creating work area: +" + << xpos << '+' << ypos << ' ' + << width << 'x' << height << endl; // FL_OBJECT * obj; - const int bw = int(abs(float(fl_get_border_width()))); + int const bw = int(std::abs(float(fl_get_border_width()))); // We really want to get rid of figinset_canvas. ::figinset_canvas = figinset_canvas = obj = @@ -81,9 +84,10 @@ WorkArea::WorkArea(BufferView * o, int xpos, int ypos, int width, int height) fl_set_object_gravity(obj, NorthWestGravity, NorthWestGravity); // a box - lyxerr << "\tbackground box: +" - << xpos << '+' << ypos << ' ' - << width - 15 << 'x' << height << endl; + if (lyxerr.debugging(Debug::GUI)) + lyxerr << "\tbackground box: +" + << xpos << '+' << ypos << ' ' + << width - 15 << 'x' << height << endl; backgroundbox = obj = fl_add_box(FL_BORDER_BOX, xpos, ypos, width - 15, @@ -95,66 +99,14 @@ WorkArea::WorkArea(BufferView * o, int xpos, int ypos, int width, int height) // THE SCROLLBAR // - // up - scrollbar button - fl_set_border_width(-1); - - lyxerr << "\tup button: +" - << xpos + width - 15 << '+' << ypos << ' ' - << 15 << 'x' << 15 << endl; - button_up = obj = fl_add_pixmapbutton(FL_TOUCH_BUTTON, - xpos + width - 15, - ypos, - 15, 15, ""); - fl_set_object_boxtype(obj,FL_UP_BOX); - fl_set_object_color(obj,FL_MCOL,FL_BLUE); - fl_set_object_resize(obj, FL_RESIZE_ALL); - fl_set_object_gravity(obj,NorthEastGravity, NorthEastGravity); - obj->u_vdata = this; - fl_set_object_callback(obj,C_WorkArea_up_cb, 0); - fl_set_pixmapbutton_data(obj, const_cast(up_xpm)); - - // Remove the blue feedback rectangle - fl_set_pixmapbutton_focus_outline(obj,0); - - // the scrollbar slider - fl_set_border_width(-bw); - lyxerr << "\tscrollbar slider: +" - << xpos + width - 15 << '+' << ypos + 15 << ' ' - << 15 << 'x' << height - 30 << endl; - scrollbar = obj = fl_add_slider(FL_VERT_SLIDER, - xpos + width - 15, - ypos + 15, - 15, height - 30, ""); - fl_set_object_color(obj,FL_COL1,FL_MCOL); + 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); - fl_set_slider_precision(obj, 0); - - // down - scrollbar button - fl_set_border_width(-1); - - lyxerr << "\tdown button: +" - << xpos + width - 15 << '+' << ypos + height - 15 << ' ' - << 15 << 'x' << 15 << endl; - button_down = obj = fl_add_pixmapbutton(FL_TOUCH_BUTTON, - xpos + width - 15, - ypos + height - 15, - 15, 15, ""); - fl_set_object_boxtype(obj,FL_UP_BOX); - fl_set_object_color(obj,FL_MCOL,FL_BLUE); - fl_set_object_resize(obj, FL_RESIZE_ALL); - fl_set_object_gravity(obj, SouthEastGravity, SouthEastGravity); - obj->u_vdata = this; - fl_set_object_callback(obj, C_WorkArea_down_cb, 0); - fl_set_pixmapbutton_data(obj, const_cast(down_xpm)); - - fl_set_border_width(-bw); - - // Remove the blue feedback rectangle - fl_set_pixmapbutton_focus_outline(obj,0); /// /// The free object @@ -162,22 +114,22 @@ WorkArea::WorkArea(BufferView * o, int xpos, int ypos, int width, int height) // Create the workarea pixmap createPixmap(width - 15 - 2 * bw, height - 2 * bw); - // setup the painter - painter_.setDisplay(fl_display); - // We add this object as late as possible to avoit problems // with drawing. - lyxerr << "\tfree object: +" - << xpos + bw << '+' << ypos + bw << ' ' - << width - 15 - 2 * bw << 'x' << height - 2 * bw << endl; - work_area = obj = fl_add_free(FL_INPUT_FREE, + if (lyxerr.debugging(Debug::GUI)) + 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_TAB; + obj->wantkey = FL_KEY_ALL; obj->u_vdata = this; /* This is how we pass the WorkArea - to the work_area_handler. */ + 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); @@ -189,7 +141,28 @@ WorkArea::WorkArea(BufferView * o, int xpos, int ypos, int width, int height) WorkArea::~WorkArea() { if (workareapixmap) - XFreePixmap(fl_display, 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; + + + //lyxerr << "Mouse: (" << x << ", " << y <<") button = " << button << endl; + //lyxerr << "Workarea: (" << work_area->x + work_area->form->x << ", " << work_area->y + work_area->form->y << ", " << work_area->w << ", " << work_area->h << ")" << endl; + //lyxerr << "Below mouse: " << work_area->belowmouse << endl; + //return work_area->belowmouse; } @@ -197,7 +170,7 @@ void WorkArea::resize(int xpos, int ypos, int width, int height) { fl_freeze_all_forms(); - const int bw = int(abs(float(fl_get_border_width()))); + int const bw = int(std::abs(float(fl_get_border_width()))); // a box fl_set_object_geometry(backgroundbox, xpos, ypos, width - 15, height); @@ -205,19 +178,8 @@ void WorkArea::resize(int xpos, int ypos, int width, int height) // // THE SCROLLBAR // - - // up - scrollbar button - fl_set_object_geometry(button_up, xpos + width - 15, - ypos, - 15, 15); - // the scrollbar slider fl_set_object_geometry(scrollbar, xpos + width - 15, - ypos + 15, - 15, height - 30); - // down - scrollbar button - fl_set_object_geometry(button_down, xpos + width - 15, - ypos + height - 15, - 15, 15); + ypos, 17, height); // Create the workarea pixmap createPixmap(width - 15 - 2 * bw, height - 2 * bw); @@ -244,16 +206,19 @@ void WorkArea::createPixmap(int width, int height) cur_height = height; if (workareapixmap) - XFreePixmap(fl_display, workareapixmap); - - lyxerr << "Creating pixmap (" << width << 'x' << height << ")" << endl; + XFreePixmap(fl_get_display(), workareapixmap); + + if (lyxerr.debugging(Debug::GUI)) + lyxerr << "Creating pixmap (" + << width << 'x' << height << ")" << endl; - workareapixmap = XCreatePixmap(fl_display, - RootWindow(fl_display, 0), + workareapixmap = XCreatePixmap(fl_get_display(), + RootWindow(fl_get_display(), 0), width, height, fl_get_visual_depth()); - lyxerr << "\tpixmap=" << workareapixmap << endl; + if (lyxerr.debugging(Debug::GUI)) + lyxerr << "\tpixmap=" << workareapixmap << endl; } @@ -273,45 +238,20 @@ void WorkArea::setFocus() const void WorkArea::setScrollbar(double pos, double length_fraction) const { - fl_set_slider_value(scrollbar, pos); - fl_set_slider_size(scrollbar, scrollbar->h * length_fraction); + 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_slider_bounds(scrollbar, l1, l2); -} - - -void WorkArea::setScrollbarIncrements(float inc) const -{ - fl_set_slider_increment(scrollbar, work_area->h - inc, inc); + fl_set_scrollbar_bounds(scrollbar, l1, l2); } -void WorkArea::up_cb(FL_OBJECT * ob, long) +void WorkArea::setScrollbarIncrements(double inc) const { - WorkArea * area = static_cast(ob->u_vdata); - XEvent const * ev2 = fl_last_event(); - static long time = 0; - ev2 = fl_last_event(); - if (ev2->type == ButtonPress || ev2->type == ButtonRelease) - time = 0; - //area->up(time++, fl_get_button_numb(ob)); - area->owner->upCB(time++, fl_get_button_numb(ob)); -} - - -void WorkArea::down_cb(FL_OBJECT * ob, long) -{ - WorkArea * area = static_cast(ob->u_vdata); - XEvent const * ev2 = fl_last_event(); - static long time = 0; - if (ev2->type == ButtonPress || ev2->type == ButtonRelease) - time = 0; - //area->down(time++, fl_get_button_numb(ob)); - area->owner->downCB(time++, fl_get_button_numb(ob)); + fl_set_scrollbar_increment(scrollbar, work_area->h - inc, inc); } @@ -319,17 +259,19 @@ void WorkArea::down_cb(FL_OBJECT * ob, long) void WorkArea::scroll_cb(FL_OBJECT * ob, long) { WorkArea * area = static_cast(ob->u_vdata); - - //area->scroll(fl_get_slider_value(ob)); - area->owner->scrollCB(fl_get_slider_value(ob)); + // 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(); } + bool Lgb_bug_find_hack = false; int WorkArea::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; @@ -340,82 +282,248 @@ int WorkArea::work_area_handler(FL_OBJECT * ob, int event, if (!area) return 1; - switch (event){ + switch (event){ case FL_DRAW: if (!area->work_area || !area->work_area->form->visible) return 1; - lyxerr.debug() << "Workarea event: DRAW" << endl; + lyxerr[Debug::GUI] << "Workarea event: DRAW" << endl; area->createPixmap(area->workWidth(), area->height()); Lgb_bug_find_hack = true; - area->owner->workAreaExpose(); + area->workAreaExpose(); Lgb_bug_find_hack = false; break; case FL_PUSH: - if (!ev) break; + if (!ev || ev->xbutton.button == 0) break; // Should really have used xbutton.state - lyxerr.debug() << "Workarea event: PUSH" << endl; - area->owner->workAreaButtonPress(ev->xbutton.x - ob->x, - ev->xbutton.y - ob->y, - ev->xbutton.button); + lyxerr[Debug::GUI] << "Workarea event: PUSH" << endl; + area->workAreaButtonPress(ev->xbutton.x - ob->x, + ev->xbutton.y - ob->y, + ev->xbutton.button); + //area->workAreaKeyPress(XK_Pointer_Button1, ev->xbutton.state); break; case FL_RELEASE: - if (!ev) break; + if (!ev || ev->xbutton.button == 0) break; // Should really have used xbutton.state - lyxerr.debug() << "Workarea event: RELEASE" << endl; - area->owner->workAreaButtonRelease(ev->xbutton.x - ob->x, - ev->xbutton.y - ob->y, - ev->xbutton.button); + lyxerr[Debug::GUI] << "Workarea event: RELEASE" << endl; + area->workAreaButtonRelease(ev->xbutton.x - ob->x, + ev->xbutton.y - ob->y, + 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_slider_value(area->scrollbar) != scrollbar_value_old) { - lyxerr.debug() << "Workarea event: MOUSE" << endl; - area->owner->workAreaMotionNotify(ev->xmotion.x - ob->x, - ev->xmotion.y - ob->y, - ev->xbutton.state); + fl_get_scrollbar_value(area->scrollbar) != scrollbar_value_old + ) { + lyxerr[Debug::GUI] << "Workarea event: MOUSE" << endl; + area->workAreaMotionNotify(ev->xmotion.x - ob->x, + ev->xmotion.y - ob->y, + ev->xbutton.state); } break; - // Done by the raw callback: - // case FL_KEYBOARD: WorkAreaKeyPress(ob, 0,0,0,ev,0); break; +#if FL_REVISION < 89 + case FL_KEYBOARD: +#else + case FL_KEYPRESS: +#endif + { + lyxerr[Debug::KEY] << "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); +#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 << "WorkArea: Key is `" << stm << "' [" + << key << "]" << endl; + lyxerr << "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, ret_state); + } + break; + +#if FL_REVISION >= 89 + case FL_KEYRELEASE: + lyxerr << "Workarea event: KEYRELEASE" << endl; + break; +#endif + case FL_FOCUS: - lyxerr << "Workarea event: FOCUS" << endl; + lyxerr[Debug::GUI] << "Workarea event: FOCUS" << endl; + area->workAreaFocus(); break; case FL_UNFOCUS: - lyxerr << "Workarea event: UNFOCUS" << endl; + lyxerr[Debug::GUI] << "Workarea event: UNFOCUS" << endl; + area->workAreaUnfocus(); break; case FL_ENTER: - lyxerr << "Workarea event: ENTER" << endl; + lyxerr[Debug::GUI] << "Workarea event: ENTER" << endl; + area->workAreaEnter(); break; case FL_LEAVE: - lyxerr << "Workarea event: LEAVE" << endl; + lyxerr[Debug::GUI] << "Workarea event: LEAVE" << endl; + area->workAreaLeave(); break; case FL_DBLCLICK: if (!ev) break; - lyxerr.debug() << "Workarea event: DBLCLICK" << endl; - area->owner->doubleClick(ev->xbutton.x - ob->x, - ev->xbutton.y - ob->y, - ev->xbutton.button); + lyxerr[Debug::GUI] << "Workarea event: DBLCLICK" << endl; + area->workAreaDoubleClick(ev->xbutton.x - ob->x, + ev->xbutton.y - ob->y, + ev->xbutton.button); break; case FL_TRPLCLICK: if (!ev) break; - lyxerr.debug() << "Workarea event: TRPLCLICK" << endl; - area->owner->tripleClick(ev->xbutton.x - ob->x, - ev->xbutton.y - ob->y, - ev->xbutton.button); + lyxerr[Debug::GUI] << "Workarea event: TRPLCLICK" << endl; + area->workAreaTripleClick(ev->xbutton.x - ob->x, + ev->xbutton.y - ob->y, + ev->xbutton.button); break; case FL_OTHER: if (!ev) break; - if (ev->type == SelectionNotify) { - lyxerr.debug() << "Workarea event: SELECTION" << endl; - area->owner->workAreaSelectionNotify(area->work_area->form->window, ev); - } else - lyxerr.debug() << "Workarea event: OTHER" << endl; + lyxerr[Debug::GUI] << "Workarea event: OTHER" << endl; break; } return 1; } + + +namespace { + +string clipboard_selection; +bool clipboard_read = false; + +extern "C" +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 + +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) { + lyxerr << "LyX: This shouldn't happen..." << endl; + fl_XNextEvent(&ev); + } + } + 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); +}