Another in the thrilling installment. This one moves WorkArea into frontends/ in preparation for its GUIIsation.
OK to apply ? thanks john -- "This is playing, not work, therefore it's not a waste of time." - Zath
Index: src/BufferView_pimpl.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/BufferView_pimpl.C,v retrieving revision 1.240 diff -u -r1.240 BufferView_pimpl.C --- src/BufferView_pimpl.C 23 May 2002 12:08:32 -0000 1.240 +++ src/BufferView_pimpl.C 23 May 2002 12:49:44 -0000 @@ -5,7 +5,7 @@ #endif #include "BufferView_pimpl.h" -#include "WorkArea.h" +#include "frontends/WorkArea.h" #include "lyxscreen.h" #include "lyxtext.h" #include "lyxrow.h" Index: src/BufferView_pimpl.h =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/BufferView_pimpl.h,v retrieving revision 1.50 diff -u -r1.50 BufferView_pimpl.h --- src/BufferView_pimpl.h 22 May 2002 01:16:34 -0000 1.50 +++ src/BufferView_pimpl.h 23 May 2002 12:49:45 -0000 @@ -6,7 +6,8 @@ #include "BufferView.h" #include "commandtags.h" #include "frontends/Timeout.h" -#include "WorkArea.h" +// FIXME remove me +#include "frontends/WorkArea.h" #include "box.h" #include "insets/insetspecialchar.h" #include "support/types.h" Index: src/Makefile.am =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/Makefile.am,v retrieving revision 1.123 diff -u -r1.123 Makefile.am --- src/Makefile.am 23 May 2002 12:13:06 -0000 1.123 +++ src/Makefile.am 23 May 2002 12:49:48 -0000 @@ -91,8 +91,6 @@ Thesaurus.h \ ToolbarDefaults.C \ ToolbarDefaults.h \ - WorkArea.C \ - WorkArea.h \ box.h \ box.C \ broken_headers.h \ @@ -214,8 +212,6 @@ undo.h \ undo_funcs.C \ undo_funcs.h \ - undostack.C \ - undostack.h \ vc-backend.C \ vc-backend.h \ version.C \ Index: src/WorkArea.C =================================================================== RCS file: src/WorkArea.C diff -N src/WorkArea.C --- src/WorkArea.C 23 May 2002 12:08:33 -0000 1.69 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,625 +0,0 @@ -/* This file is part of - * ====================================================== - * - * LyX, The Document Processor - * - * Copyright 1995 Matthias Ettrich - * Copyright 1995-2001 The LyX Team. - * - * ====================================================== */ - -#include <config.h> - -#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 "lyxlookup.h" -#endif - -#include "support/filetools.h" // LibFileSearch -#include "support/lstrings.h" -#include "support/LAssert.h" - -#include <cmath> -#include <cctype> - -// xforms doesn't define this (but it should be in <forms.h>). -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); -} - -} // 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<WorkArea*>(form->u_vdata); - return wa->event_cb(static_cast<XEvent*>(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<WorkArea*>(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<XEvent*>(xev); - WorkArea * area = static_cast<WorkArea*>(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, - ev->xbutton.button); - //area->workAreaKeyPress(XK_Pointer_Button1, ev->xbutton.state); - 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, - 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, - 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<XKeyEvent *>(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<unsigned char>(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[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, - 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, - 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<char const *>(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); -} Index: src/WorkArea.h =================================================================== RCS file: src/WorkArea.h diff -N src/WorkArea.h --- src/WorkArea.h 23 May 2002 09:21:23 -0000 1.33 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,157 +0,0 @@ -// -*- 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 <utility> - -#include <sigc++/signal_system.h> - -#include FORMS_H_LOCATION -#include "frontends/Painter.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<float, float> const getScrollbarBounds() const { - std::pair<float, float> 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<void> workAreaExpose; - /// - SigC::Signal1<void, double> scrollCB; - /// - SigC::Signal2<void, KeySym, unsigned int> workAreaKeyPress; - /// - SigC::Signal3<void, int, int, unsigned int> workAreaButtonPress; - /// - SigC::Signal3<void, int, int, unsigned int> workAreaButtonRelease; - /// - SigC::Signal3<void, int, int, unsigned int> workAreaMotionNotify; - /// - SigC::Signal0<void> workAreaFocus; - /// - SigC::Signal0<void> workAreaUnfocus; - /// - SigC::Signal0<void> workAreaEnter; - /// - SigC::Signal0<void> workAreaLeave; - /// - SigC::Signal3<void, int, int, unsigned int> workAreaDoubleClick; - /// - SigC::Signal3<void, int, int, unsigned int> workAreaTripleClick; - /// emitted when an X client has requested our selection - SigC::Signal0<void> selectionRequested; - /// emitted when another X client has stolen our selection - SigC::Signal0<void> 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 Index: src/screen.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/screen.C,v retrieving revision 1.65 diff -u -r1.65 screen.C --- src/screen.C 23 May 2002 09:21:23 -0000 1.65 +++ src/screen.C 23 May 2002 12:50:01 -0000 @@ -20,7 +20,7 @@ #include "lyxtext.h" #include "lyxrow.h" #include "frontends/Painter.h" -#include "WorkArea.h" +#include "frontends/WorkArea.h" #include "buffer.h" #include "BufferView.h" #include "font.h" Index: src/frontends/Makefile.am =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/Makefile.am,v retrieving revision 1.35 diff -u -r1.35 Makefile.am --- src/frontends/Makefile.am 23 May 2002 12:08:40 -0000 1.35 +++ src/frontends/Makefile.am 23 May 2002 12:50:02 -0000 @@ -33,4 +33,6 @@ Toolbar.C \ Toolbar.h \ LyXView.C \ - LyXView.h + LyXView.h \ + WorkArea.C \ + WorkArea.h Index: src/frontends/WorkArea.h =================================================================== RCS file: src/frontends/WorkArea.h diff -N src/frontends/WorkArea.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/frontends/WorkArea.h 23 May 2002 12:56:21 -0000 @@ -0,0 +1,157 @@ +// -*- 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 <utility> + +#include <sigc++/signal_system.h> + +#include FORMS_H_LOCATION +#include "frontends/Painter.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<float, float> const getScrollbarBounds() const { + std::pair<float, float> 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<void> workAreaExpose; + /// + SigC::Signal1<void, double> scrollCB; + /// + SigC::Signal2<void, KeySym, unsigned int> workAreaKeyPress; + /// + SigC::Signal3<void, int, int, unsigned int> workAreaButtonPress; + /// + SigC::Signal3<void, int, int, unsigned int> workAreaButtonRelease; + /// + SigC::Signal3<void, int, int, unsigned int> workAreaMotionNotify; + /// + SigC::Signal0<void> workAreaFocus; + /// + SigC::Signal0<void> workAreaUnfocus; + /// + SigC::Signal0<void> workAreaEnter; + /// + SigC::Signal0<void> workAreaLeave; + /// + SigC::Signal3<void, int, int, unsigned int> workAreaDoubleClick; + /// + SigC::Signal3<void, int, int, unsigned int> workAreaTripleClick; + /// emitted when an X client has requested our selection + SigC::Signal0<void> selectionRequested; + /// emitted when another X client has stolen our selection + SigC::Signal0<void> 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 Index: src/frontends/WorkArea.C =================================================================== RCS file: src/frontends/WorkArea.C diff -N src/frontends/WorkArea.C --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/frontends/WorkArea.C 23 May 2002 12:56:21 -0000 @@ -0,0 +1,625 @@ +/* This file is part of + * ====================================================== + * + * LyX, The Document Processor + * + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2001 The LyX Team. + * + * ====================================================== */ + +#include <config.h> + +#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 "lyxlookup.h" +#endif + +#include "support/filetools.h" // LibFileSearch +#include "support/lstrings.h" +#include "support/LAssert.h" + +#include <cmath> +#include <cctype> + +// xforms doesn't define this (but it should be in <forms.h>). +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); +} + +} // 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<WorkArea*>(form->u_vdata); + return wa->event_cb(static_cast<XEvent*>(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<WorkArea*>(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<XEvent*>(xev); + WorkArea * area = static_cast<WorkArea*>(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, + ev->xbutton.button); + //area->workAreaKeyPress(XK_Pointer_Button1, ev->xbutton.state); + 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, + 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, + 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<XKeyEvent *>(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<unsigned char>(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[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, + 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, + 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<char const *>(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); +}