Ticket #5: 10-nd-improve-multihead-support.patch

  • src/daemon/stack.c

    old new  
    3737    GSList *windows; 
    3838}; 
    3939 
    40 static gboolean 
    41 get_work_area(GtkWidget *nw, GdkRectangle *rect) 
     40/* Retrieves the largest rectangle in src1 which does not intersect with src2 */ 
     41static void 
     42gdk_rectangle_largest_box (GdkRectangle *src1, 
     43               GdkRectangle *src2, 
     44               GdkRectangle *dest) 
    4245{ 
    43     Atom workarea = XInternAtom(GDK_DISPLAY(), "_NET_WORKAREA", True); 
    44     Atom type; 
    45     Window win; 
    46     int format; 
    47     gulong num, leftovers; 
    48     gulong max_len = 4 * 32; 
    49     guchar *ret_workarea; 
    50     long *workareas; 
    51     int result; 
    52     GdkScreen *screen; 
    53     int disp_screen; 
     46    gint t_h = MAX(src2->y,src1->y); 
     47    gint l_w = MAX(src2->x,src1->x); 
     48    gint b_h = MAX(src2->height, src1->height) - 
     49           MIN(src2->y + src2->height, src1->y + src1->height); 
     50    gint r_w = MAX(src2->width, src1->width) -  
     51           MIN(src2->x + src2->width, src1->x + src1->width);    
     52    gint m_h = MAX(t_h,b_h); 
     53    gint m_w = MAX(l_w,r_w); 
    5454 
    55     gtk_widget_realize(nw); 
    56     screen = gdk_drawable_get_screen(GDK_DRAWABLE(nw->window)); 
    57     disp_screen = GDK_SCREEN_XNUMBER(screen); 
     55    /* height is largest */ 
     56    if(m_h >= m_w) 
     57    { 
     58        if(t_h >= b_h) 
     59        { 
     60            dest->x = src1->x; 
     61            dest->y = src1->y; 
     62            dest->width = src1->width; 
     63            dest->height = t_h + MIN(0,b_h); 
     64        } 
     65        else 
     66        { 
     67            dest->x = src1->x; 
     68            dest->y = src2->y + src2->height; 
     69            dest->width = src1->width; 
     70            dest->height = b_h + MIN(0,t_h); 
     71        } 
     72    } 
     73    /* width is largest */ 
     74    else 
     75    { 
     76        if(l_w >= r_w) 
     77        { 
     78            dest->x = src1->x; 
     79            dest->y = src1->y; 
     80            dest->width = m_w + MIN(0,r_w); 
     81            dest->height = src1->height; 
     82        } 
     83        else 
     84        { 
     85            dest->x = src2->x + src2->width; 
     86            dest->y = src1->y; 
     87            dest->width = m_w + MIN(0,l_w);          
     88            dest->height = src1->height; 
     89        } 
     90    } 
     91
    5892 
    59     /* Defaults in case of error */ 
    60     rect->x = 0; 
    61     rect->y = 0; 
    62     rect->width = gdk_screen_get_width(screen); 
    63     rect->height = gdk_screen_get_height(screen); 
     93static void translate_origin (GdkRectangle* src1, gint xoffset, gint yoffset) 
     94
     95    src1->x += xoffset; src1->y += yoffset; 
     96
    6497 
     98/* Returns the workarea (largest non-panel/dock occupied rectangle) for a given 
     99   monitor. */ 
     100static gboolean 
     101gdk_screen_get_monitor_workarea(GdkScreen *screen, 
     102                guint monitor_num, 
     103                GdkRectangle *workarea) 
     104{ 
     105    GdkDisplay *display; 
     106    Display *xdisplay; 
     107    Atom wintype_atom, docktype_atom, actual; 
     108    Window xrootwin; 
     109    Window ignored1, ignored2; 
     110    Window *children; 
     111    guint n_children, i; 
     112    int result, format; 
     113    gulong n, left; 
     114    guchar *data; 
     115    XWindowAttributes attrs; 
     116    gboolean is_dock; 
     117    GdkRectangle dockwin_geometry, intersection; 
     118    gint monitor_xoff, monitor_yoff; 
     119 
     120    /* Defaults */ 
     121    gdk_screen_get_monitor_geometry(screen, monitor_num, workarea); 
     122     
    65123    if (workarea == None) 
    66124        return FALSE; 
    67125 
    68     win = XRootWindow(GDK_DISPLAY(), disp_screen); 
    69     result = XGetWindowProperty(GDK_DISPLAY(), win, workarea, 0, 
    70                                 max_len, False, AnyPropertyType, 
    71                                 &type, &format, &num, &leftovers, 
    72                                 &ret_workarea); 
     126    display = gdk_screen_get_display(screen); 
     127    xdisplay = GDK_DISPLAY_XDISPLAY(display); 
    73128 
    74     if (result != Success || type == None || format == 0 || leftovers || 
    75         num % 4) 
    76     { 
    77         return FALSE; 
    78     } 
     129    /* GDK uses cache; thus this is supposingly faster than XInternAtom */ 
     130    wintype_atom = gdk_x11_get_xatom_by_name_for_display(display, 
     131                            "_NET_WM_WINDOW_TYPE"); 
     132    docktype_atom = gdk_x11_get_xatom_by_name_for_display(display, 
     133                           "_NET_WM_WINDOW_TYPE_DOCK"); 
    79134 
    80     workareas = (long *)ret_workarea; 
    81     rect->x      = workareas[disp_screen * 4]; 
    82     rect->y      = workareas[disp_screen * 4 + 1]; 
    83     rect->width  = workareas[disp_screen * 4 + 2]; 
    84     rect->height = workareas[disp_screen * 4 + 3]; 
     135    xrootwin = XRootWindow(xdisplay, GDK_SCREEN_XNUMBER(screen)); 
    85136 
    86     XFree(ret_workarea); 
     137    /* Get all windows! */ 
     138    XQueryTree(xdisplay, xrootwin, &ignored1, &ignored2, &children, &n_children); 
    87139 
     140    monitor_xoff = workarea->x; 
     141    monitor_yoff = workarea->y; 
     142     
     143    for (i = 0; i < n_children; i++) 
     144    {    
     145        result = XGetWindowProperty(xdisplay, children[i], 
     146                wintype_atom, 0L, 1L, FALSE, XA_ATOM, 
     147                &actual, &format, &n, &left, &data); 
     148 
     149        if (result != Success || actual == None || 
     150            format == 0 || left || n == 0) 
     151            continue; 
     152 
     153        /* Check for _NET_WM_WINDOW_TYPE_DOCK type */        
     154        is_dock = False; 
     155 
     156        if (*((Atom *)data) == docktype_atom) 
     157            is_dock = True; 
     158 
     159        XFree ((void *) data); 
     160 
     161        if (is_dock == False) 
     162            continue; 
     163 
     164        /* Get frame extents of the window  */   
     165        XGetWindowAttributes (xdisplay, children[i], &attrs); 
     166 
     167        dockwin_geometry.x = attrs.x; 
     168        dockwin_geometry.y = attrs.y; 
     169        dockwin_geometry.width = attrs.width; 
     170        dockwin_geometry.height = attrs.height; 
     171 
     172        /* Check if it intersects with the monitor frame */ 
     173        if (gdk_rectangle_intersect(workarea, &dockwin_geometry, &intersection) == TRUE) 
     174        {        
     175            /* Substract frame from monitor frame */ 
     176            translate_origin(workarea, -monitor_xoff, -monitor_yoff); 
     177            translate_origin(&intersection, -monitor_xoff, -monitor_yoff); 
     178             
     179            gdk_rectangle_largest_box (workarea, &intersection, workarea); 
     180             
     181            translate_origin(workarea, monitor_xoff, monitor_yoff); 
     182            translate_origin(&intersection, monitor_xoff, monitor_yoff); 
     183        } 
     184    } 
     185 
     186    if (children) 
     187        XFree (children); 
     188     
    88189    return TRUE; 
    89190} 
    90191 
     
    209310    GSList *l; 
    210311    gint x, y, shiftx = 0, shifty = 0, index = 1; 
    211312 
    212     get_work_area(GTK_WIDGET(nw), &workarea); 
     313    gtk_widget_realize(GTK_WIDGET(nw)); 
     314 
     315    gdk_screen_get_monitor_workarea(stack->screen, stack->monitor, &workarea); 
    213316    get_origin_coordinates(stack->location, &workarea, &x, &y, 
    214317                           &shiftx, &shifty, init_width, init_height); 
    215318