* \author unknown
* \author John Levon
*
- * Full author contact details are available in file CREDITS
+ * Full author contact details are available in file CREDITS.
*/
#include <config.h>
-#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 <boost/bind.hpp>
+
+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);
}
} // 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);
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;
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<XFormsView &>(owner);
+ BoxList & boxlist = xview.getBox(XFormsView::Center)->children();
+
+ wa_box_ = boxlist.push_back(Box(0,0));
+ wa_box_->set(Box::Horizontal);
+
+ shared_ptr<Box> 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<Box> 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);
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);
}
}
-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;
}
+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
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<XEvent*>(xev);
XWorkArea * area = static_cast<XWorkArea*>(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(
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;
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<XKeyEvent *>(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);
<< "' [" << 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
//}
}
-#endif
unsigned int const ret_state = xke->state;
// If you have a better way to handle "wild-output" of
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,
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,
area->dispatch(cmd);
}
break;
+
case FL_OTHER:
if (ev)
lyxerr[Debug::WORKAREA] << "Workarea event: OTHER" << endl;
fl_stuff_clipboard(work_area, 0, hold.data(), hold.size(), 0);
}
+
+} // namespace frontend
+} // namespace lyx