PageRenderTime 52ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/TeXmacs-1.0.7.11-src/src/Plugins/Qt/QTMWidget.cpp

#
C++ | 830 lines | 602 code | 108 blank | 120 comment | 133 complexity | 0e016c92abefb8303e941fbf1025b450 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. /******************************************************************************
  2. * MODULE : QTMWidget.cpp
  3. * DESCRIPTION: QT Texmacs widget class
  4. * COPYRIGHT : (C) 2008 Massimiliano Gubinelli and Joris van der Hoeven
  5. *******************************************************************************
  6. * This software falls under the GNU general public license version 3 or later.
  7. * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
  8. * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
  9. ******************************************************************************/
  10. #include <QtGui>
  11. #include "QTMWidget.hpp"
  12. #include "qt_renderer.hpp"
  13. #include "qt_gui.hpp"
  14. #include "qt_utilities.hpp"
  15. #include "qt_simple_widget.hpp"
  16. #include "converter.hpp"
  17. #include "config.h"
  18. #include "message.hpp"
  19. #ifdef USE_CAIRO
  20. #include "Cairo/cairo_renderer.hpp"
  21. #include "Cairo/tm_cairo.hpp"
  22. #if defined(Q_WS_X11)
  23. #include <QX11Info>
  24. extern Drawable qt_x11Handle(const QPaintDevice *pd);
  25. extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
  26. #undef KeyPress // conflict between QEvent::KeyPrees and X11 defintion
  27. #endif // Q_WS_X11
  28. #endif // USE_CAIRO
  29. #include <QEvent>
  30. #define PIXEL 256
  31. QSet<QTMWidget*> QTMWidget::all_widgets;
  32. hashmap<int,string> qtkeymap (0);
  33. hashmap<int,string> qtdeadmap (0);
  34. inline void
  35. scale (QPoint& point) {
  36. point.rx() *= PIXEL; point.ry() *= -PIXEL;
  37. }
  38. inline void
  39. map (int code, string name) {
  40. qtkeymap(code) = name;
  41. }
  42. inline void
  43. deadmap (int code, string name) {
  44. qtdeadmap(code) = name;
  45. }
  46. void
  47. initkeymap () {
  48. map (Qt::Key_Space , "space");
  49. map (Qt::Key_Return , "return");
  50. map (Qt::Key_Tab , "tab");
  51. map (Qt::Key_Backspace , "backspace");
  52. map (Qt::Key_Enter , "enter");
  53. map (Qt::Key_Escape , "escape");
  54. map (Qt::Key_Backspace , "backspace");
  55. map (Qt::Key_Up , "up" );
  56. map (Qt::Key_Down , "down" );
  57. map (Qt::Key_Left , "left" );
  58. map (Qt::Key_Right , "right" );
  59. map (Qt::Key_F1 , "F1" );
  60. map (Qt::Key_F2 , "F2" );
  61. map (Qt::Key_F3 , "F3" );
  62. map (Qt::Key_F4 , "F4" );
  63. map (Qt::Key_F5 , "F5" );
  64. map (Qt::Key_F6 , "F6" );
  65. map (Qt::Key_F7 , "F7" );
  66. map (Qt::Key_F8 , "F8" );
  67. map (Qt::Key_F9 , "F9" );
  68. map (Qt::Key_F10 , "F10" );
  69. map (Qt::Key_F11 , "F11" );
  70. map (Qt::Key_F12 , "F12" );
  71. map (Qt::Key_F13 , "F13" );
  72. map (Qt::Key_F14 , "F14" );
  73. map (Qt::Key_F15 , "F15" );
  74. map (Qt::Key_F16 , "F16" );
  75. map (Qt::Key_F17 , "F17" );
  76. map (Qt::Key_F18 , "F18" );
  77. map (Qt::Key_F19 , "F19" );
  78. map (Qt::Key_F20 , "F20" );
  79. map (Qt::Key_F21 , "F21" );
  80. map (Qt::Key_F22 , "F22" );
  81. map (Qt::Key_F23 , "F23" );
  82. map (Qt::Key_F24 , "F24" );
  83. map (Qt::Key_F25 , "F25" );
  84. map (Qt::Key_F26 , "F26" );
  85. map (Qt::Key_F27 , "F27" );
  86. map (Qt::Key_F28 , "F28" );
  87. map (Qt::Key_F29 , "F29" );
  88. map (Qt::Key_F30 , "F30" );
  89. map (Qt::Key_F31 , "F31" );
  90. map (Qt::Key_F32 , "F32" );
  91. map (Qt::Key_F33 , "F33" );
  92. map (Qt::Key_F34 , "F34" );
  93. map (Qt::Key_F35 , "F35" );
  94. map (Qt::Key_Insert , "insert" );
  95. map (Qt::Key_Delete , "delete" );
  96. map (Qt::Key_Home , "home" );
  97. map (Qt::Key_End , "end" );
  98. map (Qt::Key_PageUp , "pageup" );
  99. map (Qt::Key_PageDown , "pagedown" );
  100. map (Qt::Key_ScrollLock, "scrolllock" );
  101. map (Qt::Key_Pause , "pause" );
  102. map (Qt::Key_SysReq , "sysreq" );
  103. map (Qt::Key_Stop , "stop" );
  104. map (Qt::Key_Menu , "menu" );
  105. map (Qt::Key_Print , "print" );
  106. map (Qt::Key_Select , "select" );
  107. map (Qt::Key_Execute , "execute" );
  108. map (Qt::Key_Help , "help" );
  109. deadmap (Qt::Key_Dead_Acute , "acute");
  110. deadmap (Qt::Key_Dead_Grave , "grave");
  111. deadmap (Qt::Key_Dead_Diaeresis , "umlaut");
  112. deadmap (Qt::Key_Dead_Circumflex, "hat");
  113. deadmap (Qt::Key_Dead_Tilde , "tilde");
  114. // map (0x0003 , "K-enter");
  115. // map (Qt::Key_Begin , "begin" );
  116. // map (Qt::Key_PrintScreen , "printscreen" );
  117. // map (Qt::Key_Break , "break" );
  118. // map (Qt::Key_User , "user" );
  119. // map (Qt::Key_System , "system" );
  120. // map (Qt::Key_Reset , "reset" );
  121. // map (Qt::Key_ClearLine , "clear" );
  122. // map (Qt::Key_ClearDisplay, "cleardisplay" );
  123. // map (Qt::Key_InsertLine , "insertline" );
  124. // map (Qt::Key_DeleteLine , "deleteline" );
  125. // map (Qt::Key_InsertChar , "insert" );
  126. // map (Qt::Key_DeleteChar , "delete" );
  127. // map (Qt::Key_Prev , "prev" );
  128. // map (Qt::Key_Next , "next" );
  129. // map (Qt::Key_Undo , "undo" );
  130. // map (Qt::Key_Redo , "redo" );
  131. // map (Qt::Key_Find , "find" );
  132. // map (Qt::Key_ModeSwitchFunctionKey, "modeswitch" );
  133. }
  134. QTMWidget::QTMWidget (simple_widget_rep *_wid)
  135. : QTMScrollView (), backingPixmap(), imwidget(NULL) {
  136. setObjectName("A QTMWidget");
  137. setProperty ("texmacs_widget", QVariant::fromValue ((void*) _wid));
  138. surface()->setMouseTracking (true);
  139. setFocusPolicy (Qt::StrongFocus);
  140. backing_pos = origin();
  141. setAttribute(Qt::WA_InputMethodEnabled);
  142. }
  143. QTMWidget::~QTMWidget () {
  144. if (DEBUG_QT) cout << "destroying " << this << LF;
  145. }
  146. void
  147. QTMWidget::invalidate_rect (int x1, int y1, int x2, int y2) {
  148. #ifdef Q_WS_MAC
  149. //HACK: for unknown reasons we need to enlarge the invalid rect to prevent
  150. //artifacts while moving the cursor (for example at the end of a formula like
  151. // $a+f$. These artifacts seems present only on 64 bit Macs.
  152. rectangle r = rectangle (x1-10, y1-10, x2+10, y2+10);
  153. #else
  154. rectangle r = rectangle (x1, y1, x2, y2);
  155. #endif
  156. // cout << "invalidating " << r << LF;
  157. invalid_regions = invalid_regions | rectangles (r);
  158. }
  159. void
  160. QTMWidget::invalidate_all () {
  161. QSize sz = surface()->size();
  162. // QPoint pt = QAbstractScrollArea::viewport()->pos();
  163. //cout << "invalidate all " << LF;
  164. invalid_regions = rectangles();
  165. invalidate_rect (0, 0, sz.width(), sz.height());
  166. }
  167. basic_renderer_rep*
  168. QTMWidget::getRenderer() {
  169. #ifdef USE_CAIRO
  170. cairo_renderer_rep *ren = the_cairo_renderer ();
  171. cairo_surface_t *surf;
  172. #ifdef Q_WS_X11
  173. //const QX11Info & info = x11Info();//qt_x11Info(this);
  174. // Display *dpy = x11Info().display();
  175. //backingPixmap = QPixmap(width(),height());
  176. //cout << backingPixmap.width() << LF;
  177. Display *dpy = QX11Info::display();
  178. Drawable drawable = backingPixmap.handle();
  179. Visual *visual = (Visual*)(backingPixmap.x11Info().visual());
  180. surf = tm_cairo_xlib_surface_create (dpy, drawable, visual,
  181. backingPixmap.width (), backingPixmap.height ());
  182. #elif defined(Q_WS_MAC)
  183. surf = tm_cairo_quartz_surface_create_for_cg_context (
  184. (CGContextRef)(this->macCGHandle()), width(), height());
  185. #endif
  186. cairo_t *ct = tm_cairo_create (surf);
  187. ren->begin (ct);
  188. tm_cairo_surface_destroy (surf);
  189. tm_cairo_destroy (ct);
  190. #else
  191. qt_renderer_rep * ren = the_qt_renderer();
  192. ren->begin(&backingPixmap);
  193. #endif
  194. return ren;
  195. }
  196. void
  197. QTMWidget::repaint_invalid_regions () {
  198. // this function is called by the qt_gui::update method to keep the backing
  199. // store in sync and propagate the changes to the surface on screen.
  200. // first we check that the backing store geometry is right and then we
  201. // request to the texmacs canvas widget to repaint the regions which were
  202. // marked invalid. Subsequently, for each succesfully repainted region, we
  203. // propagate its contents from the backing store to the onscreen surface.
  204. // If repaint has been interrupted we do not propagate the changes and proceed
  205. // to mark the region invalid again.
  206. QRegion qrgn;
  207. // qrgn is to keep track of the area on the sceen which needs to be updated
  208. // update backing store origin wrt. TeXmacs document
  209. if ( backing_pos != origin() ) {
  210. int dx = origin().x() - backing_pos.x();
  211. int dy = origin().y() - backing_pos.y();
  212. backing_pos = origin();
  213. QPixmap newBackingPixmap (backingPixmap.size());
  214. QPainter p (&newBackingPixmap);
  215. //newBackingPixmap.fill(Qt::black);
  216. p.drawPixmap(-dx,-dy,backingPixmap);
  217. p.end();
  218. backingPixmap = newBackingPixmap;
  219. //cout << "SCROLL CONTENTS BY " << dx << " " << dy << LF;
  220. QSize sz = backingPixmap.size();
  221. rectangles invalid;
  222. while (!is_nil(invalid_regions)) {
  223. rectangle r = invalid_regions->item ;
  224. // rectangle q = rectangle(r->x1+dx,r->y1-dy,r->x2+dx,r->y2-dy);
  225. rectangle q = rectangle(r->x1-dx,r->y1-dy,r->x2-dx,r->y2-dy);
  226. invalid = rectangles (q, invalid);
  227. //cout << r << " ---> " << q << LF;
  228. invalid_regions = invalid_regions->next;
  229. }
  230. invalid_regions= invalid &
  231. rectangles(rectangle(0,0,
  232. sz.width(),sz.height())) ;
  233. if (dy<0)
  234. invalidate_rect(0,0,sz.width(),min(sz.height(),-dy));
  235. else if (dy>0)
  236. invalidate_rect(0,max(0,sz.height()-dy),sz.width(),sz.height());
  237. if (dx<0)
  238. invalidate_rect(0,0,min(-dx,sz.width()),sz.height());
  239. else if (dx>0)
  240. invalidate_rect(max(0,sz.width()-dx),0,sz.width(),sz.height());
  241. // we cal update now to allow repainint of invalid regions
  242. // this cannot be done directly since interpose handler needs
  243. // to be run at least once in some situations
  244. // (for example when scrolling is initiated by TeXmacs itself)
  245. //the_gui->update();
  246. // QAbstractScrollArea::viewport()->scroll(-dx,-dy);
  247. // QAbstractScrollArea::viewport()->update();
  248. qrgn += QRect(QPoint(0,0),sz);
  249. }
  250. // update backing store size
  251. {
  252. QSize _oldSize = backingPixmap.size();
  253. QSize _newSize = surface()->size();
  254. if (_newSize != _oldSize) {
  255. // cout << "RESIZING BITMAP"<< LF;
  256. QPixmap newBackingPixmap (_newSize);
  257. QPainter p (&newBackingPixmap);
  258. p.drawPixmap(0,0,backingPixmap);
  259. //p.fillRect(0, 0, _newSize.width(), _newSize.height(), Qt::red);
  260. if (_newSize.width() >= _oldSize.width()) {
  261. invalidate_rect(_oldSize.width(), 0, _newSize.width(), _newSize.height());
  262. p.fillRect(QRect(_oldSize.width(), 0, _newSize.width()-_oldSize.width(), _newSize.height()), Qt::gray);
  263. }
  264. if (_newSize.height() >= _oldSize.height()) {
  265. invalidate_rect(0,_oldSize.height(), _newSize.width(), _newSize.height());
  266. p.fillRect(QRect(0,_oldSize.height(), _newSize.width(), _newSize.height()-_oldSize.height()), Qt::gray);
  267. }
  268. p.end();
  269. backingPixmap = newBackingPixmap;
  270. }
  271. }
  272. // repaint invalid rectangles
  273. {
  274. rectangles new_regions;
  275. if (!is_nil (invalid_regions)) {
  276. rectangle lub= least_upper_bound (invalid_regions);
  277. if (area (lub) < 1.2 * area (invalid_regions))
  278. invalid_regions= rectangles (lub);
  279. basic_renderer_rep* ren = getRenderer();
  280. tm_widget()->set_current_renderer(ren);
  281. SI ox = -backing_pos.x()*PIXEL;
  282. SI oy = backing_pos.y()*PIXEL;
  283. rectangles rects = invalid_regions;
  284. invalid_regions = rectangles();
  285. while (!is_nil (rects)) {
  286. rectangle r = copy (rects->item);
  287. rectangle r0 = rects->item;
  288. QRect qr = QRect(r0->x1, r0->y1, r0->x2 - r0->x1, r0->y2 - r0->y1);
  289. //cout << "repainting " << r0 << "\n";
  290. ren->set_origin(ox,oy);
  291. ren->encode (r->x1, r->y1);
  292. ren->encode (r->x2, r->y2);
  293. ren->set_clipping (r->x1, r->y2, r->x2, r->y1);
  294. tm_widget()->handle_repaint (r->x1, r->y2, r->x2, r->y1);
  295. if (ren->interrupted ()) {
  296. //cout << "interrupted repainting of " << r0 << "\n";
  297. //ren->set_color(green);
  298. //ren->line(r->x1, r->y1, r->x2, r->y2);
  299. //ren->line(r->x1, r->y2, r->x2, r->y1);
  300. invalidate_rect (r0->x1, r0->y1, r0->x2, r0->y2);
  301. }
  302. qrgn += qr;
  303. rects = rects->next;
  304. }
  305. tm_widget()->set_current_renderer(NULL);
  306. ren->end();
  307. } // !is_nil(invalid_regions)
  308. }
  309. // propagate immediatly the changes to the screen
  310. surface()->repaint(qrgn);
  311. }
  312. void
  313. QTMWidget::scrollContentsBy ( int dx, int dy ) {
  314. QTMScrollView::scrollContentsBy (dx,dy);
  315. force_update();
  316. // we force an update of the internal state to be in sync with the moving
  317. // scrollbars
  318. }
  319. void
  320. QTMWidget::resizeEvent( QResizeEvent* event ) {
  321. (void) event;
  322. // cout << "QTMWidget::resizeEvent (" << event->size().width()
  323. // << "," << event->size().height() << ")" << LF;
  324. the_gui -> process_resize(tm_widget(), 0, 0); // FIXME
  325. // force_update();
  326. //FIXME: I would like to have a force_update here but this cause a failed
  327. //assertion in TeXmacs since the at the boot not every internal structure is
  328. //initialized at this point. It seems not too difficult to fix but I
  329. //postpone this to discuss with Joris.
  330. //
  331. //Not having a force_update results in some lack of sync of the surface
  332. //while the user is actively resizing with the mouse.
  333. }
  334. void
  335. QTMWidget::paintEvent (QPaintEvent* event) {
  336. // In the current implementation repainting take place during the call to
  337. // the widget's repaint_invalid_regions method in the_gui::update. All
  338. // we have to do is to take the backing store and put it on screen according
  339. // to the QRegion marked invalid.
  340. // CHECK: Maybe just put onscreen all the region bounding rectangle could not
  341. // be so expensive.
  342. if (DEBUG_QT)
  343. {
  344. QRect rect = event->rect ();
  345. cout << "paintEvent ("<< rect.x() << "," << rect.y()
  346. << "," << rect.width() << "," << rect.height() << ")" << LF ;
  347. }
  348. {
  349. QPainter p (surface());
  350. QVector<QRect> rects = event->region().rects();
  351. for (int i=0; i< rects.count(); i++) {
  352. QRect qr = rects.at(i);
  353. p.drawPixmap(qr,backingPixmap,qr);
  354. }
  355. }
  356. }
  357. void
  358. QTMWidget::keyPressEvent (QKeyEvent* event) {
  359. static bool fInit = false;
  360. if (!fInit) {
  361. if (DEBUG_QT)
  362. cout << "Initializing keymap\n";
  363. initkeymap();
  364. fInit= true;
  365. }
  366. if (DEBUG_QT)
  367. cout << "keypressed\n";
  368. simple_widget_rep *wid = tm_widget();
  369. if (!wid) return;
  370. {
  371. int key = event->key();
  372. Qt::KeyboardModifiers mods = event->modifiers();
  373. if (DEBUG_QT) {
  374. cout << "key : " << key << LF;
  375. cout << "text : " << event->text().toAscii().data() << LF;
  376. cout << "count: " << event->text().count() << LF;
  377. if (mods & Qt::ShiftModifier) cout << "shift\n";
  378. if (mods & Qt::MetaModifier) cout << "meta\n";
  379. if (mods & Qt::ControlModifier) cout << "control\n";
  380. if (mods & Qt::KeypadModifier) cout << "keypad\n";
  381. if (mods & Qt::AltModifier) cout << "alt\n";
  382. }
  383. string r;
  384. if (qtkeymap->contains (key)) {
  385. r = qtkeymap[key];
  386. } else if (qtdeadmap->contains (key)) {
  387. mods &=~ Qt::ShiftModifier;
  388. r = qtdeadmap[key];
  389. } else {
  390. QString nss = event->text();
  391. unsigned short unic= nss.data()[0].unicode();
  392. if (unic < 32 && key < 128 && key > 0) {
  393. if (((char) key) >= 'A' && ((char) key) <= 'Z') {
  394. if ((mods & Qt::ShiftModifier) == 0)
  395. key= (int) (key + ((int) 'a') - ((int) 'A'));
  396. }
  397. mods &=~ Qt::ShiftModifier;
  398. r= string ((char) key);
  399. } else {
  400. switch(unic) {
  401. case 96: r= "`";
  402. // unicode to cork conversion not appropriate for this case...
  403. #ifdef Q_WS_MAC
  404. // CHECKME: are these two MAC exceptions really needed?
  405. if (mods & Qt::AltModifier) r= "grave";
  406. #endif
  407. break;
  408. case 168: r= "umlaut"; break;
  409. case 180: r= "acute"; break;
  410. // the following combining characters should be caught by qtdeadmap
  411. case 0x300: r= "grave"; break;
  412. case 0x301: r= "acute"; break;
  413. case 0x302: r= "hat"; break;
  414. case 0x308: r= "umlaut"; break;
  415. case 0x33e: r= "tilde"; break;
  416. default:
  417. QByteArray buf= nss.toUtf8();
  418. string rr (buf.constData(), buf.count());
  419. r= utf8_to_cork (rr);
  420. if (r == "<less>") r= "<";
  421. if (r == "<gtr>") r= ">";
  422. }
  423. #ifdef Q_WS_MAC
  424. // CHECKME: are these two MAC exceptions really needed?
  425. mods &=~ Qt::AltModifier;
  426. #endif
  427. mods &=~ Qt::ShiftModifier;
  428. }
  429. }
  430. if (r == "") return;
  431. #ifdef Q_WS_MAC
  432. if (mods & Qt::ShiftModifier) r= "S-" * r;
  433. if (mods & Qt::MetaModifier) r= "C-" * r; // The "Control" key
  434. if (mods & Qt::AltModifier) r= "A-" * r;
  435. if (mods & Qt::ControlModifier) r= "M-" * r; // The "Command" key
  436. //if (mods & Qt::KeypadModifier) r= "K-" * r;
  437. #else
  438. if (mods & Qt::ShiftModifier) r= "S-" * r;
  439. if (mods & Qt::ControlModifier) r= "C-" * r;
  440. if (mods & Qt::AltModifier) r= "A-" * r;
  441. if (mods & Qt::MetaModifier) r= "M-" * r; // The "Windows" key
  442. //if (mods & Qt::KeypadModifier) r= "K-" * r;
  443. #endif
  444. if (DEBUG_QT)
  445. cout << "key press: " << r << LF;
  446. //int start= texmacs_time ();
  447. //wid -> handle_keypress (r, texmacs_time());
  448. the_gui -> process_keypress (wid, r, texmacs_time());
  449. //int end= texmacs_time ();
  450. //if (end > start) cout << "Keypress " << end - start << "\n";
  451. // the_gui->update (); // FIXME: remove this line when
  452. // edit_typeset_rep::get_env_value will be faster
  453. // needs_update();
  454. }
  455. }
  456. static unsigned int
  457. mouse_state (QMouseEvent* event, bool flag) {
  458. unsigned int i= 0;
  459. Qt::MouseButtons bstate= event->buttons ();
  460. Qt::MouseButton tstate= event->button ();
  461. Qt::KeyboardModifiers kstate= event->modifiers ();
  462. if (flag) bstate= bstate | tstate;
  463. if ((bstate & Qt::LeftButton ) != 0) i += 1;
  464. if ((bstate & Qt::MidButton ) != 0) i += 2;
  465. if ((bstate & Qt::RightButton ) != 0) i += 4;
  466. if ((bstate & Qt::XButton1 ) != 0) i += 8;
  467. if ((bstate & Qt::XButton2 ) != 0) i += 16;
  468. #ifdef Q_WS_MAC
  469. if ((kstate & Qt::AltModifier ) != 0) i = 2;
  470. if ((kstate & Qt::MetaModifier ) != 0) i = 4;
  471. if ((kstate & Qt::ShiftModifier ) != 0) i += 256;
  472. if ((kstate & Qt::ControlModifier) != 0) i += 2048;
  473. #else
  474. if ((kstate & Qt::ShiftModifier ) != 0) i += 256;
  475. if ((kstate & Qt::ControlModifier) != 0) i += 512;
  476. if ((kstate & Qt::AltModifier ) != 0) i += 2048;
  477. if ((kstate & Qt::MetaModifier ) != 0) i += 16384;
  478. #endif
  479. return i;
  480. }
  481. static string
  482. mouse_decode (unsigned int mstate) {
  483. if (mstate & 1 ) return "left";
  484. else if (mstate & 2 ) return "middle";
  485. else if (mstate & 4 ) return "right";
  486. else if (mstate & 8 ) return "up";
  487. else if (mstate & 16) return "down";
  488. return "unknown";
  489. }
  490. #if 0 // NOT USED
  491. static void setRoundedMask(QWidget *widget)
  492. {
  493. QPixmap pixmap(widget->size());
  494. QPainter painter(&pixmap);
  495. painter.fillRect(pixmap.rect(), Qt::white);
  496. painter.setBrush(Qt::black);
  497. #if (QT_VERSION >= 0x040400)
  498. painter.drawRoundedRect(pixmap.rect(),8,8, Qt::AbsoluteSize);
  499. #else
  500. painter.drawRect(pixmap.rect());
  501. #endif
  502. widget->setMask(pixmap.createMaskFromColor(Qt::white));
  503. }
  504. #endif
  505. #if 0
  506. // OLD INPUT METHOD PREVIEW
  507. void
  508. QTMWidget::inputMethodEvent (QInputMethodEvent* event) {
  509. if (! imwidget) {
  510. imwidget = new QLabel(this);
  511. imwidget->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
  512. // imwidget->setAttribute(Qt::WA_TranslucentBackground);
  513. // imwidget->setAutoFillBackground(false);
  514. imwidget->setAutoFillBackground(true);
  515. imwidget->setWindowOpacity(0.5);
  516. imwidget->setFocusPolicy(Qt::NoFocus);
  517. QPalette pal = imwidget->palette();
  518. // pal.setColor(QPalette::Window, QColor(0,0,255,80));
  519. pal.setColor(QPalette::Window, QColor(0,0,255,255));
  520. pal.setColor(QPalette::WindowText, Qt::white);
  521. imwidget->setPalette(pal);
  522. QFont f = imwidget->font();
  523. f.setPointSize(30);
  524. imwidget->setFont(f);
  525. imwidget->setMargin(5);
  526. }
  527. QString const & preedit_string = event->preeditString();
  528. QString const & commit_string = event->commitString();
  529. if (preedit_string.isEmpty()) {
  530. imwidget->hide();
  531. } else {
  532. if (DEBUG_QT)
  533. cout << "IM preediting :" << preedit_string.toUtf8().data() << LF;
  534. imwidget->setText(preedit_string);
  535. imwidget->adjustSize();
  536. QSize sz = size();
  537. QRect g = imwidget->geometry();
  538. QPoint c = mapToGlobal(cursor_pos);
  539. c += QPoint(5,5);
  540. // g.moveCenter(QPoint(sz.width()/2,sz.height()/2));
  541. g.moveTopLeft(c);
  542. if (DEBUG_QT)
  543. cout << "IM hotspot: " << cursor_pos.x() << "," << cursor_pos.y() << LF;
  544. imwidget->setGeometry(g);
  545. // setRoundedMask(imwidget);
  546. imwidget->show();
  547. #ifdef QT_MAC_USE_COCOA
  548. // HACK: we unexplicably loose the focus even when showing the small window,
  549. // so we need to restore it manually.....
  550. // The following fixes the problem (but I do not really understand why it
  551. // happens)
  552. // Maybe this is a Qt/Cocoa bug.
  553. this->window()->activateWindow();
  554. #endif
  555. }
  556. if (!commit_string.isEmpty()) {
  557. if (DEBUG_QT)
  558. cout << "IM committing :" << commit_string.toUtf8().data() << LF;
  559. int key = 0;
  560. #if 1
  561. for (int i = 0; i < commit_string.size(); ++i) {
  562. QKeyEvent ev(QEvent::KeyPress, key, Qt::NoModifier, commit_string[i]);
  563. keyPressEvent(&ev);
  564. }
  565. #else
  566. QKeyEvent ev(QEvent::KeyPress, key, Qt::NoModifier, commit_string);
  567. keyPressEvent(&ev);
  568. #endif
  569. }
  570. event->accept();
  571. }
  572. QVariant
  573. QTMWidget::inputMethodQuery ( Qt::InputMethodQuery query ) const {
  574. switch (query) {
  575. case Qt::ImMicroFocus :
  576. return QVariant(QRect(cursor_pos + QPoint(10,10),QSize(20,40)));
  577. default:
  578. return QVariant();
  579. }
  580. }
  581. #else
  582. // NEW INPUT METHOD PREVIEW
  583. void
  584. QTMWidget::inputMethodEvent (QInputMethodEvent* event) {
  585. QString const & preedit_string = event->preeditString();
  586. QString const & commit_string = event->commitString();
  587. if (!commit_string.isEmpty()) {
  588. if (DEBUG_QT)
  589. cout << "IM committing :" << commit_string.toUtf8().data() << LF;
  590. int key = 0;
  591. #if 1
  592. for (int i = 0; i < commit_string.size(); ++i) {
  593. QKeyEvent ev(QEvent::KeyPress, key, Qt::NoModifier, commit_string[i]);
  594. keyPressEvent(&ev);
  595. }
  596. #else
  597. QKeyEvent ev(QEvent::KeyPress, key, Qt::NoModifier, commit_string);
  598. keyPressEvent(&ev);
  599. #endif
  600. }
  601. if (DEBUG_QT)
  602. cout << "IM preediting :" << preedit_string.toUtf8().data() << LF;
  603. string r = "pre-edit:";
  604. if (!preedit_string.isEmpty())
  605. {
  606. // find cursor position in the preedit string
  607. QList<QInputMethodEvent::Attribute> const & attrs = event->attributes();
  608. // int pos = preedit_string.count();
  609. int pos = 0;
  610. bool visible_cur = false;
  611. for(int i=0; i< attrs.count(); i++)
  612. if (attrs[i].type == QInputMethodEvent::Cursor) {
  613. pos = attrs[i].start;
  614. visible_cur = (attrs[i].length != 0);
  615. }
  616. // find selection in the preedit string
  617. int sel_start = 0;
  618. int sel_length = 0;
  619. if (pos < preedit_string.count()) {
  620. for(int i=0; i< attrs.count(); i++)
  621. if ((attrs[i].type == QInputMethodEvent::TextFormat) &&
  622. (attrs[i].start <= pos) && (pos < attrs[i].start + attrs[i].length)) {
  623. sel_start = attrs[i].start;
  624. sel_length = attrs[i].length;
  625. if (!visible_cur) pos += attrs[i].length;
  626. }
  627. } else {
  628. sel_start = pos;
  629. sel_length = 0;
  630. }
  631. r = r * as_string(pos) * ":"
  632. * from_qstring(preedit_string);
  633. }
  634. simple_widget_rep *wid = tm_widget();
  635. if (wid)
  636. the_gui -> process_keypress (wid, r, texmacs_time());
  637. event->accept();
  638. }
  639. QVariant
  640. QTMWidget::inputMethodQuery ( Qt::InputMethodQuery query ) const {
  641. switch (query) {
  642. case Qt::ImMicroFocus :
  643. return QVariant (QRect (cursor_pos, QSize (5,5)));
  644. default:
  645. return QWidget::inputMethodQuery (query);
  646. }
  647. }
  648. #endif // input method variants
  649. void
  650. QTMWidget::mousePressEvent (QMouseEvent* event) {
  651. simple_widget_rep *wid= tm_widget ();
  652. if (!wid) return;
  653. QPoint point = event->pos() + origin();
  654. scale (point);
  655. unsigned int mstate= mouse_state (event, false);
  656. string s= "press-" * mouse_decode (mstate);
  657. the_gui -> process_mouse (wid, s, point.x (), point.y (),
  658. mstate, texmacs_time ());
  659. // wid -> handle_mouse (s, point.x (), point.y (), mstate, texmacs_time ());
  660. if (DEBUG_QT)
  661. cout << "mouse event: " << s << " at "
  662. << point.x () << ", " << point.y () << LF;
  663. }
  664. void
  665. QTMWidget::mouseReleaseEvent (QMouseEvent* event) {
  666. simple_widget_rep *wid = tm_widget();
  667. if (!wid) return;
  668. QPoint point = event->pos() + origin();
  669. scale (point);
  670. unsigned int mstate= mouse_state (event, true);
  671. string s= "release-" * mouse_decode (mstate);
  672. the_gui -> process_mouse (wid, s, point.x (), point.y (),
  673. mstate, texmacs_time ());
  674. // wid -> handle_mouse (s, point.x (), point.y (), mstate, texmacs_time ());
  675. if (DEBUG_QT)
  676. cout << "mouse event: " << s << " at "
  677. << point.x () << ", " << point.y () << LF;
  678. }
  679. void
  680. QTMWidget::mouseMoveEvent (QMouseEvent* event) {
  681. simple_widget_rep *wid = tm_widget();
  682. if (!wid) return;
  683. QPoint point = event->pos() + origin();
  684. scale (point);
  685. unsigned int mstate= mouse_state (event, false);
  686. string s= "move";
  687. the_gui -> process_mouse (wid, s, point.x (), point.y (),
  688. mstate, texmacs_time ());
  689. // wid -> handle_mouse (s, point.x (), point.y (), mstate, texmacs_time ());
  690. if (DEBUG_QT)
  691. cout << "mouse event: " << s << " at "
  692. << point.x () << ", " << point.y () << LF;
  693. }
  694. bool
  695. QTMWidget::event (QEvent* event) {
  696. if (event->type() == QEvent::KeyPress) {
  697. QKeyEvent *ke = static_cast<QKeyEvent*> (event);
  698. keyPressEvent (ke);
  699. return true;
  700. }
  701. return QTMScrollView::event (event);
  702. }
  703. void
  704. QTMWidget::focusInEvent ( QFocusEvent * event ) {
  705. if (DEBUG_QT) cout << "FOCUSIN" << LF;
  706. simple_widget_rep *wid = tm_widget ();
  707. if (wid) {
  708. the_gui -> process_keyboard_focus (wid, true, texmacs_time());
  709. //wid -> handle_keyboard_focus (true, texmacs_time ());
  710. }
  711. QTMScrollView::focusInEvent (event);
  712. }
  713. void
  714. QTMWidget::focusOutEvent ( QFocusEvent * event ) {
  715. if (DEBUG_QT) cout << "FOCUSOUT" << LF;
  716. simple_widget_rep *wid = tm_widget ();
  717. if (wid) {
  718. the_gui -> process_keyboard_focus (wid, false, texmacs_time());
  719. // wid -> handle_keyboard_focus (false, texmacs_time ());
  720. }
  721. QTMScrollView::focusOutEvent (event);
  722. }