794 lines
22 KiB
C
794 lines
22 KiB
C
#include "multiboot.h"
|
|
#include "font.h"
|
|
#include "pointer.xpm"
|
|
#include "minimize.xpm"
|
|
#include "close.xpm"
|
|
#include "defaulticon.xpm"
|
|
#include "keyboard.h"
|
|
#include "gui.h"
|
|
#include "schedule.h"
|
|
#include "mouse.h"
|
|
#include "string.h"
|
|
#include "memory.h"
|
|
#include "console.h"
|
|
|
|
extern struct task_t *current_task;
|
|
|
|
extern const struct bitmap_font font;
|
|
|
|
#define WIN_REQ_FLAG_NO_TITLE 0x01
|
|
|
|
#define BochsBreak() outportw(0x8A00,0x8A00); outportw(0x8A00,0x08AE0);
|
|
#define BochsConsolePrintChar(c) outportb(0xe9, c)
|
|
|
|
void render(unsigned char* dest, unsigned char* src, unsigned int src_width, unsigned int src_height, int dest_x, int dest_y, unsigned int dest_width, unsigned int dest_height, unsigned int src_depth);
|
|
void gui_pagemap();
|
|
|
|
struct ModeInfoBlock {
|
|
unsigned short attributes;
|
|
unsigned char winA,winB;
|
|
unsigned short granularity;
|
|
unsigned short winsize;
|
|
unsigned short segmentA, segmentB;
|
|
unsigned int winFuncPointer;
|
|
unsigned short pitch; // bytes per scanline
|
|
|
|
unsigned short Xres, Yres;
|
|
unsigned char Wchar, Ychar, planes, bpp, banks;
|
|
unsigned char memory_model, bank_size, image_pages;
|
|
unsigned char reserved0;
|
|
|
|
unsigned char red_mask, red_position;
|
|
unsigned char green_mask, green_position;
|
|
unsigned char blue_mask, blue_position;
|
|
unsigned char rsv_mask, rsv_position;
|
|
unsigned char directcolor_attributes;
|
|
|
|
unsigned int physbase; // your LFB (Linear Framebuffer) address ;)
|
|
unsigned int reserved1;
|
|
unsigned short reserved2;
|
|
} __attribute__((packed));
|
|
|
|
|
|
unsigned char *defaulticon;
|
|
unsigned char *mouseptr;
|
|
unsigned char *backbuffer;
|
|
unsigned char vidmode;
|
|
unsigned char *framebuffer;
|
|
unsigned short width, height, depth, bytesPerLine;
|
|
unsigned char *minimizebtn;
|
|
unsigned char *closebtn;
|
|
unsigned char *wallpaper;
|
|
|
|
unsigned int window_count = 0;
|
|
struct window_t **windows;
|
|
|
|
extern int mouse_pos_x;
|
|
extern int mouse_pos_y;
|
|
|
|
extern char middle_btn;
|
|
extern char left_btn;
|
|
extern char right_btn;
|
|
|
|
unsigned int serialnos;
|
|
int wallpaper_lock;
|
|
|
|
struct ModeInfoBlock *modeinfo;
|
|
|
|
void gui_convert_xpm(char **xpm, unsigned char **buffer);
|
|
|
|
void init_gui(multiboot_info_t *mbinfo) {
|
|
if (mbinfo->flags & 1 << 11) {
|
|
serialnos = 0;
|
|
vidmode = 1;
|
|
modeinfo = (struct ModeInfoBlock *)mbinfo->vbe_mode_info;
|
|
framebuffer = (unsigned char *)modeinfo->physbase;
|
|
bytesPerLine = modeinfo->pitch;
|
|
width = modeinfo->Xres;
|
|
height = modeinfo->Yres;
|
|
depth = modeinfo->bpp / 8;
|
|
gui_pagemap();
|
|
backbuffer = (unsigned char *)malloc(width * height * depth);
|
|
|
|
memset(backbuffer, 0, width * height * depth);
|
|
|
|
windows = (void *)0;
|
|
|
|
//closebtn = (char *)malloc(16 * 16 * 3);
|
|
//memset(closebtn, 0, 16 * 16 * 3);
|
|
gui_convert_xpm(close_xpm, &closebtn);
|
|
|
|
|
|
gui_convert_xpm(pointer_xpm, &mouseptr);
|
|
//mouseptr = (char *)malloc(32 * 32 * 3);
|
|
//memset(mouseptr, 0, 32 * 32 * 3);
|
|
|
|
|
|
gui_convert_xpm(minimize_xpm, &minimizebtn);
|
|
|
|
//minimizebtn = (char *)malloc(16 * 16 * 3);
|
|
//memset(minimizebtn, 0, 16 * 16 * 3);
|
|
|
|
gui_convert_xpm(defaulticon_xpm, &defaulticon);
|
|
//defaulticon = (char *)malloc(64 * 64 * 3);
|
|
//memset(defaulticon, 0, 64 * 64 * 3);
|
|
|
|
wallpaper = (void *)0;
|
|
wallpaper_lock = 0;
|
|
} else {
|
|
vidmode = 0;
|
|
}
|
|
}
|
|
|
|
void fill_rect(unsigned char *buffer, unsigned int dest_width, unsigned int dest_height, int sx, int sy, int w, int h, unsigned int colour) {
|
|
int j;
|
|
int k;
|
|
unsigned int where;
|
|
|
|
if (sy < 0) {
|
|
h = h + sy;
|
|
sy = 0;
|
|
}
|
|
|
|
if (sx < 0) {
|
|
w = w + sx;
|
|
sx = 0;
|
|
}
|
|
|
|
if (sx + w >= dest_width) {
|
|
w = dest_width - sx;
|
|
}
|
|
|
|
if (sy + h >= dest_height) {
|
|
h = dest_height - sy;
|
|
}
|
|
|
|
where = (sy * (dest_width * depth)) + (sx * depth);
|
|
|
|
for (j=0;j<h;j++) {
|
|
for (k=0;k<w;k++) {
|
|
buffer[where + k*depth] = colour & 255;
|
|
buffer[where + k*depth + 1] = (colour >> 8) & 255;
|
|
buffer[where + k*depth + 2] = (colour >> 16) & 255;
|
|
}
|
|
where += (dest_width) * depth;
|
|
}
|
|
}
|
|
|
|
void gui_putpixel(unsigned char *buffer, unsigned int dest_width, unsigned int dest_height, int x, int y, unsigned int color) {
|
|
if (x >= dest_width || y >= dest_height) {
|
|
return;
|
|
}
|
|
if (x < 0 || y < 0) {
|
|
return;
|
|
}
|
|
int where = (x * depth) + (y * dest_width * depth);
|
|
buffer[where] = color & 255; // BLUE
|
|
buffer[where + 1] = (color >> 8) & 255; // GREEN
|
|
buffer[where + 2] = (color >> 16) & 255; // RED
|
|
}
|
|
|
|
int char_to_hex(char c) {
|
|
if (c >= '0' && c <= '9') {
|
|
return c - '0';
|
|
} else {
|
|
return (c - 'A') + 10;
|
|
}
|
|
|
|
}
|
|
|
|
void gui_convert_xpm(char **xpm, unsigned char **buffer) {
|
|
unsigned int bwidth;
|
|
unsigned int bheight;
|
|
unsigned int colours;
|
|
unsigned int charsperpixel;
|
|
|
|
int offset = 0;
|
|
|
|
bwidth = 0;
|
|
while (xpm[0][offset] != ' ') {
|
|
bwidth = bwidth * 10 + (xpm[0][offset] - '0');
|
|
offset++;
|
|
}
|
|
offset++;
|
|
bheight = 0;
|
|
while (xpm[0][offset] != ' ') {
|
|
bheight = bheight * 10 + (xpm[0][offset] - '0');
|
|
offset++;
|
|
}
|
|
offset++;
|
|
|
|
colours = 0;
|
|
while (xpm[0][offset] != ' ') {
|
|
colours = colours * 10 + (xpm[0][offset] - '0');
|
|
offset++;
|
|
}
|
|
offset++;
|
|
|
|
charsperpixel = 0;
|
|
while (xpm[0][offset] != ' ' && xpm[0][offset] != '\0') {
|
|
charsperpixel = charsperpixel * 10 + (xpm[0][offset] - '0');
|
|
offset++;
|
|
}
|
|
|
|
|
|
// do colours
|
|
unsigned int *theColours = (unsigned int *)malloc(sizeof(unsigned int) * colours);
|
|
char **theKeys = (char**)malloc(colours * sizeof(char *));
|
|
|
|
int i,j,k,l;
|
|
|
|
for (i=0;i<colours;i++) {
|
|
theKeys[i] = (char *)malloc(charsperpixel);
|
|
for (j=0;j<charsperpixel;j++) {
|
|
theKeys[i][j] = xpm[i+1][j];
|
|
}
|
|
offset = 3 + charsperpixel;
|
|
if (xpm[i+1][offset] == '#') {
|
|
theColours[i] = 0;
|
|
offset++;
|
|
theColours[i] = theColours[i] | (char_to_hex(xpm[i+1][offset]) << 20);
|
|
offset++;
|
|
theColours[i] = theColours[i] | (char_to_hex(xpm[i+1][offset]) << 16);
|
|
offset++;
|
|
theColours[i] = theColours[i] | (char_to_hex(xpm[i+1][offset]) << 12);
|
|
offset++;
|
|
theColours[i] = theColours[i] | (char_to_hex(xpm[i+1][offset]) << 8);
|
|
offset++;
|
|
theColours[i] = theColours[i] | (char_to_hex(xpm[i+1][offset]) << 4);
|
|
offset++;
|
|
theColours[i] = theColours[i] | char_to_hex(xpm[i+1][offset]);
|
|
} else {
|
|
theColours[i] = 0xff000000;
|
|
}
|
|
}
|
|
unsigned char *ptr = (unsigned char *)malloc(bwidth * bheight * 3);
|
|
|
|
|
|
*buffer = ptr;
|
|
memset(ptr, 0, bwidth * bheight * 3);
|
|
|
|
int boffset = 0;
|
|
int match;
|
|
for (i=0;i<bheight;i++) {
|
|
for (j=0;j<bwidth;j++) {
|
|
|
|
for (k=0;k<colours;k++) {
|
|
match = 1;
|
|
|
|
for (l=0;l<charsperpixel;l++) {
|
|
if (theKeys[k][l] != xpm[i+colours+1][j * charsperpixel + l]){
|
|
match = 0;
|
|
}
|
|
}
|
|
if (match == 1) {
|
|
if (theColours[k] != 0xff000000) {
|
|
ptr[boffset] = theColours[k] & 255; // BLUE
|
|
ptr[boffset + 1] = (theColours[k] >> 8) & 255; // GREEN
|
|
ptr[boffset + 2] = (theColours[k] >> 16) & 255; // RED
|
|
|
|
}
|
|
boffset+=3;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
free(theColours);
|
|
|
|
for (i=0;i<colours;i++) {
|
|
free(theKeys[i]);
|
|
}
|
|
free(theKeys);
|
|
}
|
|
|
|
void gui_display_pointer() {
|
|
render(backbuffer, mouseptr, 32, 32, mouse_pos_x, mouse_pos_y, width, height, 3);
|
|
}
|
|
|
|
void gui_draw_char(unsigned char *buffer, unsigned int dest_width, unsigned int dest_height, unsigned int x, unsigned int y, char c, unsigned int colour) {
|
|
int i;
|
|
|
|
for (i=0;i<font.Chars;i++) {
|
|
if (font.Index[i] == c) break;
|
|
}
|
|
|
|
const char *font_char = &font.Bitmap[i * font.Height];
|
|
int cx,cy;
|
|
//int mask[8]={1,2,4,8,16,32,64,128};
|
|
int mask[8]={128,64,32,16,8,4,2,1};
|
|
|
|
for(cy=0;cy<16;cy++){
|
|
for(cx=0;cx<8;cx++){
|
|
if(font_char[cy]&mask[cx]) gui_putpixel(buffer, dest_width, dest_height, x+cx,y+cy, colour);
|
|
}
|
|
}
|
|
}
|
|
|
|
void draw_text(unsigned char *buffer, unsigned int dest_width, unsigned int dest_height, int sx, int sy, unsigned int colour, char *text) {
|
|
int i;
|
|
for (i=0;i<strlen(text);i++) {
|
|
gui_draw_char(buffer, dest_width, dest_height, sx + (i * 8), sy, text[i], colour);
|
|
}
|
|
}
|
|
|
|
void gui_keyboard_in(unsigned char scancode, unsigned char state) {
|
|
// add a keyboard message
|
|
if (windows[window_count-1]->event_msg_count < 99) {
|
|
struct event_msg_t *new_msg = (struct event_msg_t *)malloc(sizeof(struct event_msg_t));
|
|
new_msg->type = 1;
|
|
new_msg->code = scancode;
|
|
new_msg->state = state;
|
|
|
|
windows[window_count-1]->event_msgs[windows[window_count-1]->event_msg_count++] = new_msg;
|
|
}
|
|
}
|
|
|
|
extern int gui_change_window_caption(int serialno, char *cap) {
|
|
int i;
|
|
for (i=0;i<window_count;i++) {
|
|
if (windows[i]->serialno == serialno) {
|
|
strncpy(windows[i]->name, cap, 128);
|
|
return 0;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int gui_add_window(unsigned char *contents, char *name, int x, int y, int w, int h, unsigned char *icon, unsigned int flags, void (*keyboard_d)(char c)) {
|
|
struct window_t *new_window;
|
|
int i;
|
|
|
|
if (window_count == 0) {
|
|
windows = (struct window_t **)malloc(sizeof(struct window_t *));
|
|
} else {
|
|
windows = (struct window_t **)realloc(windows, sizeof(struct window_t *) * (window_count + 1));
|
|
}
|
|
|
|
new_window = (struct window_t *)malloc(sizeof(struct window_t));
|
|
new_window->serialno = ++serialnos;
|
|
new_window->posx = x;
|
|
new_window->posy = y;
|
|
new_window->width = w;
|
|
new_window->height = h;
|
|
new_window->minimized = 0;
|
|
new_window->iconx = 0;
|
|
new_window->icony = 0;
|
|
new_window->close_req = 0;
|
|
new_window->lclick = 0;
|
|
new_window->rclick = 0;
|
|
new_window->mclick = 0;
|
|
new_window->flags = flags;
|
|
new_window->event_msg_count = 0;
|
|
|
|
if (contents == (void *)0) {
|
|
new_window->contents = (unsigned char *)malloc(w * h * depth);
|
|
memset(new_window->contents, 0, w * h * depth);
|
|
} else {
|
|
new_window->contents = contents;
|
|
}
|
|
if (keyboard_d == (void *)0) {
|
|
new_window->keyboard_dest = gui_keyboard_in;
|
|
} else {
|
|
new_window->keyboard_dest = keyboard_d;
|
|
}
|
|
|
|
if (icon == (void *)0) {
|
|
new_window->icon = (unsigned char *)malloc(64 * 64 * 3);
|
|
memcpy(new_window->icon, defaulticon, 64 * 64 * 3);
|
|
} else {
|
|
new_window->icon = (unsigned char *)malloc(64 * 64 * 3);
|
|
memcpy(new_window->icon, icon, 64 * 64 * 3);
|
|
}
|
|
|
|
strncpy(new_window->name, name, 128);
|
|
new_window->zorder = window_count;
|
|
windows[window_count] = new_window;
|
|
window_count++;
|
|
|
|
keyboard_set_handler(new_window->keyboard_dest);
|
|
|
|
if (current_task->window_count == 0) {
|
|
current_task->window_list = (struct window_t **)malloc(sizeof(struct window_t *));
|
|
} else {
|
|
current_task->window_list = (struct window_t **)realloc(current_task->window_list, sizeof(struct window_t *) * (current_task->window_count + 1));
|
|
}
|
|
|
|
current_task->window_list[current_task->window_count] = new_window;
|
|
current_task->window_count++;
|
|
|
|
return new_window->serialno;
|
|
}
|
|
|
|
void gui_destroy_window(int serialno, struct task_t *task) {
|
|
struct window_t *window;
|
|
int i, j, k;
|
|
|
|
for (i=0;i<window_count;i++) {
|
|
if (windows[i]->serialno == serialno) {
|
|
window = windows[i];
|
|
|
|
for (k=0;k<task->window_count;k++) {
|
|
if (task->window_list[k] == window) {
|
|
for (j=k;j<task->window_count-1;j++) {
|
|
task->window_list[j] = task->window_list[j+1];
|
|
}
|
|
task->window_count--;
|
|
if (task->window_count == 0) {
|
|
free(task->window_list);
|
|
task->window_list = (void *)0;
|
|
} else {
|
|
task->window_list = (struct window_t **)realloc(task->window_list, sizeof(struct window_t *) * task->window_count);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (j=i;j<window_count-1;j++) {
|
|
windows[j] = windows[j+1];
|
|
}
|
|
|
|
|
|
window_count--;
|
|
|
|
windows = (struct window_t **)realloc(windows, sizeof(struct window_t *) * window_count);
|
|
keyboard_set_handler(windows[window_count-1]->keyboard_dest);
|
|
free(window->icon);
|
|
free(window->contents);
|
|
free(window);
|
|
return;
|
|
}
|
|
}
|
|
kprintf("Window not found %d\n", serialno);
|
|
}
|
|
|
|
void gui_drawtitlebar(unsigned char *buffer, unsigned int dest_width, unsigned int dest_height, struct window_t *window) {
|
|
fill_rect(buffer, dest_width, dest_height, window->posx, window->posy - 25, window->width, 25, 0xf182f8);
|
|
draw_text(buffer, dest_width, dest_height, window->posx + 25 + 4, window->posy - 25 + 4, 0xffffff, window->name);
|
|
render(buffer, minimizebtn, 16, 16, window->posx + window->width - 20, window->posy - 20, dest_width, dest_height, 3);
|
|
render(buffer, closebtn, 16, 16, window->posx + 5, window->posy - 20, dest_width, dest_height, 3);
|
|
|
|
}
|
|
|
|
void gui_pagemap() {
|
|
framebuffer = mem_map_framebuffer((unsigned int)framebuffer, bytesPerLine * height);
|
|
}
|
|
|
|
void gui_find_icon_space(struct window_t *window) {
|
|
int i,j;
|
|
int x, y;
|
|
int foundspot;
|
|
|
|
i = 0;
|
|
|
|
while (1) {
|
|
y = height - (((i / (width / 96)) + 1) * 96);
|
|
x = (i % (width / 96)) * 96 + 16;
|
|
foundspot = 1;
|
|
for (j=0;j<window_count;j++) {
|
|
if (!(windows[j]->iconx == 0 && windows[j]->icony == 0)) {
|
|
if (!(x > windows[j]->iconx && x < windows[j]->iconx + 96 && y > windows[j]->icony && y < windows[j]->icony + 96) && !(windows[j]->icony == y && windows[j]->iconx == x)) {
|
|
foundspot = 1;
|
|
} else {
|
|
foundspot = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (foundspot || i == 80) {
|
|
window->iconx = x;
|
|
window->icony = y;
|
|
return;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
}
|
|
|
|
int gui_blit(int wh, int x, int y, int w, int h, unsigned char *bmp) {
|
|
struct window_t *win = (void *)0;
|
|
int i;
|
|
|
|
for (i=0;i<window_count;i++) {
|
|
if (windows[i]->serialno == wh) {
|
|
win = windows[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (win == (void *)0) {
|
|
return 0;
|
|
}
|
|
|
|
render(win->contents, bmp, w, h, x, y, win->width, win->height, 3);
|
|
return 1;
|
|
}
|
|
|
|
int gui_req_input(int wh, struct window_update_req *req) {
|
|
struct window_t *win = (void *)0;
|
|
int i;
|
|
|
|
for (i=0;i<window_count;i++) {
|
|
if (windows[i]->serialno == wh) {
|
|
win = windows[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (win == (void *)0) {
|
|
return 0;
|
|
}
|
|
|
|
req->close_req = win->close_req;
|
|
|
|
req->event_msgs_count = win->event_msg_count;
|
|
|
|
for (i=0;i<req->event_msgs_count;i++) {
|
|
memcpy(&req->event_msgs[i], win->event_msgs[i], sizeof(struct event_msg_t));
|
|
free(win->event_msgs[i]);
|
|
}
|
|
win->event_msg_count = 0;
|
|
|
|
req->mousex = mouse_pos_x - win->posx;
|
|
req->mousey = mouse_pos_y - win->posy;
|
|
|
|
req->x = win->posx;
|
|
req->y = win->posy;
|
|
|
|
win->close_req = 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void gui_flip() {
|
|
int i, c, d;
|
|
struct window_t *swap;
|
|
// do click
|
|
|
|
if (mouse_get_click(0) == 1) {
|
|
for (i=window_count-1;i>=0;i--) {
|
|
if (!(windows[i]->minimized)) {
|
|
if (mouse_pos_x > windows[i]->posx && mouse_pos_x < windows[i]->posx + windows[i]->width && mouse_pos_y > windows[i]->posy - 25 && mouse_pos_y < windows[i]->posy + windows[i]->height) {
|
|
// send mouse click to client
|
|
if (mouse_pos_x > windows[i]->posx + windows[i]->width - 25 && mouse_pos_x < windows[i]->posx + windows[i]->width && mouse_pos_y > windows[i]->posy - 25 && mouse_pos_y < windows[i]->posy) {
|
|
// minimize
|
|
windows[i]->minimized = 1;
|
|
if (windows[i]->iconx == 0 && windows[i]->icony == 0) {
|
|
gui_find_icon_space(windows[i]);
|
|
}
|
|
} else if (mouse_pos_x > windows[i]->posx && mouse_pos_x < windows[i]->posx + 25 && mouse_pos_y > windows[i]->posy - 25 && mouse_pos_y < windows[i]->posy) {
|
|
windows[i]->close_req = 1;
|
|
} else if (windows[i]->zorder != window_count -1) {
|
|
windows[window_count-1]->zorder = windows[i]->zorder;
|
|
windows[i]->zorder = window_count - 1;
|
|
keyboard_set_handler(windows[i]->keyboard_dest);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i=window_count-1;i>=0;i--) {
|
|
if (windows[i]->minimized) {
|
|
if (mouse_pos_x > windows[i]->iconx -16 && mouse_pos_x < windows[i]->iconx + 72 && mouse_pos_y > windows[i]->icony -16 && mouse_pos_y < windows[i]->icony + 72) {
|
|
windows[i]->minimized = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// process mouse down / up events
|
|
for (i=window_count-1;i>=0;i--) {
|
|
if (!windows[i]->minimized) {
|
|
if (mouse_pos_x > windows[i]->posx && mouse_pos_x < windows[i]->posx + windows[i]->width && mouse_pos_y > windows[i]->posy && mouse_pos_y < windows[i]->posy + windows[i]->height) {
|
|
if (windows[i]->lclick != left_btn) {
|
|
if (windows[i]->event_msg_count < 99) {
|
|
struct event_msg_t *new_event = (struct event_msg_t *)malloc(sizeof(struct event_msg_t));
|
|
new_event->type = 2;
|
|
new_event->code = 1;
|
|
new_event->state = left_btn;
|
|
new_event->x = mouse_pos_x - windows[i]->posx;
|
|
new_event->y = mouse_pos_y - windows[i]->posy;
|
|
windows[i]->event_msgs[windows[i]->event_msg_count++] = new_event;
|
|
}
|
|
windows[i]->lclick = left_btn;
|
|
}
|
|
|
|
if (windows[i]->mclick != middle_btn) {
|
|
if (windows[i]->event_msg_count < 99) {
|
|
struct event_msg_t *new_event = (struct event_msg_t *)malloc(sizeof(struct event_msg_t));
|
|
new_event->type = 2;
|
|
new_event->code = 2;
|
|
new_event->state = middle_btn;
|
|
new_event->x = mouse_pos_x - windows[i]->posx;
|
|
new_event->y = mouse_pos_y - windows[i]->posy;
|
|
windows[i]->event_msgs[windows[i]->event_msg_count++] = new_event;
|
|
}
|
|
windows[i]->mclick = middle_btn;
|
|
}
|
|
if (windows[i]->rclick != right_btn) {
|
|
if (windows[i]->event_msg_count < 99) {
|
|
struct event_msg_t *new_event = (struct event_msg_t *)malloc(sizeof(struct event_msg_t));
|
|
new_event->type = 2;
|
|
new_event->code = 3;
|
|
new_event->state = right_btn;
|
|
new_event->x = mouse_pos_x - windows[i]->posx;
|
|
new_event->y = mouse_pos_y - windows[i]->posy;
|
|
windows[i]->event_msgs[windows[i]->event_msg_count++] = new_event;
|
|
}
|
|
windows[i]->rclick =right_btn;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int handled_drag = 0;
|
|
|
|
if (mouse_is_dragging(0)) {
|
|
for (i=window_count-1;i>=0;i--) {
|
|
if (!(windows[i]->minimized)) {
|
|
if (windows[i]->drag_start_x > -1) {
|
|
|
|
int xoffset = mouse_pos_x - windows[i]->drag_start_x;
|
|
int yoffset = mouse_pos_y - windows[i]->drag_start_y;
|
|
|
|
windows[i]->posx += xoffset;
|
|
windows[i]->posy += yoffset;
|
|
}
|
|
|
|
if (mouse_pos_x > windows[i]->posx && mouse_pos_x < windows[i]->posx + windows[i]->width && mouse_pos_y > windows[i]->posy - 25 && mouse_pos_y < windows[i]->posy) {
|
|
windows[i]->drag_start_x = mouse_pos_x;
|
|
windows[i]->drag_start_y = mouse_pos_y;
|
|
handled_drag = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!handled_drag) {
|
|
for (i=window_count-1;i>=0;i--) {
|
|
if (windows[i]->minimized) {
|
|
if (windows[i]->drag_start_x > -1) {
|
|
|
|
int xoffset = mouse_pos_x - windows[i]->drag_start_x;
|
|
int yoffset = mouse_pos_y - windows[i]->drag_start_y;
|
|
|
|
windows[i]->iconx += xoffset;
|
|
windows[i]->icony += yoffset;
|
|
}
|
|
if (mouse_pos_x > windows[i]->iconx -16 && mouse_pos_x < windows[i]->iconx + 72 && mouse_pos_y > windows[i]->icony -16 && mouse_pos_y < windows[i]->icony + 72) {
|
|
|
|
|
|
windows[i]->drag_start_x = mouse_pos_x;
|
|
windows[i]->drag_start_y = mouse_pos_y;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
for (i=window_count-1;i>=0;i--) {
|
|
windows[i]->drag_start_x = -1;
|
|
windows[i]->drag_start_y = -1;
|
|
}
|
|
}
|
|
|
|
// sort windows
|
|
for (c = 0 ; c < ( window_count - 1 ); c++) {
|
|
for (d = 0 ; d < window_count - c - 1; d++) {
|
|
if (windows[d]->zorder > windows[d+1]->zorder) {
|
|
swap = windows[d];
|
|
windows[d] = windows[d+1];
|
|
windows[d+1] = swap;
|
|
}
|
|
}
|
|
}
|
|
|
|
// draw desktop
|
|
if (wallpaper == (void *)0 || wallpaper_lock == 1) {
|
|
fill_rect(backbuffer, width, height, 0, 0, width, height, 0xfeccff);
|
|
} else {
|
|
render(backbuffer, wallpaper, 1024, 768, 0, 0, width, height, 3);
|
|
}
|
|
|
|
// draw icons
|
|
for (i=0;i<window_count;i++) {
|
|
if (windows[i]->minimized == 1) {
|
|
render(backbuffer, windows[i]->icon, 64, 64, windows[i]->iconx, windows[i]->icony, width, height, 3);
|
|
fill_rect(backbuffer, width, height, (48 - (strlen(windows[i]->name) * 8 / 2)) + (windows[i]->iconx - 16), windows[i]->icony + 74, strlen(windows[i]->name) * 8, 16, 0xf9c5ff);
|
|
draw_text(backbuffer, width, height, (48 - (strlen(windows[i]->name) * 8 / 2)) + (windows[i]->iconx - 16), windows[i]->icony + 74, 0, windows[i]->name);
|
|
}
|
|
}
|
|
|
|
// draw windows
|
|
for (i=0;i<window_count;i++) {
|
|
if (windows[i]->minimized == 0) {
|
|
|
|
if (!(windows[i]->flags & WIN_REQ_FLAG_NO_TITLE)) {
|
|
fill_rect(backbuffer, width, height, windows[i]->posx - 1, windows[i]->posy - 26, windows[i]->width + 2, windows[i]->height + 27, 0);
|
|
gui_drawtitlebar(backbuffer, width, height, windows[i]);
|
|
} else {
|
|
fill_rect(backbuffer, width, height, windows[i]->posx - 1, windows[i]->posy - 1, windows[i]->width + 2, windows[i]->height + 2, 0);
|
|
}
|
|
render(backbuffer, windows[i]->contents, windows[i]->width, windows[i]->height, windows[i]->posx, windows[i]->posy, width, height, depth);
|
|
}
|
|
}
|
|
|
|
// draw mouse
|
|
gui_display_pointer();
|
|
|
|
// flip
|
|
memcpy(framebuffer, backbuffer, bytesPerLine * height);
|
|
}
|
|
|
|
void render(unsigned char* dest, unsigned char* src, unsigned int src_width, unsigned int src_height, int dest_x, int dest_y, unsigned int dest_width, unsigned int dest_height, unsigned int src_depth) {
|
|
int i;
|
|
int pitch = dest_width * depth;
|
|
int src_off_x = 0;
|
|
int src_off_y = 0;
|
|
int index;
|
|
int dindex;
|
|
if (dest_x < 0) {
|
|
src_off_x = -dest_x;
|
|
dest_x = 0;
|
|
if (src_off_x >= src_width) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (dest_y < 0) {
|
|
src_off_y = -dest_y;
|
|
dest_y = 0;
|
|
if (src_off_y >= src_height) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
for (i=src_off_y;i<src_height;i++) {
|
|
unsigned int offset = (dest_x * depth) + (pitch * (dest_y + i));
|
|
|
|
unsigned char *pdest = (unsigned char *)(dest + offset);
|
|
unsigned char *psrc = (unsigned char *)(src + (src_width * src_depth * i));
|
|
int size = (src_width - src_off_x) * src_depth;
|
|
|
|
if (dest_y + i >= dest_height) {
|
|
break;
|
|
}
|
|
|
|
for (index = 0,dindex=0; index < size; index += src_depth,dindex+=depth) {
|
|
if (dest_x + (dindex / depth) > dest_width) {
|
|
break;
|
|
}
|
|
if (psrc[index] == 0xFF && psrc[index + 1] == 0x00 && psrc[index + 2] == 0xFF) continue;
|
|
pdest[dindex] = psrc[index + (src_off_x * src_depth)];
|
|
pdest[dindex+1] = psrc[index + (src_off_x * src_depth) + 1];
|
|
pdest[dindex+2] = psrc[index + (src_off_x * src_depth) + 2];
|
|
}
|
|
}
|
|
}
|
|
|
|
int gui_set_wallpaper(char *data, int len) {
|
|
wallpaper_lock = 1;
|
|
|
|
if (wallpaper != (void *)0) {
|
|
free(wallpaper);
|
|
}
|
|
|
|
|
|
|
|
wallpaper = (char *)dbmalloc(len, "gui_set_wallpaper");
|
|
|
|
if (!wallpaper) {
|
|
wallpaper_lock = 0;
|
|
return 0;
|
|
}
|
|
|
|
memcpy(wallpaper, data, len);
|
|
wallpaper_lock = 0;
|
|
return 1;
|
|
}
|