bug fixes + minimum and maximum window size options
This commit is contained in:
parent
d35c30c81c
commit
17d67cad27
8 changed files with 166 additions and 53 deletions
|
|
@ -107,6 +107,14 @@ PGPL_Renderer *pgpl_window_start_render(PGPL_Window *window, PGPL_Color color);
|
|||
* the pgpl_window_start_render function for more information. */
|
||||
void pgpl_window_finish_render(PGPL_Window *window, PGPL_Renderer *renderer);
|
||||
|
||||
/* This sets the minimum size that the given window can have. */
|
||||
void pgpl_window_set_minimum_size(PGPL_Window *window, uint32_t width,
|
||||
uint32_t height);
|
||||
|
||||
/* This sets the maximum size that the given window can have. */
|
||||
void pgpl_window_set_maximum_size(PGPL_Window *window, uint32_t width,
|
||||
uint32_t height);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -94,6 +94,16 @@ void pgpl_window_thread_reparent_to(PGPL_WindowThread *window_thread,
|
|||
* pgpl_window_get_raw_window for more information. */
|
||||
void *pgpl_window_thread_get_raw_window(PGPL_WindowThread *window_thread);
|
||||
|
||||
/* Threaded version of pgpl_window_set_minimum_size, see
|
||||
* pgpl_window_set_minimum_size for more information. */
|
||||
void pgpl_window_thread_set_minimum_size(PGPL_WindowThread *window_thread,
|
||||
uint32_t width, uint32_t height);
|
||||
|
||||
/* Threaded version of pgpl_window_set_maximum_size, see
|
||||
* pgpl_window_set_maximum_size for more information. */
|
||||
void pgpl_window_thread_set_maximum_size(PGPL_WindowThread *window_thread,
|
||||
uint32_t width, uint32_t height);
|
||||
|
||||
/* This function halts until the window_thread is destroyed. */
|
||||
void pgpl_window_thread_await_destruction(PGPL_WindowThread *window_thread);
|
||||
|
||||
|
|
|
|||
|
|
@ -21,4 +21,8 @@ void pgpl_window_internal_start_render(PGPL_Window *window);
|
|||
|
||||
void pgpl_window_internal_finish_render(PGPL_Window *window);
|
||||
|
||||
void pgpl_window_internal_init_shared(PGPL_WindowShared *window_shared);
|
||||
|
||||
void pgpl_window_internal_deinit_shared(PGPL_WindowShared *window_shared);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@ typedef enum PGPL_WindowThreadAction {
|
|||
PGPL_WINDOW_THREAD_SET_TRANSIENT,
|
||||
PGPL_WINDOW_THREAD_REPARENT,
|
||||
PGPL_WINDOW_THREAD_GET_RAW_WINDOW,
|
||||
PGPL_WINDOW_THREAD_CREATE_EVENT
|
||||
PGPL_WINDOW_THREAD_CREATE_EVENT,
|
||||
PGPL_WINDOW_THREAD_SET_MINIMUM_SIZE,
|
||||
PGPL_WINDOW_THREAD_SET_MAXIMUM_SIZE,
|
||||
} PGPL_WindowThreadAction;
|
||||
|
||||
typedef struct PGPL_WindowThreadCreateParameters {
|
||||
|
|
@ -178,6 +180,16 @@ static void *pgpl_window_event_loop(void *arg) {
|
|||
window_thread->data.event.type,
|
||||
window_thread->data.event.data);
|
||||
break;
|
||||
case PGPL_WINDOW_THREAD_SET_MINIMUM_SIZE:
|
||||
pgpl_window_set_minimum_size(window_thread->window,
|
||||
window_thread->data.size_data.width,
|
||||
window_thread->data.size_data.height);
|
||||
break;
|
||||
case PGPL_WINDOW_THREAD_SET_MAXIMUM_SIZE:
|
||||
pgpl_window_set_maximum_size(window_thread->window,
|
||||
window_thread->data.size_data.width,
|
||||
window_thread->data.size_data.height);
|
||||
break;
|
||||
}
|
||||
pgpl_mutex_unlock(window_thread->result_ready_lock);
|
||||
}
|
||||
|
|
@ -234,7 +246,7 @@ PGPL_WindowThread *pgpl_window_thread_create(
|
|||
|
||||
/* This is a helper function that helps send a message inside the event loop and
|
||||
* returns the result once done. */
|
||||
static PGPL_WindowThreadActionData *
|
||||
static inline PGPL_WindowThreadActionData *
|
||||
pgpl_window_thread_internal_send_message(PGPL_WindowThread *window_thread,
|
||||
PGPL_WindowThreadAction action,
|
||||
PGPL_WindowThreadActionData *data) {
|
||||
|
|
@ -366,6 +378,24 @@ void pgpl_window_thread_create_event(PGPL_WindowThread *window_thread,
|
|||
window_thread, PGPL_WINDOW_THREAD_CREATE_EVENT, &data);
|
||||
}
|
||||
|
||||
void pgpl_window_thread_set_minimum_size(PGPL_WindowThread *window_thread,
|
||||
uint32_t width, uint32_t height) {
|
||||
PGPL_WindowThreadActionData data;
|
||||
data.size_data.width = width;
|
||||
data.size_data.height = height;
|
||||
pgpl_window_thread_internal_send_message(
|
||||
window_thread, PGPL_WINDOW_THREAD_SET_MINIMUM_SIZE, &data);
|
||||
}
|
||||
|
||||
void pgpl_window_thread_set_maximum_size(PGPL_WindowThread *window_thread,
|
||||
uint32_t width, uint32_t height) {
|
||||
PGPL_WindowThreadActionData data;
|
||||
data.size_data.width = width;
|
||||
data.size_data.height = height;
|
||||
pgpl_window_thread_internal_send_message(
|
||||
window_thread, PGPL_WINDOW_THREAD_SET_MAXIMUM_SIZE, &data);
|
||||
}
|
||||
|
||||
void pgpl_window_thread_await_destruction(PGPL_WindowThread *window_thread) {
|
||||
pgpl_thread_join(window_thread->thread);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,9 +15,17 @@ struct PGPL_Window {
|
|||
PGPL_Vector *window_proc_event_data;
|
||||
int32_t last_mouse_x, last_mouse_y;
|
||||
int32_t scroll_accumulator;
|
||||
uint32_t min_width, min_height, max_width, max_height;
|
||||
char title[128];
|
||||
};
|
||||
|
||||
static inline void pgpl_window_internal_get_borders(uint32_t *width,
|
||||
uint32_t *height) {
|
||||
*width = GetSystemMetrics(SM_CXSIZEFRAME) * 2;
|
||||
*height =
|
||||
GetSystemMetrics(SM_CYSIZEFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION);
|
||||
}
|
||||
|
||||
/* Our WindowProc function, this needs to be overhauled a bit, and certain
|
||||
* things in here could be solved with more macros, to clean up and shorten the
|
||||
* code a bit.
|
||||
|
|
@ -25,7 +33,7 @@ struct PGPL_Window {
|
|||
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
||||
LPARAM lParam) {
|
||||
PGPL_Window *window = (PGPL_Window *)GetWindowLongPtr(hwnd, 0);
|
||||
PGPL_WindowEventType event_type;
|
||||
PGPL_WindowEventType event_type = PGPL_WINDOW_EVENT_NONE;
|
||||
PGPL_WindowEventData event_data;
|
||||
|
||||
if (window == NULL) {
|
||||
|
|
@ -145,14 +153,26 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
|||
case WM_CLOSE:
|
||||
event_type = PGPL_WINDOW_EVENT_CLOSE;
|
||||
break;
|
||||
case WM_GETMINMAXINFO: {
|
||||
LPMINMAXINFO min_max_info = (LPMINMAXINFO)lParam;
|
||||
uint32_t border_x;
|
||||
uint32_t border_y;
|
||||
pgpl_window_internal_get_borders(&border_x, &border_y);
|
||||
min_max_info->ptMinTrackSize.x = window->min_width + border_x;
|
||||
min_max_info->ptMinTrackSize.y = window->min_height + border_y;
|
||||
min_max_info->ptMaxTrackSize.x = window->max_width + border_x;
|
||||
min_max_info->ptMaxTrackSize.y = window->max_height + border_y;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
event_type = PGPL_WINDOW_EVENT_NONE;
|
||||
pgpl_mutex_unlock(window->window_proc_vector_lock);
|
||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
pgpl_vector_push_back(window->window_proc_event_type, &event_type);
|
||||
pgpl_vector_push_back(window->window_proc_event_data, &event_data);
|
||||
if (event_type != PGPL_WINDOW_EVENT_NONE) {
|
||||
pgpl_vector_push_back(window->window_proc_event_type, &event_type);
|
||||
pgpl_vector_push_back(window->window_proc_event_data, &event_data);
|
||||
}
|
||||
pgpl_mutex_unlock(window->window_proc_vector_lock);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -190,10 +210,14 @@ PGPL_Window *pgpl_window_create(const char *title, uint32_t width,
|
|||
0,
|
||||
0};
|
||||
|
||||
/* TODO: Move into shared function? */
|
||||
window->shared.scale = 1.0;
|
||||
window->shared.event_data = pgpl_vector_create(sizeof(PGPL_WindowEventData));
|
||||
window->shared.event_types = pgpl_vector_create(sizeof(PGPL_WindowEventType));
|
||||
pgpl_window_internal_init_shared(&window->shared);
|
||||
|
||||
window->min_width = 0;
|
||||
window->min_height = 0;
|
||||
/* For some reason, UINT32_MAX might be interpreted as a negative number in
|
||||
* wine. TODO: Investigate */
|
||||
window->max_width = INT16_MAX;
|
||||
window->max_height = INT16_MAX;
|
||||
|
||||
window->window_proc_event_data =
|
||||
pgpl_vector_create(sizeof(PGPL_WindowEventData));
|
||||
|
|
@ -238,9 +262,7 @@ PGPL_Window *pgpl_window_create(const char *title, uint32_t width,
|
|||
}
|
||||
|
||||
void pgpl_window_destroy(PGPL_Window *window) {
|
||||
/* TODO: Also turn this into a generic function perhaps. */
|
||||
pgpl_vector_destroy(window->shared.event_data);
|
||||
pgpl_vector_destroy(window->shared.event_types);
|
||||
pgpl_window_internal_deinit_shared(&window->shared);
|
||||
pgpl_mutex_destroy(window->window_proc_vector_lock);
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(window->wgl_context);
|
||||
|
|
@ -271,15 +293,20 @@ void pgpl_window_get_size(PGPL_Window *window, uint32_t *width,
|
|||
uint32_t *height) {
|
||||
RECT rect;
|
||||
GetClientRect(window->hwnd, &rect);
|
||||
*width = rect.right - rect.left;
|
||||
*height = rect.bottom - rect.top;
|
||||
if (width != NULL) {
|
||||
*width = rect.right - rect.left;
|
||||
}
|
||||
if (height != NULL) {
|
||||
*height = rect.bottom - rect.top;
|
||||
}
|
||||
}
|
||||
|
||||
void pgpl_window_set_size(PGPL_Window *window, uint32_t width,
|
||||
uint32_t height) {
|
||||
int border_x = GetSystemMetrics(SM_CXSIZEFRAME) * 2;
|
||||
int border_y =
|
||||
GetSystemMetrics(SM_CYSIZEFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION);
|
||||
uint32_t border_x;
|
||||
uint32_t border_y;
|
||||
|
||||
pgpl_window_internal_get_borders(&border_x, &border_y);
|
||||
|
||||
SetWindowPos(window->hwnd, NULL, 0, 0, width + border_x, height + border_y,
|
||||
SWP_NOMOVE);
|
||||
|
|
@ -288,8 +315,12 @@ void pgpl_window_set_size(PGPL_Window *window, uint32_t width,
|
|||
void pgpl_window_get_position(PGPL_Window *window, int32_t *x, int32_t *y) {
|
||||
WINDOWPLACEMENT placement;
|
||||
GetWindowPlacement(window->hwnd, &placement);
|
||||
*x = placement.ptMinPosition.x;
|
||||
*y = placement.ptMinPosition.y;
|
||||
if (x != NULL) {
|
||||
*x = placement.ptMinPosition.x;
|
||||
}
|
||||
if (y != NULL) {
|
||||
*y = placement.ptMinPosition.y;
|
||||
}
|
||||
}
|
||||
|
||||
void pgpl_window_set_position(PGPL_Window *window, int32_t x, int32_t y) {
|
||||
|
|
@ -355,4 +386,15 @@ void pgpl_window_internal_finish_render(PGPL_Window *window) {
|
|||
pgpl_mutex_unlock(pgpl_internal_render_lock);
|
||||
}
|
||||
|
||||
void pgpl_window_set_minimum_size(PGPL_Window *window, uint32_t width,
|
||||
uint32_t height) {
|
||||
window->min_width = width;
|
||||
window->min_height = height;
|
||||
}
|
||||
|
||||
void pgpl_window_set_maximum_size(PGPL_Window *window, uint32_t width,
|
||||
uint32_t height) {
|
||||
window->max_width = width;
|
||||
window->max_height = height;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ struct PGPL_Window {
|
|||
GLXContext glx_context;
|
||||
char *title;
|
||||
bool reparented;
|
||||
XSizeHints *size_hints;
|
||||
};
|
||||
|
||||
/* Creates a basic X11 window with GLX. We select all the events that we handle
|
||||
|
|
@ -30,10 +31,7 @@ PGPL_Window *pgpl_window_create(const char *title, uint32_t width,
|
|||
|
||||
window->title = NULL;
|
||||
|
||||
/* TODO: Move into shared function? */
|
||||
window->shared.scale = 1.0;
|
||||
window->shared.event_data = pgpl_vector_create(sizeof(PGPL_WindowEventData));
|
||||
window->shared.event_types = pgpl_vector_create(sizeof(PGPL_WindowEventType));
|
||||
pgpl_window_internal_init_shared(&window->shared);
|
||||
|
||||
window->reparented = 0;
|
||||
|
||||
|
|
@ -66,15 +64,16 @@ PGPL_Window *pgpl_window_create(const char *title, uint32_t width,
|
|||
|
||||
XFlush(window->display);
|
||||
|
||||
window->size_hints = XAllocSizeHints();
|
||||
|
||||
free(visual);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
void pgpl_window_destroy(PGPL_Window *window) {
|
||||
/* TODO: Also turn this into a generic function perhaps. */
|
||||
pgpl_vector_destroy(window->shared.event_data);
|
||||
pgpl_vector_destroy(window->shared.event_types);
|
||||
pgpl_window_internal_deinit_shared(&window->shared);
|
||||
XFree(window->size_hints);
|
||||
if (window->title != NULL) {
|
||||
XFree(window->title);
|
||||
}
|
||||
|
|
@ -145,7 +144,7 @@ void pgpl_window_set_position(PGPL_Window *window, int32_t x, int32_t y) {
|
|||
XFlush(window->display);
|
||||
}
|
||||
|
||||
static int32_t pgpl_window_internal_get_key(XKeyEvent *key_event) {
|
||||
static inline int32_t pgpl_window_internal_get_key(XKeyEvent *key_event) {
|
||||
KeySym key_sym;
|
||||
char buffer[32];
|
||||
wchar_t *wbuffer;
|
||||
|
|
@ -176,43 +175,33 @@ pgpl_window_internal_fetch_window_event(PGPL_Window *window,
|
|||
XNextEvent(window->display, &event);
|
||||
switch (event.type) {
|
||||
case KeyPress:
|
||||
if (event_data != NULL) {
|
||||
event_data->input_event.x = event.xkey.x;
|
||||
event_data->input_event.y = event.xkey.y;
|
||||
event_data->input_event.key = pgpl_window_internal_get_key(&event.xkey);
|
||||
}
|
||||
event_data->input_event.x = event.xkey.x;
|
||||
event_data->input_event.y = event.xkey.y;
|
||||
event_data->input_event.key = pgpl_window_internal_get_key(&event.xkey);
|
||||
return PGPL_WINDOW_EVENT_KEY_PRESS;
|
||||
break;
|
||||
case KeyRelease:
|
||||
if (event_data != NULL) {
|
||||
event_data->input_event.x = event.xkey.x;
|
||||
event_data->input_event.y = event.xkey.y;
|
||||
event_data->input_event.key = pgpl_window_internal_get_key(&event.xkey);
|
||||
}
|
||||
event_data->input_event.x = event.xkey.x;
|
||||
event_data->input_event.y = event.xkey.y;
|
||||
event_data->input_event.key = pgpl_window_internal_get_key(&event.xkey);
|
||||
return PGPL_WINDOW_EVENT_KEY_RELEASE;
|
||||
break;
|
||||
case ButtonPress:
|
||||
if (event_data != NULL) {
|
||||
event_data->input_event.x = event.xbutton.x;
|
||||
event_data->input_event.y = event.xbutton.y;
|
||||
event_data->input_event.key = event.xbutton.button;
|
||||
}
|
||||
event_data->input_event.x = event.xbutton.x;
|
||||
event_data->input_event.y = event.xbutton.y;
|
||||
event_data->input_event.key = event.xbutton.button;
|
||||
return PGPL_WINDOW_EVENT_MOUSE_PRESS;
|
||||
break;
|
||||
case ButtonRelease:
|
||||
if (event_data != NULL) {
|
||||
event_data->input_event.x = event.xbutton.x;
|
||||
event_data->input_event.y = event.xbutton.y;
|
||||
event_data->input_event.key = event.xbutton.button;
|
||||
}
|
||||
event_data->input_event.x = event.xbutton.x;
|
||||
event_data->input_event.y = event.xbutton.y;
|
||||
event_data->input_event.key = event.xbutton.button;
|
||||
return PGPL_WINDOW_EVENT_MOUSE_RELEASE;
|
||||
break;
|
||||
case MotionNotify:
|
||||
if (event_data != NULL) {
|
||||
event_data->input_event.x = event.xbutton.x;
|
||||
event_data->input_event.y = event.xbutton.y;
|
||||
event_data->input_event.key = 0;
|
||||
}
|
||||
event_data->input_event.x = event.xbutton.x;
|
||||
event_data->input_event.y = event.xbutton.y;
|
||||
event_data->input_event.key = 0;
|
||||
return PGPL_WINDOW_EVENT_MOUSE_MOVE;
|
||||
break;
|
||||
case ClientMessage:
|
||||
|
|
@ -249,4 +238,20 @@ void pgpl_window_internal_finish_render(PGPL_Window *window) {
|
|||
glXSwapBuffers(window->display, window->window);
|
||||
pgpl_mutex_unlock(pgpl_internal_render_lock);
|
||||
}
|
||||
|
||||
void pgpl_window_set_minimum_size(PGPL_Window *window, uint32_t width,
|
||||
uint32_t height) {
|
||||
window->size_hints->flags |= PMinSize;
|
||||
window->size_hints->min_width = width;
|
||||
window->size_hints->min_height = height;
|
||||
XSetWMNormalHints(window->display, window->window, window->size_hints);
|
||||
}
|
||||
|
||||
void pgpl_window_set_maximum_size(PGPL_Window *window, uint32_t width,
|
||||
uint32_t height) {
|
||||
window->size_hints->flags |= PMaxSize;
|
||||
window->size_hints->max_width = width;
|
||||
window->size_hints->max_height = height;
|
||||
XSetWMNormalHints(window->display, window->window, window->size_hints);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -57,6 +57,17 @@ void pgpl_window_create_event(PGPL_Window *window,
|
|||
}
|
||||
}
|
||||
|
||||
void pgpl_window_internal_init_shared(PGPL_WindowShared *window_shared) {
|
||||
window_shared->scale = 1.0;
|
||||
window_shared->event_data = pgpl_vector_create(sizeof(PGPL_WindowEventData));
|
||||
window_shared->event_types = pgpl_vector_create(sizeof(PGPL_WindowEventType));
|
||||
}
|
||||
|
||||
void pgpl_window_internal_deinit_shared(PGPL_WindowShared *window_shared) {
|
||||
pgpl_vector_destroy(window_shared->event_data);
|
||||
pgpl_vector_destroy(window_shared->event_types);
|
||||
}
|
||||
|
||||
/* Enables important OpenGL settings, like transparency support, and sets up our
|
||||
* projection matrix to be easier to work with. */
|
||||
PGPL_Renderer *pgpl_window_start_render(PGPL_Window *window, PGPL_Color color) {
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ int main(void) {
|
|||
|
||||
pgpl_gui_widget_add(gui, create_main_view(&app));
|
||||
|
||||
pgpl_window_thread_set_minimum_size(gui->window_thread, 320, 240);
|
||||
pgpl_window_thread_set_maximum_size(gui->window_thread, 640, 480);
|
||||
|
||||
pgpl_gui_run_and_show(gui, true);
|
||||
|
||||
pgpl_font_destroy(NULL, font);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue