3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * Full author contact details are available in file CREDITS.
13 #include "GWorkArea.h"
16 #include "GLyXKeySym.h"
19 #include "funcrequest.h"
22 using boost::shared_ptr;
29 ColorCache colorCache;
32 Gdk::Color * ColorCache::getColor(LColor_color clr)
34 MapIt it = cache_.find(clr);
35 return it == cache_.end() ? 0 : it->second.get();
39 XftColor * ColorCache::getXftColor(LColor_color clr)
41 MapIt2 it = cache2_.find(clr);
42 return it == cache2_.end() ? 0 : it->second.get();
46 void ColorCache::cacheColor(LColor_color clr, Gdk::Color * gclr)
48 cache_[clr] = shared_ptr<Gdk::Color>(gclr);
52 void ColorCache::cacheXftColor(LColor_color clr, XftColor * xclr)
54 cache2_[clr] = shared_ptr<XftColor>(xclr);
58 void ColorCache::clear()
65 XftColor * ColorHandler::getXftColor(LColor_color clr)
67 XftColor * xclr = colorCache.getXftColor(clr);
70 Colormap colormap = GDK_COLORMAP_XCOLORMAP(
71 owner_.getColormap()->gobj());
72 Visual * visual = GDK_VISUAL_XVISUAL(
73 owner_.getColormap()->get_visual()->gobj());
74 XftColorAllocName(owner_.getDisplay(), visual, colormap,
76 lcolor.getX11Name(clr).c_str())
78 colorCache.cacheXftColor(clr, xclr);
84 Gdk::Color * ColorHandler::getGdkColor(LColor_color clr)
86 Gdk::Color * gclr = colorCache.getColor(clr);
88 gclr = new Gdk::Color;
89 gclr->parse(lcolor.getX11Name(clr));
90 owner_.getColormap()->alloc_color(*gclr);
91 colorCache.cacheColor(clr, gclr);
101 mouse_button::state gtkButtonState(unsigned int state)
103 mouse_button::state b = mouse_button::none;
104 if (state & GDK_BUTTON1_MASK)
105 b = mouse_button::button1;
106 else if (state & GDK_BUTTON2_MASK)
107 b = mouse_button::button2;
108 else if (state & GDK_BUTTON3_MASK)
109 b = mouse_button::button3;
110 else if (state & GDK_BUTTON3_MASK)
111 b = mouse_button::button3;
112 else if (state & GDK_BUTTON4_MASK)
113 b = mouse_button::button4;
114 else if (state & GDK_BUTTON5_MASK)
115 b = mouse_button::button5;
120 key_modifier::state gtkKeyState(guint state)
122 key_modifier::state k = key_modifier::none;
123 if (state & GDK_CONTROL_MASK)
124 k |= key_modifier::ctrl;
125 if (state & GDK_SHIFT_MASK)
126 k |= key_modifier::shift;
127 if (state & GDK_MOD1_MASK)
128 k |= key_modifier::alt;
133 void inputCommitRelay(GtkIMContext */*imcontext*/, gchar * str, GWorkArea * area)
135 area->inputCommit(str);
142 GWorkArea::GWorkArea(LyXView & owner, int width, int height)
143 : workAreaPixmap_(0), painter_(*this), draw_(0), colorHandler_(*this)
145 workArea_.set_size_request(width, height);
146 workArea_.set_double_buffered(false);
147 workArea_.add_events(Gdk::STRUCTURE_MASK | Gdk::EXPOSURE_MASK |
148 Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
149 Gdk::KEY_PRESS_MASK | Gdk::BUTTON1_MOTION_MASK);
150 workArea_.signal_expose_event().connect(
151 sigc::mem_fun(*this, &GWorkArea::onExpose));
152 workArea_.signal_configure_event().connect(
153 sigc::mem_fun(*this, &GWorkArea::onConfigure));
154 workArea_.signal_button_press_event().connect(
155 sigc::mem_fun(*this, &GWorkArea::onButtonPress));
156 workArea_.signal_button_release_event().connect(
157 sigc::mem_fun(*this, &GWorkArea::onButtonRelease));
158 workArea_.signal_key_press_event().connect(
159 sigc::mem_fun(*this, &GWorkArea::onKeyPress));
160 workArea_.signal_motion_notify_event().connect(
161 sigc::mem_fun(*this, &GWorkArea::onMotionNotify));
163 vscrollbar_.get_adjustment()->signal_value_changed().connect(
164 sigc::mem_fun(*this, &GWorkArea::onScroll));
165 workArea_.signal_scroll_event().connect(
166 sigc::mem_fun(*this, &GWorkArea::onScrollWheel));
168 hbox_.children().push_back(Gtk::Box_Helpers::Element(workArea_));
169 hbox_.children().push_back(
170 Gtk::Box_Helpers::Element(vscrollbar_,Gtk::PACK_SHRINK));
173 GView & gview = static_cast<GView &>(owner);
174 gview.getBox(GView::Center).children().push_back(
175 Gtk::Box_Helpers::Element(hbox_));
177 workArea_.set_flags(workArea_.get_flags() | Gtk::CAN_DEFAULT |
179 workArea_.grab_default();
180 gview.setGWorkArea(&workArea_);
181 imContext_ = GTK_IM_CONTEXT(gtk_im_multicontext_new());
182 g_signal_connect(G_OBJECT(imContext_), "commit",
183 G_CALLBACK(&inputCommitRelay),
188 GWorkArea::~GWorkArea()
190 g_object_unref(imContext_);
194 Painter & GWorkArea::getPainter()
200 int GWorkArea::workWidth() const
202 return workArea_.get_width();
206 int GWorkArea::workHeight() const
208 return workArea_.get_height();
212 int GWorkArea::xpos() const
218 int GWorkArea::ypos() const
224 Glib::RefPtr<Gdk::Window> GWorkArea::getWindow()
226 return workArea_.get_window();
230 Display * GWorkArea::getDisplay() const
232 return GDK_WINDOW_XDISPLAY(
233 const_cast<GdkWindow*>(workArea_.get_window()->gobj()));
237 Glib::RefPtr<Gdk::Pixmap> GWorkArea::getPixmap()
239 return workAreaPixmap_;
243 Glib::RefPtr<Gdk::GC> GWorkArea::getGC()
249 Glib::RefPtr<Gdk::Colormap> GWorkArea::getColormap()
251 return workArea_.get_colormap();
255 XftDraw * GWorkArea::getXftDraw()
261 ColorHandler & GWorkArea::getColorHandler()
263 return colorHandler_;
267 bool GWorkArea::onExpose(GdkEventExpose * event)
269 workArea_.get_window()->draw_drawable(
270 workArea_.get_style()->get_black_gc(),
272 event->area.x, event->area.y,
273 event->area.x, event->area.y,
274 event->area.width, event->area.height);
279 bool GWorkArea::onConfigure(GdkEventConfigure * /*event*/)
281 int x, y, width, height, depth;
282 workArea_.get_window()->get_geometry(x, y, width, height, depth);
284 XftDrawDestroy(draw_);
285 workAreaPixmap_ = Gdk::Pixmap::create(workArea_.get_window(),
286 width, height, depth);
287 Pixmap pixmap = GDK_PIXMAP_XID(workAreaPixmap_->gobj());
288 Colormap colormap = GDK_COLORMAP_XCOLORMAP(
289 workArea_.get_colormap()->gobj());
290 Visual * visual = GDK_VISUAL_XVISUAL(
291 workArea_.get_colormap()->get_visual()->gobj());
292 draw_ = XftDrawCreate(getDisplay(), pixmap,
295 workAreaGC_ = Gdk::GC::create(workArea_.get_window());
296 Gdk::Cursor cursor(Gdk::XTERM);
297 workArea_.get_window()->set_cursor(cursor);
298 gtk_im_context_set_client_window(
299 imContext_, workArea_.get_window()->gobj());
306 void GWorkArea::setScrollbarParams(int height, int pos, int line_height)
308 Gtk::Adjustment * adjustment = vscrollbar_.get_adjustment();
309 adjustment->set_lower(0);
310 int workAreaHeight = workHeight();
311 if (!height || height < workAreaHeight) {
312 adjustment->set_upper(workAreaHeight);
313 adjustment->set_page_size(workAreaHeight);
314 adjustment->set_value(0);
315 adjustment->changed();
318 adjustment->set_step_increment(line_height);
319 adjustment->set_page_increment(workAreaHeight - line_height);
320 adjustment->set_upper(height);
321 adjustment->set_page_size(workAreaHeight);
322 adjustment->set_value(pos);
323 adjustment->changed();
327 void GWorkArea::onScroll()
329 double val = vscrollbar_.get_adjustment()->get_value();
330 scrollDocView(static_cast<int>(val));
334 bool GWorkArea::onScrollWheel(GdkEventScroll * event)
336 Gtk::Adjustment * adjustment = vscrollbar_.get_adjustment();
339 if (event->state & GDK_CONTROL_MASK)
340 step = adjustment->get_page_increment();
342 step = adjustment->get_step_increment();
344 if (event->direction == GDK_SCROLL_UP)
347 adjustment->set_value(adjustment->get_value() + step);
353 bool GWorkArea::onButtonPress(GdkEventButton * event)
355 kb_action ka = LFUN_MOUSE_PRESS;
356 switch (event->type) {
357 case GDK_BUTTON_PRESS:
358 ka = LFUN_MOUSE_PRESS;
360 case GDK_2BUTTON_PRESS:
361 ka = LFUN_MOUSE_DOUBLE;
363 case GDK_3BUTTON_PRESS:
364 ka = LFUN_MOUSE_TRIPLE;
369 dispatch(FuncRequest(ka,
370 static_cast<int>(event->x),
371 static_cast<int>(event->y),
372 static_cast<mouse_button::state>(event->button)));
373 workArea_.grab_focus();
378 bool GWorkArea::onButtonRelease(GdkEventButton * event)
380 dispatch(FuncRequest(LFUN_MOUSE_RELEASE,
381 static_cast<int>(event->x),
382 static_cast<int>(event->y),
383 static_cast<mouse_button::state>(event->button)));
388 bool GWorkArea::onMotionNotify(GdkEventMotion * event)
390 static guint32 timeBefore;
391 Gtk::Adjustment * adjustment = vscrollbar_.get_adjustment();
392 double step = adjustment->get_step_increment();
393 double value = adjustment->get_value();
396 else if (event->x > workArea_.get_height())
398 if (value != adjustment->get_value()) {
399 if (event->time - timeBefore > 200) {
400 adjustment->set_value(value);
401 adjustment->value_changed();
403 timeBefore = event->time;
405 dispatch(FuncRequest(LFUN_MOUSE_MOTION,
406 static_cast<int>(event->x),
407 static_cast<int>(event->y),
408 gtkButtonState(event->state)));
413 void GWorkArea::inputCommit(gchar * str)
415 inputCache_ = Glib::locale_from_utf8(str);
419 bool GWorkArea::onKeyPress(GdkEventKey * event)
423 bool inputGet = gtk_im_context_filter_keypress(imContext_, event);
425 if ((inputGet && inputCache_.size() == 1 && inputCache_[0] < 128) ||
428 GLyXKeySym *glk = new GLyXKeySym(event->keyval);
429 workAreaKeyPress(LyXKeySymPtr(glk),
430 gtkKeyState(event->state));
432 } else if (!inputCache_.empty())
433 workAreaCJK_IMprocess(inputCache_.size(), inputCache_.data());
439 void GWorkArea::onClipboardGet(Gtk::SelectionData & /*selection_data*/,
442 selectionRequested();
446 void GWorkArea::onClipboardClear()
452 void GWorkArea::haveSelection(bool toHave) const
455 Glib::RefPtr<Gtk::Clipboard> clipboard =
456 Gtk::Clipboard::get(GDK_SELECTION_PRIMARY);
457 std::vector<Gtk::TargetEntry> listTargets;
458 listTargets.push_back(Gtk::TargetEntry("UTF8_STRING"));
459 clipboard->set(listTargets,
460 sigc::mem_fun(const_cast<GWorkArea&>(*this),
461 &GWorkArea::onClipboardGet),
462 sigc::mem_fun(const_cast<GWorkArea&>(*this),
463 &GWorkArea::onClipboardClear));
468 string const GWorkArea::getClipboard() const
470 Glib::RefPtr<Gtk::Clipboard> clipboard =
471 Gtk::Clipboard::get(GDK_SELECTION_PRIMARY);
472 return Glib::locale_from_utf8(clipboard->wait_for_text());
476 void GWorkArea::putClipboard(string const & str) const
478 Glib::RefPtr<Gtk::Clipboard> clipboard =
479 Gtk::Clipboard::get(GDK_SELECTION_PRIMARY);
480 clipboard->set_text(Glib::locale_to_utf8(str));
483 } // namespace frontend