add handler for motion/button events
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 16 Jan 2022 09:44:37 +0000 (10:44 +0100)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 16 Jan 2022 09:44:37 +0000 (10:44 +0100)
application/main.c
application/main.h
application/player.c
application/window.c
application/window.h

index 18d534b..43d6c05 100644 (file)
@@ -133,7 +133,7 @@ int main(int argc, char** argv) {
     srand(time(NULL));
     
     WindowShow(window);
-    XtAppMainLoop(app);
+    AppMainLoop(app);
     
     return 0;
 }
@@ -160,3 +160,25 @@ char* GetOpenFileArg(void) {
 void CleanOpenFileArg(void) {
     open_file_arg = NULL;
 }
+
+static Window app_player_window = 0;
+
+void SetPlayerWindow(Window w) {
+    app_player_window = w;
+}
+
+/*
+ * Extended Xt main loop, that also handles external window events
+ */
+void AppMainLoop(XtAppContext app) {
+    while(!XtAppGetExitFlag(app)) {
+        XEvent event;
+        XtAppNextEvent(app, &event);
+        
+        if(app_player_window != 0 && event.xany.window == app_player_window) {
+            WindowPlayerWidgetEvent(GetMainWindow(), &event);
+        } else {
+            XtDispatchEvent(&event);
+        }
+    }
+}
index be957b8..e39b827 100644 (file)
@@ -41,6 +41,10 @@ void AppExecProc(XtWorkProc proc, XtPointer data);
 char* GetOpenFileArg(void);
 void CleanOpenFileArg(void);
 
+void SetPlayerWindow(Window w);
+
+void AppMainLoop(XtAppContext app);
+
 
 #ifdef __cplusplus
 }
index 9e65410..6cdba87 100644 (file)
@@ -110,6 +110,7 @@ static void* wait_for_process(void *data) {
 
     player->isactive = FALSE;
     player->status = status;
+    SetPlayerWindow(0);
     
     return NULL;
 }
@@ -329,7 +330,6 @@ static void handle_json_rpc_msg(Player *player, JSONValue *v) {
     }
     
     //json_print(v, NULL, 0);
