forked from KolibriOS/kolibrios
fcddd916db
git-svn-id: svn://kolibrios.org@3248 a494cfbc-eb01-0410-851d-a64ba20cac60
640 lines
14 KiB
C
640 lines
14 KiB
C
|
|
|
|
#include "system.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include "winlib.h"
|
|
|
|
int draw_frame(window_t *win);
|
|
static int draw_window(window_t *win);
|
|
|
|
uint32_t main_cursor;
|
|
uint32_t cursor_ns;
|
|
uint32_t cursor_we;
|
|
uint32_t cursor_nwse;
|
|
uint32_t cursor_nesw;
|
|
|
|
int win_font;
|
|
|
|
|
|
static pos_t old_pos;
|
|
|
|
ctrl_t *mouse_capture = NULL;
|
|
|
|
static link_t timers;
|
|
static uint32_t realtime;
|
|
static uint32_t wait_time;
|
|
static uint32_t exp_time;
|
|
|
|
static int need_update;
|
|
|
|
#define LOAD_FROM_MEM 1
|
|
|
|
|
|
void adjust_frame(window_t *win);
|
|
|
|
|
|
#include "control.inc"
|
|
//#include "io.inc"
|
|
#include "timer.inc"
|
|
|
|
//#include "button.inc"
|
|
//#include "scroller.inc"
|
|
|
|
static window_t Window;
|
|
|
|
|
|
|
|
void init_frame(window_t *win);
|
|
|
|
window_t *create_window(char *caption, int style, int x, int y,
|
|
int w, int h, handler_t handler)
|
|
{
|
|
int stride;
|
|
ctx_t *ctx = &Window.client_ctx;
|
|
|
|
if(handler==0) return 0;
|
|
|
|
Window.handler = handler;
|
|
Window.ctx = ctx;
|
|
|
|
list_initialize(&Window.link);
|
|
list_initialize(&Window.child);
|
|
|
|
|
|
Window.bitmap.width = 1920;
|
|
Window.bitmap.height = 1080;
|
|
Window.bitmap.flags = 0;
|
|
|
|
if( create_bitmap(&Window.bitmap) )
|
|
{
|
|
printf("not enough memory for window bitmap\n");
|
|
return 0;
|
|
}
|
|
|
|
ctx->pixmap = &Window.bitmap;
|
|
ctx->offset_x = 0;
|
|
ctx->offset_y = 0;
|
|
|
|
Window.rc.l = x;
|
|
Window.rc.t = y;
|
|
Window.rc.r = x + w;
|
|
Window.rc.b = y + h;
|
|
|
|
Window.w = w;
|
|
Window.h = h;
|
|
|
|
Window.caption_txt = caption;
|
|
Window.style = style;
|
|
|
|
Window.child_over = NULL;
|
|
Window.child_focus = NULL;
|
|
|
|
init_caption(&Window);
|
|
init_panel(&Window);
|
|
init_frame(&Window);
|
|
send_message((ctrl_t*)&Window, MSG_SIZE, 0, 0);
|
|
return &Window;
|
|
};
|
|
|
|
|
|
int def_window_proc(ctrl_t *ctrl, uint32_t msg, uint32_t arg1, uint32_t arg2)
|
|
{
|
|
ctrl_t *child;
|
|
|
|
window_t *win = (window_t*)ctrl;
|
|
|
|
switch(msg)
|
|
{
|
|
case MSG_PAINT:
|
|
draw_window(win);
|
|
break;
|
|
|
|
case 2:
|
|
child = (ctrl_t*)win->child.next;
|
|
while( &child->link != &win->child)
|
|
{
|
|
send_message(child, 2, arg1, arg2);
|
|
child = (ctrl_t*)child->link.next;
|
|
};
|
|
break;
|
|
|
|
case MSG_MOUSEMOVE:
|
|
child = win_get_child(win, arg2 & 0xFFFF, (arg2>>16));
|
|
if( win->child_over )
|
|
{
|
|
if(child == win->child_over)
|
|
send_message(child, msg, 0, arg2);
|
|
else
|
|
send_message(win->child_over, MSG_MOUSELEAVE, 0, arg2);
|
|
}
|
|
else if( child )
|
|
send_message(child, MSG_MOUSEENTER, 0, arg2);
|
|
|
|
win->child_over = child;
|
|
if( child )
|
|
send_message(child,msg,0,arg2);
|
|
else if(main_cursor != 0)
|
|
{
|
|
set_cursor(0);
|
|
main_cursor = 0;
|
|
}
|
|
break;
|
|
|
|
case MSG_SIZE:
|
|
break;
|
|
|
|
default:
|
|
child = win_get_child(win, arg2 & 0xFFFF, (arg2>>16));
|
|
win->child_over = child;
|
|
if(child) send_message(child, msg, 0, arg2);
|
|
};
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int draw_window(window_t *win)
|
|
{
|
|
ctrl_t *child;
|
|
void *ctx;
|
|
rect_t *rc = &win->client;
|
|
|
|
draw_caption(&win->caption);
|
|
draw_panel(&win->panel);
|
|
|
|
// draw_frame(win);
|
|
|
|
// child = (ctrl_t*)win->child.next;
|
|
|
|
// while( &child->link != &win->child)
|
|
// {
|
|
// send_message(child, 1, 0, 0);
|
|
// child = (ctrl_t*)child->link.next;
|
|
// };
|
|
|
|
return 0;
|
|
};
|
|
|
|
void blit_client(window_t *win)
|
|
{
|
|
int w, h;
|
|
|
|
w = win->client.r - win->client.l;
|
|
h = win->client.b - win->client.t;
|
|
|
|
Blit(win->ctx->pixmap->data, win->client.l, win->client.t,
|
|
0, 0, w, h, w, h,win->ctx->pixmap->pitch);
|
|
};
|
|
|
|
|
|
int show_window(window_t *win, int state)
|
|
{
|
|
win->win_state = state;
|
|
|
|
draw_window(win);
|
|
|
|
BeginDraw();
|
|
DrawWindow(win->rc.l, win->rc.t, win->w-1, win->h-1,
|
|
NULL,0,0x41);
|
|
EndDraw();
|
|
|
|
blit_caption(&win->caption);
|
|
blit_panel(&win->panel);
|
|
// blit_client(win);
|
|
return 0;
|
|
}
|
|
|
|
void window_update_layout(window_t *win)
|
|
{
|
|
char proc_info[1024];
|
|
|
|
int new_w, new_h;
|
|
uint8_t state;
|
|
|
|
int winx, winy, winw, winh;
|
|
|
|
// __asm__ __volatile__("int3");
|
|
|
|
get_proc_info(proc_info);
|
|
|
|
winx = *(uint32_t*)(proc_info+34);
|
|
winy = *(uint32_t*)(proc_info+38);
|
|
winw = *(uint32_t*)(proc_info+42)+1;
|
|
winh = *(uint32_t*)(proc_info+46)+1;
|
|
|
|
state = *(uint8_t*)(proc_info+70);
|
|
|
|
if(state & 2)
|
|
{ win->win_state = MINIMIZED;
|
|
return;
|
|
}
|
|
if(state & 4)
|
|
{
|
|
win->win_state = ROLLED;
|
|
return;
|
|
};
|
|
|
|
if(state & 1)
|
|
win->win_state = MAXIMIZED;
|
|
else
|
|
win->win_state = NORMAL;
|
|
|
|
if( (winx != win->rc.l) || (winy != win->rc.t) )
|
|
{
|
|
win->rc.l = winx;
|
|
win->rc.t = winy;
|
|
win->rc.r = winx + win->w;
|
|
win->rc.b = winy + win->h;
|
|
};
|
|
|
|
if( winw == win->w &&
|
|
winh == win->h)
|
|
return;
|
|
|
|
int old_size;
|
|
int new_size;
|
|
int pitch;
|
|
|
|
|
|
old_size = win->bitmap.pitch * win->bitmap.height;
|
|
old_size = (old_size+4095) & ~4095;
|
|
|
|
pitch = ALIGN(win->w*4, 16);
|
|
|
|
new_size = pitch * win->h;
|
|
new_size = (new_size+4095) & ~4095;
|
|
|
|
if( new_size < old_size)
|
|
user_unmap(win->bitmap.data, new_size, old_size-new_size);
|
|
|
|
win->bitmap.width = win->w;
|
|
win->bitmap.pitch = pitch;
|
|
|
|
win->rc.r = winx + winw;
|
|
win->rc.b = winy + winh;
|
|
win->w = winw;
|
|
win->h = winh;
|
|
|
|
update_caption_size(win);
|
|
update_panel_size(win);
|
|
adjust_frame(win);
|
|
|
|
send_message((ctrl_t*)win, MSG_SIZE, 0, 0);
|
|
draw_window(win);
|
|
};
|
|
|
|
|
|
int send_mouse_message(window_t *win, uint32_t msg)
|
|
{
|
|
ctrl_t *child;
|
|
|
|
if(mouse_capture)
|
|
return send_message(mouse_capture, msg, 0, old_pos.val);
|
|
|
|
if(pt_in_rect(&win->caption.ctrl.rc, old_pos.x, old_pos.y))
|
|
{
|
|
return send_message(&win->caption.ctrl, msg, 0, old_pos.val);
|
|
}
|
|
|
|
if(pt_in_rect(&win->panel.ctrl.rc, old_pos.x, old_pos.y))
|
|
{
|
|
// old_pos.x-= win->panel.ctrl.rc.l;
|
|
// old_pos.y-= win->panel.ctrl.rc.t;
|
|
return send_message(&win->panel.ctrl, msg, 0, old_pos.val);
|
|
}
|
|
|
|
if(pt_in_rect(&win->client, old_pos.x, old_pos.y))
|
|
return send_message((ctrl_t*)win, msg, 0, old_pos.val);
|
|
|
|
return send_message(&win->frame, msg, 0, old_pos .val);
|
|
|
|
// if( ( old_pos.x < win->rc.r) && ( old_pos.y < win->rc.b))
|
|
// send_message((ctrl_t*)win, msg, 0, old_pos.val);
|
|
};
|
|
|
|
void do_sys_draw(window_t *win)
|
|
{
|
|
// printf("%s win:%x\n", __FUNCTION__, win);
|
|
|
|
window_update_layout(win);
|
|
|
|
BeginDraw();
|
|
DrawWindow(0,0,0,0, NULL, 0x000000,0x41);
|
|
EndDraw();
|
|
|
|
blit_caption(&win->caption);
|
|
blit_panel(&win->panel);
|
|
|
|
// blit_client(win);
|
|
send_message((ctrl_t*)win, MSG_DRAW_CLIENT, 0, 0);
|
|
need_update=0;
|
|
};
|
|
|
|
static void do_sys_mouse(window_t *win)
|
|
{
|
|
static uint32_t mouse_click_time;
|
|
static int mouse_action;
|
|
static int old_buttons;
|
|
int buttons;
|
|
uint32_t wheels;
|
|
uint32_t click_time;
|
|
int action;
|
|
|
|
pos_t pos;
|
|
|
|
mouse_action = 0;
|
|
pos = get_mouse_pos();
|
|
|
|
if(pos.val != old_pos.val)
|
|
{
|
|
mouse_action = 0x80000000;
|
|
old_pos = pos;
|
|
};
|
|
// printf("pos x%d y%d\n", pos.x, pos.y);
|
|
|
|
buttons = get_mouse_buttons();
|
|
wheels = get_mouse_wheels();
|
|
|
|
if( wheels & 0xFFFF){
|
|
wheels = (short)wheels>0 ? MSG_WHEELDOWN : MSG_WHEELUP;
|
|
send_mouse_message(win, wheels);
|
|
}
|
|
|
|
if((action = (buttons ^ old_buttons))!=0)
|
|
{
|
|
mouse_action|= action<<3;
|
|
mouse_action|= buttons & ~old_buttons;
|
|
}
|
|
old_buttons = buttons;
|
|
|
|
if(mouse_action & 0x80000000) {
|
|
DBG("mouse move \n\r");
|
|
send_mouse_message(win, MSG_MOUSEMOVE);
|
|
};
|
|
|
|
if(mouse_action & 0x09)
|
|
{
|
|
if((mouse_action & 0x09)==0x09)
|
|
{
|
|
// printf("left button down x= %d y= %d\n\r", old_x.x, old_x.y);
|
|
click_time = get_tick_count();
|
|
if(click_time < mouse_click_time+35) {
|
|
mouse_click_time = click_time;
|
|
send_mouse_message(win,MSG_LBTNDBLCLK);
|
|
}
|
|
else {
|
|
mouse_click_time = click_time;
|
|
send_mouse_message(win,MSG_LBTNDOWN);
|
|
};
|
|
}
|
|
else {
|
|
// printf("left button up \n\r");
|
|
send_mouse_message(win,MSG_LBTNUP);
|
|
}
|
|
};
|
|
|
|
if(mouse_action & 0x12)
|
|
{
|
|
if((mouse_action & 0x12)==0x12) {
|
|
DBG("right button down \n\r");
|
|
send_mouse_message(win,MSG_RBTNDOWN);
|
|
}
|
|
else {
|
|
DBG("right button up \n\r");
|
|
send_mouse_message(win,MSG_RBTNUP);
|
|
};
|
|
};
|
|
if(mouse_action & 0x24)
|
|
{
|
|
if((mouse_action & 0x24)==0x24){
|
|
DBG("middle button down \n\r");
|
|
send_mouse_message(win,MSG_MBTNDOWN);
|
|
}
|
|
else {
|
|
DBG("middle button up \n\r");
|
|
send_mouse_message(win,MSG_MBTNUP);
|
|
};
|
|
};
|
|
|
|
|
|
};
|
|
|
|
|
|
void run_window(window_t *win)
|
|
{
|
|
int ev;
|
|
oskey_t key;
|
|
|
|
// buttons = get_mouse_buttons();
|
|
// wheels = get_mouse_wheels();
|
|
realtime = get_tick_count();
|
|
exp_time = -1;
|
|
|
|
while(1)
|
|
{
|
|
wait_time = exp_time - realtime;
|
|
|
|
ev = wait_for_event(wait_time);
|
|
|
|
realtime = get_tick_count();
|
|
|
|
// if(exp_time < realtime)
|
|
// exp_time = update_timers(realtime);
|
|
|
|
switch(ev)
|
|
{
|
|
case MSG_PAINT:
|
|
do_sys_draw(win);
|
|
continue;
|
|
|
|
case 2:
|
|
key = get_key();
|
|
if( key.state == 0)
|
|
send_message((ctrl_t*)win, ev, 0, key.code);
|
|
continue;
|
|
|
|
case 6:
|
|
do_sys_mouse(win);
|
|
continue;
|
|
|
|
default:
|
|
continue;
|
|
};
|
|
};
|
|
}
|
|
|
|
void render_time(void *render);
|
|
|
|
void run_render(window_t *win, void *render)
|
|
{
|
|
int ev;
|
|
oskey_t key;
|
|
|
|
realtime = get_tick_count();
|
|
exp_time = -1;
|
|
|
|
while(win->win_command != WIN_CLOSED)
|
|
{
|
|
wait_time = exp_time - realtime;
|
|
|
|
ev = check_os_event();
|
|
|
|
realtime = get_tick_count();
|
|
|
|
// if(exp_time < realtime)
|
|
// exp_time = update_timers(realtime);
|
|
|
|
switch(ev)
|
|
{
|
|
case MSG_PAINT:
|
|
do_sys_draw(win);
|
|
break;
|
|
|
|
case 2:
|
|
key = get_key();
|
|
if( key.state == 0)
|
|
send_message((ctrl_t*)win, ev, 0, key.code);
|
|
break;
|
|
|
|
case 6:
|
|
do_sys_mouse(win);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
};
|
|
|
|
render_time(render);
|
|
};
|
|
};
|
|
|
|
|
|
|
|
extern unsigned char res_cursor_ns[];
|
|
extern unsigned char res_cursor_we[];
|
|
extern unsigned char res_cursor_nwse[];
|
|
extern unsigned char res_cursor_nesw[];
|
|
|
|
int init_resources()
|
|
{
|
|
cursor_ns = load_cursor(res_cursor_ns, LOAD_FROM_MEM);
|
|
cursor_we = load_cursor(res_cursor_we, LOAD_FROM_MEM);
|
|
cursor_nwse = load_cursor(res_cursor_nwse, LOAD_FROM_MEM);
|
|
cursor_nesw = load_cursor(res_cursor_nesw, LOAD_FROM_MEM);
|
|
|
|
win_font = init_fontlib();
|
|
|
|
return 1;
|
|
}
|
|
|
|
int fini_winlib()
|
|
{
|
|
int ret;
|
|
|
|
ret = destroy_cursor(cursor_nesw);
|
|
ret |= destroy_cursor(cursor_nwse);
|
|
ret |= destroy_cursor(cursor_we);
|
|
ret |= destroy_cursor(cursor_ns);
|
|
|
|
return ret;
|
|
};
|
|
|
|
|
|
|
|
void init_winlib(void)
|
|
{
|
|
__asm__ __volatile__(
|
|
"int $0x40"
|
|
::"a"(40), "b"(0xC0000027));
|
|
|
|
init_resources();
|
|
list_initialize(&timers);
|
|
};
|
|
|
|
ctx_t *get_window_ctx()
|
|
{
|
|
return &Window.client_ctx;
|
|
};
|
|
|
|
void update_rect(ctrl_t *ctrl)
|
|
{
|
|
int ctx_w, ctx_h;
|
|
int src_x, src_y;
|
|
|
|
src_x = ctrl->rc.l - ctrl->ctx->offset_x;
|
|
src_y = ctrl->rc.t - ctrl->ctx->offset_y;
|
|
|
|
ctx_w = ctrl->parent->w;
|
|
ctx_h = ctrl->parent->h;
|
|
|
|
Blit(ctrl->ctx->pixmap->data, ctrl->rc.l, ctrl->rc.t, src_x, src_y,
|
|
ctrl->w, ctrl->h, ctx_w, ctx_h, ctrl->ctx->pixmap->pitch);
|
|
|
|
// need_update++;
|
|
};
|
|
|
|
|
|
void Blit(void *bitmap, int dst_x, int dst_y,
|
|
int src_x, int src_y, int w, int h,
|
|
int src_w, int src_h, int stride)
|
|
{
|
|
volatile struct blit_call bc;
|
|
|
|
bc.dstx = dst_x;
|
|
bc.dsty = dst_y;
|
|
bc.w = w;
|
|
bc.h = h;
|
|
bc.srcx = src_x;
|
|
bc.srcy = src_y;
|
|
bc.srcw = src_w;
|
|
bc.srch = src_h;
|
|
bc.stride = stride;
|
|
bc.bitmap = bitmap;
|
|
|
|
__asm__ __volatile__(
|
|
"int $0x40"
|
|
::"a"(73),"b"(0x20),"c"(&bc.dstx));
|
|
|
|
};
|
|
|
|
ctrl_t *get_child(ctrl_t *ctrl, int x, int y)
|
|
{
|
|
ctrl_t *child = NULL;
|
|
|
|
ctrl_t *tmp = (ctrl_t*)ctrl->child.next;
|
|
|
|
while( &tmp->link != &ctrl->child )
|
|
{
|
|
if(pt_in_rect(&tmp->rc, x, y))
|
|
{
|
|
child = get_child(tmp, x, y);
|
|
return child == NULL ? tmp : child;
|
|
};
|
|
tmp = (ctrl_t*)tmp->link.next;
|
|
};
|
|
return child;
|
|
};
|
|
|
|
ctrl_t *capture_mouse(ctrl_t *newm)
|
|
{
|
|
ctrl_t *old = mouse_capture;
|
|
|
|
mouse_capture = newm;
|
|
|
|
__asm__ __volatile__(
|
|
"int $0x40"
|
|
::"a"(40), "b"(0x80000027));
|
|
|
|
return old;
|
|
}
|
|
|
|
void release_mouse(void)
|
|
{
|
|
mouse_capture = NULL;
|
|
__asm__ __volatile__(
|
|
"int $0x40"
|
|
::"a"(40), "b"(0xC0000027));
|
|
}
|