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 <X11/Xft/Xft.h>
15 #include "GWorkArea.h"
18 #include "GLyXKeySym.h"
21 #include "funcrequest.h"
24 ColorCache colorCache;
27 void ColorCache::clear()
29 MapIt it = cache_.begin();
30 for (; it != cache_.end(); ++it)
33 MapIt2 it2 = cache2_.begin();
34 for (; it2 != cache2_.end(); ++it2)
40 XftColor * ColorHandler::getXftColor(EnumLColor clr)
42 XftColor * xclr = colorCache.getXftColor(clr);
45 Colormap colormap = GDK_COLORMAP_XCOLORMAP(
46 owner_.getColormap()->gobj());
47 Visual * visual = GDK_VISUAL_XVISUAL(
48 owner_.getColormap()->get_visual()->gobj());
49 XftColorAllocName(owner_.getDisplay(), visual, colormap,
50 lcolor.getX11Name(clr).c_str(), xclr);
51 colorCache.cacheXftColor(clr, xclr);
57 Gdk::Color * ColorHandler::getGdkColor(EnumLColor clr)
59 Gdk::Color * gclr = colorCache.getColor(clr);
61 gclr = new Gdk::Color;
62 gclr->parse(lcolor.getX11Name(clr));
63 owner_.getColormap()->alloc_color(*gclr);
64 colorCache.cacheColor(clr, gclr);
74 mouse_button::state gtkButtonState(unsigned int state)
76 mouse_button::state b = mouse_button::none;
77 if (state & GDK_BUTTON1_MASK)
78 b = mouse_button::button1;
79 else if (state & GDK_BUTTON2_MASK)
80 b = mouse_button::button2;
81 else if (state & GDK_BUTTON3_MASK)
82 b = mouse_button::button3;
83 else if (state & GDK_BUTTON3_MASK)
84 b = mouse_button::button3;
85 else if (state & GDK_BUTTON4_MASK)
86 b = mouse_button::button4;
87 else if (state & GDK_BUTTON5_MASK)
88 b = mouse_button::button5;
93 key_modifier::state gtkKeyState(guint state)
95 key_modifier::state k = key_modifier::none;
96 if (state & GDK_CONTROL_MASK)
97 k |= key_modifier::ctrl;
98 if (state & GDK_SHIFT_MASK)
99 k |= key_modifier::shift;
100 if (state & GDK_MOD1_MASK)
101 k |= key_modifier::alt;
106 void inputCommitRelay(GtkIMContext */*imcontext*/, gchar * str, GWorkArea * area)
108 area->inputCommit(str);
115 GWorkArea::GWorkArea(int width, int height)
116 : workAreaPixmap_(0), painter_(*this), draw_(0), colorHandler_(*this)
118 workArea_.set_size_request(width, height);
119 workArea_.set_double_buffered(false);
120 workArea_.add_events(Gdk::STRUCTURE_MASK | Gdk::EXPOSURE_MASK |
121 Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
122 Gdk::KEY_PRESS_MASK | Gdk::BUTTON1_MOTION_MASK);
123 workArea_.signal_expose_event().connect(
124 SigC::slot(*this, &GWorkArea::onExpose));
125 workArea_.signal_configure_event().connect(
126 SigC::slot(*this, &GWorkArea::onConfigure));
127 workArea_.signal_button_press_event().connect(
128 SigC::slot(*this, &GWorkArea::onButtonPress));
129 workArea_.signal_button_release_event().connect(
130 SigC::slot(*this, &GWorkArea::onButtonRelease));
131 workArea_.signal_key_press_event().connect(
132 SigC::slot(*this, &GWorkArea::onKeyPress));
133 workArea_.signal_motion_notify_event().connect(
134 SigC::slot(*this, &GWorkArea::onMotionNotify));
136 vscrollbar_.get_adjustment()->signal_value_changed().connect(
137 SigC::slot(*this, &GWorkArea::onScroll));
139 hbox_.children().push_back(Gtk::Box_Helpers::Element(workArea_));
140 hbox_.children().push_back(
141 Gtk::Box_Helpers::Element(vscrollbar_,Gtk::PACK_SHRINK));
143 GView::instance()->getVBox().children().push_back(
144 Gtk::Box_Helpers::Element(hbox_));
145 workArea_.set_flags(workArea_.get_flags() | Gtk::CAN_DEFAULT |
147 workArea_.grab_default();
148 GView::instance()->setGWorkArea(&workArea_);
149 imContext_ = GTK_IM_CONTEXT(gtk_im_multicontext_new());
150 g_signal_connect(G_OBJECT(imContext_), "commit",
151 G_CALLBACK(&inputCommitRelay),
156 GWorkArea::~GWorkArea()
158 g_object_unref(imContext_);
162 bool GWorkArea::onExpose(GdkEventExpose * event)
164 workArea_.get_window()->draw_drawable(
165 workArea_.get_style()->get_black_gc(),
167 event->area.x, event->area.y,
168 event->area.x, event->area.y,
169 event->area.width, event->area.height);
174 bool GWorkArea::onConfigure(GdkEventConfigure * /*event*/)
176 int x, y, width, height, depth;
177 workArea_.get_window()->get_geometry(x, y, width, height, depth);
179 XftDrawDestroy(draw_);
180 workAreaPixmap_ = Gdk::Pixmap::create(workArea_.get_window(),
181 width, height, depth);
182 Pixmap pixmap = GDK_PIXMAP_XID(workAreaPixmap_->gobj());
183 Colormap colormap = GDK_COLORMAP_XCOLORMAP(
184 workArea_.get_colormap()->gobj());
185 Visual * visual = GDK_VISUAL_XVISUAL(
186 workArea_.get_colormap()->get_visual()->gobj());
187 draw_ = XftDrawCreate(getDisplay(), pixmap,
190 workAreaGC_ = Gdk::GC::create(workArea_.get_window());
191 Gdk::Cursor cursor(Gdk::XTERM);
192 workArea_.get_window()->set_cursor(cursor);
193 gtk_im_context_set_client_window(
194 imContext_, workArea_.get_window()->gobj());
201 void GWorkArea::setScrollbarParams(int height, int pos, int line_height)
203 Gtk::Adjustment * adjustment = vscrollbar_.get_adjustment();
204 adjustment->set_lower(0);
205 int workAreaHeight = workHeight();
206 if (!height || height < workAreaHeight) {
207 adjustment->set_upper(workAreaHeight);
208 adjustment->set_page_size(workAreaHeight);
209 adjustment->set_value(0);
210 adjustment->changed();
213 adjustment->set_step_increment(line_height);
214 adjustment->set_page_increment(workAreaHeight - line_height);
215 adjustment->set_upper(height);
216 adjustment->set_page_size(workAreaHeight);
217 adjustment->set_value(pos);
218 adjustment->changed();
222 void GWorkArea::onScroll()
224 double val = vscrollbar_.get_adjustment()->get_value();
225 scrollDocView(static_cast<int>(val));
229 bool GWorkArea::onButtonPress(GdkEventButton * event)
231 kb_action ka = LFUN_MOUSE_PRESS;
232 switch (event->type) {
233 case GDK_BUTTON_PRESS:
234 ka = LFUN_MOUSE_PRESS;
236 case GDK_2BUTTON_PRESS:
237 ka = LFUN_MOUSE_DOUBLE;
239 case GDK_3BUTTON_PRESS:
240 ka = LFUN_MOUSE_TRIPLE;
245 dispatch(FuncRequest(ka,
246 static_cast<int>(event->x),
247 static_cast<int>(event->y),
248 static_cast<mouse_button::state>(event->button)));
249 workArea_.grab_focus();
254 bool GWorkArea::onButtonRelease(GdkEventButton * event)
256 dispatch(FuncRequest(LFUN_MOUSE_RELEASE,
257 static_cast<int>(event->x),
258 static_cast<int>(event->y),
259 static_cast<mouse_button::state>(event->button)));
264 bool GWorkArea::onMotionNotify(GdkEventMotion * event)
266 static guint32 timeBefore;
267 Gtk::Adjustment * adjustment = vscrollbar_.get_adjustment();
268 double step = adjustment->get_step_increment();
269 double value = adjustment->get_value();
272 else if (event->x > workArea_.get_height())
274 if (value != adjustment->get_value()) {
275 if (event->time - timeBefore > 200) {
276 adjustment->set_value(value);
277 adjustment->value_changed();
279 timeBefore = event->time;
281 dispatch(FuncRequest(LFUN_MOUSE_MOTION,
282 static_cast<int>(event->x),
283 static_cast<int>(event->y),
284 gtkButtonState(event->state)));
289 void GWorkArea::inputCommit(gchar * str)
291 inputCache_ = Glib::locale_from_utf8(str);
295 bool GWorkArea::onKeyPress(GdkEventKey * event)
299 bool inputGet = gtk_im_context_filter_keypress(imContext_, event);
301 if ((inputGet && inputCache_.size() == 1 && inputCache_[0] < 128) ||
304 GLyXKeySym *glk = new GLyXKeySym(event->keyval);
305 workAreaKeyPress(LyXKeySymPtr(glk),
306 gtkKeyState(event->state));
308 } else if (!inputCache_.empty())
309 workAreaCJK_IMprocess(inputCache_.size(), inputCache_.data());
315 void GWorkArea::onClipboardGet(Gtk::SelectionData & /*selection_data*/,
318 selectionRequested();
322 void GWorkArea::onClipboardClear()
328 void GWorkArea::haveSelection(bool toHave) const
331 Glib::RefPtr<Gtk::Clipboard> clipboard =
332 Gtk::Clipboard::get(GDK_SELECTION_PRIMARY);
333 std::vector<Gtk::TargetEntry> listTargets;
334 listTargets.push_back(Gtk::TargetEntry("UTF8_STRING"));
335 clipboard->set(listTargets,
336 SigC::slot(const_cast<GWorkArea&>(*this),
337 &GWorkArea::onClipboardGet),
338 SigC::slot(const_cast<GWorkArea&>(*this),
339 &GWorkArea::onClipboardClear));
344 string const GWorkArea::getClipboard() const
346 Glib::RefPtr<Gtk::Clipboard> clipboard =
347 Gtk::Clipboard::get(GDK_SELECTION_PRIMARY);
348 return Glib::locale_from_utf8(clipboard->wait_for_text());
352 void GWorkArea::putClipboard(string const & str) const
354 Glib::RefPtr<Gtk::Clipboard> clipboard =
355 Gtk::Clipboard::get(GDK_SELECTION_PRIMARY);
356 clipboard->set_text(Glib::locale_to_utf8(str));