Mercurial > dwindows
diff gtk/dw.c @ 1469:b9efb744cfbd
Second try and window positioning for GTK2 and port to GTK3.
Added dw_window_set_gravity() for GTK3.
Switched to requesting the frame extents property directly from the
window manager if the window isn't mapped... if the property isn't
supported guess using the old values we had been using.
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Tue, 20 Dec 2011 12:44:41 +0000 |
parents | b2235efd9914 |
children | a317c2ec1d4c |
line wrap: on
line diff
--- a/gtk/dw.c Mon Dec 19 13:16:34 2011 +0000 +++ b/gtk/dw.c Tue Dec 20 12:44:41 2011 +0000 @@ -10105,6 +10105,73 @@ _dw_box_pack(box, item, 0, width, height, hsize, vsize, pad, "dw_box_pack_end()"); } +union extents_union { guchar **gu_extents; unsigned long **extents; }; +static Atom extents_atom = 0; + +static Bool property_notify_predicate(Display *xdisplay, XEvent *event, XPointer window_id) +{ + unsigned long *window = (unsigned long *)window_id; + + if(event->xany.type == PropertyNotify && event->xany.window == *window && event->xproperty.atom == extents_atom) + return True; + return False; +} + +/* Internal function to figure out the frame extents of an unmapped window */ +void _dw_get_frame_extents(GtkWidget *window, int *vert, int *horz) +{ + const char *request = "_NET_REQUEST_FRAME_EXTENTS"; + unsigned long *extents = NULL; + union extents_union eu; + GdkAtom request_extents = gdk_atom_intern(request, FALSE); + + /* Set some rational defaults.. just in case */ + *vert = 28; + *horz = 12; + + /* See if the current window manager supports _NET_REQUEST_FRAME_EXTENTS */ + if(gdk_net_wm_supports(request_extents)) + { + GdkDisplay *display = gtk_widget_get_display(window); + Display *xdisplay = GDK_DISPLAY_XDISPLAY(display); + GdkWindow *root_window = gdk_get_default_root_window(); + Window xroot_window = GDK_WINDOW_XID(root_window); + Atom extents_request_atom = gdk_x11_get_xatom_by_name_for_display(display, request); + unsigned long window_id = GDK_WINDOW_XID(GDK_DRAWABLE(window->window)); + XEvent notify_xevent, xevent = {0}; + + if(!extents_atom) + { + const char *extents_name = "_NET_FRAME_EXTENTS"; + extents_atom = gdk_x11_get_xatom_by_name_for_display(display, extents_name); + } + + xevent.xclient.type = ClientMessage; + xevent.xclient.message_type = extents_request_atom; + xevent.xclient.display = xdisplay; + xevent.xclient.window = window_id; + xevent.xclient.format = 32; + + XSendEvent(xdisplay, xroot_window, False, + (SubstructureRedirectMask | SubstructureNotifyMask), + &xevent); + + XIfEvent(xdisplay, ¬ify_xevent, property_notify_predicate, (XPointer)&window_id); + } + + /* Attempt to retrieve window's frame extents. */ + eu.extents = &extents; + if(gdk_property_get(window->window, + gdk_atom_intern("_NET_FRAME_EXTENTS", FALSE), + gdk_atom_intern("CARDINAL", FALSE), + 0, sizeof(unsigned long)*4, FALSE, + NULL, NULL, NULL, eu.gu_extents)) + { + *horz = extents[0] + extents[1]; + *vert = extents[2] + extents[3]; + } +} + /* * Sets the size of a given window (widget). * Parameters: @@ -10115,7 +10182,6 @@ void dw_window_set_size(HWND handle, unsigned long width, unsigned long height) { int _locked_by_me = FALSE; - int cx = 0, cy = 0; if(!handle) return; @@ -10123,11 +10189,13 @@ DW_MUTEX_LOCK; if(GTK_IS_WINDOW(handle)) { + int cx = 0, cy = 0; + #ifdef GDK_WINDOWING_X11 _size_allocate(GTK_WINDOW(handle)); #endif - /* If the window is realized */ - if(handle->window && gdk_window_is_visible(handle->window)) + /* If the window is mapped */ + if(handle->window && GTK_WIDGET_MAPPED(handle)) { #if GTK_MAJOR_VERSION > 1 GdkRectangle frame; @@ -10144,15 +10212,27 @@ if(cy < 0) cy = 0; #endif - /* Resize minus the border size */ - gdk_window_resize(handle->window, width - cx , height - cy ); - } - if(!cx && !cy) - { + } + else + { + /* Check if we have cached frame size values */ + if(!((cx = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(handle), "_dw_frame_width"))) | + (cy = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(handle), "_dw_frame_height"))))) + { + /* If not try to ask the window manager for the estimated size... + * and finally if all else fails, guess. + */ + _dw_get_frame_extents(handle, &cy, &cx); + /* Cache values for later use */ + gtk_object_set_data(GTK_OBJECT(handle), "_dw_frame_width", GINT_TO_POINTER(cx)); + gtk_object_set_data(GTK_OBJECT(handle), "_dw_frame_height", GINT_TO_POINTER(cy)); + } /* Save the size for when it is shown */ gtk_object_set_data(GTK_OBJECT(handle), "_dw_width", GINT_TO_POINTER(width)); gtk_object_set_data(GTK_OBJECT(handle), "_dw_height", GINT_TO_POINTER(height)); } + /* Resize minus the border size */ + gdk_window_resize(handle->window, width - cx , height - cy ); gtk_window_set_default_size(GTK_WINDOW(handle), width - cx, height - cy ); } else @@ -10263,52 +10343,82 @@ else #endif { - GdkWindow *window = NULL; - if(GTK_IS_WINDOW(handle)) { #if GTK_MAJOR_VERSION > 1 - /* If the window is visible */ - if(handle->window && gdk_window_is_visible(handle->window)) + int horz = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(handle), "_dw_grav_horz")); + int vert = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(handle), "_dw_grav_vert")); + int newx = x, newy = y, width = 0, height = 0; + + /* If the window is mapped */ + if(handle->window && GTK_WIDGET_MAPPED(handle)) { - int horz = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(handle), "_dw_grav_horz")); - int vert = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(handle), "_dw_grav_vert")); - int newx = x, newy = y; - + /* If we need the width or height... */ if(horz || vert) { GdkRectangle frame; /* Get the frame size */ gdk_window_get_frame_extents(handle->window, &frame); - - /* Handle horizontal center gravity */ - if((horz & 0xf) == DW_GRAV_CENTER) - newx += ((gdk_screen_width() / 2) - (frame.width / 2)); - /* Handle right gravity */ - else if((horz & 0xf) == DW_GRAV_RIGHT) - newx = gdk_screen_width() - frame.width - x; - /* Handle vertical center gravity */ - if((vert & 0xf) == DW_GRAV_CENTER) - newy += ((gdk_screen_height() / 2) - (frame.height / 2)); - else if((vert & 0xf) == DW_GRAV_BOTTOM) - newy = gdk_screen_height() - frame.height - x; - } - gtk_window_move(GTK_WINDOW(handle), newx, newy); + width = frame.width; + height = frame.height; + } } else { + int cx , cy; + + /* Check if we have cached frame size values */ + if(!((cx = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(handle), "_dw_frame_width"))) | + (cy = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(handle), "_dw_frame_height"))))) + { + /* If not try to ask the window manager for the estimated size... + * and finally if all else fails, guess. + */ + _dw_get_frame_extents(handle, &cy, &cx); + /* Cache values for later use */ + gtk_object_set_data(GTK_OBJECT(handle), "_dw_frame_width", GINT_TO_POINTER(cx)); + gtk_object_set_data(GTK_OBJECT(handle), "_dw_frame_height", GINT_TO_POINTER(cy)); + } /* Save the positions for when it is shown */ gtk_object_set_data(GTK_OBJECT(handle), "_dw_x", GINT_TO_POINTER(x)); gtk_object_set_data(GTK_OBJECT(handle), "_dw_y", GINT_TO_POINTER(y)); gtk_object_set_data(GTK_OBJECT(handle), "_dw_pos", GINT_TO_POINTER(1)); + /* Check to see if there is a pending size request too */ + width = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(handle), "_dw_width")); + height = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(handle), "_dw_height")); + if(width | height) + { + /* Ask what GTK is planning on suggesting for the window size */ + gtk_window_get_size(GTK_WINDOW(handle), !width ? &width : NULL, !height ? &height : NULL); + } + /* Add the frame size to it */ + width += cx; + height += cy; } + /* Do any gravity calculations */ + if(horz || vert) + { + /* Handle horizontal center gravity */ + if((horz & 0xf) == DW_GRAV_CENTER) + newx += ((gdk_screen_width() / 2) - (width / 2)); + /* Handle right gravity */ + else if((horz & 0xf) == DW_GRAV_RIGHT) + newx = gdk_screen_width() - width - x; + /* Handle vertical center gravity */ + if((vert & 0xf) == DW_GRAV_CENTER) + newy += ((gdk_screen_height() / 2) - (height / 2)); + else if((vert & 0xf) == DW_GRAV_BOTTOM) + newy = gdk_screen_height() - height - x; + } + /* Finally move the window into place */ + gtk_window_move(GTK_WINDOW(handle), newx, newy); #else gtk_widget_set_uposition(handle, x, y); #endif } - else if((window = gtk_widget_get_window(handle))) - gdk_window_move(window, x, y); + else if(handle->window) + gdk_window_move(handle->window, x, y); } DW_MUTEX_UNLOCK; }