Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/gui/window.c

    r6d5e378 r2cc1ec0  
    3434 */
    3535
    36 #include <bool.h>
     36#include <stdbool.h>
    3737#include <errno.h>
    3838#include <stdio.h>
     
    5555#include <drawctx.h>
    5656#include <surface.h>
    57 
     57#include <font/embedded.h>
     58
     59#include "common.h"
    5860#include "connection.h"
    5961#include "widget.h"
    6062#include "window.h"
    6163
    62 static sysarg_t border_thickness = 5;
     64static sysarg_t border_thickness = 4;
     65static sysarg_t bevel_thickness = 1;
    6366static sysarg_t header_height = 20;
    6467static sysarg_t header_min_width = 40;
    65 static sysarg_t close_width = 20;
    66 
    67 static pixel_t border_color = PIXEL(255, 0, 0, 0);
    68 static pixel_t header_bgcolor = PIXEL(255, 25, 25, 112);
    69 static pixel_t header_fgcolor = PIXEL(255, 255, 255, 255);
    70 
    71 static void paint_internal(widget_t *w)
    72 {
    73         surface_t *surface = window_claim(w->window);
    74         if (!surface) {
    75                 window_yield(w->window);
    76         }
    77 
     68static sysarg_t close_thickness = 20;
     69
     70static pixel_t color_highlight = PIXEL(255, 255, 255, 255);
     71static pixel_t color_shadow = PIXEL(255, 85, 85, 85);
     72static pixel_t color_surface = PIXEL(255, 186, 186, 186);
     73
     74static pixel_t color_header_focus_highlight = PIXEL(255, 120, 145, 255);
     75static pixel_t color_header_focus_shadow = PIXEL(255, 40, 48, 89);
     76static pixel_t color_header_focus_surface = PIXEL(255, 88, 106, 196);
     77
     78static pixel_t color_header_unfocus_highlight = PIXEL(255, 16, 78, 126);
     79static pixel_t color_header_unfocus_shadow = PIXEL(255, 5, 26, 42);
     80static pixel_t color_header_unfocus_surface = PIXEL(255, 12, 57, 92);
     81
     82static pixel_t color_caption_focus = PIXEL(255, 255, 255, 255);
     83static pixel_t color_caption_unfocus = PIXEL(255, 207, 207, 207);
     84
     85static void paint_internal(widget_t *widget)
     86{
     87        surface_t *surface = window_claim(widget->window);
     88        if (!surface)
     89                window_yield(widget->window);
     90       
    7891        source_t source;
    79         font_t font;
     92        source_init(&source);
     93       
    8094        drawctx_t drawctx;
    81 
    82         source_init(&source);
    83         font_init(&font, FONT_DECODER_EMBEDDED, NULL, 16);
    8495        drawctx_init(&drawctx, surface);
    8596        drawctx_set_source(&drawctx, &source);
    86         drawctx_set_font(&drawctx, &font);
    87 
    88         source_set_color(&source, border_color);
    89         drawctx_transfer(&drawctx, w->hpos, w->vpos, border_thickness, w->height);
    90         drawctx_transfer(&drawctx, w->hpos + w->width - border_thickness,
    91             w->vpos, border_thickness, w->height);
    92         drawctx_transfer(&drawctx, w->hpos, w->vpos, w->width, border_thickness);
    93         drawctx_transfer(&drawctx, w->hpos,
    94             w->vpos + w->height - border_thickness, w->width, border_thickness);
    95 
    96         source_set_color(&source, header_bgcolor);
    97         drawctx_transfer(&drawctx,
    98             w->hpos + border_thickness, w->vpos + border_thickness,
    99                 w->width - 2 * border_thickness, header_height);
    100 
     97       
     98        /* Window border outer bevel */
     99       
     100        draw_bevel(&drawctx, &source, widget->vpos, widget->hpos,
     101            widget->width, widget->height, color_highlight, color_shadow);
     102       
     103        /* Window border surface */
     104       
     105        source_set_color(&source, color_surface);
     106        drawctx_transfer(&drawctx, widget->hpos + 1, widget->vpos + 1,
     107            widget->width - 2, 2);
     108        drawctx_transfer(&drawctx, widget->hpos + 1, widget->vpos + 1,
     109            2, widget->height - 2);
     110        drawctx_transfer(&drawctx, widget->hpos + 1,
     111            widget->vpos + widget->height - 3, widget->width - 2, 2);
     112        drawctx_transfer(&drawctx, widget->hpos + widget->width - 3,
     113            widget->vpos + 1, 2, widget->height - 4);
     114       
     115        /* Window border inner bevel */
     116       
     117        draw_bevel(&drawctx, &source, widget->hpos + 3, widget->vpos + 3,
     118            widget->width - 6, widget->height - 6, color_shadow,
     119            color_highlight);
     120       
     121        /* Header bevel */
     122       
     123        sysarg_t header_hpos = widget->hpos + border_thickness;
     124        sysarg_t header_vpos = widget->vpos + border_thickness;
     125        sysarg_t header_width = widget->width - 2 * border_thickness -
     126            close_thickness;
     127       
     128        draw_bevel(&drawctx, &source, header_hpos, header_vpos,
     129            header_width, header_height, widget->window->is_focused ?
     130            color_header_focus_highlight : color_header_unfocus_highlight,
     131            widget->window->is_focused ?
     132            color_header_focus_shadow : color_header_unfocus_shadow);
     133       
     134        /* Header surface */
     135       
     136        source_set_color(&source, widget->window->is_focused ?
     137            color_header_focus_surface : color_header_unfocus_surface);
     138        drawctx_transfer(&drawctx, header_hpos + 1, header_vpos + 1,
     139            header_width - 2, header_height - 2);
     140       
     141        /* Close button bevel */
     142       
     143        sysarg_t close_hpos = widget->hpos + widget->width -
     144            border_thickness - close_thickness;
     145        sysarg_t close_vpos = widget->vpos + border_thickness;
     146       
     147        draw_bevel(&drawctx, &source, close_hpos, close_vpos,
     148            close_thickness, close_thickness, color_highlight, color_shadow);
     149       
     150        /* Close button surface */
     151       
     152        source_set_color(&source, color_surface);
     153        drawctx_transfer(&drawctx, close_hpos + 1, close_vpos + 1,
     154            close_thickness - 2, close_thickness - 2);
     155       
     156        /* Close button icon */
     157       
     158        draw_icon_cross(surface, close_hpos + 3, close_vpos + 3,
     159            color_highlight, color_shadow);
     160       
     161        /* Window caption */
     162       
     163        font_t *font;
     164        int rc = embedded_font_create(&font, 16);
     165        if (rc != EOK) {
     166                window_yield(widget->window);
     167                return;
     168        }
     169       
     170        drawctx_set_font(&drawctx, font);
     171        source_set_color(&source, widget->window->is_focused ?
     172            color_caption_focus : color_caption_unfocus);
     173       
    101174        sysarg_t cpt_width;
    102175        sysarg_t cpt_height;
    103         font_get_box(&font, w->window->caption, &cpt_width, &cpt_height);
    104         sysarg_t cls_width;
    105         sysarg_t cls_height;
    106         char cls_pict[] = "x";
    107         font_get_box(&font, cls_pict, &cls_width, &cls_height);
    108         source_set_color(&source, header_fgcolor);
    109         sysarg_t cls_x = ((close_width - cls_width) / 2) + w->hpos + w->width -
    110             border_thickness - close_width;
    111         sysarg_t cls_y = ((header_height - cls_height) / 2) + w->vpos + border_thickness;
    112         drawctx_print(&drawctx, cls_pict, cls_x, cls_y);
    113 
    114         bool draw_title = (w->width >= 2 * border_thickness + close_width + cpt_width);
     176        font_get_box(font, widget->window->caption, &cpt_width, &cpt_height);
     177       
     178        bool draw_title =
     179            (widget->width >= 2 * border_thickness + 2 * bevel_thickness +
     180            close_thickness + cpt_width);
    115181        if (draw_title) {
    116                 sysarg_t cpt_x = ((w->width - cpt_width) / 2) + w->hpos;
    117                 sysarg_t cpt_y = ((header_height - cpt_height) / 2) + w->vpos + border_thickness;
    118                 if (w->window->caption) {
    119                         drawctx_print(&drawctx, w->window->caption, cpt_x, cpt_y);
    120                 }
    121         }
    122 
    123         font_release(&font);
    124         window_yield(w->window);
     182                sysarg_t cpt_x = ((widget->width - cpt_width) / 2) + widget->hpos;
     183                sysarg_t cpt_y = ((header_height - cpt_height) / 2) +
     184                    widget->vpos + border_thickness;
     185               
     186                if (widget->window->caption)
     187                        drawctx_print(&drawctx, widget->window->caption, cpt_x, cpt_y);
     188        }
     189       
     190        font_release(font);
     191        window_yield(widget->window);
    125192}
    126193
     
    133200{
    134201        if (widget->window->is_decorated) {
    135                 list_foreach(widget->children, link) {
    136                         widget_t *child = list_get_instance(link, widget_t, link);
    137                         child->rearrange(child,
     202                list_foreach(widget->children, link, widget_t, child) {
     203                        child->rearrange(child,
    138204                            widget->hpos + border_thickness,
    139205                            widget->vpos + border_thickness + header_height,
     
    142208                }
    143209        } else {
    144                 list_foreach(widget->children, link) {
    145                         widget_t *child = list_get_instance(link, widget_t, link);
     210                list_foreach(widget->children, link, widget_t, child) {
    146211                        child->rearrange(child, widget->hpos, widget->vpos,
    147212                            widget->width, widget->height);
     
    156221        if (widget->window->is_decorated) {
    157222                paint_internal(widget);
    158                 list_foreach(widget->children, link) {
    159                         widget_t *child = list_get_instance(link, widget_t, link);
     223                list_foreach(widget->children, link, widget_t, child) {
    160224                        child->rearrange(child,
    161225                            hpos + border_thickness,
     
    165229                }
    166230        } else {
    167                 list_foreach(widget->children, link) {
    168                         widget_t *child = list_get_instance(link, widget_t, link);
     231                list_foreach(widget->children, link, widget_t, child) {
    169232                        child->rearrange(child, hpos, vpos, width, height);
    170233                }
     
    177240                paint_internal(widget);
    178241        }
    179         list_foreach(widget->children, link) {
    180                 widget_t *child = list_get_instance(link, widget_t, link);
     242        list_foreach(widget->children, link, widget_t, child) {
    181243                child->repaint(child);
    182244        }
     
    212274                    (event.vpos >= border_thickness) &&
    213275                    (event.vpos < border_thickness + header_height);
    214                 bool close = header && (event.hpos >= width - border_thickness - close_width);
     276                bool close = (header) &&
     277                    (event.hpos >= width - border_thickness - close_thickness);
    215278
    216279                if (top && left && allowed_button) {
     
    264327                        win_grab(widget->window->osess, event.pos_id, flags);
    265328                } else {
    266                         list_foreach(widget->children, link) {
    267                                 widget_t *child = list_get_instance(link, widget_t, link);
     329                        list_foreach(widget->children, link, widget_t, child) {
    268330                                child->handle_position_event(child, event);
    269331                        }
    270332                }
    271333        } else {
    272                 list_foreach(widget->children, link) {
    273                         widget_t *child = list_get_instance(link, widget_t, link);
     334                list_foreach(widget->children, link, widget_t, child) {
    274335                        child->handle_position_event(child, event);
    275336                }
     
    295356}
    296357
    297 static void handle_signal_event(window_t *win, sig_event_t event)
     358static void handle_signal_event(window_t *win, signal_event_t event)
    298359{
    299360        widget_t *widget = (widget_t *) event.object;
     
    306367}
    307368
    308 static void handle_resize(window_t *win, sysarg_t width, sysarg_t height)
    309 {
    310         int rc;
    311         surface_t *old_surface;
    312         surface_t *new_surface;
    313 
     369static void handle_resize(window_t *win, sysarg_t offset_x, sysarg_t offset_y,
     370    sysarg_t width, sysarg_t height, window_placement_flags_t placement_flags)
     371{
    314372        if (width < 2 * border_thickness + header_min_width) {
    315373                win_damage(win->osess, 0, 0, 0, 0);
    316374                return;
    317375        }
    318 
     376       
    319377        if (height < 2 * border_thickness + header_height) {
    320378                win_damage(win->osess, 0, 0, 0, 0);
    321379                return;
    322380        }
    323 
     381       
    324382        /* Allocate resources for new surface. */
    325         new_surface = surface_create(width, height, NULL, SURFACE_FLAG_SHARED);
    326         if (!new_surface) {
     383        surface_t *new_surface = surface_create(width, height, NULL,
     384            SURFACE_FLAG_SHARED);
     385        if (!new_surface)
    327386                return;
    328         }
    329 
     387       
    330388        /* Switch new and old surface. */
    331389        fibril_mutex_lock(&win->guard);
    332         old_surface = win->surface;
     390        surface_t *old_surface = win->surface;
    333391        win->surface = new_surface;
    334392        fibril_mutex_unlock(&win->guard);
    335 
    336         /* Let all widgets in the tree alter their position and size. Widgets might
    337          * also paint themselves onto the new surface. */
     393       
     394        /*
     395         * Let all widgets in the tree alter their position and size.
     396         * Widgets might also paint themselves onto the new surface.
     397         */
    338398        win->root.rearrange(&win->root, 0, 0, width, height);
    339 
     399       
    340400        fibril_mutex_lock(&win->guard);
    341401        surface_reset_damaged_region(win->surface);
    342402        fibril_mutex_unlock(&win->guard);
    343 
     403       
    344404        /* Inform compositor about new surface. */
    345         rc = win_resize(win->osess,
    346                 width, height, surface_direct_access(new_surface));
    347 
     405        int rc = win_resize(win->osess, offset_x, offset_y, width, height,
     406            placement_flags, surface_direct_access(new_surface));
     407       
    348408        if (rc != EOK) {
    349409                /* Rollback to old surface. Reverse all changes. */
    350 
     410               
    351411                sysarg_t old_width = 0;
    352412                sysarg_t old_height = 0;
    353                 if (old_surface) {
     413                if (old_surface)
    354414                        surface_get_resolution(old_surface, &old_width, &old_height);
    355                 }
    356 
     415               
    357416                fibril_mutex_lock(&win->guard);
    358417                new_surface = win->surface;
    359418                win->surface = old_surface;
    360419                fibril_mutex_unlock(&win->guard);
    361 
     420               
    362421                win->root.rearrange(&win->root, 0, 0, old_width, old_height);
    363422               
     
    367426                        fibril_mutex_unlock(&win->guard);
    368427                }
    369 
     428               
    370429                surface_destroy(new_surface);
    371                 return;
    372         }
    373 
    374         /* Finally deallocate old surface. */
    375         if (old_surface) {
    376                 surface_destroy(old_surface);
     430        } else {
     431                /* Deallocate old surface. */
     432                if (old_surface)
     433                        surface_destroy(old_surface);
    377434        }
    378435}
     
    420477
    421478        while (!list_empty(&win->events.list)) {
    422                 list_remove(list_first(&win->events.list));
     479                window_event_t *event = (window_event_t *) list_first(&win->events.list);
     480                list_remove(&event->link);
     481                free(event);
    423482        }
    424483
     
    447506                        break;
    448507                case ET_POSITION_EVENT:
     508                        if (!win->is_focused) {
     509                                win->is_focused = true;
     510                                handle_refresh(win);
     511                        }
    449512                        deliver_position_event(win, event->data.pos);
    450513                        break;
    451514                case ET_SIGNAL_EVENT:
    452                         handle_signal_event(win, event->data.sig);
     515                        handle_signal_event(win, event->data.signal);
    453516                        break;
    454517                case ET_WINDOW_RESIZE:
    455                         handle_resize(win, event->data.rsz.width, event->data.rsz.height);
     518                        handle_resize(win, event->data.resize.offset_x,
     519                            event->data.resize.offset_y, event->data.resize.width,
     520                            event->data.resize.height, event->data.resize.placement_flags);
     521                        break;
     522                case ET_WINDOW_FOCUS:
     523                        if (!win->is_focused) {
     524                                win->is_focused = true;
     525                                handle_refresh(win);
     526                        }
     527                        break;
     528                case ET_WINDOW_UNFOCUS:
     529                        if (win->is_focused) {
     530                                win->is_focused = false;
     531                                handle_refresh(win);
     532                        }
    456533                        break;
    457534                case ET_WINDOW_REFRESH:
     
    514591}
    515592
    516 window_t *window_open(char *winreg, bool is_main, bool is_decorated, const char *caption)
    517 {
    518         int rc;
    519 
     593window_t *window_open(const char *winreg, bool is_main, bool is_decorated,
     594    const char *caption)
     595{
    520596        window_t *win = (window_t *) malloc(sizeof(window_t));
    521         if (!win) {
     597        if (!win)
    522598                return NULL;
    523         }
    524 
     599       
    525600        win->is_main = is_main;
    526601        win->is_decorated = is_decorated;
     602        win->is_focused = true;
    527603        prodcons_initialize(&win->events);
    528604        fibril_mutex_initialize(&win->guard);
     605       
    529606        widget_init(&win->root, NULL);
    530607        win->root.window = win;
     
    538615        win->focus = NULL;
    539616        win->surface = NULL;
    540 
     617       
    541618        service_id_t reg_dsid;
    542         async_sess_t *reg_sess;
    543 
    544         rc = loc_service_get_id(winreg, &reg_dsid, 0);
     619        int rc = loc_service_get_id(winreg, &reg_dsid, 0);
    545620        if (rc != EOK) {
    546621                free(win);
    547622                return NULL;
    548623        }
    549 
    550         reg_sess = loc_service_connect(EXCHANGE_SERIALIZE, reg_dsid, 0);
     624       
     625        async_sess_t *reg_sess = loc_service_connect(EXCHANGE_SERIALIZE,
     626            reg_dsid, 0);
    551627        if (reg_sess == NULL) {
    552628                free(win);
    553629                return NULL;
    554630        }
    555 
     631       
    556632        service_id_t in_dsid;
    557633        service_id_t out_dsid;
    558        
    559634        rc = win_register(reg_sess, &in_dsid, &out_dsid);
    560635        async_hangup(reg_sess);
     
    563638                return NULL;
    564639        }
    565 
     640       
    566641        win->osess = loc_service_connect(EXCHANGE_SERIALIZE, out_dsid, 0);
    567642        if (win->osess == NULL) {
     
    569644                return NULL;
    570645        }
    571 
     646       
    572647        win->isess = loc_service_connect(EXCHANGE_SERIALIZE, in_dsid, 0);
    573648        if (win->isess == NULL) {
     
    576651                return NULL;
    577652        }
    578 
    579         if (caption == NULL) {
     653       
     654        if (caption == NULL)
    580655                win->caption = NULL;
    581         } else {
     656        else
    582657                win->caption = str_dup(caption);
    583         }
    584 
     658       
    585659        return win;
    586660}
    587661
    588 void window_resize(window_t *win, sysarg_t width, sysarg_t height)
     662void window_resize(window_t *win, sysarg_t offset_x, sysarg_t offset_y,
     663    sysarg_t width, sysarg_t height, window_placement_flags_t placement_flags)
    589664{
    590665        window_event_t *event = (window_event_t *) malloc(sizeof(window_event_t));
     
    592667                link_initialize(&event->link);
    593668                event->type = ET_WINDOW_RESIZE;
    594                 event->data.rsz.width = width;
    595                 event->data.rsz.height = height;
     669                event->data.resize.offset_x = offset_x;
     670                event->data.resize.offset_y = offset_y;
     671                event->data.resize.width = width;
     672                event->data.resize.height = height;
     673                event->data.resize.placement_flags = placement_flags;
    596674                prodcons_produce(&win->events, &event->link);
    597675        }
Note: See TracChangeset for help on using the changeset viewer.