Hi,

Scintilla's autocomplete popup appears above the current line if there isn't room in the client rectangle below the current line and there is room above. The client rectangle is where the text is drawn. This means that the popup appears above the current line even when there is space below on the monitor.

The attached patch allows the popup to be displayed below as long as it can fit on the monitor the cursor is on. It's only implemented on the gtk platform, but hopefully isn't too difficult to implement on other platforms. The same positioning behavior might also be applied to calltips and other popups.

Cheers,

John
Index: include/Platform.h
===================================================================
--- include/Platform.h  (revision 15788)
+++ include/Platform.h  (working copy)
@@ -405,6 +405,7 @@
        enum Cursor { cursorInvalid, cursorText, cursorArrow, cursorUp, 
cursorWait, cursorHoriz, cursorVert, cursorReverseArrow, cursorHand };
        void SetCursor(Cursor curs);
        void SetTitle(const char *s);
+       PRectangle GetMonitorRect(Point pt);
 #if PLAT_MACOSX
        void SetWindow(void *ref) { windowRef = ref; };
        void SetControl(void *_control) { control = _control; };
Index: gtk/PlatGTK.cxx
===================================================================
--- gtk/PlatGTK.cxx     (revision 15769)
+++ gtk/PlatGTK.cxx     (working copy)
@@ -1930,6 +1930,33 @@
        gtk_window_set_title(GTK_WINDOW(id), s);
 }
 
+/* Returns rectangle of monitor pt is on, both rect and pt are in Window's 
+   gdk window coordinates */
+PRectangle Window::GetMonitorRect(Point pt) {
+       gint x_offset, y_offset;
+
+       gdk_window_get_origin(PWidget(id)->window, &x_offset, &y_offset);
+
+// gtk 2.2+
+#if GTK_MAJOR_VERSION > 2 || (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 2)
+       {
+               GdkScreen* screen;
+               gint monitor_num;
+               GdkRectangle rect;
+       
+               screen = gtk_widget_get_screen(PWidget(id));
+               monitor_num = gdk_screen_get_monitor_at_point(screen, pt.x + 
x_offset, pt.y + y_offset);
+               gdk_screen_get_monitor_geometry(screen, monitor_num, &rect);
+               rect.x -= x_offset;
+               rect.y -= y_offset;
+               return PRectangle(rect.x, rect.y, rect.x + rect.width, rect.y + 
rect.height);
+       }
+#else
+       return PRectangle(-x_offset, -y_offset, (-x_offset) + 
gdk_screen_width(),
+                         (-y_offset) + gdk_screen_height());
+#endif
+}
+
 struct ListImage {
        const char *xpm_data;
 #if GTK_MAJOR_VERSION < 2
Index: src/ScintillaBase.cxx
===================================================================
--- src/ScintillaBase.cxx       (revision 15760)
+++ src/ScintillaBase.cxx       (working copy)
@@ -231,6 +231,7 @@
 
        PRectangle rcClient = GetClientRectangle();
        Point pt = LocationFromPosition(currentPos - lenEntered);
+       PRectangle rcPopupBounds = wMain.GetMonitorRect(pt);
 
        int heightLB = 100;
        int widthLB = 100;
@@ -241,18 +242,18 @@
        }
        PRectangle rcac;
        rcac.left = pt.x - ac.lb->CaretFromEdge();
-       if (pt.y >= rcClient.bottom - heightLB &&  // Wont fit below.
-               pt.y >= (rcClient.bottom + rcClient.top) / 2) { // and there is 
more room above.
+       if (pt.y >= rcPopupBounds.bottom - heightLB &&  // Wont fit below.
+               pt.y >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2) { // 
and there is more room above.
                rcac.top = pt.y - heightLB;
-               if (rcac.top < 0) {
-                       heightLB += rcac.top;
-                       rcac.top = 0;
+               if (rcac.top < rcPopupBounds.top) {
+                       heightLB -= (rcPopupBounds.top - rcac.top);
+                       rcac.top = rcPopupBounds.top;
                }
        } else {
                rcac.top = pt.y + vs.lineHeight;
        }
        rcac.right = rcac.left + widthLB;
-       rcac.bottom = Platform::Minimum(rcac.top + heightLB, rcClient.bottom);
+       rcac.bottom = Platform::Minimum(rcac.top + heightLB, 
rcPopupBounds.bottom);
        ac.lb->SetPositionRelative(rcac, wMain);
        ac.lb->SetFont(vs.styles[STYLE_DEFAULT].font);
        unsigned int aveCharWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
@@ -270,8 +271,8 @@
        // Make an allowance for large strings in list
        rcList.left = pt.x - ac.lb->CaretFromEdge();
        rcList.right = rcList.left + widthLB;
-       if (((pt.y + vs.lineHeight) >= (rcClient.bottom - heightAlloced)) &&  
// Wont fit below.
-               ((pt.y + vs.lineHeight / 2) >= (rcClient.bottom + rcClient.top) 
/ 2)) { // and there is more room above.
+       if (((pt.y + vs.lineHeight) >= (rcPopupBounds.bottom - heightAlloced)) 
&&  // Wont fit below.
+               ((pt.y + vs.lineHeight / 2) >= (rcPopupBounds.bottom + 
rcPopupBounds.top) / 2)) { // and there is more room above.
                rcList.top = pt.y - heightAlloced;
        } else {
                rcList.top = pt.y + vs.lineHeight;
_______________________________________________
Scintilla-interest mailing list
[email protected]
http://mailman.lyra.org/mailman/listinfo/scintilla-interest

Reply via email to