-    fflush(stdout);
 }
 
 static Boolean player_widget_set_size(XtPointer data) {
@@ -411,6 +411,9 @@ static Boolean get_player_window(XtPointer data) {
     if(nchild > 0) {
         p->window = child[0];
         XFree(child);
+        
+        SetPlayerWindow(p->window);
+        XSelectInput(XtDisplay(win->player_widget), p->window, PointerMotionMask);
     }
     
     return 0;
@@ -420,14 +423,24 @@ static void handle_json_rpc_event(Player *p, JSONValue *v, JSONValue *event) {
     if(!json_strcmp(event, "property-change")) {
         JSONValue *name = json_obj_get(&v->value.object, "name");
         JSONValue *data = json_obj_get(&v->value.object, "data");
-        if(!json_strcmp(name, "eof-reached")) {
+        if(!json_strcmp(name, "playback-time")) {
+            if(data && data->type == JSON_NUMBER) {
+                p->playback_time = data->value.number.value;
+                //printf("playback-time: %f\n", p->playback_time);
+            }
+        } else if(!json_strcmp(name, "eof-reached")) {
             if(data && data->type == JSON_LITERAL && data->value.literal.literal == JSON_TRUE) {
                 PlayerEOF(p);
             }
+        } else if(!json_strcmp(name, "osd-height")) {
+            if(data->type == JSON_NUMBER) {
+                p->osd_height = data->value.number.value;
+            }
         }
     } else if(!p->isstarted && !json_strcmp(event, "playback-restart")) {
         char *cmd = "{ \"command\": [\"observe_property\", 1, \"playback-time\"] }\n"
                     "{ \"command\": [\"observe_property\", 1, \"eof-reached\"] }\n"
+                    "{ \"command\": [\"observe_property\", 1, \"osd-height\"] }\n"
                     "{ \"command\": [\"get_property\", \"width\"], request_id=\"" REQ_ID_WIDTH "\" }\n"
                     "{ \"command\": [\"get_property\", \"height\"], request_id=\"" REQ_ID_HEIGHT "\" }\n"
                     "{ \"command\": [\"set_property\", \"keep-open\", true] }\n";
@@ -454,6 +467,7 @@ void PlayerDestroy(Player *p) {
         kill(p->process, SIGTERM);
     }
     
+    SetPlayerWindow(0);
     free(p);
 }
 
index e7c85df..26092cd 100644 (file)
@@ -39,6 +39,24 @@ static void ViewFullscreenCB(Widget w, void *udata, void *cdata);
 
 static void WindowRealized(MainWindow *win);
 
+static int blank_cursor_init = 0;
+static Pixmap blank_cursor_pixmap;
+static Cursor blank_cursor;
+
+static void init_blank_cursor(Widget w) {
+    char data = 0;
+    
+    XColor c;
+    
+    blank_cursor_pixmap = XCreateBitmapFromData(XtDisplay(w), XtWindow(w), &data, 1, 1);
+    if(!blank_cursor_pixmap) return;
+    
+    blank_cursor = XCreatePixmapCursor(XtDisplay(w), blank_cursor_pixmap, blank_cursor_pixmap, &c, &c, 0, 0);
+    
+    XFreePixmap(XtDisplay(w), blank_cursor_pixmap);
+    blank_cursor_init = 1;
+}
+
 static void window_close_handler(Widget window, void *udata, void *cdata) {
     WindowClosePlayer(main_window);
     ApplicationExit();
@@ -56,7 +74,7 @@ static void windowKeyEH(Widget widget, XtPointer data, XEvent *event, Boolean *d
 
 static int main_window_is_realized = 0;
 
-static void resizeEH(Widget widget, XtPointer data, XEvent *event, Boolean *dispatch) {
+static void resizeEH(Widget widget, XtPointer data, XEvent *event, Boolean *dispatch) {  
     if(!main_window_is_realized) {
         if(XtIsRealized(widget)) {
             main_window_is_realized = 1;
@@ -77,6 +95,10 @@ static void WindowRealized(MainWindow *win) {
         PlayerOpenFile(win);
         CleanOpenFileArg();
     }
+    
+    if(!blank_cursor_init) {
+        init_blank_cursor(win->player_widget);
+    }
 }
 
 static void playerWidgetInputCB(Widget widget, XtPointer u, XtPointer c) {
@@ -88,40 +110,51 @@ static void playerWidgetInputCB(Widget widget, XtPointer u, XtPointer c) {
     }
 }
 
-static void playerEH(Widget widget, XtPointer data, XEvent *event, Boolean *dispatch) {
-    MainWindow *win = data;
-    if(!win->player || win->player->window == 0) return;
-    
-    /*
-    if(event->type == EnterNotify) {
-        printf("enter: grab pointer\n");
-        
-        XtGrabPointer(
+static void windowGrabButton(MainWindow *win) {
+    //printf("grab\n");
+    XtGrabButton(
                 win->player_widget,
+                AnyButton,
+                AnyModifier,
                 True,
                 ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask | EnterWindowMask | LeaveWindowMask,
                 GrabModeAsync,
                 GrabModeAsync,
                 None,
-                None,
-                CurrentTime);
-        
+                None);
+    win->buttongrab = True;
+}
+
+static void playerEH(Widget widget, XtPointer data, XEvent *event, Boolean *dispatch) {
+    MainWindow *win = data;
+    int etype = event->type;
+    
+    ///*
+    if(etype == EnterNotify) {
+        //printf("enter\n");
+        windowGrabButton(win);
         return;
     }
-    if(event->type == LeaveNotify) {
-        printf("leave\n");
-        XtUngrabPointer(win->player_widget, CurrentTime); 
+    if(etype == LeaveNotify) {
+        //printf("leave\n");
+        //XtUngrabButton(win->player_widget, AnyButton, AnyModifier); 
+        //win->buttongrab = False;
         return;
     }
     
-    if(event->type == MotionNotify) {
-        static int testv = 0;
-        printf("test %d\n", testv++);
+    int pass = 0;
+    if(etype == ButtonPress || etype == ButtonRelease || etype == KeyPress || etype == KeyRelease) {
+        //printf("button press\n");
+        pass = 1;
     }
-    */
     
-    if(event->type == KeyPress || event->type == KeyRelease) {
+    if(!win->player || win->player->window == 0) return;
+    
+    WindowPlayerWidgetEvent(win, event);
+    
+    if(pass) {
         // redirect key events to the player window
+        //printf("redirect\n");
         event->xkey.window = win->player->window;
         XSendEvent(
                 XtDisplay(win->player_widget),
@@ -132,10 +165,22 @@ static void playerEH(Widget widget, XtPointer data, XEvent *event, Boolean *disp
     }
 }
 
+void WindowPlayerWidgetEvent(MainWindow *win, XEvent *event) {
+    int etype = event->type;
+    
+    if(etype == MotionNotify) {
+        
+    } else if(etype == ButtonPress) {
+        
+    } else if(etype == ButtonRelease) {
+        
+    }
+}
+
 MainWindow* WindowCreate(Display *display) {
     Arg args[32];
     int n;
-    
+     
     MainWindow *window = malloc(sizeof(MainWindow));
     memset(window, 0, sizeof(MainWindow));
     main_window = window;
@@ -423,7 +468,7 @@ static void ViewFullscreenCB(Widget w, void *udata, void *cdata) {
 void WindowAdjustAspectRatio(MainWindow *win) {
     if(!win->player) return;
     if(!win->player->isactive || win->player->width <= 0 || win->player->height <= 0) return;
-    
+      
     // we have a running player width video
     // adjust window aspect ratio (the window aspect ratio is different from
     // the video, because of window decoration, menubar and other extra controls)
@@ -455,3 +500,19 @@ void WindowClosePlayer(MainWindow *win) {
     }
     win->player = NULL;
 }
+
+void WindowHidePlayerCursor(MainWindow *win) {
+    if(!win->cursorhidden && win->player && win->player->window != 0) {
+        //XDefineCursor(XtDisplay(win->player_widget), XtWindow(win->player_widget), blank_cursor);
+        win->cursorhidden = True;
+        XFlush(XtDisplay(win->player_widget));
+    }
+}
+
+void WindowShowPlayerCursor(MainWindow *win) {
+    if(win->cursorhidden && win->player && win->player->window != 0) {
+        XDefineCursor(XtDisplay(win->player_widget), XtWindow(win->player_widget), None);
+        win->cursorhidden = False;
+        XFlush(XtDisplay(win->player_widget));
+    }
+}
index 82623e7..4424273 100644 (file)
@@ -44,6 +44,7 @@ typedef struct Player {
     double playback_time;
     int width;
     int height;
+    int osd_height;
 } Player;
     
 typedef struct MainWindow {
@@ -54,6 +55,8 @@ typedef struct MainWindow {
     Player *player;
     bool fullscreen;
     bool mbvisible;
+    bool cursorhidden;
+    bool buttongrab;
 } MainWindow;
 
 MainWindow* WindowCreate(Display *dp);
@@ -72,6 +75,11 @@ void WindowAdjustAspectRatio(MainWindow *win);
 
 void WindowClosePlayer(MainWindow *win);
 
+void WindowHidePlayerCursor(MainWindow *win);
+void WindowShowPlayerCursor(MainWindow *win);
+
+void WindowPlayerWidgetEvent(MainWindow *win, XEvent *event);
+
 #ifdef __cplusplus
 }
 #endif